1mod aes_cbc_operation;
6mod aes_common;
7mod aes_ctr_operation;
8mod aes_gcm_operation;
9mod aes_kw_operation;
10mod aes_ocb_operation;
11mod argon2_operation;
12mod chacha20_poly1305_operation;
13mod cshake_operation;
14mod ec_common;
15mod ecdh_operation;
16mod ecdsa_operation;
17mod ed25519_operation;
18mod hkdf_operation;
19mod hmac_operation;
20mod kangarootwelve_operation;
21mod ml_dsa_operation;
22mod ml_kem_operation;
23mod pbkdf2_operation;
24mod rsa_common;
25mod rsa_oaep_operation;
26mod rsa_pss_operation;
27mod rsassa_pkcs1_v1_5_operation;
28mod sha3_operation;
29mod sha_operation;
30mod turboshake_operation;
31mod x25519_operation;
32
33use std::fmt::Display;
34use std::ptr;
35use std::rc::Rc;
36use std::str::FromStr;
37
38use base64ct::{Base64UrlUnpadded, Encoding};
39use dom_struct::dom_struct;
40use js::conversions::{ConversionBehavior, ConversionResult, FromJSValConvertible};
41use js::jsapi::{Heap, JSObject};
42use js::jsval::UndefinedValue;
43use js::realm::CurrentRealm;
44use js::rust::wrappers2::JS_ParseJSON;
45use js::rust::{HandleObject, MutableHandleValue, Trace};
46use js::typedarray::{ArrayBufferU8, HeapUint8Array};
47use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
48use servo_constellation_traits::{
49 SerializableAesKeyAlgorithm, SerializableAlgorithm, SerializableCShakeParams,
50 SerializableDigestAlgorithm, SerializableEcKeyAlgorithm, SerializableHmacKeyAlgorithm,
51 SerializableKangarooTwelveParams, SerializableKeyAlgorithm,
52 SerializableKeyAlgorithmAndDerivatives, SerializableRsaHashedKeyAlgorithm,
53 SerializableTurboShakeParams,
54};
55use strum::{EnumString, IntoStaticStr, VariantArray};
56use zeroize::Zeroizing;
57
58use crate::dom::bindings::buffer_source::create_buffer_source;
59use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
60 CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
61};
62use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
63 AesKeyAlgorithm, Algorithm, AlgorithmIdentifier, EcKeyAlgorithm, EncapsulatedBits,
64 EncapsulatedKey, HmacKeyAlgorithm, JsonWebKey, KeyAlgorithm, KeyFormat, RsaHashedKeyAlgorithm,
65 RsaKeyAlgorithm, SubtleCryptoMethods,
66};
67use crate::dom::bindings::codegen::UnionTypes::{
68 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey, ObjectOrString,
69};
70use crate::dom::bindings::conversions::{
71 SafeToJSValConvertible, StringificationBehavior, get_property,
72};
73use crate::dom::bindings::error::{Error, Fallible};
74use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
75use crate::dom::bindings::reflector::DomGlobal;
76use crate::dom::bindings::root::DomRoot;
77use crate::dom::bindings::str::{DOMString, serialize_jsval_to_json_utf8};
78use crate::dom::bindings::trace::RootedTraceableBox;
79use crate::dom::cryptokey::{CryptoKey, CryptoKeyOrCryptoKeyPair};
80use crate::dom::globalscope::GlobalScope;
81use crate::dom::promise::Promise;
82
83const NAMED_CURVE_P256: &str = "P-256";
85const NAMED_CURVE_P384: &str = "P-384";
86const NAMED_CURVE_P521: &str = "P-521";
87
88static SUPPORTED_CURVES: &[&str] = &[NAMED_CURVE_P256, NAMED_CURVE_P384, NAMED_CURVE_P521];
89
90#[derive(EnumString, VariantArray, IntoStaticStr, PartialEq, Clone, Copy, MallocSizeOf)]
91enum CryptoAlgorithm {
92 #[strum(serialize = "RSASSA-PKCS1-v1_5")]
93 RsassaPkcs1V1_5,
94 #[strum(serialize = "RSA-PSS")]
95 RsaPss,
96 #[strum(serialize = "RSA-OAEP")]
97 RsaOaep,
98 #[strum(serialize = "ECDSA")]
99 Ecdsa,
100 #[strum(serialize = "ECDH")]
101 Ecdh,
102 #[strum(serialize = "Ed25519")]
103 Ed25519,
104 #[strum(serialize = "X25519")]
105 X25519,
106 #[strum(serialize = "AES-CTR")]
107 AesCtr,
108 #[strum(serialize = "AES-CBC")]
109 AesCbc,
110 #[strum(serialize = "AES-GCM")]
111 AesGcm,
112 #[strum(serialize = "AES-KW")]
113 AesKw,
114 #[strum(serialize = "HMAC")]
115 Hmac,
116 #[strum(serialize = "SHA-1")]
117 Sha1,
118 #[strum(serialize = "SHA-256")]
119 Sha256,
120 #[strum(serialize = "SHA-384")]
121 Sha384,
122 #[strum(serialize = "SHA-512")]
123 Sha512,
124 #[strum(serialize = "HKDF")]
125 Hkdf,
126 #[strum(serialize = "PBKDF2")]
127 Pbkdf2,
128 #[strum(serialize = "ML-KEM-512")]
129 MlKem512,
130 #[strum(serialize = "ML-KEM-768")]
131 MlKem768,
132 #[strum(serialize = "ML-KEM-1024")]
133 MlKem1024,
134 #[strum(serialize = "ML-DSA-44")]
135 MlDsa44,
136 #[strum(serialize = "ML-DSA-65")]
137 MlDsa65,
138 #[strum(serialize = "ML-DSA-87")]
139 MlDsa87,
140 #[strum(serialize = "AES-OCB")]
141 AesOcb,
142 #[strum(serialize = "ChaCha20-Poly1305")]
143 ChaCha20Poly1305,
144 #[strum(serialize = "SHA3-256")]
145 Sha3_256,
146 #[strum(serialize = "SHA3-384")]
147 Sha3_384,
148 #[strum(serialize = "SHA3-512")]
149 Sha3_512,
150 #[strum(serialize = "cSHAKE128")]
151 CShake128,
152 #[strum(serialize = "cSHAKE256")]
153 CShake256,
154 #[strum(serialize = "TurboSHAKE128")]
155 TurboShake128,
156 #[strum(serialize = "TurboSHAKE256")]
157 TurboShake256,
158 #[strum(serialize = "KT128")]
159 Kt128,
160 #[strum(serialize = "KT256")]
161 Kt256,
162 #[strum(serialize = "Argon2d")]
163 Argon2D,
164 #[strum(serialize = "Argon2i")]
165 Argon2I,
166 #[strum(serialize = "Argon2id")]
167 Argon2ID,
168}
169
170impl CryptoAlgorithm {
171 fn as_str(&self) -> &'static str {
173 (*self).into()
174 }
175
176 fn from_str_ignore_case(algorithm_name: &str) -> Fallible<CryptoAlgorithm> {
177 Self::VARIANTS
178 .iter()
179 .find(|algorithm| algorithm.as_str().eq_ignore_ascii_case(algorithm_name))
180 .cloned()
181 .ok_or(Error::NotSupported(Some(format!(
182 "Unsupported algorithm: {algorithm_name}"
183 ))))
184 }
185}
186
187#[dom_struct]
188pub(crate) struct SubtleCrypto {
189 reflector_: Reflector,
190}
191
192impl SubtleCrypto {
193 fn new_inherited() -> SubtleCrypto {
194 SubtleCrypto {
195 reflector_: Reflector::new(),
196 }
197 }
198
199 pub(crate) fn new(
200 cx: &mut js::context::JSContext,
201 global: &GlobalScope,
202 ) -> DomRoot<SubtleCrypto> {
203 reflect_dom_object_with_cx(Box::new(SubtleCrypto::new_inherited()), global, cx)
204 }
205
206 fn resolve_promise_with_data(&self, promise: Rc<Promise>, data: Zeroizing<Vec<u8>>) {
210 let trusted_promise = TrustedPromise::new(promise);
211 self.global()
212 .task_manager()
213 .crypto_task_source()
214 .queue(task!(resolve_data: move |cx| {
215 let promise = trusted_promise.root();
216
217 rooted!(&in(cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
218 match create_buffer_source::<ArrayBufferU8>(cx,
219 &data,
220 array_buffer_ptr.handle_mut(),
221 ) {
222 Ok(_) => promise.resolve_native(cx, &*array_buffer_ptr),
223 Err(_) => promise.reject_error(cx, Error::JSFailed),
224 }
225 }));
226 }
227
228 fn resolve_promise_with_jwk(
232 &self,
233 cx: &mut js::context::JSContext,
234 promise: Rc<Promise>,
235 jwk: Box<JsonWebKey>,
236 ) {
237 let stringified_jwk = match jwk.stringify(cx) {
240 Ok(stringified_jwk) => Zeroizing::new(stringified_jwk.to_string()),
241 Err(error) => {
242 self.reject_promise_with_error(promise, error);
243 return;
244 },
245 };
246
247 let trusted_subtle = Trusted::new(self);
248 let trusted_promise = TrustedPromise::new(promise);
249 self.global()
250 .task_manager()
251 .crypto_task_source()
252 .queue(task!(resolve_jwk: move |cx| {
253 let subtle = trusted_subtle.root();
254 let promise = trusted_promise.root();
255
256 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
257 Ok(jwk) => {
258 rooted!(&in(cx) let mut rval = UndefinedValue());
259 jwk.safe_to_jsval(cx, rval.handle_mut());
260 rooted!(&in(cx) let mut object = rval.to_object());
261 promise.resolve_native(cx, &*object);
262 },
263 Err(error) => {
264 subtle.reject_promise_with_error(promise, error);
265 return;
266 },
267 }
268 }));
269 }
270
271 fn resolve_promise_with_key(&self, promise: Rc<Promise>, key: DomRoot<CryptoKey>) {
274 let trusted_key = Trusted::new(&*key);
275 let trusted_promise = TrustedPromise::new(promise);
276 self.global()
277 .task_manager()
278 .crypto_task_source()
279 .queue(task!(resolve_key: move |cx| {
280 let key = trusted_key.root();
281 let promise = trusted_promise.root();
282 promise.resolve_native(cx, &key);
283 }));
284 }
285
286 fn resolve_promise_with_key_pair(&self, promise: Rc<Promise>, key_pair: CryptoKeyPair) {
289 let trusted_private_key = key_pair.privateKey.map(|key| Trusted::new(&*key));
290 let trusted_public_key = key_pair.publicKey.map(|key| Trusted::new(&*key));
291 let trusted_promise = TrustedPromise::new(promise);
292 self.global()
293 .task_manager()
294 .crypto_task_source()
295 .queue(task!(resolve_key: move |cx| {
296 let key_pair = CryptoKeyPair {
297 privateKey: trusted_private_key.map(|trusted_key| trusted_key.root()),
298 publicKey: trusted_public_key.map(|trusted_key| trusted_key.root()),
299 };
300 let promise = trusted_promise.root();
301 promise.resolve_native(cx, &key_pair);
302 }));
303 }
304
305 fn resolve_promise_with_bool(&self, promise: Rc<Promise>, result: bool) {
308 let trusted_promise = TrustedPromise::new(promise);
309 self.global()
310 .task_manager()
311 .crypto_task_source()
312 .queue(task!(resolve_bool: move |cx| {
313 let promise = trusted_promise.root();
314 promise.resolve_native(cx, &result);
315 }));
316 }
317
318 fn reject_promise_with_error(&self, promise: Rc<Promise>, error: Error) {
321 let trusted_promise = TrustedPromise::new(promise);
322 self.global()
323 .task_manager()
324 .crypto_task_source()
325 .queue(task!(reject_error: move |cx| {
326 let promise = trusted_promise.root();
327 promise.reject_error(cx, error);
328 }));
329 }
330
331 fn resolve_promise_with_encapsulated_key(
335 &self,
336 promise: Rc<Promise>,
337 encapsulated_key: SubtleEncapsulatedKey,
338 ) {
339 let trusted_promise = TrustedPromise::new(promise);
340 self.global().task_manager().crypto_task_source().queue(
341 task!(resolve_encapsulated_key: move |cx| {
342 let promise = trusted_promise.root();
343 promise.resolve_native(cx, &encapsulated_key);
344 }),
345 );
346 }
347
348 fn resolve_promise_with_encapsulated_bits(
352 &self,
353 promise: Rc<Promise>,
354 encapsulated_bits: SubtleEncapsulatedBits,
355 ) {
356 let trusted_promise = TrustedPromise::new(promise);
357 self.global().task_manager().crypto_task_source().queue(
358 task!(resolve_encapsulated_bits: move |cx| {
359 let promise = trusted_promise.root();
360 promise.resolve_native(cx, &encapsulated_bits);
361 }),
362 );
363 }
364}
365
366impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
367 fn Encrypt(
369 &self,
370 cx: &mut CurrentRealm,
371 algorithm: AlgorithmIdentifier,
372 key: &CryptoKey,
373 data: ArrayBufferViewOrArrayBuffer,
374 ) -> Rc<Promise> {
375 let normalized_algorithm = match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
383 Ok(normalized_algorithm) => normalized_algorithm,
384 Err(error) => {
385 let promise = Promise::new_in_realm(cx);
386 promise.reject_error(cx, error);
387 return promise;
388 },
389 };
390
391 let data = match data {
394 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => Zeroizing::new(view.to_vec()),
395 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => Zeroizing::new(buffer.to_vec()),
396 };
397
398 let promise = Promise::new_in_realm(cx);
401
402 let this = Trusted::new(self);
404 let trusted_promise = TrustedPromise::new(promise.clone());
405 let trusted_key = Trusted::new(key);
406 self.global()
407 .task_manager()
408 .dom_manipulation_task_source()
409 .queue(task!(encrypt: move || {
410 let subtle = this.root();
411 let promise = trusted_promise.root();
412 let key = trusted_key.root();
413
414 if normalized_algorithm.name() != key.algorithm().name() {
422 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
423 return;
424 }
425
426 if !key.usages().contains(&KeyUsage::Encrypt) {
429 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
430 return;
431 }
432
433 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
437 Ok(ciphertext) => ciphertext,
438 Err(error) => {
439 subtle.reject_promise_with_error(promise, error);
440 return;
441 },
442 };
443
444 subtle.resolve_promise_with_data(promise, ciphertext.into());
450 }));
451 promise
452 }
453
454 fn Decrypt(
456 &self,
457 cx: &mut CurrentRealm,
458 algorithm: AlgorithmIdentifier,
459 key: &CryptoKey,
460 data: ArrayBufferViewOrArrayBuffer,
461 ) -> Rc<Promise> {
462 let normalized_algorithm = match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
470 Ok(normalized_algorithm) => normalized_algorithm,
471 Err(error) => {
472 let promise = Promise::new_in_realm(cx);
473 promise.reject_error(cx, error);
474 return promise;
475 },
476 };
477
478 let data = match data {
481 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
482 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
483 };
484
485 let promise = Promise::new_in_realm(cx);
488
489 let this = Trusted::new(self);
491 let trusted_promise = TrustedPromise::new(promise.clone());
492 let trusted_key = Trusted::new(key);
493 self.global()
494 .task_manager()
495 .dom_manipulation_task_source()
496 .queue(task!(decrypt: move || {
497 let subtle = this.root();
498 let promise = trusted_promise.root();
499 let key = trusted_key.root();
500
501 if normalized_algorithm.name() != key.algorithm().name() {
509 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
510 return;
511 }
512
513 if !key.usages().contains(&KeyUsage::Decrypt) {
516 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
517 return;
518 }
519
520 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
524 Ok(plaintext) => Zeroizing::new(plaintext),
525 Err(error) => {
526 subtle.reject_promise_with_error(promise, error);
527 return;
528 },
529 };
530
531 subtle.resolve_promise_with_data(promise, plaintext);
537 }));
538 promise
539 }
540
541 fn Sign(
543 &self,
544 cx: &mut CurrentRealm,
545 algorithm: AlgorithmIdentifier,
546 key: &CryptoKey,
547 data: ArrayBufferViewOrArrayBuffer,
548 ) -> Rc<Promise> {
549 let normalized_algorithm = match normalize_algorithm::<SignOperation>(cx, &algorithm) {
557 Ok(normalized_algorithm) => normalized_algorithm,
558 Err(error) => {
559 let promise = Promise::new_in_realm(cx);
560 promise.reject_error(cx, error);
561 return promise;
562 },
563 };
564
565 let data = match &data {
568 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
569 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
570 };
571
572 let promise = Promise::new_in_realm(cx);
575
576 let this = Trusted::new(self);
578 let trusted_promise = TrustedPromise::new(promise.clone());
579 let trusted_key = Trusted::new(key);
580 self.global()
581 .task_manager()
582 .dom_manipulation_task_source()
583 .queue(task!(sign: move || {
584 let subtle = this.root();
585 let promise = trusted_promise.root();
586 let key = trusted_key.root();
587
588 if normalized_algorithm.name() != key.algorithm().name() {
596 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
597 return;
598 }
599
600 if !key.usages().contains(&KeyUsage::Sign) {
603 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
604 return;
605 }
606
607 let signature = match normalized_algorithm.sign(&key, &data) {
610 Ok(signature) => signature,
611 Err(error) => {
612 subtle.reject_promise_with_error(promise, error);
613 return;
614 },
615 };
616
617 subtle.resolve_promise_with_data(promise, signature.into());
623 }));
624 promise
625 }
626
627 fn Verify(
629 &self,
630 cx: &mut CurrentRealm,
631 algorithm: AlgorithmIdentifier,
632 key: &CryptoKey,
633 signature: ArrayBufferViewOrArrayBuffer,
634 data: ArrayBufferViewOrArrayBuffer,
635 ) -> Rc<Promise> {
636 let normalized_algorithm = match normalize_algorithm::<VerifyOperation>(cx, &algorithm) {
644 Ok(algorithm) => algorithm,
645 Err(error) => {
646 let promise = Promise::new_in_realm(cx);
647 promise.reject_error(cx, error);
648 return promise;
649 },
650 };
651
652 let signature = match &signature {
655 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
656 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
657 };
658
659 let data = match &data {
662 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
663 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
664 };
665
666 let promise = Promise::new_in_realm(cx);
669
670 let this = Trusted::new(self);
672 let trusted_promise = TrustedPromise::new(promise.clone());
673 let trusted_key = Trusted::new(key);
674 self.global()
675 .task_manager()
676 .dom_manipulation_task_source()
677 .queue(task!(sign: move || {
678 let subtle = this.root();
679 let promise = trusted_promise.root();
680 let key = trusted_key.root();
681
682 if normalized_algorithm.name() != key.algorithm().name() {
690 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
691 return;
692 }
693
694 if !key.usages().contains(&KeyUsage::Verify) {
697 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
698 return;
699 }
700
701 let result = match normalized_algorithm.verify(&key, &data, &signature) {
705 Ok(result) => result,
706 Err(error) => {
707 subtle.reject_promise_with_error(promise, error);
708 return;
709 },
710 };
711
712 subtle.resolve_promise_with_bool(promise, result);
716 }));
717 promise
718 }
719
720 fn Digest(
722 &self,
723 cx: &mut CurrentRealm,
724 algorithm: AlgorithmIdentifier,
725 data: ArrayBufferViewOrArrayBuffer,
726 ) -> Rc<Promise> {
727 let normalized_algorithm = match normalize_algorithm::<DigestOperation>(cx, &algorithm) {
734 Ok(normalized_algorithm) => normalized_algorithm,
735 Err(error) => {
736 let promise = Promise::new_in_realm(cx);
737 promise.reject_error(cx, error);
738 return promise;
739 },
740 };
741
742 let data = match data {
745 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
746 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
747 };
748
749 let promise = Promise::new_in_realm(cx);
752
753 let this = Trusted::new(self);
755 let trusted_promise = TrustedPromise::new(promise.clone());
756 self.global()
757 .task_manager()
758 .dom_manipulation_task_source()
759 .queue(task!(digest_: move || {
760 let subtle = this.root();
761 let promise = trusted_promise.root();
762
763 let digest = match normalized_algorithm.digest(&data) {
770 Ok(digest) => digest,
771 Err(error) => {
772 subtle.reject_promise_with_error(promise, error);
773 return;
774 }
775 };
776
777 subtle.resolve_promise_with_data(promise, digest.into());
783 }));
784 promise
785 }
786
787 fn GenerateKey(
789 &self,
790 cx: &mut CurrentRealm,
791 algorithm: AlgorithmIdentifier,
792 extractable: bool,
793 key_usages: Vec<KeyUsage>,
794 ) -> Rc<Promise> {
795 let promise = Promise::new_in_realm(cx);
802 let normalized_algorithm = match normalize_algorithm::<GenerateKeyOperation>(cx, &algorithm)
803 {
804 Ok(normalized_algorithm) => normalized_algorithm,
805 Err(error) => {
806 promise.reject_error(cx, error);
807 return promise;
808 },
809 };
810
811 let trusted_subtle = Trusted::new(self);
817 let trusted_promise = TrustedPromise::new(promise.clone());
818 self.global()
819 .task_manager()
820 .dom_manipulation_task_source()
821 .queue(task!(generate_key: move |cx| {
822 let subtle = trusted_subtle.root();
823 let promise = trusted_promise.root();
824
825 let result = match normalized_algorithm.generate_key(
832 cx,
833 &subtle.global(),
834 extractable,
835 key_usages,
836 ) {
837 Ok(result) => result,
838 Err(error) => {
839 subtle.reject_promise_with_error(promise, error);
840 return;
841 }
842 };
843
844 match &result {
852 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
853 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
854 && crpyto_key.usages().is_empty()
855 {
856 subtle.reject_promise_with_error(promise, Error::Syntax(None));
857 return;
858 }
859 },
860 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(crypto_key_pair) => {
861 if crypto_key_pair
862 .privateKey
863 .as_ref()
864 .is_none_or(|private_key| private_key.usages().is_empty())
865 {
866 subtle.reject_promise_with_error(promise, Error::Syntax(None));
867 return;
868 }
869 }
870 };
871
872 match result {
878 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
879 subtle.resolve_promise_with_key(promise, key);
880 },
881 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(key_pair) => {
882 subtle.resolve_promise_with_key_pair(promise, key_pair);
883 },
884 }
885 }));
886
887 promise
888 }
889
890 fn DeriveKey(
892 &self,
893 cx: &mut CurrentRealm,
894 algorithm: AlgorithmIdentifier,
895 base_key: &CryptoKey,
896 derived_key_type: AlgorithmIdentifier,
897 extractable: bool,
898 usages: Vec<KeyUsage>,
899 ) -> Rc<Promise> {
900 let promise = Promise::new_in_realm(cx);
909 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
910 {
911 Ok(normalized_algorithm) => normalized_algorithm,
912 Err(error) => {
913 promise.reject_error(cx, error);
914 return promise;
915 },
916 };
917
918 let normalized_derived_key_algorithm_import =
923 match normalize_algorithm::<ImportKeyOperation>(cx, &derived_key_type) {
924 Ok(normalized_algorithm) => normalized_algorithm,
925 Err(error) => {
926 promise.reject_error(cx, error);
927 return promise;
928 },
929 };
930
931 let normalized_derived_key_algorithm_length =
936 match normalize_algorithm::<GetKeyLengthOperation>(cx, &derived_key_type) {
937 Ok(normalized_algorithm) => normalized_algorithm,
938 Err(error) => {
939 promise.reject_error(cx, error);
940 return promise;
941 },
942 };
943
944 let trusted_subtle = Trusted::new(self);
950 let trusted_base_key = Trusted::new(base_key);
951 let trusted_promise = TrustedPromise::new(promise.clone());
952 self.global().task_manager().dom_manipulation_task_source().queue(
953 task!(derive_key: move |cx| {
954 let subtle = trusted_subtle.root();
955 let base_key = trusted_base_key.root();
956 let promise = trusted_promise.root();
957
958 if normalized_algorithm.name() != base_key.algorithm().name() {
966 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
967 return;
968 }
969
970 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
973 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
974 return;
975 }
976
977 let length = match normalized_derived_key_algorithm_length.get_key_length() {
980 Ok(length) => length,
981 Err(error) => {
982 subtle.reject_promise_with_error(promise, error);
983 return;
984 }
985 };
986
987 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
990 Ok(secret) => Zeroizing::new(secret),
991 Err(error) => {
992 subtle.reject_promise_with_error(promise, error);
993 return;
994 }
995 };
996
997 let result = match normalized_derived_key_algorithm_import.import_key(
1003 cx,
1004 &subtle.global(),
1005 KeyFormat::Raw_secret,
1006 &secret,
1007 extractable,
1008 usages.clone(),
1009 ) {
1010 Ok(algorithm) => algorithm,
1011 Err(error) => {
1012 subtle.reject_promise_with_error(promise, error);
1013 return;
1014 },
1015 };
1016
1017 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1020 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1021 return;
1022 }
1023
1024 subtle.resolve_promise_with_key(promise, result);
1035 }),
1036 );
1037 promise
1038 }
1039
1040 fn DeriveBits(
1042 &self,
1043 cx: &mut CurrentRealm,
1044 algorithm: AlgorithmIdentifier,
1045 base_key: &CryptoKey,
1046 length: Option<u32>,
1047 ) -> Rc<Promise> {
1048 let promise = Promise::new_in_realm(cx);
1056 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
1057 {
1058 Ok(normalized_algorithm) => normalized_algorithm,
1059 Err(error) => {
1060 promise.reject_error(cx, error);
1061 return promise;
1062 },
1063 };
1064
1065 let trsuted_subtle = Trusted::new(self);
1071 let trusted_base_key = Trusted::new(base_key);
1072 let trusted_promise = TrustedPromise::new(promise.clone());
1073 self.global()
1074 .task_manager()
1075 .dom_manipulation_task_source()
1076 .queue(task!(import_key: move || {
1077 let subtle = trsuted_subtle.root();
1078 let base_key = trusted_base_key.root();
1079 let promise = trusted_promise.root();
1080
1081 if normalized_algorithm.name() != base_key.algorithm().name() {
1089 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1090 return;
1091 }
1092
1093 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
1096 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1097 return;
1098 }
1099
1100 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
1103 Ok(bits) => Zeroizing::new(bits),
1104 Err(error) => {
1105 subtle.reject_promise_with_error(promise, error);
1106 return;
1107 }
1108 };
1109
1110 subtle.resolve_promise_with_data(promise, bits);
1116 }));
1117 promise
1118 }
1119
1120 fn ImportKey(
1122 &self,
1123 cx: &mut CurrentRealm,
1124 format: KeyFormat,
1125 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
1126 algorithm: AlgorithmIdentifier,
1127 extractable: bool,
1128 key_usages: Vec<KeyUsage>,
1129 ) -> Rc<Promise> {
1130 let normalized_algorithm = match normalize_algorithm::<ImportKeyOperation>(cx, &algorithm) {
1137 Ok(algorithm) => algorithm,
1138 Err(error) => {
1139 let promise = Promise::new_in_realm(cx);
1140 promise.reject_error(cx, error);
1141 return promise;
1142 },
1143 };
1144
1145 let key_data = match format {
1147 KeyFormat::Jwk => {
1149 match key_data {
1150 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1151 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1152 let promise = Promise::new_in_realm(cx);
1155 promise.reject_error(
1156 cx,
1157 Error::Type(c"The keyData type does not match the format".to_owned()),
1158 );
1159 return promise;
1160 },
1161
1162 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1163 match jwk.stringify(cx) {
1171 Ok(stringified) => Zeroizing::new(stringified.as_bytes().to_vec()),
1172 Err(error) => {
1173 let promise = Promise::new_in_realm(cx);
1174 promise.reject_error(cx, error);
1175 return promise;
1176 },
1177 }
1178 },
1179 }
1180 },
1181 _ => {
1183 match key_data {
1184 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1187 let promise = Promise::new_in_realm(cx);
1188 promise.reject_error(
1189 cx,
1190 Error::Type(c"The keyData type does not match the format".to_owned()),
1191 );
1192 return promise;
1193 },
1194
1195 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1198 Zeroizing::new(view.to_vec())
1199 },
1200 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1201 Zeroizing::new(buffer.to_vec())
1202 },
1203 }
1204 },
1205 };
1206
1207 let promise = Promise::new_in_realm(cx);
1210
1211 let this = Trusted::new(self);
1213 let trusted_promise = TrustedPromise::new(promise.clone());
1214 self.global()
1215 .task_manager()
1216 .dom_manipulation_task_source()
1217 .queue(task!(import_key: move |cx| {
1218 let subtle = this.root();
1219 let promise = trusted_promise.root();
1220
1221 let result = match normalized_algorithm.import_key(
1229 cx,
1230 &subtle.global(),
1231 format,
1232 &key_data,
1233 extractable,
1234 key_usages.clone(),
1235 ) {
1236 Ok(key) => key,
1237 Err(error) => {
1238 subtle.reject_promise_with_error(promise, error);
1239 return;
1240 },
1241 };
1242
1243 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && key_usages.is_empty() {
1246 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1247 return;
1248 }
1249
1250 result.set_extractable(extractable);
1252
1253 result.set_usages(cx, &key_usages);
1255
1256 subtle.resolve_promise_with_key(promise, result);
1262 }));
1263
1264 promise
1265 }
1266
1267 fn ExportKey(&self, cx: &mut CurrentRealm, format: KeyFormat, key: &CryptoKey) -> Rc<Promise> {
1269 let promise = Promise::new_in_realm(cx);
1276
1277 let trusted_subtle = Trusted::new(self);
1279 let trusted_promise = TrustedPromise::new(promise.clone());
1280 let trusted_key = Trusted::new(key);
1281 self.global()
1282 .task_manager()
1283 .dom_manipulation_task_source()
1284 .queue(task!(export_key: move |cx| {
1285 let subtle = trusted_subtle.root();
1286 let promise = trusted_promise.root();
1287 let key = trusted_key.root();
1288
1289 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1300 cx,
1301 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1302 ) {
1303 Ok(normalized_algorithm) => normalized_algorithm,
1304 Err(error) => {
1305 subtle.reject_promise_with_error(promise, error);
1306 return;
1307 },
1308 };
1309
1310 if !key.Extractable() {
1313 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1314 return;
1315 }
1316
1317 let result = match export_key_algorithm.export_key(format, &key) {
1320 Ok(exported_key) => exported_key,
1321 Err(error) => {
1322 subtle.reject_promise_with_error(promise, error);
1323 return;
1324 },
1325 };
1326
1327 match result {
1340 ExportedKey::Bytes(bytes) => {
1341 subtle.resolve_promise_with_data(promise, bytes);
1342 },
1343 ExportedKey::Jwk(jwk) => {
1344 subtle.resolve_promise_with_jwk(cx, promise, jwk);
1345 },
1346 }
1347 }));
1348 promise
1349 }
1350
1351 fn WrapKey(
1353 &self,
1354 cx: &mut CurrentRealm,
1355 format: KeyFormat,
1356 key: &CryptoKey,
1357 wrapping_key: &CryptoKey,
1358 algorithm: AlgorithmIdentifier,
1359 ) -> Rc<Promise> {
1360 enum WrapKeyAlgorithmOrEncryptAlgorithm {
1370 WrapKeyAlgorithm(WrapKeyAlgorithm),
1371 EncryptAlgorithm(EncryptAlgorithm),
1372 }
1373 let normalized_algorithm = if let Ok(algorithm) =
1374 normalize_algorithm::<WrapKeyOperation>(cx, &algorithm)
1375 {
1376 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm)
1377 } else {
1378 match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
1379 Ok(algorithm) => WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm),
1380 Err(error) => {
1381 let promise = Promise::new_in_realm(cx);
1382 promise.reject_error(cx, error);
1383 return promise;
1384 },
1385 }
1386 };
1387
1388 let promise = Promise::new_in_realm(cx);
1391
1392 let trusted_subtle = Trusted::new(self);
1394 let trusted_key = Trusted::new(key);
1395 let trusted_wrapping_key = Trusted::new(wrapping_key);
1396 let trusted_promise = TrustedPromise::new(promise.clone());
1397 self.global()
1398 .task_manager()
1399 .dom_manipulation_task_source()
1400 .queue(task!(wrap_key: move |cx| {
1401 let subtle = trusted_subtle.root();
1402 let key = trusted_key.root();
1403 let wrapping_key = trusted_wrapping_key.root();
1404 let promise = trusted_promise.root();
1405
1406 let normalized_algorithm_name = match &normalized_algorithm {
1414 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1415 algorithm.name()
1416 },
1417 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1418 algorithm.name()
1419 },
1420 };
1421 if normalized_algorithm_name != wrapping_key.algorithm().name() {
1422 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1423 return;
1424 }
1425
1426 if !wrapping_key.usages().contains(&KeyUsage::WrapKey) {
1429 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1430 return;
1431 }
1432
1433 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1439 cx,
1440 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1441 ) {
1442 Ok(normalized_algorithm) => normalized_algorithm,
1443 Err(error) => {
1444 subtle.reject_promise_with_error(promise, error);
1445 return;
1446 },
1447 };
1448
1449 if !key.Extractable() {
1452 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1453 return;
1454 }
1455
1456 let exported_key = match export_key_algorithm.export_key(format, &key) {
1459 Ok(exported_key) => exported_key,
1460 Err(error) => {
1461 subtle.reject_promise_with_error(promise, error);
1462 return;
1463 },
1464 };
1465
1466 let bytes = match exported_key {
1478 ExportedKey::Bytes(bytes) => bytes,
1479 ExportedKey::Jwk(jwk) => match jwk.stringify(cx) {
1480 Ok(stringified_jwk) => Zeroizing::new(stringified_jwk.as_bytes().to_vec()),
1481 Err(error) => {
1482 subtle.reject_promise_with_error(promise, error);
1483 return;
1484 },
1485 },
1486 };
1487
1488 let result = match normalized_algorithm {
1500 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1501 algorithm.wrap_key(&wrapping_key, &bytes)
1502 },
1503 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1504 algorithm.encrypt(&wrapping_key, &bytes)
1505 },
1506 };
1507 let result = match result {
1508 Ok(result) => result,
1509 Err(error) => {
1510 subtle.reject_promise_with_error(promise, error);
1511 return;
1512 },
1513 };
1514
1515 subtle.resolve_promise_with_data(promise, result.into());
1521 }));
1522 promise
1523 }
1524
1525 fn UnwrapKey(
1527 &self,
1528 cx: &mut CurrentRealm,
1529 format: KeyFormat,
1530 wrapped_key: ArrayBufferViewOrArrayBuffer,
1531 unwrapping_key: &CryptoKey,
1532 algorithm: AlgorithmIdentifier,
1533 unwrapped_key_algorithm: AlgorithmIdentifier,
1534 extractable: bool,
1535 usages: Vec<KeyUsage>,
1536 ) -> Rc<Promise> {
1537 enum UnwrapKeyAlgorithmOrDecryptAlgorithm {
1548 UnwrapKeyAlgorithm(UnwrapKeyAlgorithm),
1549 DecryptAlgorithm(DecryptAlgorithm),
1550 }
1551 let normalized_algorithm = if let Ok(algorithm) =
1552 normalize_algorithm::<UnwrapKeyOperation>(cx, &algorithm)
1553 {
1554 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm)
1555 } else {
1556 match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
1557 Ok(algorithm) => UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm),
1558 Err(error) => {
1559 let promise = Promise::new_in_realm(cx);
1560 promise.reject_error(cx, error);
1561 return promise;
1562 },
1563 }
1564 };
1565
1566 let normalized_key_algorithm =
1570 match normalize_algorithm::<ImportKeyOperation>(cx, &unwrapped_key_algorithm) {
1571 Ok(algorithm) => algorithm,
1572 Err(error) => {
1573 let promise = Promise::new_in_realm(cx);
1574 promise.reject_error(cx, error);
1575 return promise;
1576 },
1577 };
1578
1579 let wrapped_key = match wrapped_key {
1582 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1583 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1584 };
1585
1586 let promise = Promise::new_in_realm(cx);
1589
1590 let trusted_subtle = Trusted::new(self);
1592 let trusted_unwrapping_key = Trusted::new(unwrapping_key);
1593 let trusted_promise = TrustedPromise::new(promise.clone());
1594 self.global().task_manager().dom_manipulation_task_source().queue(
1595 task!(unwrap_key: move |cx| {
1596 let subtle = trusted_subtle.root();
1597 let unwrapping_key = trusted_unwrapping_key.root();
1598 let promise = trusted_promise.root();
1599
1600 let normalized_algorithm_name = match &normalized_algorithm {
1608 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm) => {
1609 algorithm.name()
1610 },
1611 UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm) => {
1612 algorithm.name()
1613 },
1614 };
1615 if normalized_algorithm_name != unwrapping_key.algorithm().name() {
1616 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1617 return;
1618 }
1619
1620 if !unwrapping_key.usages().contains(&KeyUsage::UnwrapKey) {
1623 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1624 return;
1625 }
1626
1627 let bytes = match normalized_algorithm {
1639 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm) => {
1640 algorithm.unwrap_key(&unwrapping_key, &wrapped_key)
1641 },
1642 UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm) => {
1643 algorithm.decrypt(&unwrapping_key, &wrapped_key)
1644 },
1645 };
1646 let bytes = match bytes {
1647 Ok(bytes) => Zeroizing::new(bytes),
1648 Err(error) => {
1649 subtle.reject_promise_with_error(promise, error);
1650 return;
1651 },
1652 };
1653
1654 if format == KeyFormat::Jwk
1665 && let Err(error) = JsonWebKey::parse(cx, &bytes) {
1666 subtle.reject_promise_with_error(promise, error);
1667 return;
1668 }
1669 let key = bytes;
1670
1671 let result = match normalized_key_algorithm.import_key(
1675 cx,
1676 &subtle.global(),
1677 format,
1678 &key,
1679 extractable,
1680 usages.clone(),
1681 ) {
1682 Ok(result) => result,
1683 Err(error) => {
1684 subtle.reject_promise_with_error(promise, error);
1685 return;
1686 },
1687 };
1688
1689 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1692 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1693 return;
1694 }
1695
1696 subtle.resolve_promise_with_key(promise, result);
1707 }),
1708 );
1709 promise
1710 }
1711
1712 fn EncapsulateKey(
1714 &self,
1715 cx: &mut CurrentRealm,
1716 encapsulation_algorithm: AlgorithmIdentifier,
1717 encapsulation_key: &CryptoKey,
1718 shared_key_algorithm: AlgorithmIdentifier,
1719 extractable: bool,
1720 usages: Vec<KeyUsage>,
1721 ) -> Rc<Promise> {
1722 let promise = Promise::new_in_realm(cx);
1732 let normalized_encapsulation_algorithm =
1733 match normalize_algorithm::<EncapsulateOperation>(cx, &encapsulation_algorithm) {
1734 Ok(algorithm) => algorithm,
1735 Err(error) => {
1736 promise.reject_error(cx, error);
1737 return promise;
1738 },
1739 };
1740
1741 let normalized_shared_key_algorithm =
1746 match normalize_algorithm::<ImportKeyOperation>(cx, &shared_key_algorithm) {
1747 Ok(algorithm) => algorithm,
1748 Err(error) => {
1749 promise.reject_error(cx, error);
1750 return promise;
1751 },
1752 };
1753
1754 let trusted_subtle = Trusted::new(self);
1760 let trusted_encapsulated_key = Trusted::new(encapsulation_key);
1761 let trusted_promise = TrustedPromise::new(promise.clone());
1762 self.global().task_manager().dom_manipulation_task_source().queue(
1763 task!(encapsulate_keys: move |cx| {
1764 let subtle = trusted_subtle.root();
1765 let encapsulation_key = trusted_encapsulated_key.root();
1766 let promise = trusted_promise.root();
1767
1768 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1776 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1777 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1778 normalizedEncapsulationAlgorithm".to_string(),
1779 )));
1780 return;
1781 }
1782
1783 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateKey) {
1786 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1787 "[[usages]] internal slot of encapsulationKey does not contain an \
1788 entry that is \"encapsulateBits\"".to_string(),
1789 )));
1790 return;
1791 }
1792
1793 let encapsulated_bits_result =
1799 normalized_encapsulation_algorithm.encapsulate(&encapsulation_key);
1800 let encapsulated_bits = match encapsulated_bits_result {
1801 Ok(encapsulated_bits) => encapsulated_bits,
1802 Err(error) => {
1803 subtle.reject_promise_with_error(promise, error);
1804 return;
1805 },
1806 };
1807
1808 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 = SubtleEncapsulatedKey {
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 ) -> Rc<Promise> {
1865 let promise = Promise::new_in_realm(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::new(promise.clone());
1890 self.global().task_manager().dom_manipulation_task_source().queue(
1891 task!(derive_key: move || {
1892 let subtle = trusted_subtle.root();
1893 let encapsulation_key = trusted_encapsulation_key.root();
1894 let promise = trusted_promise.root();
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 ) -> Rc<Promise> {
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(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(cx);
1985 promise.reject_error(cx, error);
1986 return promise;
1987 },
1988 };
1989
1990 let ciphertext = match ciphertext {
1993 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1994 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1995 };
1996
1997 let promise = Promise::new_in_realm(cx);
2000
2001 let trusted_subtle = Trusted::new(self);
2003 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2004 let trusted_promise = TrustedPromise::new(promise.clone());
2005 self.global()
2006 .task_manager()
2007 .dom_manipulation_task_source()
2008 .queue(task!(decapsulate_key: move |cx| {
2009 let subtle = trusted_subtle.root();
2010 let promise = trusted_promise.root();
2011 let decapsulation_key = trusted_decapsulation_key.root();
2012
2013 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2021 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2022 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2023 normalizedDecapsulationAlgorithm".to_string()
2024 )));
2025 return;
2026 }
2027
2028 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateKey) {
2031 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2032 "[[usages]] internal slot of decapsulationKey does not contain an \
2033 entry that is \"decapsulateBits\"".to_string(),
2034 )));
2035 return;
2036 }
2037
2038 let decapsulated_bits_result =
2044 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2045 let decapsulated_bits = match decapsulated_bits_result {
2046 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2047 Err(error) => {
2048 subtle.reject_promise_with_error(promise, error);
2049 return;
2050 },
2051 };
2052
2053
2054 let shared_key_result = normalized_shared_key_algorithm.import_key(
2062 cx,
2063 &subtle.global(),
2064 KeyFormat::Raw_secret,
2065 &decapsulated_bits,
2066 extractable,
2067 usages.clone(),
2068 );
2069 let shared_key = match shared_key_result {
2070 Ok(shared_key) => shared_key,
2071 Err(error) => {
2072 subtle.reject_promise_with_error(promise, error);
2073 return;
2074 },
2075 };
2076
2077
2078 subtle.resolve_promise_with_key(promise, shared_key);
2084 }));
2085 promise
2086 }
2087
2088 fn DecapsulateBits(
2090 &self,
2091 cx: &mut CurrentRealm,
2092 decapsulation_algorithm: AlgorithmIdentifier,
2093 decapsulation_key: &CryptoKey,
2094 ciphertext: ArrayBufferViewOrArrayBuffer,
2095 ) -> Rc<Promise> {
2096 let normalized_decapsulation_algorithm =
2104 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
2105 Ok(normalized_algorithm) => normalized_algorithm,
2106 Err(error) => {
2107 let promise = Promise::new_in_realm(cx);
2108 promise.reject_error(cx, error);
2109 return promise;
2110 },
2111 };
2112
2113 let ciphertext = match ciphertext {
2116 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2117 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2118 };
2119
2120 let promise = Promise::new_in_realm(cx);
2123
2124 let trusted_subtle = Trusted::new(self);
2126 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2127 let trusted_promise = TrustedPromise::new(promise.clone());
2128 self.global()
2129 .task_manager()
2130 .dom_manipulation_task_source()
2131 .queue(task!(decapsulate_bits: move || {
2132 let subtle = trusted_subtle.root();
2133 let promise = trusted_promise.root();
2134 let decapsulation_key = trusted_decapsulation_key.root();
2135
2136 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2144 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2145 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2146 normalizedDecapsulationAlgorithm".to_string()
2147 )));
2148 return;
2149 }
2150
2151 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateBits) {
2154 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2155 "[[usages]] internal slot of decapsulationKey does not contain an \
2156 entry that is \"decapsulateBits\"".to_string(),
2157 )));
2158 return;
2159 }
2160
2161 let decapsulated_bits_result =
2167 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2168 let decapsulated_bits = match decapsulated_bits_result {
2169 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2170 Err(error) => {
2171 subtle.reject_promise_with_error(promise, error);
2172 return;
2173 },
2174 };
2175
2176 subtle.resolve_promise_with_data(promise, decapsulated_bits);
2182 }));
2183 promise
2184 }
2185
2186 fn GetPublicKey(
2188 &self,
2189 cx: &mut CurrentRealm,
2190 key: &CryptoKey,
2191 usages: Vec<KeyUsage>,
2192 ) -> Rc<Promise> {
2193 let algorithm = key.algorithm();
2198
2199 let get_public_key_algorithm = match normalize_algorithm::<GetPublicKeyOperation>(
2206 cx,
2207 &AlgorithmIdentifier::String(DOMString::from(algorithm.name().as_str())),
2208 ) {
2209 Ok(normalized_algorithm) => normalized_algorithm,
2210 Err(error) => {
2211 let promise = Promise::new_in_realm(cx);
2212 promise.reject_error(cx, error);
2213 return promise;
2214 },
2215 };
2216
2217 let promise = Promise::new_in_realm(cx);
2220
2221 let trusted_subtle = Trusted::new(self);
2223 let trusted_promise = TrustedPromise::new(promise.clone());
2224 let trusted_key = Trusted::new(key);
2225 self.global()
2226 .task_manager()
2227 .dom_manipulation_task_source()
2228 .queue(task!(get_public_key: move |cx| {
2229 let subtle = trusted_subtle.root();
2230 let promise = trusted_promise.root();
2231 let key = trusted_key.root();
2232
2233 if key.Type() != KeyType::Private {
2240 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2241 "[[type]] internal slot of key is not \"private\"".to_string()
2242 )));
2243 return;
2244 }
2245
2246 let result = match get_public_key_algorithm.get_public_key(
2260 cx,
2261 &subtle.global(),
2262 &key,
2263 key.algorithm(),
2264 usages.clone(),
2265 ) {
2266 Ok(public_key) => public_key,
2267 Err(error) => {
2268 subtle.reject_promise_with_error(promise, error);
2269 return;
2270 },
2271 };
2272
2273 subtle.resolve_promise_with_key(promise, result);
2279 }));
2280 promise
2281 }
2282
2283 fn Supports(
2285 cx: &mut js::context::JSContext,
2286 _global: &GlobalScope,
2287 operation: DOMString,
2288 algorithm: AlgorithmIdentifier,
2289 length: Option<u32>,
2290 ) -> bool {
2291 let operation = &*operation.str();
2296 if !matches!(
2297 operation,
2298 "encrypt" |
2299 "decrypt" |
2300 "sign" |
2301 "verify" |
2302 "digest" |
2303 "generateKey" |
2304 "deriveKey" |
2305 "deriveBits" |
2306 "importKey" |
2307 "exportKey" |
2308 "wrapKey" |
2309 "unwrapKey" |
2310 "encapsulateKey" |
2311 "encapsulateBits" |
2312 "decapsulateKey" |
2313 "decapsulateBits" |
2314 "getPublicKey"
2315 ) {
2316 return false;
2317 }
2318
2319 check_support_for_algorithm(cx, operation, &algorithm, length)
2322 }
2323
2324 fn Supports_(
2326 cx: &mut js::context::JSContext,
2327 _global: &GlobalScope,
2328 operation: DOMString,
2329 algorithm: AlgorithmIdentifier,
2330 additional_algorithm: AlgorithmIdentifier,
2331 ) -> bool {
2332 let mut operation = &*operation.str();
2337 if !matches!(
2338 operation,
2339 "encrypt" |
2340 "decrypt" |
2341 "sign" |
2342 "verify" |
2343 "digest" |
2344 "generateKey" |
2345 "deriveKey" |
2346 "deriveBits" |
2347 "importKey" |
2348 "exportKey" |
2349 "wrapKey" |
2350 "unwrapKey" |
2351 "encapsulateKey" |
2352 "encapsulateBits" |
2353 "decapsulateKey" |
2354 "decapsulateBits" |
2355 "getPublicKey"
2356 ) {
2357 return false;
2358 }
2359
2360 if matches!(
2368 operation,
2369 "deriveKey" | "unwrapKey" | "encapsulateKey" | "decapsulateKey"
2370 ) && !check_support_for_algorithm(cx, "importKey", &additional_algorithm, None)
2371 {
2372 return false;
2373 }
2374 if operation == "wrapKey" &&
2375 !check_support_for_algorithm(cx, "exportKey", &additional_algorithm, None)
2376 {
2377 return false;
2378 }
2379
2380 let mut length = None;
2382
2383 if operation == "deriveKey" {
2385 if !check_support_for_algorithm(cx, "get key length", &additional_algorithm, None) {
2388 return false;
2389 }
2390
2391 let Ok(normalized_additional_algorithm) =
2394 normalize_algorithm::<GetKeyLengthOperation>(cx, &additional_algorithm)
2395 else {
2396 return false;
2397 };
2398
2399 match normalized_additional_algorithm.get_key_length() {
2402 Ok(key_length) => {
2403 length = key_length;
2404 },
2405 Err(_) => return false,
2406 };
2407
2408 operation = "deriveBits";
2410 }
2411
2412 check_support_for_algorithm(cx, operation, &algorithm, length)
2415 }
2416}
2417
2418pub(crate) fn check_support_for_algorithm(
2420 cx: &mut js::context::JSContext,
2421 mut operation: &str,
2422 algorithm: &AlgorithmIdentifier,
2423 length: Option<u32>,
2424) -> bool {
2425 if operation == "encapsulateKey" || operation == "encapsulateBits" {
2427 operation = "encapsulate";
2428 }
2429
2430 if operation == "decapsulateKey" || operation == "decapsulateBits" {
2432 operation = "decapsulate";
2433 }
2434
2435 if operation == "getPublicKey" {
2437 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2441 else {
2442 return false;
2443 };
2444
2445 return normalize_algorithm::<GetPublicKeyOperation>(
2452 cx,
2453 &AlgorithmIdentifier::String(DOMString::from(normalized_algorithm.name().as_str())),
2454 )
2455 .is_ok();
2456 }
2457
2458 match operation {
2497 "encrypt" => {
2498 let Ok(normalized_algorithm) = normalize_algorithm::<EncryptOperation>(cx, algorithm)
2499 else {
2500 return false;
2501 };
2502
2503 match normalized_algorithm {
2504 EncryptAlgorithm::RsaOaep(_) => true,
2505 EncryptAlgorithm::AesCtr(normalized_algorithm) => {
2506 normalized_algorithm.counter.len() == 16 &&
2507 normalized_algorithm.length != 0 &&
2508 normalized_algorithm.length <= 128
2509 },
2510 EncryptAlgorithm::AesCbc(normalized_algorithm) => {
2511 normalized_algorithm.iv.len() == 16
2512 },
2513 EncryptAlgorithm::AesGcm(normalized_algorithm) => {
2514 normalized_algorithm.iv.len() <= u32::MAX as usize &&
2515 normalized_algorithm.tag_length.is_none_or(|length| {
2516 matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)
2517 })
2518 },
2519 EncryptAlgorithm::AesOcb(normalized_algorithm) => {
2520 normalized_algorithm.iv.len() <= 15 &&
2521 normalized_algorithm
2522 .tag_length
2523 .is_none_or(|length| matches!(length, 64 | 96 | 128))
2524 },
2525 EncryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
2526 normalized_algorithm.iv.len() == 12 &&
2527 normalized_algorithm
2528 .tag_length
2529 .is_none_or(|length| length == 128)
2530 },
2531 }
2532 },
2533 "decrypt" => {
2534 let Ok(normalized_algorithm) = normalize_algorithm::<DecryptOperation>(cx, algorithm)
2535 else {
2536 return false;
2537 };
2538
2539 match normalized_algorithm {
2540 DecryptAlgorithm::RsaOaep(_) => true,
2541 DecryptAlgorithm::AesCtr(normalized_algorithm) => {
2542 normalized_algorithm.counter.len() == 16 &&
2543 normalized_algorithm.length != 0 &&
2544 normalized_algorithm.length <= 128
2545 },
2546 DecryptAlgorithm::AesCbc(normalized_algorithm) => {
2547 normalized_algorithm.iv.len() == 16
2548 },
2549 DecryptAlgorithm::AesGcm(normalized_algorithm) => {
2550 normalized_algorithm
2551 .tag_length
2552 .is_none_or(|length| matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)) &&
2553 normalized_algorithm.iv.len() <= u32::MAX as usize &&
2554 normalized_algorithm
2555 .additional_data
2556 .is_none_or(|data| data.len() <= u32::MAX as usize)
2557 },
2558 DecryptAlgorithm::AesOcb(normalized_algorithm) => {
2559 normalized_algorithm.iv.len() <= 15 &&
2560 normalized_algorithm
2561 .tag_length
2562 .is_none_or(|length| matches!(length, 64 | 96 | 128))
2563 },
2564 DecryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
2565 normalized_algorithm.iv.len() == 12 &&
2566 normalized_algorithm
2567 .tag_length
2568 .is_none_or(|length| length == 128)
2569 },
2570 }
2571 },
2572 "sign" => {
2573 let Ok(normalized_algorithm) = normalize_algorithm::<SignOperation>(cx, algorithm)
2574 else {
2575 return false;
2576 };
2577
2578 match normalized_algorithm {
2579 SignAlgorithm::RsassaPkcs1V1_5(_) |
2580 SignAlgorithm::RsaPss(_) |
2581 SignAlgorithm::Ecdsa(_) |
2582 SignAlgorithm::Ed25519(_) |
2583 SignAlgorithm::Hmac(_) |
2584 SignAlgorithm::MlDsa(_) => true,
2585 }
2586 },
2587 "verify" => {
2588 let Ok(normalized_algorithm) = normalize_algorithm::<VerifyOperation>(cx, algorithm)
2589 else {
2590 return false;
2591 };
2592
2593 match normalized_algorithm {
2594 VerifyAlgorithm::RsassaPkcs1V1_5(_) |
2595 VerifyAlgorithm::RsaPss(_) |
2596 VerifyAlgorithm::Ecdsa(_) |
2597 VerifyAlgorithm::Ed25519(_) |
2598 VerifyAlgorithm::Hmac(_) |
2599 VerifyAlgorithm::MlDsa(_) => true,
2600 }
2601 },
2602 "digest" => {
2603 let Ok(normalized_algorithm) = normalize_algorithm::<DigestOperation>(cx, algorithm)
2604 else {
2605 return false;
2606 };
2607
2608 match normalized_algorithm {
2609 DigestAlgorithm::Sha(_) |
2610 DigestAlgorithm::Sha3(_) |
2611 DigestAlgorithm::CShake(_) |
2612 DigestAlgorithm::TurboShake(_) => true,
2613 DigestAlgorithm::KangarooTwelve(normalized_algorithm) => {
2614 normalized_algorithm.output_length != 0 &&
2615 normalized_algorithm.output_length.is_multiple_of(8)
2616 },
2617 }
2618 },
2619 "deriveBits" => {
2620 let Ok(normalized_algorithm) =
2621 normalize_algorithm::<DeriveBitsOperation>(cx, algorithm)
2622 else {
2623 return false;
2624 };
2625
2626 match normalized_algorithm {
2627 DeriveBitsAlgorithm::Ecdh(normalized_algorithm) => length.is_none_or(|length| {
2628 ecdh_operation::secret_length(&normalized_algorithm)
2629 .is_ok_and(|secret_length| secret_length * 8 >= length)
2630 }),
2631 DeriveBitsAlgorithm::X25519(_) => {
2632 length.is_none_or(|length| x25519_operation::SECRET_LENGTH as u32 * 8 >= length)
2633 },
2634 DeriveBitsAlgorithm::Hkdf(_) => length.is_some_and(|length| length % 8 == 0),
2635 DeriveBitsAlgorithm::Pbkdf2(normalized_algorithm) => {
2636 length.is_some_and(|length| length % 8 == 0) &&
2637 normalized_algorithm.iterations != 0
2638 },
2639 DeriveBitsAlgorithm::Argon2(normalized_algorithm) => {
2640 length.is_some_and(|length| length >= 32 && length % 8 == 0) &&
2641 normalized_algorithm
2642 .version
2643 .is_none_or(|version| version == 19) &&
2644 normalized_algorithm.parallelism != 0 &&
2645 normalized_algorithm.parallelism <= 16777215 &&
2646 normalized_algorithm.memory >= 8 * normalized_algorithm.parallelism &&
2647 normalized_algorithm.passes != 0
2648 },
2649 }
2650 },
2651 "wrapKey" => {
2652 let Ok(normalized_algorithm) = normalize_algorithm::<WrapKeyOperation>(cx, algorithm)
2653 else {
2654 return check_support_for_algorithm(cx, "encrypt", algorithm, length);
2655 };
2656
2657 match normalized_algorithm {
2658 WrapKeyAlgorithm::AesKw(_) => true,
2659 }
2660 },
2661 "unwrapKey" => {
2662 let Ok(normalized_algorithm) = normalize_algorithm::<UnwrapKeyOperation>(cx, algorithm)
2663 else {
2664 return check_support_for_algorithm(cx, "decrypt", algorithm, length);
2665 };
2666
2667 match normalized_algorithm {
2668 UnwrapKeyAlgorithm::AesKw(_) => true,
2669 }
2670 },
2671 "generateKey" => {
2672 let Ok(normalized_algorithm) =
2673 normalize_algorithm::<GenerateKeyOperation>(cx, algorithm)
2674 else {
2675 return false;
2676 };
2677
2678 match normalized_algorithm {
2679 GenerateKeyAlgorithm::RsassaPkcs1V1_5(_) |
2680 GenerateKeyAlgorithm::RsaPss(_) |
2681 GenerateKeyAlgorithm::RsaOaep(_) => true,
2682 GenerateKeyAlgorithm::Ecdsa(normalized_algorithm) |
2683 GenerateKeyAlgorithm::Ecdh(normalized_algorithm) => {
2684 SUPPORTED_CURVES.contains(&normalized_algorithm.named_curve.as_str())
2685 },
2686 GenerateKeyAlgorithm::Ed25519(_) | GenerateKeyAlgorithm::X25519(_) => true,
2687 GenerateKeyAlgorithm::AesCtr(normalized_algorithm) |
2688 GenerateKeyAlgorithm::AesCbc(normalized_algorithm) |
2689 GenerateKeyAlgorithm::AesGcm(normalized_algorithm) |
2690 GenerateKeyAlgorithm::AesKw(normalized_algorithm) => {
2691 matches!(normalized_algorithm.length, 128 | 192 | 256)
2692 },
2693 GenerateKeyAlgorithm::Hmac(normalized_algorithm) => {
2694 normalized_algorithm.length.is_none_or(|length| length != 0)
2695 },
2696 GenerateKeyAlgorithm::MlKem(_) | GenerateKeyAlgorithm::MlDsa(_) => true,
2697 GenerateKeyAlgorithm::AesOcb(normalized_algorithm) => {
2698 matches!(normalized_algorithm.length, 128 | 192 | 256)
2699 },
2700 GenerateKeyAlgorithm::ChaCha20Poly1305(_) => true,
2701 }
2702 },
2703 "importKey" => {
2704 let Ok(normalized_algorithm) = normalize_algorithm::<ImportKeyOperation>(cx, algorithm)
2705 else {
2706 return false;
2707 };
2708
2709 match normalized_algorithm {
2710 ImportKeyAlgorithm::RsassaPkcs1V1_5(_) |
2711 ImportKeyAlgorithm::RsaPss(_) |
2712 ImportKeyAlgorithm::RsaOaep(_) |
2713 ImportKeyAlgorithm::Ecdsa(_) |
2714 ImportKeyAlgorithm::Ecdh(_) |
2715 ImportKeyAlgorithm::Ed25519(_) |
2716 ImportKeyAlgorithm::X25519(_) |
2717 ImportKeyAlgorithm::AesCtr(_) |
2718 ImportKeyAlgorithm::AesCbc(_) |
2719 ImportKeyAlgorithm::AesGcm(_) |
2720 ImportKeyAlgorithm::AesKw(_) |
2721 ImportKeyAlgorithm::Hmac(_) |
2722 ImportKeyAlgorithm::Hkdf(_) |
2723 ImportKeyAlgorithm::Pbkdf2(_) |
2724 ImportKeyAlgorithm::MlKem(_) |
2725 ImportKeyAlgorithm::MlDsa(_) |
2726 ImportKeyAlgorithm::AesOcb(_) |
2727 ImportKeyAlgorithm::ChaCha20Poly1305(_) |
2728 ImportKeyAlgorithm::Argon2(_) => true,
2729 }
2730 },
2731 "exportKey" => {
2732 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2733 else {
2734 return false;
2735 };
2736
2737 match normalized_algorithm {
2738 ExportKeyAlgorithm::RsassaPkcs1V1_5(_) |
2739 ExportKeyAlgorithm::RsaPss(_) |
2740 ExportKeyAlgorithm::RsaOaep(_) |
2741 ExportKeyAlgorithm::Ecdsa(_) |
2742 ExportKeyAlgorithm::Ecdh(_) |
2743 ExportKeyAlgorithm::Ed25519(_) |
2744 ExportKeyAlgorithm::X25519(_) |
2745 ExportKeyAlgorithm::AesCtr(_) |
2746 ExportKeyAlgorithm::AesCbc(_) |
2747 ExportKeyAlgorithm::AesGcm(_) |
2748 ExportKeyAlgorithm::AesKw(_) |
2749 ExportKeyAlgorithm::Hmac(_) |
2750 ExportKeyAlgorithm::MlKem(_) |
2751 ExportKeyAlgorithm::MlDsa(_) |
2752 ExportKeyAlgorithm::AesOcb(_) |
2753 ExportKeyAlgorithm::ChaCha20Poly1305(_) => true,
2754 }
2755 },
2756 "get key length" => {
2757 let Ok(normalized_algorithm) =
2758 normalize_algorithm::<GetKeyLengthOperation>(cx, algorithm)
2759 else {
2760 return false;
2761 };
2762
2763 match normalized_algorithm {
2764 GetKeyLengthAlgorithm::AesCtr(normalized_derived_key_algorithm) |
2765 GetKeyLengthAlgorithm::AesCbc(normalized_derived_key_algorithm) |
2766 GetKeyLengthAlgorithm::AesGcm(normalized_derived_key_algorithm) |
2767 GetKeyLengthAlgorithm::AesKw(normalized_derived_key_algorithm) => {
2768 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
2769 },
2770 GetKeyLengthAlgorithm::Hmac(normalized_derived_key_algorithm) => {
2771 normalized_derived_key_algorithm
2772 .length
2773 .is_none_or(|length| length != 0)
2774 },
2775 GetKeyLengthAlgorithm::Hkdf(_) | GetKeyLengthAlgorithm::Pbkdf2(_) => true,
2776 GetKeyLengthAlgorithm::AesOcb(normalized_derived_key_algorithm) => {
2777 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
2778 },
2779 GetKeyLengthAlgorithm::ChaCha20Poly1305(_) | GetKeyLengthAlgorithm::Argon2(_) => {
2780 true
2781 },
2782 }
2783 },
2784 "encapsulate" => {
2785 let Ok(normalized_algorithm) =
2786 normalize_algorithm::<EncapsulateOperation>(cx, algorithm)
2787 else {
2788 return false;
2789 };
2790
2791 match normalized_algorithm {
2792 EncapsulateAlgorithm::MlKem(_) => true,
2793 }
2794 },
2795 "decapsulate" => {
2796 let Ok(normalized_algorithm) =
2797 normalize_algorithm::<DecapsulateOperation>(cx, algorithm)
2798 else {
2799 return false;
2800 };
2801
2802 match normalized_algorithm {
2803 DecapsulateAlgorithm::MlKem(_) => true,
2804 }
2805 },
2806 _ => false,
2807 }
2808
2809 }
2813
2814trait TryFromWithCxAndName<T>: Sized {
2816 type Error;
2817
2818 fn try_from_with_cx_and_name(
2819 value: T,
2820 cx: &mut js::context::JSContext,
2821 algorithm_name: CryptoAlgorithm,
2822 ) -> Result<Self, Self::Error>;
2823}
2824
2825trait TryIntoWithCxAndName<T>: Sized {
2827 type Error;
2828
2829 fn try_into_with_cx_and_name(
2830 self,
2831 cx: &mut js::context::JSContext,
2832 algorithm_name: CryptoAlgorithm,
2833 ) -> Result<T, Self::Error>;
2834}
2835
2836impl<T, U> TryIntoWithCxAndName<U> for T
2837where
2838 U: TryFromWithCxAndName<T>,
2839{
2840 type Error = U::Error;
2841
2842 fn try_into_with_cx_and_name(
2843 self,
2844 cx: &mut js::context::JSContext,
2845 algorithm_name: CryptoAlgorithm,
2846 ) -> Result<U, Self::Error> {
2847 U::try_from_with_cx_and_name(self, cx, algorithm_name)
2848 }
2849}
2850
2851#[derive(Clone, MallocSizeOf)]
2856struct SubtleAlgorithm {
2857 name: CryptoAlgorithm,
2859}
2860
2861impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAlgorithm {
2862 type Error = Error;
2863
2864 fn try_from_with_cx_and_name(
2865 _object: HandleObject<'a>,
2866 _cx: &mut js::context::JSContext,
2867 algorithm_name: CryptoAlgorithm,
2868 ) -> Result<Self, Self::Error> {
2869 Ok(SubtleAlgorithm {
2870 name: algorithm_name,
2871 })
2872 }
2873}
2874
2875impl TryFrom<SerializableAlgorithm> for SubtleAlgorithm {
2876 type Error = ();
2877
2878 fn try_from(value: SerializableAlgorithm) -> Result<Self, Self::Error> {
2879 Ok(SubtleAlgorithm {
2880 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2881 })
2882 }
2883}
2884
2885impl From<&SubtleAlgorithm> for SerializableAlgorithm {
2886 fn from(value: &SubtleAlgorithm) -> Self {
2887 SerializableAlgorithm {
2888 name: value.name.as_str().into(),
2889 }
2890 }
2891}
2892
2893#[derive(Clone, MallocSizeOf)]
2895pub(crate) struct SubtleKeyAlgorithm {
2896 name: CryptoAlgorithm,
2898}
2899
2900impl SafeToJSValConvertible for SubtleKeyAlgorithm {
2901 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
2902 let dictionary = KeyAlgorithm {
2903 name: self.name.as_str().into(),
2904 };
2905 dictionary.safe_to_jsval(cx, rval);
2906 }
2907}
2908
2909impl TryFrom<SerializableKeyAlgorithm> for SubtleKeyAlgorithm {
2910 type Error = ();
2911
2912 fn try_from(value: SerializableKeyAlgorithm) -> Result<Self, Self::Error> {
2913 Ok(SubtleKeyAlgorithm {
2914 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2915 })
2916 }
2917}
2918
2919impl From<&SubtleKeyAlgorithm> for SerializableKeyAlgorithm {
2920 fn from(value: &SubtleKeyAlgorithm) -> Self {
2921 SerializableKeyAlgorithm {
2922 name: value.name.as_str().into(),
2923 }
2924 }
2925}
2926
2927#[derive(Clone, MallocSizeOf)]
2929pub(crate) struct SubtleRsaHashedKeyGenParams {
2930 name: CryptoAlgorithm,
2932
2933 modulus_length: u32,
2935
2936 public_exponent: Vec<u8>,
2938
2939 hash: DigestAlgorithm,
2941}
2942
2943impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaHashedKeyGenParams {
2944 type Error = Error;
2945
2946 fn try_from_with_cx_and_name(
2947 object: HandleObject,
2948 cx: &mut js::context::JSContext,
2949 algorithm_name: CryptoAlgorithm,
2950 ) -> Result<Self, Self::Error> {
2951 let hash = get_required_parameter(cx, object, c"hash", ())?;
2952
2953 Ok(SubtleRsaHashedKeyGenParams {
2954 name: algorithm_name,
2955 modulus_length: get_required_parameter(
2956 cx,
2957 object,
2958 c"modulusLength",
2959 ConversionBehavior::Default,
2960 )?,
2961 public_exponent: get_required_parameter_in_box::<HeapUint8Array>(
2962 cx,
2963 object,
2964 c"publicExponent",
2965 (),
2966 )?
2967 .to_vec(),
2968 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
2969 })
2970 }
2971}
2972
2973#[derive(Clone, MallocSizeOf)]
2975pub(crate) struct SubtleRsaHashedKeyAlgorithm {
2976 name: CryptoAlgorithm,
2978
2979 modulus_length: u32,
2981
2982 public_exponent: Vec<u8>,
2984
2985 hash: DigestAlgorithm,
2987}
2988
2989impl SafeToJSValConvertible for SubtleRsaHashedKeyAlgorithm {
2990 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
2991 rooted!(&in(cx) let mut js_object = ptr::null_mut::<JSObject>());
2992 let public_exponent =
2993 create_buffer_source(cx, &self.public_exponent, js_object.handle_mut())
2994 .expect("Fail to convert publicExponent to Uint8Array");
2995 let key_algorithm = KeyAlgorithm {
2996 name: self.name.as_str().into(),
2997 };
2998 let rsa_key_algorithm = RootedTraceableBox::new(RsaKeyAlgorithm {
2999 parent: key_algorithm,
3000 modulusLength: self.modulus_length,
3001 publicExponent: public_exponent,
3002 });
3003 let rsa_hashed_key_algorithm = RootedTraceableBox::new(RsaHashedKeyAlgorithm {
3004 parent: rsa_key_algorithm,
3005 hash: KeyAlgorithm {
3006 name: self.hash.name().as_str().into(),
3007 },
3008 });
3009 rsa_hashed_key_algorithm.safe_to_jsval(cx, rval);
3010 }
3011}
3012
3013impl TryFrom<SerializableRsaHashedKeyAlgorithm> for SubtleRsaHashedKeyAlgorithm {
3014 type Error = ();
3015
3016 fn try_from(value: SerializableRsaHashedKeyAlgorithm) -> Result<Self, Self::Error> {
3017 Ok(SubtleRsaHashedKeyAlgorithm {
3018 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3019 modulus_length: value.modulus_length,
3020 public_exponent: value.public_exponent,
3021 hash: value.hash.try_into()?,
3022 })
3023 }
3024}
3025
3026impl From<&SubtleRsaHashedKeyAlgorithm> for SerializableRsaHashedKeyAlgorithm {
3027 fn from(value: &SubtleRsaHashedKeyAlgorithm) -> Self {
3028 SerializableRsaHashedKeyAlgorithm {
3029 name: value.name.as_str().into(),
3030 modulus_length: value.modulus_length,
3031 public_exponent: value.public_exponent.clone(),
3032 hash: (&value.hash).into(),
3033 }
3034 }
3035}
3036
3037#[derive(Clone, MallocSizeOf)]
3039struct SubtleRsaHashedImportParams {
3040 name: CryptoAlgorithm,
3042
3043 hash: DigestAlgorithm,
3045}
3046
3047impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaHashedImportParams {
3048 type Error = Error;
3049
3050 fn try_from_with_cx_and_name(
3051 object: HandleObject,
3052 cx: &mut js::context::JSContext,
3053 algorithm_name: CryptoAlgorithm,
3054 ) -> Result<Self, Self::Error> {
3055 let hash = get_required_parameter(cx, object, c"hash", ())?;
3056
3057 Ok(SubtleRsaHashedImportParams {
3058 name: algorithm_name,
3059 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3060 })
3061 }
3062}
3063
3064#[derive(Clone, MallocSizeOf)]
3066struct SubtleRsaPssParams {
3067 name: CryptoAlgorithm,
3069
3070 salt_length: u32,
3072}
3073
3074impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaPssParams {
3075 type Error = Error;
3076
3077 fn try_from_with_cx_and_name(
3078 object: HandleObject,
3079 cx: &mut js::context::JSContext,
3080 algorithm_name: CryptoAlgorithm,
3081 ) -> Result<Self, Self::Error> {
3082 Ok(SubtleRsaPssParams {
3083 name: algorithm_name,
3084 salt_length: get_required_parameter(
3085 cx,
3086 object,
3087 c"saltLength",
3088 ConversionBehavior::EnforceRange,
3089 )?,
3090 })
3091 }
3092}
3093
3094#[derive(Clone, MallocSizeOf)]
3096struct SubtleRsaOaepParams {
3097 name: CryptoAlgorithm,
3099
3100 label: Option<Vec<u8>>,
3102}
3103
3104impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaOaepParams {
3105 type Error = Error;
3106
3107 fn try_from_with_cx_and_name(
3108 object: HandleObject<'a>,
3109 cx: &mut js::context::JSContext,
3110 algorithm_name: CryptoAlgorithm,
3111 ) -> Result<Self, Self::Error> {
3112 Ok(SubtleRsaOaepParams {
3113 name: algorithm_name,
3114 label: get_optional_buffer_source(cx, object, c"label")?,
3115 })
3116 }
3117}
3118
3119#[derive(Clone, MallocSizeOf)]
3121struct SubtleEcdsaParams {
3122 name: CryptoAlgorithm,
3124
3125 hash: DigestAlgorithm,
3127}
3128
3129impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcdsaParams {
3130 type Error = Error;
3131
3132 fn try_from_with_cx_and_name(
3133 object: HandleObject<'a>,
3134 cx: &mut js::context::JSContext,
3135 algorithm_name: CryptoAlgorithm,
3136 ) -> Result<Self, Self::Error> {
3137 let hash = get_required_parameter(cx, object, c"hash", ())?;
3138
3139 Ok(SubtleEcdsaParams {
3140 name: algorithm_name,
3141 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3142 })
3143 }
3144}
3145
3146#[derive(Clone, MallocSizeOf)]
3148struct SubtleEcKeyGenParams {
3149 name: CryptoAlgorithm,
3151
3152 named_curve: String,
3154}
3155
3156impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcKeyGenParams {
3157 type Error = Error;
3158
3159 fn try_from_with_cx_and_name(
3160 object: HandleObject<'a>,
3161 cx: &mut js::context::JSContext,
3162 algorithm_name: CryptoAlgorithm,
3163 ) -> Result<Self, Self::Error> {
3164 Ok(SubtleEcKeyGenParams {
3165 name: algorithm_name,
3166 named_curve: String::from(get_required_parameter::<DOMString>(
3167 cx,
3168 object,
3169 c"namedCurve",
3170 StringificationBehavior::Default,
3171 )?),
3172 })
3173 }
3174}
3175
3176#[derive(Clone, MallocSizeOf)]
3178pub(crate) struct SubtleEcKeyAlgorithm {
3179 name: CryptoAlgorithm,
3181
3182 named_curve: String,
3184}
3185
3186impl SafeToJSValConvertible for SubtleEcKeyAlgorithm {
3187 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
3188 let parent = KeyAlgorithm {
3189 name: self.name.as_str().into(),
3190 };
3191 let dictionary = EcKeyAlgorithm {
3192 parent,
3193 namedCurve: self.named_curve.clone().into(),
3194 };
3195 dictionary.safe_to_jsval(cx, rval);
3196 }
3197}
3198
3199impl TryFrom<SerializableEcKeyAlgorithm> for SubtleEcKeyAlgorithm {
3200 type Error = ();
3201
3202 fn try_from(value: SerializableEcKeyAlgorithm) -> Result<Self, Self::Error> {
3203 Ok(SubtleEcKeyAlgorithm {
3204 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3205 named_curve: value.named_curve,
3206 })
3207 }
3208}
3209
3210impl From<&SubtleEcKeyAlgorithm> for SerializableEcKeyAlgorithm {
3211 fn from(value: &SubtleEcKeyAlgorithm) -> Self {
3212 SerializableEcKeyAlgorithm {
3213 name: value.name.as_str().into(),
3214 named_curve: value.named_curve.clone(),
3215 }
3216 }
3217}
3218
3219#[derive(Clone, MallocSizeOf)]
3221struct SubtleEcKeyImportParams {
3222 name: CryptoAlgorithm,
3224
3225 named_curve: String,
3227}
3228
3229impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcKeyImportParams {
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(SubtleEcKeyImportParams {
3238 name: algorithm_name,
3239 named_curve: String::from(get_required_parameter::<DOMString>(
3240 cx,
3241 object,
3242 c"namedCurve",
3243 StringificationBehavior::Default,
3244 )?),
3245 })
3246 }
3247}
3248
3249#[derive(Clone, MallocSizeOf)]
3251struct SubtleEcdhKeyDeriveParams {
3252 name: CryptoAlgorithm,
3254
3255 public: Trusted<CryptoKey>,
3257}
3258
3259impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcdhKeyDeriveParams {
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 let public = get_required_parameter::<DomRoot<CryptoKey>>(cx, object, c"public", ())?;
3268
3269 Ok(SubtleEcdhKeyDeriveParams {
3270 name: algorithm_name,
3271 public: Trusted::new(&public),
3272 })
3273 }
3274}
3275
3276#[derive(Clone, MallocSizeOf)]
3278struct SubtleAesCtrParams {
3279 name: CryptoAlgorithm,
3281
3282 counter: Vec<u8>,
3284
3285 length: u8,
3287}
3288
3289impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesCtrParams {
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(SubtleAesCtrParams {
3298 name: algorithm_name,
3299 counter: get_required_buffer_source(cx, object, c"counter")?,
3300 length: get_required_parameter(
3301 cx,
3302 object,
3303 c"length",
3304 ConversionBehavior::EnforceRange,
3305 )?,
3306 })
3307 }
3308}
3309
3310#[derive(Clone, MallocSizeOf)]
3312pub(crate) struct SubtleAesKeyAlgorithm {
3313 name: CryptoAlgorithm,
3315
3316 length: u16,
3318}
3319
3320impl SafeToJSValConvertible for SubtleAesKeyAlgorithm {
3321 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
3322 let parent = KeyAlgorithm {
3323 name: self.name.as_str().into(),
3324 };
3325 let dictionary = AesKeyAlgorithm {
3326 parent,
3327 length: self.length,
3328 };
3329 dictionary.safe_to_jsval(cx, rval);
3330 }
3331}
3332
3333impl TryFrom<SerializableAesKeyAlgorithm> for SubtleAesKeyAlgorithm {
3334 type Error = ();
3335
3336 fn try_from(value: SerializableAesKeyAlgorithm) -> Result<Self, Self::Error> {
3337 Ok(SubtleAesKeyAlgorithm {
3338 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3339 length: value.length,
3340 })
3341 }
3342}
3343
3344impl From<&SubtleAesKeyAlgorithm> for SerializableAesKeyAlgorithm {
3345 fn from(value: &SubtleAesKeyAlgorithm) -> Self {
3346 SerializableAesKeyAlgorithm {
3347 name: value.name.as_str().into(),
3348 length: value.length,
3349 }
3350 }
3351}
3352
3353#[derive(Clone, MallocSizeOf)]
3355struct SubtleAesKeyGenParams {
3356 name: CryptoAlgorithm,
3358
3359 length: u16,
3361}
3362
3363impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesKeyGenParams {
3364 type Error = Error;
3365
3366 fn try_from_with_cx_and_name(
3367 object: HandleObject<'a>,
3368 cx: &mut js::context::JSContext,
3369 algorithm_name: CryptoAlgorithm,
3370 ) -> Result<Self, Self::Error> {
3371 Ok(SubtleAesKeyGenParams {
3372 name: algorithm_name,
3373 length: get_required_parameter(
3374 cx,
3375 object,
3376 c"length",
3377 ConversionBehavior::EnforceRange,
3378 )?,
3379 })
3380 }
3381}
3382
3383#[derive(Clone, MallocSizeOf)]
3385struct SubtleAesDerivedKeyParams {
3386 name: CryptoAlgorithm,
3388
3389 length: u16,
3391}
3392
3393impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesDerivedKeyParams {
3394 type Error = Error;
3395
3396 fn try_from_with_cx_and_name(
3397 object: HandleObject<'a>,
3398 cx: &mut js::context::JSContext,
3399 algorithm_name: CryptoAlgorithm,
3400 ) -> Result<Self, Self::Error> {
3401 Ok(SubtleAesDerivedKeyParams {
3402 name: algorithm_name,
3403 length: get_required_parameter(
3404 cx,
3405 object,
3406 c"length",
3407 ConversionBehavior::EnforceRange,
3408 )?,
3409 })
3410 }
3411}
3412
3413#[derive(Clone, MallocSizeOf)]
3415struct SubtleAesCbcParams {
3416 name: CryptoAlgorithm,
3418
3419 iv: Vec<u8>,
3421}
3422
3423impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesCbcParams {
3424 type Error = Error;
3425
3426 fn try_from_with_cx_and_name(
3427 object: HandleObject<'a>,
3428 cx: &mut js::context::JSContext,
3429 algorithm_name: CryptoAlgorithm,
3430 ) -> Result<Self, Self::Error> {
3431 Ok(SubtleAesCbcParams {
3432 name: algorithm_name,
3433 iv: get_required_buffer_source(cx, object, c"iv")?,
3434 })
3435 }
3436}
3437
3438#[derive(Clone, MallocSizeOf)]
3440struct SubtleAesGcmParams {
3441 name: CryptoAlgorithm,
3443
3444 iv: Vec<u8>,
3446
3447 additional_data: Option<Vec<u8>>,
3449
3450 tag_length: Option<u8>,
3452}
3453
3454impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesGcmParams {
3455 type Error = Error;
3456
3457 fn try_from_with_cx_and_name(
3458 object: HandleObject<'a>,
3459 cx: &mut js::context::JSContext,
3460 algorithm_name: CryptoAlgorithm,
3461 ) -> Result<Self, Self::Error> {
3462 Ok(SubtleAesGcmParams {
3463 name: algorithm_name,
3464 iv: get_required_buffer_source(cx, object, c"iv")?,
3465 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3466 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3467 })
3468 }
3469}
3470
3471#[derive(Clone, MallocSizeOf)]
3473struct SubtleHmacImportParams {
3474 name: CryptoAlgorithm,
3476
3477 hash: DigestAlgorithm,
3479
3480 length: Option<u32>,
3482}
3483
3484impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHmacImportParams {
3485 type Error = Error;
3486
3487 fn try_from_with_cx_and_name(
3488 object: HandleObject<'a>,
3489 cx: &mut js::context::JSContext,
3490 algorithm_name: CryptoAlgorithm,
3491 ) -> Result<Self, Self::Error> {
3492 let hash = get_required_parameter(cx, object, c"hash", ())?;
3493
3494 Ok(SubtleHmacImportParams {
3495 name: algorithm_name,
3496 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3497 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3498 })
3499 }
3500}
3501
3502#[derive(Clone, MallocSizeOf)]
3504pub(crate) struct SubtleHmacKeyAlgorithm {
3505 name: CryptoAlgorithm,
3507
3508 hash: DigestAlgorithm,
3510
3511 length: u32,
3513}
3514
3515impl SafeToJSValConvertible for SubtleHmacKeyAlgorithm {
3516 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
3517 let parent = KeyAlgorithm {
3518 name: self.name.as_str().into(),
3519 };
3520 let hash = KeyAlgorithm {
3521 name: self.hash.name().as_str().into(),
3522 };
3523 let dictionary = HmacKeyAlgorithm {
3524 parent,
3525 hash,
3526 length: self.length,
3527 };
3528 dictionary.safe_to_jsval(cx, rval);
3529 }
3530}
3531
3532impl TryFrom<SerializableHmacKeyAlgorithm> for SubtleHmacKeyAlgorithm {
3533 type Error = ();
3534
3535 fn try_from(value: SerializableHmacKeyAlgorithm) -> Result<Self, Self::Error> {
3536 Ok(SubtleHmacKeyAlgorithm {
3537 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3538 hash: value.hash.try_into()?,
3539 length: value.length,
3540 })
3541 }
3542}
3543
3544impl From<&SubtleHmacKeyAlgorithm> for SerializableHmacKeyAlgorithm {
3545 fn from(value: &SubtleHmacKeyAlgorithm) -> Self {
3546 SerializableHmacKeyAlgorithm {
3547 name: value.name.as_str().into(),
3548 hash: (&value.hash).into(),
3549 length: value.length,
3550 }
3551 }
3552}
3553
3554#[derive(Clone, MallocSizeOf)]
3556struct SubtleHmacKeyGenParams {
3557 name: CryptoAlgorithm,
3559
3560 hash: DigestAlgorithm,
3562
3563 length: Option<u32>,
3565}
3566
3567impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHmacKeyGenParams {
3568 type Error = Error;
3569
3570 fn try_from_with_cx_and_name(
3571 object: HandleObject<'a>,
3572 cx: &mut js::context::JSContext,
3573 algorithm_name: CryptoAlgorithm,
3574 ) -> Result<Self, Self::Error> {
3575 let hash = get_required_parameter(cx, object, c"hash", ())?;
3576
3577 Ok(SubtleHmacKeyGenParams {
3578 name: algorithm_name,
3579 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3580 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3581 })
3582 }
3583}
3584
3585#[derive(Clone, MallocSizeOf)]
3587pub(crate) struct SubtleHkdfParams {
3588 name: CryptoAlgorithm,
3590
3591 hash: DigestAlgorithm,
3593
3594 salt: Vec<u8>,
3596
3597 info: Vec<u8>,
3599}
3600
3601impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHkdfParams {
3602 type Error = Error;
3603
3604 fn try_from_with_cx_and_name(
3605 object: HandleObject<'a>,
3606 cx: &mut js::context::JSContext,
3607 algorithm_name: CryptoAlgorithm,
3608 ) -> Result<Self, Self::Error> {
3609 let hash = get_required_parameter(cx, object, c"hash", ())?;
3610
3611 Ok(SubtleHkdfParams {
3612 name: algorithm_name,
3613 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3614 salt: get_required_buffer_source(cx, object, c"salt")?,
3615 info: get_required_buffer_source(cx, object, c"info")?,
3616 })
3617 }
3618}
3619
3620#[derive(Clone, MallocSizeOf)]
3622pub(crate) struct SubtlePbkdf2Params {
3623 name: CryptoAlgorithm,
3625
3626 salt: Vec<u8>,
3628
3629 iterations: u32,
3631
3632 hash: DigestAlgorithm,
3634}
3635
3636impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtlePbkdf2Params {
3637 type Error = Error;
3638
3639 fn try_from_with_cx_and_name(
3640 object: HandleObject<'a>,
3641 cx: &mut js::context::JSContext,
3642 algorithm_name: CryptoAlgorithm,
3643 ) -> Result<Self, Self::Error> {
3644 let hash = get_required_parameter(cx, object, c"hash", ())?;
3645
3646 Ok(SubtlePbkdf2Params {
3647 name: algorithm_name,
3648 salt: get_required_buffer_source(cx, object, c"salt")?,
3649 iterations: get_required_parameter(
3650 cx,
3651 object,
3652 c"iterations",
3653 ConversionBehavior::EnforceRange,
3654 )?,
3655 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3656 })
3657 }
3658}
3659
3660#[derive(Clone, MallocSizeOf)]
3662struct SubtleContextParams {
3663 name: CryptoAlgorithm,
3665
3666 context: Option<Vec<u8>>,
3668}
3669
3670impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleContextParams {
3671 type Error = Error;
3672
3673 fn try_from_with_cx_and_name(
3674 object: HandleObject<'a>,
3675 cx: &mut js::context::JSContext,
3676 algorithm_name: CryptoAlgorithm,
3677 ) -> Result<Self, Self::Error> {
3678 Ok(SubtleContextParams {
3679 name: algorithm_name,
3680 context: get_optional_buffer_source(cx, object, c"context")?,
3681 })
3682 }
3683}
3684
3685#[derive(Clone, MallocSizeOf)]
3687struct SubtleAeadParams {
3688 name: CryptoAlgorithm,
3690
3691 iv: Vec<u8>,
3693
3694 additional_data: Option<Vec<u8>>,
3696
3697 tag_length: Option<u8>,
3699}
3700
3701impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAeadParams {
3702 type Error = Error;
3703
3704 fn try_from_with_cx_and_name(
3705 object: HandleObject<'a>,
3706 cx: &mut js::context::JSContext,
3707 algorithm_name: CryptoAlgorithm,
3708 ) -> Result<Self, Self::Error> {
3709 Ok(SubtleAeadParams {
3710 name: algorithm_name,
3711 iv: get_required_buffer_source(cx, object, c"iv")?,
3712 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3713 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3714 })
3715 }
3716}
3717
3718#[derive(Clone, MallocSizeOf)]
3720struct SubtleCShakeParams {
3721 name: CryptoAlgorithm,
3723
3724 output_length: u32,
3726
3727 function_name: Option<Vec<u8>>,
3729
3730 customization: Option<Vec<u8>>,
3732}
3733
3734impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleCShakeParams {
3735 type Error = Error;
3736
3737 fn try_from_with_cx_and_name(
3738 object: HandleObject<'a>,
3739 cx: &mut js::context::JSContext,
3740 algorithm_name: CryptoAlgorithm,
3741 ) -> Result<Self, Self::Error> {
3742 Ok(SubtleCShakeParams {
3743 name: algorithm_name,
3744 output_length: get_required_parameter(
3745 cx,
3746 object,
3747 c"outputLength",
3748 ConversionBehavior::EnforceRange,
3749 )?,
3750 function_name: get_optional_buffer_source(cx, object, c"functionName")?,
3751 customization: get_optional_buffer_source(cx, object, c"customization")?,
3752 })
3753 }
3754}
3755
3756impl TryFrom<SerializableCShakeParams> for SubtleCShakeParams {
3757 type Error = ();
3758
3759 fn try_from(value: SerializableCShakeParams) -> Result<Self, Self::Error> {
3760 Ok(SubtleCShakeParams {
3761 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3762 output_length: value.output_length,
3763 function_name: value.function_name,
3764 customization: value.customization,
3765 })
3766 }
3767}
3768
3769impl From<&SubtleCShakeParams> for SerializableCShakeParams {
3770 fn from(value: &SubtleCShakeParams) -> Self {
3771 SerializableCShakeParams {
3772 name: value.name.as_str().into(),
3773 output_length: value.output_length,
3774 function_name: value.function_name.clone(),
3775 customization: value.customization.clone(),
3776 }
3777 }
3778}
3779
3780#[derive(Clone, MallocSizeOf)]
3782struct SubtleTurboShakeParams {
3783 name: CryptoAlgorithm,
3785
3786 output_length: u32,
3788
3789 domain_separation: Option<u8>,
3791}
3792
3793impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleTurboShakeParams {
3794 type Error = Error;
3795
3796 fn try_from_with_cx_and_name(
3797 object: HandleObject<'a>,
3798 cx: &mut js::context::JSContext,
3799 algorithm_name: CryptoAlgorithm,
3800 ) -> Result<Self, Self::Error> {
3801 Ok(SubtleTurboShakeParams {
3802 name: algorithm_name,
3803 output_length: get_required_parameter(
3804 cx,
3805 object,
3806 c"outputLength",
3807 ConversionBehavior::EnforceRange,
3808 )?,
3809 domain_separation: get_property(
3810 cx,
3811 object,
3812 c"domainSeparation",
3813 ConversionBehavior::EnforceRange,
3814 )?,
3815 })
3816 }
3817}
3818
3819impl TryFrom<SerializableTurboShakeParams> for SubtleTurboShakeParams {
3820 type Error = ();
3821
3822 fn try_from(value: SerializableTurboShakeParams) -> Result<Self, Self::Error> {
3823 Ok(SubtleTurboShakeParams {
3824 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3825 output_length: value.output_length,
3826 domain_separation: value.domain_separation,
3827 })
3828 }
3829}
3830
3831impl From<&SubtleTurboShakeParams> for SerializableTurboShakeParams {
3832 fn from(value: &SubtleTurboShakeParams) -> Self {
3833 SerializableTurboShakeParams {
3834 name: value.name.as_str().into(),
3835 output_length: value.output_length,
3836 domain_separation: value.domain_separation,
3837 }
3838 }
3839}
3840
3841#[derive(Clone, MallocSizeOf)]
3843struct SubtleKangarooTwelveParams {
3844 name: CryptoAlgorithm,
3846
3847 output_length: u32,
3849
3850 customization: Option<Vec<u8>>,
3852}
3853
3854impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleKangarooTwelveParams {
3855 type Error = Error;
3856
3857 fn try_from_with_cx_and_name(
3858 object: HandleObject<'a>,
3859 cx: &mut js::context::JSContext,
3860 algorithm_name: CryptoAlgorithm,
3861 ) -> Result<Self, Self::Error> {
3862 Ok(SubtleKangarooTwelveParams {
3863 name: algorithm_name,
3864 output_length: get_required_parameter(
3865 cx,
3866 object,
3867 c"outputLength",
3868 ConversionBehavior::EnforceRange,
3869 )?,
3870 customization: get_optional_buffer_source(cx, object, c"customization")?,
3871 })
3872 }
3873}
3874
3875impl TryFrom<SerializableKangarooTwelveParams> for SubtleKangarooTwelveParams {
3876 type Error = ();
3877
3878 fn try_from(value: SerializableKangarooTwelveParams) -> Result<Self, Self::Error> {
3879 Ok(SubtleKangarooTwelveParams {
3880 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3881 output_length: value.output_length,
3882 customization: value.customization,
3883 })
3884 }
3885}
3886
3887impl From<&SubtleKangarooTwelveParams> for SerializableKangarooTwelveParams {
3888 fn from(value: &SubtleKangarooTwelveParams) -> Self {
3889 SerializableKangarooTwelveParams {
3890 name: value.name.as_str().into(),
3891 output_length: value.output_length,
3892 customization: value.customization.clone(),
3893 }
3894 }
3895}
3896
3897#[derive(Clone, MallocSizeOf)]
3899struct SubtleArgon2Params {
3900 name: CryptoAlgorithm,
3902
3903 nonce: Vec<u8>,
3905
3906 parallelism: u32,
3908
3909 memory: u32,
3911
3912 passes: u32,
3914
3915 version: Option<u8>,
3917
3918 secret_value: Option<Vec<u8>>,
3920
3921 associated_data: Option<Vec<u8>>,
3923}
3924
3925impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleArgon2Params {
3926 type Error = Error;
3927
3928 fn try_from_with_cx_and_name(
3929 object: HandleObject<'a>,
3930 cx: &mut js::context::JSContext,
3931 algorithm_name: CryptoAlgorithm,
3932 ) -> Result<Self, Self::Error> {
3933 Ok(SubtleArgon2Params {
3934 name: algorithm_name,
3935 nonce: get_required_buffer_source(cx, object, c"nonce")?,
3936 parallelism: get_required_parameter(
3937 cx,
3938 object,
3939 c"parallelism",
3940 ConversionBehavior::EnforceRange,
3941 )?,
3942 memory: get_required_parameter(
3943 cx,
3944 object,
3945 c"memory",
3946 ConversionBehavior::EnforceRange,
3947 )?,
3948 passes: get_required_parameter(
3949 cx,
3950 object,
3951 c"passes",
3952 ConversionBehavior::EnforceRange,
3953 )?,
3954 version: get_property(cx, object, c"version", ConversionBehavior::EnforceRange)?,
3955 secret_value: get_optional_buffer_source(cx, object, c"secretValue")?,
3956 associated_data: get_optional_buffer_source(cx, object, c"associatedData")?,
3957 })
3958 }
3959}
3960
3961struct SubtleEncapsulatedKey {
3963 shared_key: Option<Trusted<CryptoKey>>,
3965
3966 ciphertext: Option<Vec<u8>>,
3968}
3969
3970impl SafeToJSValConvertible for SubtleEncapsulatedKey {
3971 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
3972 let shared_key = self.shared_key.as_ref().map(|shared_key| shared_key.root());
3973 let ciphertext = self.ciphertext.as_ref().map(|data| {
3974 rooted!(&in(cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
3975 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut())
3976 .expect("Failed to convert ciphertext to ArrayBufferU8")
3977 });
3978 let encapsulated_key = RootedTraceableBox::new(EncapsulatedKey {
3979 sharedKey: shared_key,
3980 ciphertext,
3981 });
3982 encapsulated_key.safe_to_jsval(cx, rval);
3983 }
3984}
3985
3986struct SubtleEncapsulatedBits {
3988 shared_key: Option<Zeroizing<Vec<u8>>>,
3990
3991 ciphertext: Option<Vec<u8>>,
3993}
3994
3995impl SafeToJSValConvertible for SubtleEncapsulatedBits {
3996 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
3997 let shared_key = self.shared_key.as_ref().map(|data| {
3998 rooted!(&in(cx) let mut shared_key_ptr = ptr::null_mut::<JSObject>());
3999 create_buffer_source::<ArrayBufferU8>(cx, data, shared_key_ptr.handle_mut())
4000 .expect("Failed to convert shared key to ArrayBufferU8")
4001 });
4002 let ciphertext = self.ciphertext.as_ref().map(|data| {
4003 rooted!(&in(cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
4004 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut())
4005 .expect("Failed to convert ciphertext to ArrayBufferU8")
4006 });
4007 let encapsulated_bits = RootedTraceableBox::new(EncapsulatedBits {
4008 sharedKey: shared_key,
4009 ciphertext,
4010 });
4011 encapsulated_bits.safe_to_jsval(cx, rval);
4012 }
4013}
4014
4015fn get_required_parameter<T: FromJSValConvertible>(
4017 cx: &mut js::context::JSContext,
4018 object: HandleObject,
4019 parameter: &std::ffi::CStr,
4020 option: T::Config,
4021) -> Fallible<T> {
4022 get_property::<T>(cx, object, parameter, option)?
4023 .ok_or(Error::Type(c"Missing required parameter".into()))
4024}
4025
4026fn get_required_parameter_in_box<T: FromJSValConvertible + Trace>(
4028 cx: &mut js::context::JSContext,
4029 object: HandleObject,
4030 parameter: &std::ffi::CStr,
4031 option: T::Config,
4032) -> Fallible<RootedTraceableBox<T>> {
4033 get_property::<T>(cx, object, parameter, option)?
4034 .map(RootedTraceableBox::new)
4035 .ok_or(Error::Type(c"Missing required parameter".into()))
4036}
4037
4038fn get_optional_buffer_source(
4042 cx: &mut js::context::JSContext,
4043 object: HandleObject,
4044 parameter: &std::ffi::CStr,
4045) -> Fallible<Option<Vec<u8>>> {
4046 let buffer_source = get_property::<ArrayBufferViewOrArrayBuffer>(cx, object, parameter, ())?;
4047 match buffer_source {
4048 Some(ArrayBufferViewOrArrayBuffer::ArrayBufferView(view)) => Ok(Some(view.to_vec())),
4049 Some(ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer)) => Ok(Some(buffer.to_vec())),
4050 None => Ok(None),
4051 }
4052}
4053
4054fn get_required_buffer_source(
4058 cx: &mut js::context::JSContext,
4059 object: HandleObject,
4060 parameter: &std::ffi::CStr,
4061) -> Fallible<Vec<u8>> {
4062 get_optional_buffer_source(cx, object, parameter)?
4063 .ok_or(Error::Type(c"Missing required parameter".into()))
4064}
4065
4066enum ExportedKey {
4070 Bytes(Zeroizing<Vec<u8>>),
4071 Jwk(Box<JsonWebKey>),
4072}
4073
4074impl ExportedKey {
4075 fn new_bytes(bytes: Vec<u8>) -> ExportedKey {
4076 ExportedKey::Bytes(Zeroizing::new(bytes))
4077 }
4078
4079 fn new_jwk(jwk: JsonWebKey) -> ExportedKey {
4080 ExportedKey::Jwk(Box::new(jwk))
4081 }
4082}
4083
4084#[derive(Clone, MallocSizeOf)]
4088#[expect(clippy::enum_variant_names)]
4089pub(crate) enum KeyAlgorithmAndDerivatives {
4090 KeyAlgorithm(SubtleKeyAlgorithm),
4091 RsaHashedKeyAlgorithm(SubtleRsaHashedKeyAlgorithm),
4092 EcKeyAlgorithm(SubtleEcKeyAlgorithm),
4093 AesKeyAlgorithm(SubtleAesKeyAlgorithm),
4094 HmacKeyAlgorithm(SubtleHmacKeyAlgorithm),
4095}
4096
4097impl KeyAlgorithmAndDerivatives {
4098 fn name(&self) -> CryptoAlgorithm {
4099 match self {
4100 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => algorithm.name,
4101 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => algorithm.name,
4102 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => algorithm.name,
4103 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => algorithm.name,
4104 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => algorithm.name,
4105 }
4106 }
4107}
4108
4109impl SafeToJSValConvertible for KeyAlgorithmAndDerivatives {
4110 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
4111 match self {
4112 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4113 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4114 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4115 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4116 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4117 }
4118 }
4119}
4120
4121impl TryFrom<SerializableKeyAlgorithmAndDerivatives> for KeyAlgorithmAndDerivatives {
4122 type Error = ();
4123
4124 fn try_from(value: SerializableKeyAlgorithmAndDerivatives) -> Result<Self, Self::Error> {
4125 match value {
4126 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => Ok(
4127 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.try_into()?),
4128 ),
4129 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => Ok(
4130 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.try_into()?),
4131 ),
4132 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => Ok(
4133 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.try_into()?),
4134 ),
4135 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => Ok(
4136 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.try_into()?),
4137 ),
4138 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => Ok(
4139 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.try_into()?),
4140 ),
4141 }
4142 }
4143}
4144
4145impl From<&KeyAlgorithmAndDerivatives> for SerializableKeyAlgorithmAndDerivatives {
4146 fn from(value: &KeyAlgorithmAndDerivatives) -> Self {
4147 match value {
4148 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => {
4149 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.into())
4150 },
4151 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => {
4152 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.into())
4153 },
4154 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => {
4155 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.into())
4156 },
4157 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => {
4158 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.into())
4159 },
4160 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => {
4161 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.into())
4162 },
4163 }
4164 }
4165}
4166
4167#[derive(Clone, Copy)]
4168enum JwkStringField {
4169 X,
4170 Y,
4171 D,
4172 N,
4173 E,
4174 P,
4175 Q,
4176 DP,
4177 DQ,
4178 QI,
4179 K,
4180 Priv,
4181 Pub,
4182}
4183
4184impl Display for JwkStringField {
4185 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4186 let field_name = match self {
4187 JwkStringField::X => "x",
4188 JwkStringField::Y => "y",
4189 JwkStringField::D => "d",
4190 JwkStringField::N => "n",
4191 JwkStringField::E => "e",
4192 JwkStringField::P => "q",
4193 JwkStringField::Q => "q",
4194 JwkStringField::DP => "dp",
4195 JwkStringField::DQ => "dq",
4196 JwkStringField::QI => "qi",
4197 JwkStringField::K => "k",
4198 JwkStringField::Priv => "priv",
4199 JwkStringField::Pub => "pub",
4200 };
4201 write!(f, "{}", field_name)
4202 }
4203}
4204
4205trait JsonWebKeyExt {
4206 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
4207 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error>;
4208 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
4209 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
4210 fn set_key_ops(&mut self, usages: &[KeyUsage]);
4211 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]);
4212 fn decode_optional_string_field(
4213 &self,
4214 field: JwkStringField,
4215 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error>;
4216 fn decode_required_string_field(
4217 &self,
4218 field: JwkStringField,
4219 ) -> Result<Zeroizing<Vec<u8>>, Error>;
4220 fn decode_primes_from_oth_field(
4221 &self,
4222 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4223 ) -> Result<(), Error>;
4224}
4225
4226impl JsonWebKeyExt for JsonWebKey {
4227 #[expect(unsafe_code)]
4229 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
4230 let json = String::from_utf8_lossy(data);
4235
4236 let json: Vec<_> = json.encode_utf16().collect();
4238
4239 rooted!(&in(cx) let mut result = UndefinedValue());
4243 unsafe {
4244 if !JS_ParseJSON(cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
4245 return Err(Error::JSFailed);
4246 }
4247 }
4248
4249 let key = match JsonWebKey::new(cx, result.handle()) {
4251 Ok(ConversionResult::Success(key)) => key,
4252 Ok(ConversionResult::Failure(error)) => {
4253 return Err(Error::Type(error.into_owned()));
4254 },
4255 Err(()) => {
4256 return Err(Error::JSFailed);
4257 },
4258 };
4259
4260 if key.kty.is_none() {
4262 return Err(Error::Data(None));
4263 }
4264
4265 Ok(key)
4267 }
4268
4269 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error> {
4275 rooted!(&in(cx) let mut data = UndefinedValue());
4276 self.safe_to_jsval(cx, data.handle_mut());
4277 serialize_jsval_to_json_utf8(cx, data.handle()).map(Zeroizing::new)
4278 }
4279
4280 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
4281 let mut usages = vec![];
4282 for op in self.key_ops.as_ref().ok_or(Error::Data(None))? {
4283 usages.push(KeyUsage::from_str(&op.str()).map_err(|_| Error::Data(None))?);
4284 }
4285 Ok(usages)
4286 }
4287
4288 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
4292 if let Some(ref key_ops) = self.key_ops {
4294 if key_ops
4297 .iter()
4298 .collect::<std::collections::HashSet<_>>()
4299 .len() <
4300 key_ops.len()
4301 {
4302 return Err(Error::Data(None));
4303 }
4304 if let Some(ref use_) = self.use_ &&
4307 key_ops.iter().any(|op| op != use_)
4308 {
4309 return Err(Error::Data(None));
4310 }
4311
4312 let key_ops_as_usages = self.get_usages_from_key_ops()?;
4314 if !specified_usages
4315 .iter()
4316 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
4317 {
4318 return Err(Error::Data(None));
4319 }
4320 }
4321
4322 Ok(())
4323 }
4324
4325 fn set_key_ops(&mut self, usages: &[KeyUsage]) {
4327 self.key_ops = Some(
4328 usages
4329 .iter()
4330 .map(|usage| DOMString::from(usage.as_str()))
4331 .collect(),
4332 );
4333 }
4334
4335 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]) {
4338 let encoded_data = DOMString::from(Base64UrlUnpadded::encode_string(data));
4339 match field {
4340 JwkStringField::X => self.x = Some(encoded_data),
4341 JwkStringField::Y => self.y = Some(encoded_data),
4342 JwkStringField::D => self.d = Some(encoded_data),
4343 JwkStringField::N => self.n = Some(encoded_data),
4344 JwkStringField::E => self.e = Some(encoded_data),
4345 JwkStringField::P => self.p = Some(encoded_data),
4346 JwkStringField::Q => self.q = Some(encoded_data),
4347 JwkStringField::DP => self.dp = Some(encoded_data),
4348 JwkStringField::DQ => self.dq = Some(encoded_data),
4349 JwkStringField::QI => self.qi = Some(encoded_data),
4350 JwkStringField::K => self.k = Some(encoded_data),
4351 JwkStringField::Priv => self.priv_ = Some(encoded_data),
4352 JwkStringField::Pub => self.pub_ = Some(encoded_data),
4353 }
4354 }
4355
4356 fn decode_optional_string_field(
4359 &self,
4360 field: JwkStringField,
4361 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error> {
4362 let field_string = match field {
4363 JwkStringField::X => &self.x,
4364 JwkStringField::Y => &self.y,
4365 JwkStringField::D => &self.d,
4366 JwkStringField::N => &self.n,
4367 JwkStringField::E => &self.e,
4368 JwkStringField::P => &self.p,
4369 JwkStringField::Q => &self.q,
4370 JwkStringField::DP => &self.dp,
4371 JwkStringField::DQ => &self.dq,
4372 JwkStringField::QI => &self.qi,
4373 JwkStringField::K => &self.k,
4374 JwkStringField::Priv => &self.priv_,
4375 JwkStringField::Pub => &self.pub_,
4376 };
4377
4378 field_string
4379 .as_ref()
4380 .map(|field_string| {
4381 Base64UrlUnpadded::decode_vec(&field_string.str()).map(Zeroizing::new)
4382 })
4383 .transpose()
4384 .map_err(|_| Error::Data(Some(format!("Failed to decode {} field in jwk", field))))
4385 }
4386
4387 fn decode_required_string_field(
4390 &self,
4391 field: JwkStringField,
4392 ) -> Result<Zeroizing<Vec<u8>>, Error> {
4393 self.decode_optional_string_field(field)?
4394 .ok_or(Error::Data(Some(format!(
4395 "The {} field is not present in jwk",
4396 field
4397 ))))
4398 }
4399
4400 fn decode_primes_from_oth_field(
4409 &self,
4410 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4411 ) -> Result<(), Error> {
4412 if self.oth.is_some() &&
4413 (self.p.is_none() ||
4414 self.q.is_none() ||
4415 self.dp.is_none() ||
4416 self.dq.is_none() ||
4417 self.qi.is_none())
4418 {
4419 return Err(Error::Data(Some(
4420 "The oth field is present while at least one of p, q, dp, dq, qi is missing, in jwk".to_string()
4421 )));
4422 }
4423
4424 for rsa_other_prime_info in self.oth.as_ref().unwrap_or(&Vec::new()) {
4425 let r = Base64UrlUnpadded::decode_vec(
4426 &rsa_other_prime_info
4427 .r
4428 .as_ref()
4429 .ok_or(Error::Data(Some(
4430 "The r field is not present in one of the entry of oth field in jwk"
4431 .to_string(),
4432 )))?
4433 .str(),
4434 )
4435 .map_err(|_| {
4436 Error::Data(Some(
4437 "Fail to decode r field in one of the entry of oth field in jwk".to_string(),
4438 ))
4439 })?;
4440 primes.push(Zeroizing::new(r));
4441
4442 let _d = Base64UrlUnpadded::decode_vec(
4443 &rsa_other_prime_info
4444 .d
4445 .as_ref()
4446 .ok_or(Error::Data(Some(
4447 "The d field is not present in one of the entry of oth field in jwk"
4448 .to_string(),
4449 )))?
4450 .str(),
4451 )
4452 .map_err(|_| {
4453 Error::Data(Some(
4454 "Fail to decode d field in one of the entry of oth field in jwk".to_string(),
4455 ))
4456 })?;
4457
4458 let _t = Base64UrlUnpadded::decode_vec(
4459 &rsa_other_prime_info
4460 .t
4461 .as_ref()
4462 .ok_or(Error::Data(Some(
4463 "The t field is not present in one of the entry of oth field in jwk"
4464 .to_string(),
4465 )))?
4466 .str(),
4467 )
4468 .map_err(|_| {
4469 Error::Data(Some(
4470 "Fail to decode t field in one of the entry of oth field in jwk".to_string(),
4471 ))
4472 })?;
4473 }
4474
4475 Ok(())
4476 }
4477}
4478
4479fn normalize_algorithm<Op: Operation>(
4481 cx: &mut js::context::JSContext,
4482 algorithm: &AlgorithmIdentifier,
4483) -> Result<Op::RegisteredAlgorithm, Error> {
4484 match algorithm {
4485 ObjectOrString::String(name) => {
4487 let algorithm = Algorithm {
4491 name: name.to_owned(),
4492 };
4493 rooted!(&in(cx) let mut algorithm_value = UndefinedValue());
4494 algorithm.safe_to_jsval(cx, algorithm_value.handle_mut());
4495 let algorithm_object = RootedTraceableBox::new(Heap::default());
4496 algorithm_object.set(algorithm_value.to_object());
4497 normalize_algorithm::<Op>(cx, &ObjectOrString::Object(algorithm_object))
4498 },
4499 ObjectOrString::Object(object) => {
4501 let algorithm_name = get_required_parameter::<DOMString>(
4509 cx,
4510 object.handle(),
4511 c"name",
4512 StringificationBehavior::Default,
4513 )?;
4514
4515 let algorithm_name = CryptoAlgorithm::from_str_ignore_case(&algorithm_name.str())?;
4556 let normalized_algorithm =
4557 Op::RegisteredAlgorithm::from_object(cx, algorithm_name, object.handle())?;
4558
4559 Ok(normalized_algorithm)
4561 },
4562 }
4563}
4564
4565trait Operation {
4619 type RegisteredAlgorithm: NormalizedAlgorithm;
4620}
4621
4622trait NormalizedAlgorithm: Sized {
4623 fn from_object(
4625 cx: &mut js::context::JSContext,
4626 algorithm_name: CryptoAlgorithm,
4627 object: HandleObject,
4628 ) -> Fallible<Self>;
4629 fn name(&self) -> CryptoAlgorithm;
4630}
4631
4632struct EncryptOperation {}
4634
4635impl Operation for EncryptOperation {
4636 type RegisteredAlgorithm = EncryptAlgorithm;
4637}
4638
4639enum EncryptAlgorithm {
4642 RsaOaep(SubtleRsaOaepParams),
4643 AesCtr(SubtleAesCtrParams),
4644 AesCbc(SubtleAesCbcParams),
4645 AesGcm(SubtleAesGcmParams),
4646 AesOcb(SubtleAeadParams),
4647 ChaCha20Poly1305(SubtleAeadParams),
4648}
4649
4650impl NormalizedAlgorithm for EncryptAlgorithm {
4651 fn from_object(
4652 cx: &mut js::context::JSContext,
4653 algorithm_name: CryptoAlgorithm,
4654 object: HandleObject,
4655 ) -> Fallible<Self> {
4656 match algorithm_name {
4657 CryptoAlgorithm::RsaOaep => Ok(EncryptAlgorithm::RsaOaep(
4658 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4659 )),
4660 CryptoAlgorithm::AesCtr => Ok(EncryptAlgorithm::AesCtr(
4661 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4662 )),
4663 CryptoAlgorithm::AesCbc => Ok(EncryptAlgorithm::AesCbc(
4664 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4665 )),
4666 CryptoAlgorithm::AesGcm => Ok(EncryptAlgorithm::AesGcm(
4667 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4668 )),
4669 CryptoAlgorithm::AesOcb => Ok(EncryptAlgorithm::AesOcb(
4670 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4671 )),
4672 CryptoAlgorithm::ChaCha20Poly1305 => Ok(EncryptAlgorithm::ChaCha20Poly1305(
4673 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4674 )),
4675 _ => Err(Error::NotSupported(Some(format!(
4676 "{} does not support \"encrypt\" operation",
4677 algorithm_name.as_str()
4678 )))),
4679 }
4680 }
4681
4682 fn name(&self) -> CryptoAlgorithm {
4683 match self {
4684 EncryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
4685 EncryptAlgorithm::AesCtr(algorithm) => algorithm.name,
4686 EncryptAlgorithm::AesCbc(algorithm) => algorithm.name,
4687 EncryptAlgorithm::AesGcm(algorithm) => algorithm.name,
4688 EncryptAlgorithm::AesOcb(algorithm) => algorithm.name,
4689 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4690 }
4691 }
4692}
4693
4694impl EncryptAlgorithm {
4695 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
4696 match self {
4697 EncryptAlgorithm::RsaOaep(algorithm) => {
4698 rsa_oaep_operation::encrypt(algorithm, key, plaintext)
4699 },
4700 EncryptAlgorithm::AesCtr(algorithm) => {
4701 aes_ctr_operation::encrypt(algorithm, key, plaintext)
4702 },
4703 EncryptAlgorithm::AesCbc(algorithm) => {
4704 aes_cbc_operation::encrypt(algorithm, key, plaintext)
4705 },
4706 EncryptAlgorithm::AesGcm(algorithm) => {
4707 aes_gcm_operation::encrypt(algorithm, key, plaintext)
4708 },
4709 EncryptAlgorithm::AesOcb(algorithm) => {
4710 aes_ocb_operation::encrypt(algorithm, key, plaintext)
4711 },
4712 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => {
4713 chacha20_poly1305_operation::encrypt(algorithm, key, plaintext)
4714 },
4715 }
4716 }
4717}
4718
4719struct DecryptOperation {}
4721
4722impl Operation for DecryptOperation {
4723 type RegisteredAlgorithm = DecryptAlgorithm;
4724}
4725
4726enum DecryptAlgorithm {
4729 RsaOaep(SubtleRsaOaepParams),
4730 AesCtr(SubtleAesCtrParams),
4731 AesCbc(SubtleAesCbcParams),
4732 AesGcm(SubtleAesGcmParams),
4733 AesOcb(SubtleAeadParams),
4734 ChaCha20Poly1305(SubtleAeadParams),
4735}
4736
4737impl NormalizedAlgorithm for DecryptAlgorithm {
4738 fn from_object(
4739 cx: &mut js::context::JSContext,
4740 algorithm_name: CryptoAlgorithm,
4741 object: HandleObject,
4742 ) -> Fallible<Self> {
4743 match algorithm_name {
4744 CryptoAlgorithm::RsaOaep => Ok(DecryptAlgorithm::RsaOaep(
4745 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4746 )),
4747 CryptoAlgorithm::AesCtr => Ok(DecryptAlgorithm::AesCtr(
4748 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4749 )),
4750 CryptoAlgorithm::AesCbc => Ok(DecryptAlgorithm::AesCbc(
4751 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4752 )),
4753 CryptoAlgorithm::AesGcm => Ok(DecryptAlgorithm::AesGcm(
4754 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4755 )),
4756 CryptoAlgorithm::AesOcb => Ok(DecryptAlgorithm::AesOcb(
4757 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4758 )),
4759 CryptoAlgorithm::ChaCha20Poly1305 => Ok(DecryptAlgorithm::ChaCha20Poly1305(
4760 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4761 )),
4762 _ => Err(Error::NotSupported(Some(format!(
4763 "{} does not support \"decrypt\" operation",
4764 algorithm_name.as_str()
4765 )))),
4766 }
4767 }
4768
4769 fn name(&self) -> CryptoAlgorithm {
4770 match self {
4771 DecryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
4772 DecryptAlgorithm::AesCtr(algorithm) => algorithm.name,
4773 DecryptAlgorithm::AesCbc(algorithm) => algorithm.name,
4774 DecryptAlgorithm::AesGcm(algorithm) => algorithm.name,
4775 DecryptAlgorithm::AesOcb(algorithm) => algorithm.name,
4776 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4777 }
4778 }
4779}
4780
4781impl DecryptAlgorithm {
4782 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
4783 match self {
4784 DecryptAlgorithm::RsaOaep(algorithm) => {
4785 rsa_oaep_operation::decrypt(algorithm, key, ciphertext)
4786 },
4787 DecryptAlgorithm::AesCtr(algorithm) => {
4788 aes_ctr_operation::decrypt(algorithm, key, ciphertext)
4789 },
4790 DecryptAlgorithm::AesCbc(algorithm) => {
4791 aes_cbc_operation::decrypt(algorithm, key, ciphertext)
4792 },
4793 DecryptAlgorithm::AesGcm(algorithm) => {
4794 aes_gcm_operation::decrypt(algorithm, key, ciphertext)
4795 },
4796 DecryptAlgorithm::AesOcb(algorithm) => {
4797 aes_ocb_operation::decrypt(algorithm, key, ciphertext)
4798 },
4799 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => {
4800 chacha20_poly1305_operation::decrypt(algorithm, key, ciphertext)
4801 },
4802 }
4803 }
4804}
4805
4806struct SignOperation {}
4808
4809impl Operation for SignOperation {
4810 type RegisteredAlgorithm = SignAlgorithm;
4811}
4812
4813enum SignAlgorithm {
4816 RsassaPkcs1V1_5(SubtleAlgorithm),
4817 RsaPss(SubtleRsaPssParams),
4818 Ecdsa(SubtleEcdsaParams),
4819 Ed25519(SubtleAlgorithm),
4820 Hmac(SubtleAlgorithm),
4821 MlDsa(SubtleContextParams),
4822}
4823
4824impl NormalizedAlgorithm for SignAlgorithm {
4825 fn from_object(
4826 cx: &mut js::context::JSContext,
4827 algorithm_name: CryptoAlgorithm,
4828 object: HandleObject,
4829 ) -> Fallible<Self> {
4830 match algorithm_name {
4831 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(SignAlgorithm::RsassaPkcs1V1_5(
4832 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4833 )),
4834 CryptoAlgorithm::RsaPss => Ok(SignAlgorithm::RsaPss(
4835 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4836 )),
4837 CryptoAlgorithm::Ecdsa => Ok(SignAlgorithm::Ecdsa(
4838 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4839 )),
4840 CryptoAlgorithm::Ed25519 => Ok(SignAlgorithm::Ed25519(
4841 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4842 )),
4843 CryptoAlgorithm::Hmac => Ok(SignAlgorithm::Hmac(
4844 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4845 )),
4846 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
4847 SignAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
4848 ),
4849 _ => Err(Error::NotSupported(Some(format!(
4850 "{} does not support \"sign\" operation",
4851 algorithm_name.as_str()
4852 )))),
4853 }
4854 }
4855
4856 fn name(&self) -> CryptoAlgorithm {
4857 match self {
4858 SignAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
4859 SignAlgorithm::RsaPss(algorithm) => algorithm.name,
4860 SignAlgorithm::Ecdsa(algorithm) => algorithm.name,
4861 SignAlgorithm::Ed25519(algorithm) => algorithm.name,
4862 SignAlgorithm::Hmac(algorithm) => algorithm.name,
4863 SignAlgorithm::MlDsa(algorithm) => algorithm.name,
4864 }
4865 }
4866}
4867
4868impl SignAlgorithm {
4869 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
4870 match self {
4871 SignAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
4872 rsassa_pkcs1_v1_5_operation::sign(key, message)
4873 },
4874 SignAlgorithm::RsaPss(algorithm) => rsa_pss_operation::sign(algorithm, key, message),
4875 SignAlgorithm::Ecdsa(algorithm) => ecdsa_operation::sign(algorithm, key, message),
4876 SignAlgorithm::Ed25519(_algorithm) => ed25519_operation::sign(key, message),
4877 SignAlgorithm::Hmac(_algorithm) => hmac_operation::sign(key, message),
4878 SignAlgorithm::MlDsa(algorithm) => ml_dsa_operation::sign(algorithm, key, message),
4879 }
4880 }
4881}
4882
4883struct VerifyOperation {}
4885
4886impl Operation for VerifyOperation {
4887 type RegisteredAlgorithm = VerifyAlgorithm;
4888}
4889
4890enum VerifyAlgorithm {
4893 RsassaPkcs1V1_5(SubtleAlgorithm),
4894 RsaPss(SubtleRsaPssParams),
4895 Ecdsa(SubtleEcdsaParams),
4896 Ed25519(SubtleAlgorithm),
4897 Hmac(SubtleAlgorithm),
4898 MlDsa(SubtleContextParams),
4899}
4900
4901impl NormalizedAlgorithm for VerifyAlgorithm {
4902 fn from_object(
4903 cx: &mut js::context::JSContext,
4904 algorithm_name: CryptoAlgorithm,
4905 object: HandleObject,
4906 ) -> Fallible<Self> {
4907 match algorithm_name {
4908 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(VerifyAlgorithm::RsassaPkcs1V1_5(
4909 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4910 )),
4911 CryptoAlgorithm::RsaPss => Ok(VerifyAlgorithm::RsaPss(
4912 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4913 )),
4914 CryptoAlgorithm::Ecdsa => Ok(VerifyAlgorithm::Ecdsa(
4915 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4916 )),
4917 CryptoAlgorithm::Ed25519 => Ok(VerifyAlgorithm::Ed25519(
4918 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4919 )),
4920 CryptoAlgorithm::Hmac => Ok(VerifyAlgorithm::Hmac(
4921 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4922 )),
4923 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
4924 VerifyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
4925 ),
4926 _ => Err(Error::NotSupported(Some(format!(
4927 "{} does not support \"verify\" operation",
4928 algorithm_name.as_str()
4929 )))),
4930 }
4931 }
4932
4933 fn name(&self) -> CryptoAlgorithm {
4934 match self {
4935 VerifyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
4936 VerifyAlgorithm::RsaPss(algorithm) => algorithm.name,
4937 VerifyAlgorithm::Ecdsa(algorithm) => algorithm.name,
4938 VerifyAlgorithm::Ed25519(algorithm) => algorithm.name,
4939 VerifyAlgorithm::Hmac(algorithm) => algorithm.name,
4940 VerifyAlgorithm::MlDsa(algorithm) => algorithm.name,
4941 }
4942 }
4943}
4944
4945impl VerifyAlgorithm {
4946 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
4947 match self {
4948 VerifyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
4949 rsassa_pkcs1_v1_5_operation::verify(key, message, signature)
4950 },
4951 VerifyAlgorithm::RsaPss(algorithm) => {
4952 rsa_pss_operation::verify(algorithm, key, message, signature)
4953 },
4954 VerifyAlgorithm::Ecdsa(algorithm) => {
4955 ecdsa_operation::verify(algorithm, key, message, signature)
4956 },
4957 VerifyAlgorithm::Ed25519(_algorithm) => {
4958 ed25519_operation::verify(key, message, signature)
4959 },
4960 VerifyAlgorithm::Hmac(_algorithm) => hmac_operation::verify(key, message, signature),
4961 VerifyAlgorithm::MlDsa(algorithm) => {
4962 ml_dsa_operation::verify(algorithm, key, message, signature)
4963 },
4964 }
4965 }
4966}
4967
4968struct DigestOperation {}
4970
4971impl Operation for DigestOperation {
4972 type RegisteredAlgorithm = DigestAlgorithm;
4973}
4974
4975#[derive(Clone, MallocSizeOf)]
4978enum DigestAlgorithm {
4979 Sha(SubtleAlgorithm),
4980 Sha3(SubtleAlgorithm),
4981 CShake(SubtleCShakeParams),
4982 TurboShake(SubtleTurboShakeParams),
4983 KangarooTwelve(SubtleKangarooTwelveParams),
4984}
4985
4986impl NormalizedAlgorithm for DigestAlgorithm {
4987 fn from_object(
4988 cx: &mut js::context::JSContext,
4989 algorithm_name: CryptoAlgorithm,
4990 object: HandleObject,
4991 ) -> Fallible<Self> {
4992 match algorithm_name {
4993 CryptoAlgorithm::Sha1 |
4994 CryptoAlgorithm::Sha256 |
4995 CryptoAlgorithm::Sha384 |
4996 CryptoAlgorithm::Sha512 => Ok(DigestAlgorithm::Sha(
4997 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4998 )),
4999 CryptoAlgorithm::Sha3_256 | CryptoAlgorithm::Sha3_384 | CryptoAlgorithm::Sha3_512 => {
5000 Ok(DigestAlgorithm::Sha3(
5001 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5002 ))
5003 },
5004 CryptoAlgorithm::CShake128 | CryptoAlgorithm::CShake256 => Ok(DigestAlgorithm::CShake(
5005 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5006 )),
5007 CryptoAlgorithm::TurboShake128 | CryptoAlgorithm::TurboShake256 => Ok(
5008 DigestAlgorithm::TurboShake(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5009 ),
5010 CryptoAlgorithm::Kt128 | CryptoAlgorithm::Kt256 => Ok(DigestAlgorithm::KangarooTwelve(
5011 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5012 )),
5013 _ => Err(Error::NotSupported(Some(format!(
5014 "{} does not support \"digest\" operation",
5015 algorithm_name.as_str()
5016 )))),
5017 }
5018 }
5019
5020 fn name(&self) -> CryptoAlgorithm {
5021 match self {
5022 DigestAlgorithm::Sha(algorithm) => algorithm.name,
5023 DigestAlgorithm::Sha3(algorithm) => algorithm.name,
5024 DigestAlgorithm::CShake(algorithm) => algorithm.name,
5025 DigestAlgorithm::TurboShake(algorithm) => algorithm.name,
5026 DigestAlgorithm::KangarooTwelve(algorithm) => algorithm.name,
5027 }
5028 }
5029}
5030
5031impl DigestAlgorithm {
5032 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
5033 match self {
5034 DigestAlgorithm::Sha(algorithm) => sha_operation::digest(algorithm, message),
5035 DigestAlgorithm::Sha3(algorithm) => sha3_operation::digest(algorithm, message),
5036 DigestAlgorithm::CShake(algorithm) => cshake_operation::digest(algorithm, message),
5037 DigestAlgorithm::TurboShake(algorithm) => {
5038 turboshake_operation::digest(algorithm, message)
5039 },
5040 DigestAlgorithm::KangarooTwelve(algorithm) => {
5041 kangarootwelve_operation::digest(algorithm, message)
5042 },
5043 }
5044 }
5045}
5046
5047impl TryFrom<SerializableDigestAlgorithm> for DigestAlgorithm {
5048 type Error = ();
5049
5050 fn try_from(value: SerializableDigestAlgorithm) -> Result<Self, Self::Error> {
5051 match value {
5052 SerializableDigestAlgorithm::Sha(algorithm) => {
5053 Ok(DigestAlgorithm::Sha(algorithm.try_into()?))
5054 },
5055 SerializableDigestAlgorithm::Sha3(algorithm) => {
5056 Ok(DigestAlgorithm::Sha3(algorithm.try_into()?))
5057 },
5058 SerializableDigestAlgorithm::CShake(algorithm) => {
5059 Ok(DigestAlgorithm::CShake(algorithm.try_into()?))
5060 },
5061 SerializableDigestAlgorithm::TurboShake(algorithm) => {
5062 Ok(DigestAlgorithm::TurboShake(algorithm.try_into()?))
5063 },
5064 SerializableDigestAlgorithm::KangarooTwelve(algorithm) => {
5065 Ok(DigestAlgorithm::KangarooTwelve(algorithm.try_into()?))
5066 },
5067 }
5068 }
5069}
5070
5071impl From<&DigestAlgorithm> for SerializableDigestAlgorithm {
5072 fn from(value: &DigestAlgorithm) -> Self {
5073 match value {
5074 DigestAlgorithm::Sha(algorithm) => SerializableDigestAlgorithm::Sha(algorithm.into()),
5075 DigestAlgorithm::Sha3(algorithm) => SerializableDigestAlgorithm::Sha3(algorithm.into()),
5076 DigestAlgorithm::CShake(algorithm) => {
5077 SerializableDigestAlgorithm::CShake(algorithm.into())
5078 },
5079 DigestAlgorithm::TurboShake(algorithm) => {
5080 SerializableDigestAlgorithm::TurboShake(algorithm.into())
5081 },
5082 DigestAlgorithm::KangarooTwelve(algorithm) => {
5083 SerializableDigestAlgorithm::KangarooTwelve(algorithm.into())
5084 },
5085 }
5086 }
5087}
5088
5089struct DeriveBitsOperation {}
5091
5092impl Operation for DeriveBitsOperation {
5093 type RegisteredAlgorithm = DeriveBitsAlgorithm;
5094}
5095
5096enum DeriveBitsAlgorithm {
5099 Ecdh(SubtleEcdhKeyDeriveParams),
5100 X25519(SubtleEcdhKeyDeriveParams),
5101 Hkdf(SubtleHkdfParams),
5102 Pbkdf2(SubtlePbkdf2Params),
5103 Argon2(SubtleArgon2Params),
5104}
5105
5106impl NormalizedAlgorithm for DeriveBitsAlgorithm {
5107 fn from_object(
5108 cx: &mut js::context::JSContext,
5109 algorithm_name: CryptoAlgorithm,
5110 object: HandleObject,
5111 ) -> Fallible<Self> {
5112 match algorithm_name {
5113 CryptoAlgorithm::Ecdh => Ok(DeriveBitsAlgorithm::Ecdh(
5114 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5115 )),
5116 CryptoAlgorithm::X25519 => Ok(DeriveBitsAlgorithm::X25519(
5117 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5118 )),
5119 CryptoAlgorithm::Hkdf => Ok(DeriveBitsAlgorithm::Hkdf(
5120 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5121 )),
5122 CryptoAlgorithm::Pbkdf2 => Ok(DeriveBitsAlgorithm::Pbkdf2(
5123 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5124 )),
5125 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5126 DeriveBitsAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5127 ),
5128 _ => Err(Error::NotSupported(Some(format!(
5129 "{} does not support \"deriveBits\" operation",
5130 algorithm_name.as_str()
5131 )))),
5132 }
5133 }
5134
5135 fn name(&self) -> CryptoAlgorithm {
5136 match self {
5137 DeriveBitsAlgorithm::Ecdh(algorithm) => algorithm.name,
5138 DeriveBitsAlgorithm::X25519(algorithm) => algorithm.name,
5139 DeriveBitsAlgorithm::Hkdf(algorithm) => algorithm.name,
5140 DeriveBitsAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5141 DeriveBitsAlgorithm::Argon2(algorithm) => algorithm.name,
5142 }
5143 }
5144}
5145
5146impl DeriveBitsAlgorithm {
5147 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
5148 match self {
5149 DeriveBitsAlgorithm::Ecdh(algorithm) => {
5150 ecdh_operation::derive_bits(algorithm, key, length)
5151 },
5152 DeriveBitsAlgorithm::X25519(algorithm) => {
5153 x25519_operation::derive_bits(algorithm, key, length)
5154 },
5155 DeriveBitsAlgorithm::Hkdf(algorithm) => {
5156 hkdf_operation::derive_bits(algorithm, key, length)
5157 },
5158 DeriveBitsAlgorithm::Pbkdf2(algorithm) => {
5159 pbkdf2_operation::derive_bits(algorithm, key, length)
5160 },
5161 DeriveBitsAlgorithm::Argon2(algorithm) => {
5162 argon2_operation::derive_bits(algorithm, key, length)
5163 },
5164 }
5165 }
5166}
5167
5168struct WrapKeyOperation {}
5170
5171impl Operation for WrapKeyOperation {
5172 type RegisteredAlgorithm = WrapKeyAlgorithm;
5173}
5174
5175enum WrapKeyAlgorithm {
5178 AesKw(SubtleAlgorithm),
5179}
5180
5181impl NormalizedAlgorithm for WrapKeyAlgorithm {
5182 fn from_object(
5183 cx: &mut js::context::JSContext,
5184 algorithm_name: CryptoAlgorithm,
5185 object: HandleObject,
5186 ) -> Fallible<Self> {
5187 match algorithm_name {
5188 CryptoAlgorithm::AesKw => Ok(WrapKeyAlgorithm::AesKw(
5189 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5190 )),
5191 _ => Err(Error::NotSupported(Some(format!(
5192 "{} does not support \"wrapKey\" operation",
5193 algorithm_name.as_str()
5194 )))),
5195 }
5196 }
5197
5198 fn name(&self) -> CryptoAlgorithm {
5199 match self {
5200 WrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5201 }
5202 }
5203}
5204
5205impl WrapKeyAlgorithm {
5206 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
5207 match self {
5208 WrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::wrap_key(key, plaintext),
5209 }
5210 }
5211}
5212
5213struct UnwrapKeyOperation {}
5215
5216impl Operation for UnwrapKeyOperation {
5217 type RegisteredAlgorithm = UnwrapKeyAlgorithm;
5218}
5219
5220enum UnwrapKeyAlgorithm {
5223 AesKw(SubtleAlgorithm),
5224}
5225
5226impl NormalizedAlgorithm for UnwrapKeyAlgorithm {
5227 fn from_object(
5228 cx: &mut js::context::JSContext,
5229 algorithm_name: CryptoAlgorithm,
5230 object: HandleObject,
5231 ) -> Fallible<Self> {
5232 match algorithm_name {
5233 CryptoAlgorithm::AesKw => Ok(UnwrapKeyAlgorithm::AesKw(
5234 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5235 )),
5236 _ => Err(Error::NotSupported(Some(format!(
5237 "{} does not support \"unwrapKey\" operation",
5238 algorithm_name.as_str()
5239 )))),
5240 }
5241 }
5242
5243 fn name(&self) -> CryptoAlgorithm {
5244 match self {
5245 UnwrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5246 }
5247 }
5248}
5249
5250impl UnwrapKeyAlgorithm {
5251 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5252 match self {
5253 UnwrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::unwrap_key(key, ciphertext),
5254 }
5255 }
5256}
5257
5258struct GenerateKeyOperation {}
5260
5261impl Operation for GenerateKeyOperation {
5262 type RegisteredAlgorithm = GenerateKeyAlgorithm;
5263}
5264
5265enum GenerateKeyAlgorithm {
5268 RsassaPkcs1V1_5(SubtleRsaHashedKeyGenParams),
5269 RsaPss(SubtleRsaHashedKeyGenParams),
5270 RsaOaep(SubtleRsaHashedKeyGenParams),
5271 Ecdsa(SubtleEcKeyGenParams),
5272 Ecdh(SubtleEcKeyGenParams),
5273 Ed25519(SubtleAlgorithm),
5274 X25519(SubtleAlgorithm),
5275 AesCtr(SubtleAesKeyGenParams),
5276 AesCbc(SubtleAesKeyGenParams),
5277 AesGcm(SubtleAesKeyGenParams),
5278 AesKw(SubtleAesKeyGenParams),
5279 Hmac(SubtleHmacKeyGenParams),
5280 MlKem(SubtleAlgorithm),
5281 MlDsa(SubtleAlgorithm),
5282 AesOcb(SubtleAesKeyGenParams),
5283 ChaCha20Poly1305(SubtleAlgorithm),
5284}
5285
5286impl NormalizedAlgorithm for GenerateKeyAlgorithm {
5287 fn from_object(
5288 cx: &mut js::context::JSContext,
5289 algorithm_name: CryptoAlgorithm,
5290 object: HandleObject,
5291 ) -> Fallible<Self> {
5292 match algorithm_name {
5293 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GenerateKeyAlgorithm::RsassaPkcs1V1_5(
5294 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5295 )),
5296 CryptoAlgorithm::RsaPss => Ok(GenerateKeyAlgorithm::RsaPss(
5297 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5298 )),
5299 CryptoAlgorithm::RsaOaep => Ok(GenerateKeyAlgorithm::RsaOaep(
5300 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5301 )),
5302 CryptoAlgorithm::Ecdsa => Ok(GenerateKeyAlgorithm::Ecdsa(
5303 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5304 )),
5305 CryptoAlgorithm::Ecdh => Ok(GenerateKeyAlgorithm::Ecdh(
5306 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5307 )),
5308 CryptoAlgorithm::Ed25519 => Ok(GenerateKeyAlgorithm::Ed25519(
5309 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5310 )),
5311 CryptoAlgorithm::X25519 => Ok(GenerateKeyAlgorithm::X25519(
5312 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5313 )),
5314 CryptoAlgorithm::AesCtr => Ok(GenerateKeyAlgorithm::AesCtr(
5315 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5316 )),
5317 CryptoAlgorithm::AesCbc => Ok(GenerateKeyAlgorithm::AesCbc(
5318 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5319 )),
5320 CryptoAlgorithm::AesGcm => Ok(GenerateKeyAlgorithm::AesGcm(
5321 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5322 )),
5323 CryptoAlgorithm::AesKw => Ok(GenerateKeyAlgorithm::AesKw(
5324 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5325 )),
5326 CryptoAlgorithm::Hmac => Ok(GenerateKeyAlgorithm::Hmac(
5327 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5328 )),
5329 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5330 Ok(GenerateKeyAlgorithm::MlKem(
5331 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5332 ))
5333 },
5334 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5335 GenerateKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5336 ),
5337 CryptoAlgorithm::AesOcb => Ok(GenerateKeyAlgorithm::AesOcb(
5338 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5339 )),
5340 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GenerateKeyAlgorithm::ChaCha20Poly1305(
5341 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5342 )),
5343 _ => Err(Error::NotSupported(Some(format!(
5344 "{} does not support \"generateKey\" operation",
5345 algorithm_name.as_str()
5346 )))),
5347 }
5348 }
5349
5350 fn name(&self) -> CryptoAlgorithm {
5351 match self {
5352 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5353 GenerateKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5354 GenerateKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5355 GenerateKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5356 GenerateKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5357 GenerateKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5358 GenerateKeyAlgorithm::X25519(algorithm) => algorithm.name,
5359 GenerateKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5360 GenerateKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5361 GenerateKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5362 GenerateKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5363 GenerateKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5364 GenerateKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5365 GenerateKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5366 GenerateKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5367 GenerateKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5368 }
5369 }
5370}
5371
5372impl GenerateKeyAlgorithm {
5373 fn generate_key(
5374 &self,
5375 cx: &mut js::context::JSContext,
5376 global: &GlobalScope,
5377 extractable: bool,
5378 usages: Vec<KeyUsage>,
5379 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
5380 match self {
5381 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5382 rsassa_pkcs1_v1_5_operation::generate_key(
5383 cx,
5384 global,
5385 algorithm,
5386 extractable,
5387 usages,
5388 )
5389 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5390 },
5391 GenerateKeyAlgorithm::RsaPss(algorithm) => {
5392 rsa_pss_operation::generate_key(cx, global, algorithm, extractable, usages)
5393 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5394 },
5395 GenerateKeyAlgorithm::RsaOaep(algorithm) => {
5396 rsa_oaep_operation::generate_key(cx, global, algorithm, extractable, usages)
5397 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5398 },
5399 GenerateKeyAlgorithm::Ecdsa(algorithm) => {
5400 ecdsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5401 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5402 },
5403 GenerateKeyAlgorithm::Ecdh(algorithm) => {
5404 ecdh_operation::generate_key(cx, global, algorithm, extractable, usages)
5405 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5406 },
5407 GenerateKeyAlgorithm::Ed25519(_algorithm) => {
5408 ed25519_operation::generate_key(cx, global, extractable, usages)
5409 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5410 },
5411 GenerateKeyAlgorithm::X25519(_algorithm) => {
5412 x25519_operation::generate_key(cx, global, extractable, usages)
5413 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5414 },
5415 GenerateKeyAlgorithm::AesCtr(algorithm) => {
5416 aes_ctr_operation::generate_key(cx, global, algorithm, extractable, usages)
5417 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5418 },
5419 GenerateKeyAlgorithm::AesCbc(algorithm) => {
5420 aes_cbc_operation::generate_key(cx, global, algorithm, extractable, usages)
5421 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5422 },
5423 GenerateKeyAlgorithm::AesGcm(algorithm) => {
5424 aes_gcm_operation::generate_key(cx, global, algorithm, extractable, usages)
5425 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5426 },
5427 GenerateKeyAlgorithm::AesKw(algorithm) => {
5428 aes_kw_operation::generate_key(cx, global, algorithm, extractable, usages)
5429 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5430 },
5431 GenerateKeyAlgorithm::Hmac(algorithm) => {
5432 hmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5433 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5434 },
5435 GenerateKeyAlgorithm::MlKem(algorithm) => {
5436 ml_kem_operation::generate_key(cx, global, algorithm, extractable, usages)
5437 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5438 },
5439 GenerateKeyAlgorithm::MlDsa(algorithm) => {
5440 ml_dsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5441 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5442 },
5443 GenerateKeyAlgorithm::AesOcb(algorithm) => {
5444 aes_ocb_operation::generate_key(cx, global, algorithm, extractable, usages)
5445 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5446 },
5447 GenerateKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5448 chacha20_poly1305_operation::generate_key(cx, global, extractable, usages)
5449 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5450 },
5451 }
5452 }
5453}
5454
5455struct ImportKeyOperation {}
5457
5458impl Operation for ImportKeyOperation {
5459 type RegisteredAlgorithm = ImportKeyAlgorithm;
5460}
5461
5462enum ImportKeyAlgorithm {
5465 RsassaPkcs1V1_5(SubtleRsaHashedImportParams),
5466 RsaPss(SubtleRsaHashedImportParams),
5467 RsaOaep(SubtleRsaHashedImportParams),
5468 Ecdsa(SubtleEcKeyImportParams),
5469 Ecdh(SubtleEcKeyImportParams),
5470 Ed25519(SubtleAlgorithm),
5471 X25519(SubtleAlgorithm),
5472 AesCtr(SubtleAlgorithm),
5473 AesCbc(SubtleAlgorithm),
5474 AesGcm(SubtleAlgorithm),
5475 AesKw(SubtleAlgorithm),
5476 Hmac(SubtleHmacImportParams),
5477 Hkdf(SubtleAlgorithm),
5478 Pbkdf2(SubtleAlgorithm),
5479 MlKem(SubtleAlgorithm),
5480 MlDsa(SubtleAlgorithm),
5481 AesOcb(SubtleAlgorithm),
5482 ChaCha20Poly1305(SubtleAlgorithm),
5483 Argon2(SubtleAlgorithm),
5484}
5485
5486impl NormalizedAlgorithm for ImportKeyAlgorithm {
5487 fn from_object(
5488 cx: &mut js::context::JSContext,
5489 algorithm_name: CryptoAlgorithm,
5490 object: HandleObject,
5491 ) -> Fallible<Self> {
5492 match algorithm_name {
5493 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ImportKeyAlgorithm::RsassaPkcs1V1_5(
5494 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5495 )),
5496 CryptoAlgorithm::RsaPss => Ok(ImportKeyAlgorithm::RsaPss(
5497 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5498 )),
5499 CryptoAlgorithm::RsaOaep => Ok(ImportKeyAlgorithm::RsaOaep(
5500 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5501 )),
5502 CryptoAlgorithm::Ecdsa => Ok(ImportKeyAlgorithm::Ecdsa(
5503 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5504 )),
5505 CryptoAlgorithm::Ecdh => Ok(ImportKeyAlgorithm::Ecdh(
5506 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5507 )),
5508 CryptoAlgorithm::Ed25519 => Ok(ImportKeyAlgorithm::Ed25519(
5509 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5510 )),
5511 CryptoAlgorithm::X25519 => Ok(ImportKeyAlgorithm::X25519(
5512 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5513 )),
5514 CryptoAlgorithm::AesCtr => Ok(ImportKeyAlgorithm::AesCtr(
5515 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5516 )),
5517 CryptoAlgorithm::AesCbc => Ok(ImportKeyAlgorithm::AesCbc(
5518 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5519 )),
5520 CryptoAlgorithm::AesGcm => Ok(ImportKeyAlgorithm::AesGcm(
5521 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5522 )),
5523 CryptoAlgorithm::AesKw => Ok(ImportKeyAlgorithm::AesKw(
5524 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5525 )),
5526 CryptoAlgorithm::Hmac => Ok(ImportKeyAlgorithm::Hmac(
5527 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5528 )),
5529 CryptoAlgorithm::Hkdf => Ok(ImportKeyAlgorithm::Hkdf(
5530 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5531 )),
5532 CryptoAlgorithm::Pbkdf2 => Ok(ImportKeyAlgorithm::Pbkdf2(
5533 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5534 )),
5535 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5536 Ok(ImportKeyAlgorithm::MlKem(
5537 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5538 ))
5539 },
5540 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5541 ImportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5542 ),
5543 CryptoAlgorithm::AesOcb => Ok(ImportKeyAlgorithm::AesOcb(
5544 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5545 )),
5546 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ImportKeyAlgorithm::ChaCha20Poly1305(
5547 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5548 )),
5549 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5550 ImportKeyAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5551 ),
5552 _ => Err(Error::NotSupported(Some(format!(
5553 "{} does not support \"importKey\" operation",
5554 algorithm_name.as_str()
5555 )))),
5556 }
5557 }
5558
5559 fn name(&self) -> CryptoAlgorithm {
5560 match self {
5561 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5562 ImportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5563 ImportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5564 ImportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5565 ImportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5566 ImportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5567 ImportKeyAlgorithm::X25519(algorithm) => algorithm.name,
5568 ImportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5569 ImportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5570 ImportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5571 ImportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5572 ImportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5573 ImportKeyAlgorithm::Hkdf(algorithm) => algorithm.name,
5574 ImportKeyAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5575 ImportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5576 ImportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5577 ImportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5578 ImportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5579 ImportKeyAlgorithm::Argon2(algorithm) => algorithm.name,
5580 }
5581 }
5582}
5583
5584impl ImportKeyAlgorithm {
5585 fn import_key(
5586 &self,
5587 cx: &mut js::context::JSContext,
5588 global: &GlobalScope,
5589 format: KeyFormat,
5590 key_data: &[u8],
5591 extractable: bool,
5592 usages: Vec<KeyUsage>,
5593 ) -> Result<DomRoot<CryptoKey>, Error> {
5594 match self {
5595 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5596 rsassa_pkcs1_v1_5_operation::import_key(
5597 cx,
5598 global,
5599 algorithm,
5600 format,
5601 key_data,
5602 extractable,
5603 usages,
5604 )
5605 },
5606 ImportKeyAlgorithm::RsaPss(algorithm) => rsa_pss_operation::import_key(
5607 cx,
5608 global,
5609 algorithm,
5610 format,
5611 key_data,
5612 extractable,
5613 usages,
5614 ),
5615 ImportKeyAlgorithm::RsaOaep(algorithm) => rsa_oaep_operation::import_key(
5616 cx,
5617 global,
5618 algorithm,
5619 format,
5620 key_data,
5621 extractable,
5622 usages,
5623 ),
5624 ImportKeyAlgorithm::Ecdsa(algorithm) => ecdsa_operation::import_key(
5625 cx,
5626 global,
5627 algorithm,
5628 format,
5629 key_data,
5630 extractable,
5631 usages,
5632 ),
5633 ImportKeyAlgorithm::Ecdh(algorithm) => ecdh_operation::import_key(
5634 cx,
5635 global,
5636 algorithm,
5637 format,
5638 key_data,
5639 extractable,
5640 usages,
5641 ),
5642 ImportKeyAlgorithm::Ed25519(_algorithm) => {
5643 ed25519_operation::import_key(cx, global, format, key_data, extractable, usages)
5644 },
5645 ImportKeyAlgorithm::X25519(_algorithm) => {
5646 x25519_operation::import_key(cx, global, format, key_data, extractable, usages)
5647 },
5648 ImportKeyAlgorithm::AesCtr(_algorithm) => {
5649 aes_ctr_operation::import_key(cx, global, format, key_data, extractable, usages)
5650 },
5651 ImportKeyAlgorithm::AesCbc(_algorithm) => {
5652 aes_cbc_operation::import_key(cx, global, format, key_data, extractable, usages)
5653 },
5654 ImportKeyAlgorithm::AesGcm(_algorithm) => {
5655 aes_gcm_operation::import_key(cx, global, format, key_data, extractable, usages)
5656 },
5657 ImportKeyAlgorithm::AesKw(_algorithm) => {
5658 aes_kw_operation::import_key(cx, global, format, key_data, extractable, usages)
5659 },
5660 ImportKeyAlgorithm::Hmac(algorithm) => hmac_operation::import_key(
5661 cx,
5662 global,
5663 algorithm,
5664 format,
5665 key_data,
5666 extractable,
5667 usages,
5668 ),
5669 ImportKeyAlgorithm::Hkdf(_algorithm) => {
5670 hkdf_operation::import_key(cx, global, format, key_data, extractable, usages)
5671 },
5672 ImportKeyAlgorithm::Pbkdf2(_algorithm) => {
5673 pbkdf2_operation::import_key(cx, global, format, key_data, extractable, usages)
5674 },
5675 ImportKeyAlgorithm::MlKem(algorithm) => ml_kem_operation::import_key(
5676 cx,
5677 global,
5678 algorithm,
5679 format,
5680 key_data,
5681 extractable,
5682 usages,
5683 ),
5684 ImportKeyAlgorithm::MlDsa(algorithm) => ml_dsa_operation::import_key(
5685 cx,
5686 global,
5687 algorithm,
5688 format,
5689 key_data,
5690 extractable,
5691 usages,
5692 ),
5693 ImportKeyAlgorithm::AesOcb(_algorithm) => {
5694 aes_ocb_operation::import_key(cx, global, format, key_data, extractable, usages)
5695 },
5696 ImportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5697 chacha20_poly1305_operation::import_key(
5698 cx,
5699 global,
5700 format,
5701 key_data,
5702 extractable,
5703 usages,
5704 )
5705 },
5706 ImportKeyAlgorithm::Argon2(algorithm) => argon2_operation::import_key(
5707 cx,
5708 global,
5709 algorithm,
5710 format,
5711 key_data,
5712 extractable,
5713 usages,
5714 ),
5715 }
5716 }
5717}
5718
5719struct ExportKeyOperation {}
5721
5722impl Operation for ExportKeyOperation {
5723 type RegisteredAlgorithm = ExportKeyAlgorithm;
5724}
5725
5726enum ExportKeyAlgorithm {
5729 RsassaPkcs1V1_5(SubtleAlgorithm),
5730 RsaPss(SubtleAlgorithm),
5731 RsaOaep(SubtleAlgorithm),
5732 Ecdsa(SubtleAlgorithm),
5733 Ecdh(SubtleAlgorithm),
5734 Ed25519(SubtleAlgorithm),
5735 X25519(SubtleAlgorithm),
5736 AesCtr(SubtleAlgorithm),
5737 AesCbc(SubtleAlgorithm),
5738 AesGcm(SubtleAlgorithm),
5739 AesKw(SubtleAlgorithm),
5740 Hmac(SubtleAlgorithm),
5741 MlKem(SubtleAlgorithm),
5742 MlDsa(SubtleAlgorithm),
5743 AesOcb(SubtleAlgorithm),
5744 ChaCha20Poly1305(SubtleAlgorithm),
5745}
5746
5747impl NormalizedAlgorithm for ExportKeyAlgorithm {
5748 fn from_object(
5749 cx: &mut js::context::JSContext,
5750 algorithm_name: CryptoAlgorithm,
5751 object: HandleObject,
5752 ) -> Fallible<Self> {
5753 match algorithm_name {
5754 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ExportKeyAlgorithm::RsassaPkcs1V1_5(
5755 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5756 )),
5757 CryptoAlgorithm::RsaPss => Ok(ExportKeyAlgorithm::RsaPss(
5758 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5759 )),
5760 CryptoAlgorithm::RsaOaep => Ok(ExportKeyAlgorithm::RsaOaep(
5761 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5762 )),
5763 CryptoAlgorithm::Ecdsa => Ok(ExportKeyAlgorithm::Ecdsa(
5764 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5765 )),
5766 CryptoAlgorithm::Ecdh => Ok(ExportKeyAlgorithm::Ecdh(
5767 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5768 )),
5769 CryptoAlgorithm::Ed25519 => Ok(ExportKeyAlgorithm::Ed25519(
5770 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5771 )),
5772 CryptoAlgorithm::X25519 => Ok(ExportKeyAlgorithm::X25519(
5773 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5774 )),
5775 CryptoAlgorithm::AesCtr => Ok(ExportKeyAlgorithm::AesCtr(
5776 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5777 )),
5778 CryptoAlgorithm::AesCbc => Ok(ExportKeyAlgorithm::AesCbc(
5779 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5780 )),
5781 CryptoAlgorithm::AesGcm => Ok(ExportKeyAlgorithm::AesGcm(
5782 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5783 )),
5784 CryptoAlgorithm::AesKw => Ok(ExportKeyAlgorithm::AesKw(
5785 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5786 )),
5787 CryptoAlgorithm::Hmac => Ok(ExportKeyAlgorithm::Hmac(
5788 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5789 )),
5790 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5791 Ok(ExportKeyAlgorithm::MlKem(
5792 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5793 ))
5794 },
5795 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5796 ExportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5797 ),
5798 CryptoAlgorithm::AesOcb => Ok(ExportKeyAlgorithm::AesOcb(
5799 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5800 )),
5801 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ExportKeyAlgorithm::ChaCha20Poly1305(
5802 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5803 )),
5804 _ => Err(Error::NotSupported(Some(format!(
5805 "{} does not support \"exportKey\" operation",
5806 algorithm_name.as_str()
5807 )))),
5808 }
5809 }
5810
5811 fn name(&self) -> CryptoAlgorithm {
5812 match self {
5813 ExportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5814 ExportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5815 ExportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5816 ExportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5817 ExportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5818 ExportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5819 ExportKeyAlgorithm::X25519(algorithm) => algorithm.name,
5820 ExportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5821 ExportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5822 ExportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5823 ExportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5824 ExportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5825 ExportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5826 ExportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5827 ExportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5828 ExportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5829 }
5830 }
5831}
5832
5833impl ExportKeyAlgorithm {
5834 fn export_key(&self, format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
5835 match self {
5836 ExportKeyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5837 rsassa_pkcs1_v1_5_operation::export_key(format, key)
5838 },
5839 ExportKeyAlgorithm::RsaPss(_algorithm) => rsa_pss_operation::export_key(format, key),
5840 ExportKeyAlgorithm::RsaOaep(_algorithm) => rsa_oaep_operation::export_key(format, key),
5841 ExportKeyAlgorithm::Ecdsa(_algorithm) => ecdsa_operation::export_key(format, key),
5842 ExportKeyAlgorithm::Ecdh(_algorithm) => ecdh_operation::export_key(format, key),
5843 ExportKeyAlgorithm::Ed25519(_algorithm) => ed25519_operation::export_key(format, key),
5844 ExportKeyAlgorithm::X25519(_algorithm) => x25519_operation::export_key(format, key),
5845 ExportKeyAlgorithm::AesCtr(_algorithm) => aes_ctr_operation::export_key(format, key),
5846 ExportKeyAlgorithm::AesCbc(_algorithm) => aes_cbc_operation::export_key(format, key),
5847 ExportKeyAlgorithm::AesGcm(_algorithm) => aes_gcm_operation::export_key(format, key),
5848 ExportKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::export_key(format, key),
5849 ExportKeyAlgorithm::Hmac(_algorithm) => hmac_operation::export_key(format, key),
5850 ExportKeyAlgorithm::MlKem(_algorithm) => ml_kem_operation::export_key(format, key),
5851 ExportKeyAlgorithm::MlDsa(_algorithm) => ml_dsa_operation::export_key(format, key),
5852 ExportKeyAlgorithm::AesOcb(_algorithm) => aes_ocb_operation::export_key(format, key),
5853 ExportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5854 chacha20_poly1305_operation::export_key(format, key)
5855 },
5856 }
5857 }
5858}
5859
5860struct GetKeyLengthOperation {}
5862
5863impl Operation for GetKeyLengthOperation {
5864 type RegisteredAlgorithm = GetKeyLengthAlgorithm;
5865}
5866
5867enum GetKeyLengthAlgorithm {
5870 AesCtr(SubtleAesDerivedKeyParams),
5871 AesCbc(SubtleAesDerivedKeyParams),
5872 AesGcm(SubtleAesDerivedKeyParams),
5873 AesKw(SubtleAesDerivedKeyParams),
5874 Hmac(SubtleHmacImportParams),
5875 Hkdf(SubtleAlgorithm),
5876 Pbkdf2(SubtleAlgorithm),
5877 AesOcb(SubtleAesDerivedKeyParams),
5878 ChaCha20Poly1305(SubtleAlgorithm),
5879 Argon2(SubtleAlgorithm),
5880}
5881
5882impl NormalizedAlgorithm for GetKeyLengthAlgorithm {
5883 fn from_object(
5884 cx: &mut js::context::JSContext,
5885 algorithm_name: CryptoAlgorithm,
5886 object: HandleObject,
5887 ) -> Fallible<Self> {
5888 match algorithm_name {
5889 CryptoAlgorithm::AesCtr => Ok(GetKeyLengthAlgorithm::AesCtr(
5890 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5891 )),
5892 CryptoAlgorithm::AesCbc => Ok(GetKeyLengthAlgorithm::AesCbc(
5893 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5894 )),
5895 CryptoAlgorithm::AesGcm => Ok(GetKeyLengthAlgorithm::AesGcm(
5896 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5897 )),
5898 CryptoAlgorithm::AesKw => Ok(GetKeyLengthAlgorithm::AesKw(
5899 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5900 )),
5901 CryptoAlgorithm::Hmac => Ok(GetKeyLengthAlgorithm::Hmac(
5902 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5903 )),
5904 CryptoAlgorithm::Hkdf => Ok(GetKeyLengthAlgorithm::Hkdf(
5905 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5906 )),
5907 CryptoAlgorithm::Pbkdf2 => Ok(GetKeyLengthAlgorithm::Pbkdf2(
5908 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5909 )),
5910 CryptoAlgorithm::AesOcb => Ok(GetKeyLengthAlgorithm::AesOcb(
5911 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5912 )),
5913 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GetKeyLengthAlgorithm::ChaCha20Poly1305(
5914 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5915 )),
5916 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => {
5917 Ok(GetKeyLengthAlgorithm::Argon2(
5918 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5919 ))
5920 },
5921 _ => Err(Error::NotSupported(Some(format!(
5922 "{} does not support \"get key length\" operation",
5923 algorithm_name.as_str()
5924 )))),
5925 }
5926 }
5927
5928 fn name(&self) -> CryptoAlgorithm {
5929 match self {
5930 GetKeyLengthAlgorithm::AesCtr(algorithm) => algorithm.name,
5931 GetKeyLengthAlgorithm::AesCbc(algorithm) => algorithm.name,
5932 GetKeyLengthAlgorithm::AesGcm(algorithm) => algorithm.name,
5933 GetKeyLengthAlgorithm::AesKw(algorithm) => algorithm.name,
5934 GetKeyLengthAlgorithm::Hmac(algorithm) => algorithm.name,
5935 GetKeyLengthAlgorithm::Hkdf(algorithm) => algorithm.name,
5936 GetKeyLengthAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5937 GetKeyLengthAlgorithm::AesOcb(algorithm) => algorithm.name,
5938 GetKeyLengthAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5939 GetKeyLengthAlgorithm::Argon2(algorithm) => algorithm.name,
5940 }
5941 }
5942}
5943
5944impl GetKeyLengthAlgorithm {
5945 fn get_key_length(&self) -> Result<Option<u32>, Error> {
5946 match self {
5947 GetKeyLengthAlgorithm::AesCtr(algorithm) => {
5948 aes_ctr_operation::get_key_length(algorithm)
5949 },
5950 GetKeyLengthAlgorithm::AesCbc(algorithm) => {
5951 aes_cbc_operation::get_key_length(algorithm)
5952 },
5953 GetKeyLengthAlgorithm::AesGcm(algorithm) => {
5954 aes_gcm_operation::get_key_length(algorithm)
5955 },
5956 GetKeyLengthAlgorithm::AesKw(algorithm) => aes_kw_operation::get_key_length(algorithm),
5957 GetKeyLengthAlgorithm::Hmac(algorithm) => hmac_operation::get_key_length(algorithm),
5958 GetKeyLengthAlgorithm::Hkdf(_algorithm) => hkdf_operation::get_key_length(),
5959 GetKeyLengthAlgorithm::Pbkdf2(_algorithm) => pbkdf2_operation::get_key_length(),
5960 GetKeyLengthAlgorithm::AesOcb(algorithm) => {
5961 aes_ocb_operation::get_key_length(algorithm)
5962 },
5963 GetKeyLengthAlgorithm::ChaCha20Poly1305(_algorithm) => {
5964 chacha20_poly1305_operation::get_key_length()
5965 },
5966 GetKeyLengthAlgorithm::Argon2(_algorithm) => argon2_operation::get_key_length(),
5967 }
5968 }
5969}
5970
5971struct EncapsulateOperation {}
5973
5974impl Operation for EncapsulateOperation {
5975 type RegisteredAlgorithm = EncapsulateAlgorithm;
5976}
5977
5978enum EncapsulateAlgorithm {
5981 MlKem(SubtleAlgorithm),
5982}
5983
5984impl NormalizedAlgorithm for EncapsulateAlgorithm {
5985 fn from_object(
5986 cx: &mut js::context::JSContext,
5987 algorithm_name: CryptoAlgorithm,
5988 object: HandleObject,
5989 ) -> Fallible<Self> {
5990 match algorithm_name {
5991 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5992 Ok(EncapsulateAlgorithm::MlKem(
5993 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5994 ))
5995 },
5996 _ => Err(Error::NotSupported(Some(format!(
5997 "{} does not support \"encapsulate\" operation",
5998 algorithm_name.as_str()
5999 )))),
6000 }
6001 }
6002
6003 fn name(&self) -> CryptoAlgorithm {
6004 match self {
6005 EncapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
6006 }
6007 }
6008}
6009
6010impl EncapsulateAlgorithm {
6011 fn encapsulate(&self, key: &CryptoKey) -> Result<SubtleEncapsulatedBits, Error> {
6012 match self {
6013 EncapsulateAlgorithm::MlKem(algorithm) => ml_kem_operation::encapsulate(algorithm, key),
6014 }
6015 }
6016}
6017
6018struct DecapsulateOperation {}
6020
6021impl Operation for DecapsulateOperation {
6022 type RegisteredAlgorithm = DecapsulateAlgorithm;
6023}
6024
6025enum DecapsulateAlgorithm {
6028 MlKem(SubtleAlgorithm),
6029}
6030
6031impl NormalizedAlgorithm for DecapsulateAlgorithm {
6032 fn from_object(
6033 cx: &mut js::context::JSContext,
6034 algorithm_name: CryptoAlgorithm,
6035 object: HandleObject,
6036 ) -> Fallible<Self> {
6037 match algorithm_name {
6038 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6039 Ok(DecapsulateAlgorithm::MlKem(
6040 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6041 ))
6042 },
6043 _ => Err(Error::NotSupported(Some(format!(
6044 "{} does not support \"decapsulate\" operation",
6045 algorithm_name.as_str()
6046 )))),
6047 }
6048 }
6049
6050 fn name(&self) -> CryptoAlgorithm {
6051 match self {
6052 DecapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
6053 }
6054 }
6055}
6056
6057impl DecapsulateAlgorithm {
6058 fn decapsulate(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
6059 match self {
6060 DecapsulateAlgorithm::MlKem(algorithm) => {
6061 ml_kem_operation::decapsulate(algorithm, key, ciphertext)
6062 },
6063 }
6064 }
6065}
6066
6067struct GetPublicKeyOperation {}
6069
6070impl Operation for GetPublicKeyOperation {
6071 type RegisteredAlgorithm = GetPublicKeyAlgorithm;
6072}
6073
6074enum GetPublicKeyAlgorithm {
6077 RsassaPkcs1v1_5(SubtleAlgorithm),
6078 RsaPss(SubtleAlgorithm),
6079 RsaOaep(SubtleAlgorithm),
6080 Ecdsa(SubtleAlgorithm),
6081 Ecdh(SubtleAlgorithm),
6082 Ed25519(SubtleAlgorithm),
6083 X25519(SubtleAlgorithm),
6084 MlKem(SubtleAlgorithm),
6085 MlDsa(SubtleAlgorithm),
6086}
6087
6088impl NormalizedAlgorithm for GetPublicKeyAlgorithm {
6089 fn from_object(
6090 cx: &mut js::context::JSContext,
6091 algorithm_name: CryptoAlgorithm,
6092 object: HandleObject,
6093 ) -> Fallible<Self> {
6094 match algorithm_name {
6095 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GetPublicKeyAlgorithm::RsassaPkcs1v1_5(
6096 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6097 )),
6098 CryptoAlgorithm::RsaPss => Ok(GetPublicKeyAlgorithm::RsaPss(
6099 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6100 )),
6101 CryptoAlgorithm::RsaOaep => Ok(GetPublicKeyAlgorithm::RsaOaep(
6102 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6103 )),
6104 CryptoAlgorithm::Ecdsa => Ok(GetPublicKeyAlgorithm::Ecdsa(
6105 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6106 )),
6107 CryptoAlgorithm::Ecdh => Ok(GetPublicKeyAlgorithm::Ecdh(
6108 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6109 )),
6110 CryptoAlgorithm::Ed25519 => Ok(GetPublicKeyAlgorithm::Ed25519(
6111 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6112 )),
6113 CryptoAlgorithm::X25519 => Ok(GetPublicKeyAlgorithm::X25519(
6114 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6115 )),
6116 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6117 Ok(GetPublicKeyAlgorithm::MlKem(
6118 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6119 ))
6120 },
6121 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6122 GetPublicKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6123 ),
6124 _ => Err(Error::NotSupported(Some(format!(
6125 "{} does not support \"getPublicKey\" operation",
6126 algorithm_name.as_str()
6127 )))),
6128 }
6129 }
6130
6131 fn name(&self) -> CryptoAlgorithm {
6132 match self {
6133 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(algorithm) => algorithm.name,
6134 GetPublicKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6135 GetPublicKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6136 GetPublicKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6137 GetPublicKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6138 GetPublicKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6139 GetPublicKeyAlgorithm::X25519(algorithm) => algorithm.name,
6140 GetPublicKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6141 GetPublicKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6142 }
6143 }
6144}
6145
6146impl GetPublicKeyAlgorithm {
6147 fn get_public_key(
6148 &self,
6149 cx: &mut js::context::JSContext,
6150 global: &GlobalScope,
6151 key: &CryptoKey,
6152 algorithm: &KeyAlgorithmAndDerivatives,
6153 usages: Vec<KeyUsage>,
6154 ) -> Result<DomRoot<CryptoKey>, Error> {
6155 match self {
6156 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(_algorithm) => {
6157 rsassa_pkcs1_v1_5_operation::get_public_key(cx, global, key, algorithm, usages)
6158 },
6159 GetPublicKeyAlgorithm::RsaPss(_algorithm) => {
6160 rsa_pss_operation::get_public_key(cx, global, key, algorithm, usages)
6161 },
6162 GetPublicKeyAlgorithm::RsaOaep(_algorithm) => {
6163 rsa_oaep_operation::get_public_key(cx, global, key, algorithm, usages)
6164 },
6165 GetPublicKeyAlgorithm::Ecdsa(_algorithm) => {
6166 ecdsa_operation::get_public_key(cx, global, key, algorithm, usages)
6167 },
6168 GetPublicKeyAlgorithm::Ecdh(_algorithm) => {
6169 ecdh_operation::get_public_key(cx, global, key, algorithm, usages)
6170 },
6171 GetPublicKeyAlgorithm::Ed25519(_algorithm) => {
6172 ed25519_operation::get_public_key(cx, global, key, algorithm, usages)
6173 },
6174 GetPublicKeyAlgorithm::X25519(_algorithm) => {
6175 x25519_operation::get_public_key(cx, global, key, algorithm, usages)
6176 },
6177 GetPublicKeyAlgorithm::MlKem(_algorithm) => {
6178 ml_kem_operation::get_public_key(cx, global, key, algorithm, usages)
6179 },
6180 GetPublicKeyAlgorithm::MlDsa(_algorithm) => {
6181 ml_dsa_operation::get_public_key(cx, global, key, algorithm, usages)
6182 },
6183 }
6184 }
6185}