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 ml_dsa_operation;
21mod ml_kem_operation;
22mod pbkdf2_operation;
23mod rsa_common;
24mod rsa_oaep_operation;
25mod rsa_pss_operation;
26mod rsassa_pkcs1_v1_5_operation;
27mod sha3_operation;
28mod sha_operation;
29mod turboshake_operation;
30mod x25519_operation;
31
32use std::fmt::Display;
33use std::ptr;
34use std::rc::Rc;
35use std::str::FromStr;
36
37use base64ct::{Base64UrlUnpadded, Encoding};
38use dom_struct::dom_struct;
39use js::conversions::{ConversionBehavior, ConversionResult, FromJSValConvertible};
40use js::jsapi::{Heap, JSObject};
41use js::jsval::UndefinedValue;
42use js::realm::CurrentRealm;
43use js::rust::wrappers2::JS_ParseJSON;
44use js::rust::{HandleObject, MutableHandleValue, Trace};
45use js::typedarray::{ArrayBufferU8, HeapUint8Array};
46use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
47use servo_constellation_traits::{
48 SerializableAesKeyAlgorithm, SerializableAlgorithm, SerializableCShakeParams,
49 SerializableDigestAlgorithm, SerializableEcKeyAlgorithm, SerializableHmacKeyAlgorithm,
50 SerializableKeyAlgorithm, SerializableKeyAlgorithmAndDerivatives,
51 SerializableRsaHashedKeyAlgorithm, SerializableTurboShakeParams,
52};
53use strum::{EnumString, IntoStaticStr, VariantArray};
54use zeroize::Zeroizing;
55
56use crate::dom::bindings::buffer_source::create_buffer_source;
57use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
58 CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
59};
60use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
61 AesKeyAlgorithm, Algorithm, AlgorithmIdentifier, EcKeyAlgorithm, EncapsulatedBits,
62 EncapsulatedKey, HmacKeyAlgorithm, JsonWebKey, KeyAlgorithm, KeyFormat, RsaHashedKeyAlgorithm,
63 RsaKeyAlgorithm, SubtleCryptoMethods,
64};
65use crate::dom::bindings::codegen::UnionTypes::{
66 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey, ObjectOrString,
67};
68use crate::dom::bindings::conversions::{
69 SafeToJSValConvertible, StringificationBehavior, get_property,
70};
71use crate::dom::bindings::error::{Error, Fallible};
72use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
73use crate::dom::bindings::reflector::DomGlobal;
74use crate::dom::bindings::root::DomRoot;
75use crate::dom::bindings::str::{DOMString, serialize_jsval_to_json_utf8};
76use crate::dom::bindings::trace::RootedTraceableBox;
77use crate::dom::cryptokey::{CryptoKey, CryptoKeyOrCryptoKeyPair};
78use crate::dom::globalscope::GlobalScope;
79use crate::dom::promise::Promise;
80use crate::script_runtime::{CanGc, JSContext};
81
82const NAMED_CURVE_P256: &str = "P-256";
84const NAMED_CURVE_P384: &str = "P-384";
85const NAMED_CURVE_P521: &str = "P-521";
86
87static SUPPORTED_CURVES: &[&str] = &[NAMED_CURVE_P256, NAMED_CURVE_P384, NAMED_CURVE_P521];
88
89#[derive(EnumString, VariantArray, IntoStaticStr, PartialEq, Clone, Copy, MallocSizeOf)]
90enum CryptoAlgorithm {
91 #[strum(serialize = "RSASSA-PKCS1-v1_5")]
92 RsassaPkcs1V1_5,
93 #[strum(serialize = "RSA-PSS")]
94 RsaPss,
95 #[strum(serialize = "RSA-OAEP")]
96 RsaOaep,
97 #[strum(serialize = "ECDSA")]
98 Ecdsa,
99 #[strum(serialize = "ECDH")]
100 Ecdh,
101 #[strum(serialize = "Ed25519")]
102 Ed25519,
103 #[strum(serialize = "X25519")]
104 X25519,
105 #[strum(serialize = "AES-CTR")]
106 AesCtr,
107 #[strum(serialize = "AES-CBC")]
108 AesCbc,
109 #[strum(serialize = "AES-GCM")]
110 AesGcm,
111 #[strum(serialize = "AES-KW")]
112 AesKw,
113 #[strum(serialize = "HMAC")]
114 Hmac,
115 #[strum(serialize = "SHA-1")]
116 Sha1,
117 #[strum(serialize = "SHA-256")]
118 Sha256,
119 #[strum(serialize = "SHA-384")]
120 Sha384,
121 #[strum(serialize = "SHA-512")]
122 Sha512,
123 #[strum(serialize = "HKDF")]
124 Hkdf,
125 #[strum(serialize = "PBKDF2")]
126 Pbkdf2,
127 #[strum(serialize = "ML-KEM-512")]
128 MlKem512,
129 #[strum(serialize = "ML-KEM-768")]
130 MlKem768,
131 #[strum(serialize = "ML-KEM-1024")]
132 MlKem1024,
133 #[strum(serialize = "ML-DSA-44")]
134 MlDsa44,
135 #[strum(serialize = "ML-DSA-65")]
136 MlDsa65,
137 #[strum(serialize = "ML-DSA-87")]
138 MlDsa87,
139 #[strum(serialize = "AES-OCB")]
140 AesOcb,
141 #[strum(serialize = "ChaCha20-Poly1305")]
142 ChaCha20Poly1305,
143 #[strum(serialize = "SHA3-256")]
144 Sha3_256,
145 #[strum(serialize = "SHA3-384")]
146 Sha3_384,
147 #[strum(serialize = "SHA3-512")]
148 Sha3_512,
149 #[strum(serialize = "cSHAKE128")]
150 CShake128,
151 #[strum(serialize = "cSHAKE256")]
152 CShake256,
153 #[strum(serialize = "TurboSHAKE128")]
154 TurboShake128,
155 #[strum(serialize = "TurboSHAKE256")]
156 TurboShake256,
157 #[strum(serialize = "Argon2d")]
158 Argon2D,
159 #[strum(serialize = "Argon2i")]
160 Argon2I,
161 #[strum(serialize = "Argon2id")]
162 Argon2ID,
163}
164
165impl CryptoAlgorithm {
166 fn as_str(&self) -> &'static str {
168 (*self).into()
169 }
170
171 fn from_str_ignore_case(algorithm_name: &str) -> Fallible<CryptoAlgorithm> {
172 Self::VARIANTS
173 .iter()
174 .find(|algorithm| algorithm.as_str().eq_ignore_ascii_case(algorithm_name))
175 .cloned()
176 .ok_or(Error::NotSupported(Some(format!(
177 "Unsupported algorithm: {algorithm_name}"
178 ))))
179 }
180}
181
182#[dom_struct]
183pub(crate) struct SubtleCrypto {
184 reflector_: Reflector,
185}
186
187impl SubtleCrypto {
188 fn new_inherited() -> SubtleCrypto {
189 SubtleCrypto {
190 reflector_: Reflector::new(),
191 }
192 }
193
194 pub(crate) fn new(
195 cx: &mut js::context::JSContext,
196 global: &GlobalScope,
197 ) -> DomRoot<SubtleCrypto> {
198 reflect_dom_object_with_cx(Box::new(SubtleCrypto::new_inherited()), global, cx)
199 }
200
201 fn resolve_promise_with_data(&self, promise: Rc<Promise>, data: Zeroizing<Vec<u8>>) {
205 let trusted_promise = TrustedPromise::new(promise);
206 self.global()
207 .task_manager()
208 .crypto_task_source()
209 .queue(task!(resolve_data: move |cx| {
210 let promise = trusted_promise.root();
211
212 rooted!(&in(cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
213 match create_buffer_source::<ArrayBufferU8>(
214 cx.into(),
215 &data,
216 array_buffer_ptr.handle_mut(),
217 CanGc::from_cx(cx),
218 ) {
219 Ok(_) => promise.resolve_native_with_cx(cx, &*array_buffer_ptr),
220 Err(_) => promise.reject_error_with_cx(cx, Error::JSFailed),
221 }
222 }));
223 }
224
225 fn resolve_promise_with_jwk(
229 &self,
230 cx: &mut js::context::JSContext,
231 promise: Rc<Promise>,
232 jwk: Box<JsonWebKey>,
233 ) {
234 let stringified_jwk = match jwk.stringify(cx) {
237 Ok(stringified_jwk) => Zeroizing::new(stringified_jwk.to_string()),
238 Err(error) => {
239 self.reject_promise_with_error(promise, error);
240 return;
241 },
242 };
243
244 let trusted_subtle = Trusted::new(self);
245 let trusted_promise = TrustedPromise::new(promise);
246 self.global()
247 .task_manager()
248 .crypto_task_source()
249 .queue(task!(resolve_jwk: move |cx| {
250 let subtle = trusted_subtle.root();
251 let promise = trusted_promise.root();
252
253 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
254 Ok(jwk) => {
255 rooted!(&in(cx) let mut rval = UndefinedValue());
256 jwk.safe_to_jsval(cx.into(), rval.handle_mut(), CanGc::from_cx(cx));
257 rooted!(&in(cx) let mut object = rval.to_object());
258 promise.resolve_native_with_cx(cx, &*object);
259 },
260 Err(error) => {
261 subtle.reject_promise_with_error(promise, error);
262 return;
263 },
264 }
265 }));
266 }
267
268 fn resolve_promise_with_key(&self, promise: Rc<Promise>, key: DomRoot<CryptoKey>) {
271 let trusted_key = Trusted::new(&*key);
272 let trusted_promise = TrustedPromise::new(promise);
273 self.global()
274 .task_manager()
275 .crypto_task_source()
276 .queue(task!(resolve_key: move |cx| {
277 let key = trusted_key.root();
278 let promise = trusted_promise.root();
279 promise.resolve_native_with_cx(cx, &key);
280 }));
281 }
282
283 fn resolve_promise_with_key_pair(&self, promise: Rc<Promise>, key_pair: CryptoKeyPair) {
286 let trusted_private_key = key_pair.privateKey.map(|key| Trusted::new(&*key));
287 let trusted_public_key = key_pair.publicKey.map(|key| Trusted::new(&*key));
288 let trusted_promise = TrustedPromise::new(promise);
289 self.global()
290 .task_manager()
291 .crypto_task_source()
292 .queue(task!(resolve_key: move |cx| {
293 let key_pair = CryptoKeyPair {
294 privateKey: trusted_private_key.map(|trusted_key| trusted_key.root()),
295 publicKey: trusted_public_key.map(|trusted_key| trusted_key.root()),
296 };
297 let promise = trusted_promise.root();
298 promise.resolve_native_with_cx(cx, &key_pair);
299 }));
300 }
301
302 fn resolve_promise_with_bool(&self, promise: Rc<Promise>, result: bool) {
305 let trusted_promise = TrustedPromise::new(promise);
306 self.global()
307 .task_manager()
308 .crypto_task_source()
309 .queue(task!(resolve_bool: move |cx| {
310 let promise = trusted_promise.root();
311 promise.resolve_native_with_cx(cx, &result);
312 }));
313 }
314
315 fn reject_promise_with_error(&self, promise: Rc<Promise>, error: Error) {
318 let trusted_promise = TrustedPromise::new(promise);
319 self.global()
320 .task_manager()
321 .crypto_task_source()
322 .queue(task!(reject_error: move |cx| {
323 let promise = trusted_promise.root();
324 promise.reject_error_with_cx(cx, error);
325 }));
326 }
327
328 fn resolve_promise_with_encapsulated_key(
332 &self,
333 promise: Rc<Promise>,
334 encapsulated_key: SubtleEncapsulatedKey,
335 ) {
336 let trusted_promise = TrustedPromise::new(promise);
337 self.global().task_manager().crypto_task_source().queue(
338 task!(resolve_encapsulated_key: move |cx| {
339 let promise = trusted_promise.root();
340 promise.resolve_native_with_cx(cx, &encapsulated_key);
341 }),
342 );
343 }
344
345 fn resolve_promise_with_encapsulated_bits(
349 &self,
350 promise: Rc<Promise>,
351 encapsulated_bits: SubtleEncapsulatedBits,
352 ) {
353 let trusted_promise = TrustedPromise::new(promise);
354 self.global().task_manager().crypto_task_source().queue(
355 task!(resolve_encapsulated_bits: move |cx| {
356 let promise = trusted_promise.root();
357 promise.resolve_native_with_cx(cx, &encapsulated_bits);
358 }),
359 );
360 }
361}
362
363impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
364 fn Encrypt(
366 &self,
367 cx: &mut CurrentRealm,
368 algorithm: AlgorithmIdentifier,
369 key: &CryptoKey,
370 data: ArrayBufferViewOrArrayBuffer,
371 ) -> Rc<Promise> {
372 let normalized_algorithm = match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
380 Ok(normalized_algorithm) => normalized_algorithm,
381 Err(error) => {
382 let promise = Promise::new_in_realm(cx);
383 promise.reject_error_with_cx(cx, error);
384 return promise;
385 },
386 };
387
388 let data = match data {
391 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => Zeroizing::new(view.to_vec()),
392 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => Zeroizing::new(buffer.to_vec()),
393 };
394
395 let promise = Promise::new_in_realm(cx);
398
399 let this = Trusted::new(self);
401 let trusted_promise = TrustedPromise::new(promise.clone());
402 let trusted_key = Trusted::new(key);
403 self.global()
404 .task_manager()
405 .dom_manipulation_task_source()
406 .queue(task!(encrypt: move || {
407 let subtle = this.root();
408 let promise = trusted_promise.root();
409 let key = trusted_key.root();
410
411 if normalized_algorithm.name() != key.algorithm().name() {
419 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
420 return;
421 }
422
423 if !key.usages().contains(&KeyUsage::Encrypt) {
426 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
427 return;
428 }
429
430 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
434 Ok(ciphertext) => ciphertext,
435 Err(error) => {
436 subtle.reject_promise_with_error(promise, error);
437 return;
438 },
439 };
440
441 subtle.resolve_promise_with_data(promise, ciphertext.into());
447 }));
448 promise
449 }
450
451 fn Decrypt(
453 &self,
454 cx: &mut CurrentRealm,
455 algorithm: AlgorithmIdentifier,
456 key: &CryptoKey,
457 data: ArrayBufferViewOrArrayBuffer,
458 ) -> Rc<Promise> {
459 let normalized_algorithm = match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
467 Ok(normalized_algorithm) => normalized_algorithm,
468 Err(error) => {
469 let promise = Promise::new_in_realm(cx);
470 promise.reject_error_with_cx(cx, error);
471 return promise;
472 },
473 };
474
475 let data = match data {
478 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
479 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
480 };
481
482 let promise = Promise::new_in_realm(cx);
485
486 let this = Trusted::new(self);
488 let trusted_promise = TrustedPromise::new(promise.clone());
489 let trusted_key = Trusted::new(key);
490 self.global()
491 .task_manager()
492 .dom_manipulation_task_source()
493 .queue(task!(decrypt: move || {
494 let subtle = this.root();
495 let promise = trusted_promise.root();
496 let key = trusted_key.root();
497
498 if normalized_algorithm.name() != key.algorithm().name() {
506 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
507 return;
508 }
509
510 if !key.usages().contains(&KeyUsage::Decrypt) {
513 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
514 return;
515 }
516
517 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
521 Ok(plaintext) => Zeroizing::new(plaintext),
522 Err(error) => {
523 subtle.reject_promise_with_error(promise, error);
524 return;
525 },
526 };
527
528 subtle.resolve_promise_with_data(promise, plaintext);
534 }));
535 promise
536 }
537
538 fn Sign(
540 &self,
541 cx: &mut CurrentRealm,
542 algorithm: AlgorithmIdentifier,
543 key: &CryptoKey,
544 data: ArrayBufferViewOrArrayBuffer,
545 ) -> Rc<Promise> {
546 let normalized_algorithm = match normalize_algorithm::<SignOperation>(cx, &algorithm) {
554 Ok(normalized_algorithm) => normalized_algorithm,
555 Err(error) => {
556 let promise = Promise::new_in_realm(cx);
557 promise.reject_error_with_cx(cx, error);
558 return promise;
559 },
560 };
561
562 let data = match &data {
565 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
566 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
567 };
568
569 let promise = Promise::new_in_realm(cx);
572
573 let this = Trusted::new(self);
575 let trusted_promise = TrustedPromise::new(promise.clone());
576 let trusted_key = Trusted::new(key);
577 self.global()
578 .task_manager()
579 .dom_manipulation_task_source()
580 .queue(task!(sign: move || {
581 let subtle = this.root();
582 let promise = trusted_promise.root();
583 let key = trusted_key.root();
584
585 if normalized_algorithm.name() != key.algorithm().name() {
593 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
594 return;
595 }
596
597 if !key.usages().contains(&KeyUsage::Sign) {
600 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
601 return;
602 }
603
604 let signature = match normalized_algorithm.sign(&key, &data) {
607 Ok(signature) => signature,
608 Err(error) => {
609 subtle.reject_promise_with_error(promise, error);
610 return;
611 },
612 };
613
614 subtle.resolve_promise_with_data(promise, signature.into());
620 }));
621 promise
622 }
623
624 fn Verify(
626 &self,
627 cx: &mut CurrentRealm,
628 algorithm: AlgorithmIdentifier,
629 key: &CryptoKey,
630 signature: ArrayBufferViewOrArrayBuffer,
631 data: ArrayBufferViewOrArrayBuffer,
632 ) -> Rc<Promise> {
633 let normalized_algorithm = match normalize_algorithm::<VerifyOperation>(cx, &algorithm) {
641 Ok(algorithm) => algorithm,
642 Err(error) => {
643 let promise = Promise::new_in_realm(cx);
644 promise.reject_error_with_cx(cx, error);
645 return promise;
646 },
647 };
648
649 let signature = match &signature {
652 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
653 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
654 };
655
656 let data = match &data {
659 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
660 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
661 };
662
663 let promise = Promise::new_in_realm(cx);
666
667 let this = Trusted::new(self);
669 let trusted_promise = TrustedPromise::new(promise.clone());
670 let trusted_key = Trusted::new(key);
671 self.global()
672 .task_manager()
673 .dom_manipulation_task_source()
674 .queue(task!(sign: move || {
675 let subtle = this.root();
676 let promise = trusted_promise.root();
677 let key = trusted_key.root();
678
679 if normalized_algorithm.name() != key.algorithm().name() {
687 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
688 return;
689 }
690
691 if !key.usages().contains(&KeyUsage::Verify) {
694 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
695 return;
696 }
697
698 let result = match normalized_algorithm.verify(&key, &data, &signature) {
702 Ok(result) => result,
703 Err(error) => {
704 subtle.reject_promise_with_error(promise, error);
705 return;
706 },
707 };
708
709 subtle.resolve_promise_with_bool(promise, result);
713 }));
714 promise
715 }
716
717 fn Digest(
719 &self,
720 cx: &mut CurrentRealm,
721 algorithm: AlgorithmIdentifier,
722 data: ArrayBufferViewOrArrayBuffer,
723 ) -> Rc<Promise> {
724 let normalized_algorithm = match normalize_algorithm::<DigestOperation>(cx, &algorithm) {
731 Ok(normalized_algorithm) => normalized_algorithm,
732 Err(error) => {
733 let promise = Promise::new_in_realm(cx);
734 promise.reject_error_with_cx(cx, error);
735 return promise;
736 },
737 };
738
739 let data = match data {
742 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
743 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
744 };
745
746 let promise = Promise::new_in_realm(cx);
749
750 let this = Trusted::new(self);
752 let trusted_promise = TrustedPromise::new(promise.clone());
753 self.global()
754 .task_manager()
755 .dom_manipulation_task_source()
756 .queue(task!(digest_: move || {
757 let subtle = this.root();
758 let promise = trusted_promise.root();
759
760 let digest = match normalized_algorithm.digest(&data) {
767 Ok(digest) => digest,
768 Err(error) => {
769 subtle.reject_promise_with_error(promise, error);
770 return;
771 }
772 };
773
774 subtle.resolve_promise_with_data(promise, digest.into());
780 }));
781 promise
782 }
783
784 fn GenerateKey(
786 &self,
787 cx: &mut CurrentRealm,
788 algorithm: AlgorithmIdentifier,
789 extractable: bool,
790 key_usages: Vec<KeyUsage>,
791 ) -> Rc<Promise> {
792 let promise = Promise::new_in_realm(cx);
799 let normalized_algorithm = match normalize_algorithm::<GenerateKeyOperation>(cx, &algorithm)
800 {
801 Ok(normalized_algorithm) => normalized_algorithm,
802 Err(error) => {
803 promise.reject_error_with_cx(cx, error);
804 return promise;
805 },
806 };
807
808 let trusted_subtle = Trusted::new(self);
814 let trusted_promise = TrustedPromise::new(promise.clone());
815 self.global()
816 .task_manager()
817 .dom_manipulation_task_source()
818 .queue(task!(generate_key: move |cx| {
819 let subtle = trusted_subtle.root();
820 let promise = trusted_promise.root();
821
822 let result = match normalized_algorithm.generate_key(
829 cx,
830 &subtle.global(),
831 extractable,
832 key_usages,
833 ) {
834 Ok(result) => result,
835 Err(error) => {
836 subtle.reject_promise_with_error(promise, error);
837 return;
838 }
839 };
840
841 match &result {
849 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
850 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
851 && crpyto_key.usages().is_empty()
852 {
853 subtle.reject_promise_with_error(promise, Error::Syntax(None));
854 return;
855 }
856 },
857 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(crypto_key_pair) => {
858 if crypto_key_pair
859 .privateKey
860 .as_ref()
861 .is_none_or(|private_key| private_key.usages().is_empty())
862 {
863 subtle.reject_promise_with_error(promise, Error::Syntax(None));
864 return;
865 }
866 }
867 };
868
869 match result {
875 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
876 subtle.resolve_promise_with_key(promise, key);
877 },
878 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(key_pair) => {
879 subtle.resolve_promise_with_key_pair(promise, key_pair);
880 },
881 }
882 }));
883
884 promise
885 }
886
887 fn DeriveKey(
889 &self,
890 cx: &mut CurrentRealm,
891 algorithm: AlgorithmIdentifier,
892 base_key: &CryptoKey,
893 derived_key_type: AlgorithmIdentifier,
894 extractable: bool,
895 usages: Vec<KeyUsage>,
896 ) -> Rc<Promise> {
897 let promise = Promise::new_in_realm(cx);
906 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
907 {
908 Ok(normalized_algorithm) => normalized_algorithm,
909 Err(error) => {
910 promise.reject_error_with_cx(cx, error);
911 return promise;
912 },
913 };
914
915 let normalized_derived_key_algorithm_import =
920 match normalize_algorithm::<ImportKeyOperation>(cx, &derived_key_type) {
921 Ok(normalized_algorithm) => normalized_algorithm,
922 Err(error) => {
923 promise.reject_error_with_cx(cx, error);
924 return promise;
925 },
926 };
927
928 let normalized_derived_key_algorithm_length =
933 match normalize_algorithm::<GetKeyLengthOperation>(cx, &derived_key_type) {
934 Ok(normalized_algorithm) => normalized_algorithm,
935 Err(error) => {
936 promise.reject_error_with_cx(cx, error);
937 return promise;
938 },
939 };
940
941 let trusted_subtle = Trusted::new(self);
947 let trusted_base_key = Trusted::new(base_key);
948 let trusted_promise = TrustedPromise::new(promise.clone());
949 self.global().task_manager().dom_manipulation_task_source().queue(
950 task!(derive_key: move |cx| {
951 let subtle = trusted_subtle.root();
952 let base_key = trusted_base_key.root();
953 let promise = trusted_promise.root();
954
955 if normalized_algorithm.name() != base_key.algorithm().name() {
963 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
964 return;
965 }
966
967 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
970 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
971 return;
972 }
973
974 let length = match normalized_derived_key_algorithm_length.get_key_length() {
977 Ok(length) => length,
978 Err(error) => {
979 subtle.reject_promise_with_error(promise, error);
980 return;
981 }
982 };
983
984 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
987 Ok(secret) => Zeroizing::new(secret),
988 Err(error) => {
989 subtle.reject_promise_with_error(promise, error);
990 return;
991 }
992 };
993
994 let result = match normalized_derived_key_algorithm_import.import_key(
1000 cx,
1001 &subtle.global(),
1002 KeyFormat::Raw_secret,
1003 &secret,
1004 extractable,
1005 usages.clone(),
1006 ) {
1007 Ok(algorithm) => algorithm,
1008 Err(error) => {
1009 subtle.reject_promise_with_error(promise, error);
1010 return;
1011 },
1012 };
1013
1014 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1017 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1018 return;
1019 }
1020
1021 subtle.resolve_promise_with_key(promise, result);
1032 }),
1033 );
1034 promise
1035 }
1036
1037 fn DeriveBits(
1039 &self,
1040 cx: &mut CurrentRealm,
1041 algorithm: AlgorithmIdentifier,
1042 base_key: &CryptoKey,
1043 length: Option<u32>,
1044 ) -> Rc<Promise> {
1045 let promise = Promise::new_in_realm(cx);
1053 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
1054 {
1055 Ok(normalized_algorithm) => normalized_algorithm,
1056 Err(error) => {
1057 promise.reject_error_with_cx(cx, error);
1058 return promise;
1059 },
1060 };
1061
1062 let trsuted_subtle = Trusted::new(self);
1068 let trusted_base_key = Trusted::new(base_key);
1069 let trusted_promise = TrustedPromise::new(promise.clone());
1070 self.global()
1071 .task_manager()
1072 .dom_manipulation_task_source()
1073 .queue(task!(import_key: move || {
1074 let subtle = trsuted_subtle.root();
1075 let base_key = trusted_base_key.root();
1076 let promise = trusted_promise.root();
1077
1078 if normalized_algorithm.name() != base_key.algorithm().name() {
1086 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1087 return;
1088 }
1089
1090 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
1093 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1094 return;
1095 }
1096
1097 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
1100 Ok(bits) => Zeroizing::new(bits),
1101 Err(error) => {
1102 subtle.reject_promise_with_error(promise, error);
1103 return;
1104 }
1105 };
1106
1107 subtle.resolve_promise_with_data(promise, bits);
1113 }));
1114 promise
1115 }
1116
1117 fn ImportKey(
1119 &self,
1120 cx: &mut CurrentRealm,
1121 format: KeyFormat,
1122 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
1123 algorithm: AlgorithmIdentifier,
1124 extractable: bool,
1125 key_usages: Vec<KeyUsage>,
1126 ) -> Rc<Promise> {
1127 let normalized_algorithm = match normalize_algorithm::<ImportKeyOperation>(cx, &algorithm) {
1134 Ok(algorithm) => algorithm,
1135 Err(error) => {
1136 let promise = Promise::new_in_realm(cx);
1137 promise.reject_error_with_cx(cx, error);
1138 return promise;
1139 },
1140 };
1141
1142 let key_data = match format {
1144 KeyFormat::Jwk => {
1146 match key_data {
1147 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1148 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1149 let promise = Promise::new_in_realm(cx);
1152 promise.reject_error_with_cx(
1153 cx,
1154 Error::Type(c"The keyData type does not match the format".to_owned()),
1155 );
1156 return promise;
1157 },
1158
1159 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1160 match jwk.stringify(cx) {
1168 Ok(stringified) => Zeroizing::new(stringified.as_bytes().to_vec()),
1169 Err(error) => {
1170 let promise = Promise::new_in_realm(cx);
1171 promise.reject_error_with_cx(cx, error);
1172 return promise;
1173 },
1174 }
1175 },
1176 }
1177 },
1178 _ => {
1180 match key_data {
1181 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1184 let promise = Promise::new_in_realm(cx);
1185 promise.reject_error_with_cx(
1186 cx,
1187 Error::Type(c"The keyData type does not match the format".to_owned()),
1188 );
1189 return promise;
1190 },
1191
1192 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1195 Zeroizing::new(view.to_vec())
1196 },
1197 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1198 Zeroizing::new(buffer.to_vec())
1199 },
1200 }
1201 },
1202 };
1203
1204 let promise = Promise::new_in_realm(cx);
1207
1208 let this = Trusted::new(self);
1210 let trusted_promise = TrustedPromise::new(promise.clone());
1211 self.global()
1212 .task_manager()
1213 .dom_manipulation_task_source()
1214 .queue(task!(import_key: move |cx| {
1215 let subtle = this.root();
1216 let promise = trusted_promise.root();
1217
1218 let result = match normalized_algorithm.import_key(
1226 cx,
1227 &subtle.global(),
1228 format,
1229 &key_data,
1230 extractable,
1231 key_usages.clone(),
1232 ) {
1233 Ok(key) => key,
1234 Err(error) => {
1235 subtle.reject_promise_with_error(promise, error);
1236 return;
1237 },
1238 };
1239
1240 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && key_usages.is_empty() {
1243 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1244 return;
1245 }
1246
1247 result.set_extractable(extractable);
1249
1250 result.set_usages(cx, &key_usages);
1252
1253 subtle.resolve_promise_with_key(promise, result);
1259 }));
1260
1261 promise
1262 }
1263
1264 fn ExportKey(&self, cx: &mut CurrentRealm, format: KeyFormat, key: &CryptoKey) -> Rc<Promise> {
1266 let promise = Promise::new_in_realm(cx);
1273
1274 let trusted_subtle = Trusted::new(self);
1276 let trusted_promise = TrustedPromise::new(promise.clone());
1277 let trusted_key = Trusted::new(key);
1278 self.global()
1279 .task_manager()
1280 .dom_manipulation_task_source()
1281 .queue(task!(export_key: move |cx| {
1282 let subtle = trusted_subtle.root();
1283 let promise = trusted_promise.root();
1284 let key = trusted_key.root();
1285
1286 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1297 cx,
1298 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1299 ) {
1300 Ok(normalized_algorithm) => normalized_algorithm,
1301 Err(error) => {
1302 subtle.reject_promise_with_error(promise, error);
1303 return;
1304 },
1305 };
1306
1307 if !key.Extractable() {
1310 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1311 return;
1312 }
1313
1314 let result = match export_key_algorithm.export_key(format, &key) {
1317 Ok(exported_key) => exported_key,
1318 Err(error) => {
1319 subtle.reject_promise_with_error(promise, error);
1320 return;
1321 },
1322 };
1323
1324 match result {
1337 ExportedKey::Bytes(bytes) => {
1338 subtle.resolve_promise_with_data(promise, bytes);
1339 },
1340 ExportedKey::Jwk(jwk) => {
1341 subtle.resolve_promise_with_jwk(cx, promise, jwk);
1342 },
1343 }
1344 }));
1345 promise
1346 }
1347
1348 fn WrapKey(
1350 &self,
1351 cx: &mut CurrentRealm,
1352 format: KeyFormat,
1353 key: &CryptoKey,
1354 wrapping_key: &CryptoKey,
1355 algorithm: AlgorithmIdentifier,
1356 ) -> Rc<Promise> {
1357 enum WrapKeyAlgorithmOrEncryptAlgorithm {
1367 WrapKeyAlgorithm(WrapKeyAlgorithm),
1368 EncryptAlgorithm(EncryptAlgorithm),
1369 }
1370 let normalized_algorithm = if let Ok(algorithm) =
1371 normalize_algorithm::<WrapKeyOperation>(cx, &algorithm)
1372 {
1373 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm)
1374 } else {
1375 match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
1376 Ok(algorithm) => WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm),
1377 Err(error) => {
1378 let promise = Promise::new_in_realm(cx);
1379 promise.reject_error_with_cx(cx, error);
1380 return promise;
1381 },
1382 }
1383 };
1384
1385 let promise = Promise::new_in_realm(cx);
1388
1389 let trusted_subtle = Trusted::new(self);
1391 let trusted_key = Trusted::new(key);
1392 let trusted_wrapping_key = Trusted::new(wrapping_key);
1393 let trusted_promise = TrustedPromise::new(promise.clone());
1394 self.global()
1395 .task_manager()
1396 .dom_manipulation_task_source()
1397 .queue(task!(wrap_key: move |cx| {
1398 let subtle = trusted_subtle.root();
1399 let key = trusted_key.root();
1400 let wrapping_key = trusted_wrapping_key.root();
1401 let promise = trusted_promise.root();
1402
1403 let normalized_algorithm_name = match &normalized_algorithm {
1411 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1412 algorithm.name()
1413 },
1414 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1415 algorithm.name()
1416 },
1417 };
1418 if normalized_algorithm_name != wrapping_key.algorithm().name() {
1419 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1420 return;
1421 }
1422
1423 if !wrapping_key.usages().contains(&KeyUsage::WrapKey) {
1426 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1427 return;
1428 }
1429
1430 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1436 cx,
1437 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1438 ) {
1439 Ok(normalized_algorithm) => normalized_algorithm,
1440 Err(error) => {
1441 subtle.reject_promise_with_error(promise, error);
1442 return;
1443 },
1444 };
1445
1446 if !key.Extractable() {
1449 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1450 return;
1451 }
1452
1453 let exported_key = match export_key_algorithm.export_key(format, &key) {
1456 Ok(exported_key) => exported_key,
1457 Err(error) => {
1458 subtle.reject_promise_with_error(promise, error);
1459 return;
1460 },
1461 };
1462
1463 let bytes = match exported_key {
1475 ExportedKey::Bytes(bytes) => bytes,
1476 ExportedKey::Jwk(jwk) => match jwk.stringify(cx) {
1477 Ok(stringified_jwk) => Zeroizing::new(stringified_jwk.as_bytes().to_vec()),
1478 Err(error) => {
1479 subtle.reject_promise_with_error(promise, error);
1480 return;
1481 },
1482 },
1483 };
1484
1485 let result = match normalized_algorithm {
1497 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1498 algorithm.wrap_key(&wrapping_key, &bytes)
1499 },
1500 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1501 algorithm.encrypt(&wrapping_key, &bytes)
1502 },
1503 };
1504 let result = match result {
1505 Ok(result) => result,
1506 Err(error) => {
1507 subtle.reject_promise_with_error(promise, error);
1508 return;
1509 },
1510 };
1511
1512 subtle.resolve_promise_with_data(promise, result.into());
1518 }));
1519 promise
1520 }
1521
1522 fn UnwrapKey(
1524 &self,
1525 cx: &mut CurrentRealm,
1526 format: KeyFormat,
1527 wrapped_key: ArrayBufferViewOrArrayBuffer,
1528 unwrapping_key: &CryptoKey,
1529 algorithm: AlgorithmIdentifier,
1530 unwrapped_key_algorithm: AlgorithmIdentifier,
1531 extractable: bool,
1532 usages: Vec<KeyUsage>,
1533 ) -> Rc<Promise> {
1534 enum UnwrapKeyAlgorithmOrDecryptAlgorithm {
1545 UnwrapKeyAlgorithm(UnwrapKeyAlgorithm),
1546 DecryptAlgorithm(DecryptAlgorithm),
1547 }
1548 let normalized_algorithm = if let Ok(algorithm) =
1549 normalize_algorithm::<UnwrapKeyOperation>(cx, &algorithm)
1550 {
1551 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm)
1552 } else {
1553 match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
1554 Ok(algorithm) => UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm),
1555 Err(error) => {
1556 let promise = Promise::new_in_realm(cx);
1557 promise.reject_error_with_cx(cx, error);
1558 return promise;
1559 },
1560 }
1561 };
1562
1563 let normalized_key_algorithm =
1567 match normalize_algorithm::<ImportKeyOperation>(cx, &unwrapped_key_algorithm) {
1568 Ok(algorithm) => algorithm,
1569 Err(error) => {
1570 let promise = Promise::new_in_realm(cx);
1571 promise.reject_error_with_cx(cx, error);
1572 return promise;
1573 },
1574 };
1575
1576 let wrapped_key = match wrapped_key {
1579 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1580 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1581 };
1582
1583 let promise = Promise::new_in_realm(cx);
1586
1587 let trusted_subtle = Trusted::new(self);
1589 let trusted_unwrapping_key = Trusted::new(unwrapping_key);
1590 let trusted_promise = TrustedPromise::new(promise.clone());
1591 self.global().task_manager().dom_manipulation_task_source().queue(
1592 task!(unwrap_key: move |cx| {
1593 let subtle = trusted_subtle.root();
1594 let unwrapping_key = trusted_unwrapping_key.root();
1595 let promise = trusted_promise.root();
1596
1597 let normalized_algorithm_name = match &normalized_algorithm {
1605 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm) => {
1606 algorithm.name()
1607 },
1608 UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm) => {
1609 algorithm.name()
1610 },
1611 };
1612 if normalized_algorithm_name != unwrapping_key.algorithm().name() {
1613 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1614 return;
1615 }
1616
1617 if !unwrapping_key.usages().contains(&KeyUsage::UnwrapKey) {
1620 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1621 return;
1622 }
1623
1624 let bytes = match normalized_algorithm {
1636 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm) => {
1637 algorithm.unwrap_key(&unwrapping_key, &wrapped_key)
1638 },
1639 UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm) => {
1640 algorithm.decrypt(&unwrapping_key, &wrapped_key)
1641 },
1642 };
1643 let bytes = match bytes {
1644 Ok(bytes) => Zeroizing::new(bytes),
1645 Err(error) => {
1646 subtle.reject_promise_with_error(promise, error);
1647 return;
1648 },
1649 };
1650
1651 if format == KeyFormat::Jwk
1662 && let Err(error) = JsonWebKey::parse(cx, &bytes) {
1663 subtle.reject_promise_with_error(promise, error);
1664 return;
1665 }
1666 let key = bytes;
1667
1668 let result = match normalized_key_algorithm.import_key(
1672 cx,
1673 &subtle.global(),
1674 format,
1675 &key,
1676 extractable,
1677 usages.clone(),
1678 ) {
1679 Ok(result) => result,
1680 Err(error) => {
1681 subtle.reject_promise_with_error(promise, error);
1682 return;
1683 },
1684 };
1685
1686 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1689 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1690 return;
1691 }
1692
1693 subtle.resolve_promise_with_key(promise, result);
1704 }),
1705 );
1706 promise
1707 }
1708
1709 fn EncapsulateKey(
1711 &self,
1712 cx: &mut CurrentRealm,
1713 encapsulation_algorithm: AlgorithmIdentifier,
1714 encapsulation_key: &CryptoKey,
1715 shared_key_algorithm: AlgorithmIdentifier,
1716 extractable: bool,
1717 usages: Vec<KeyUsage>,
1718 ) -> Rc<Promise> {
1719 let promise = Promise::new_in_realm(cx);
1729 let normalized_encapsulation_algorithm =
1730 match normalize_algorithm::<EncapsulateOperation>(cx, &encapsulation_algorithm) {
1731 Ok(algorithm) => algorithm,
1732 Err(error) => {
1733 promise.reject_error_with_cx(cx, error);
1734 return promise;
1735 },
1736 };
1737
1738 let normalized_shared_key_algorithm =
1743 match normalize_algorithm::<ImportKeyOperation>(cx, &shared_key_algorithm) {
1744 Ok(algorithm) => algorithm,
1745 Err(error) => {
1746 promise.reject_error_with_cx(cx, error);
1747 return promise;
1748 },
1749 };
1750
1751 let trusted_subtle = Trusted::new(self);
1757 let trusted_encapsulated_key = Trusted::new(encapsulation_key);
1758 let trusted_promise = TrustedPromise::new(promise.clone());
1759 self.global().task_manager().dom_manipulation_task_source().queue(
1760 task!(encapsulate_keys: move |cx| {
1761 let subtle = trusted_subtle.root();
1762 let encapsulation_key = trusted_encapsulated_key.root();
1763 let promise = trusted_promise.root();
1764
1765 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1773 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1774 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1775 normalizedEncapsulationAlgorithm".to_string(),
1776 )));
1777 return;
1778 }
1779
1780 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateKey) {
1783 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1784 "[[usages]] internal slot of encapsulationKey does not contain an \
1785 entry that is \"encapsulateBits\"".to_string(),
1786 )));
1787 return;
1788 }
1789
1790 let encapsulated_bits_result =
1796 normalized_encapsulation_algorithm.encapsulate(&encapsulation_key);
1797 let encapsulated_bits = match encapsulated_bits_result {
1798 Ok(encapsulated_bits) => encapsulated_bits,
1799 Err(error) => {
1800 subtle.reject_promise_with_error(promise, error);
1801 return;
1802 },
1803 };
1804
1805 let encapsulated_shared_key = match &encapsulated_bits.shared_key {
1813 Some(shared_key) => shared_key,
1814 None => {
1815 subtle.reject_promise_with_error(promise, Error::Operation(Some(
1816 "Shared key is missing in the result of the encapsulate operation"
1817 .to_string())));
1818 return;
1819 },
1820 };
1821 let shared_key_result = normalized_shared_key_algorithm.import_key(
1822 cx,
1823 &subtle.global(),
1824 KeyFormat::Raw_secret,
1825 encapsulated_shared_key,
1826 extractable,
1827 usages.clone(),
1828 );
1829 let shared_key = match shared_key_result {
1830 Ok(shared_key) => shared_key,
1831 Err(error) => {
1832 subtle.reject_promise_with_error(promise, error);
1833 return;
1834 },
1835 };
1836
1837 let encapsulated_key = SubtleEncapsulatedKey {
1840 shared_key: Some(Trusted::new(&shared_key)),
1841 ciphertext:encapsulated_bits.ciphertext,
1842 };
1843
1844 subtle.resolve_promise_with_encapsulated_key(promise, encapsulated_key);
1850 })
1851 );
1852 promise
1853 }
1854
1855 fn EncapsulateBits(
1857 &self,
1858 cx: &mut CurrentRealm,
1859 encapsulation_algorithm: AlgorithmIdentifier,
1860 encapsulation_key: &CryptoKey,
1861 ) -> Rc<Promise> {
1862 let promise = Promise::new_in_realm(cx);
1870 let normalized_encapsulation_algorithm =
1871 match normalize_algorithm::<EncapsulateOperation>(cx, &encapsulation_algorithm) {
1872 Ok(algorithm) => algorithm,
1873 Err(error) => {
1874 promise.reject_error_with_cx(cx, error);
1875 return promise;
1876 },
1877 };
1878
1879 let trusted_subtle = Trusted::new(self);
1885 let trusted_encapsulation_key = Trusted::new(encapsulation_key);
1886 let trusted_promise = TrustedPromise::new(promise.clone());
1887 self.global().task_manager().dom_manipulation_task_source().queue(
1888 task!(derive_key: move || {
1889 let subtle = trusted_subtle.root();
1890 let encapsulation_key = trusted_encapsulation_key.root();
1891 let promise = trusted_promise.root();
1892
1893 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1901 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1902 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1903 normalizedEncapsulationAlgorithm".to_string(),
1904 )));
1905 return;
1906 }
1907
1908 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateBits) {
1911 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1912 "[[usages]] internal slot of encapsulationKey does not contain an \
1913 entry that is \"encapsulateBits\"".to_string(),
1914 )));
1915 return;
1916 }
1917
1918 let encapsulated_bits =
1924 match normalized_encapsulation_algorithm.encapsulate(&encapsulation_key) {
1925 Ok(encapsulated_bits) => encapsulated_bits,
1926 Err(error) => {
1927 subtle.reject_promise_with_error(promise, error);
1928 return;
1929 },
1930 };
1931
1932 subtle.resolve_promise_with_encapsulated_bits(promise, encapsulated_bits);
1938 }),
1939 );
1940 promise
1941 }
1942
1943 fn DecapsulateKey(
1945 &self,
1946 cx: &mut CurrentRealm,
1947 decapsulation_algorithm: AlgorithmIdentifier,
1948 decapsulation_key: &CryptoKey,
1949 ciphertext: ArrayBufferViewOrArrayBuffer,
1950 shared_key_algorithm: AlgorithmIdentifier,
1951 extractable: bool,
1952 usages: Vec<KeyUsage>,
1953 ) -> Rc<Promise> {
1954 let normalized_decapsulation_algorithm =
1964 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
1965 Ok(normalized_algorithm) => normalized_algorithm,
1966 Err(error) => {
1967 let promise = Promise::new_in_realm(cx);
1968 promise.reject_error_with_cx(cx, error);
1969 return promise;
1970 },
1971 };
1972
1973 let normalized_shared_key_algorithm =
1978 match normalize_algorithm::<ImportKeyOperation>(cx, &shared_key_algorithm) {
1979 Ok(normalized_algorithm) => normalized_algorithm,
1980 Err(error) => {
1981 let promise = Promise::new_in_realm(cx);
1982 promise.reject_error_with_cx(cx, error);
1983 return promise;
1984 },
1985 };
1986
1987 let ciphertext = match ciphertext {
1990 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1991 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1992 };
1993
1994 let promise = Promise::new_in_realm(cx);
1997
1998 let trusted_subtle = Trusted::new(self);
2000 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2001 let trusted_promise = TrustedPromise::new(promise.clone());
2002 self.global()
2003 .task_manager()
2004 .dom_manipulation_task_source()
2005 .queue(task!(decapsulate_key: move |cx| {
2006 let subtle = trusted_subtle.root();
2007 let promise = trusted_promise.root();
2008 let decapsulation_key = trusted_decapsulation_key.root();
2009
2010 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2018 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2019 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2020 normalizedDecapsulationAlgorithm".to_string()
2021 )));
2022 return;
2023 }
2024
2025 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateKey) {
2028 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2029 "[[usages]] internal slot of decapsulationKey does not contain an \
2030 entry that is \"decapsulateBits\"".to_string(),
2031 )));
2032 return;
2033 }
2034
2035 let decapsulated_bits_result =
2041 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2042 let decapsulated_bits = match decapsulated_bits_result {
2043 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2044 Err(error) => {
2045 subtle.reject_promise_with_error(promise, error);
2046 return;
2047 },
2048 };
2049
2050
2051 let shared_key_result = normalized_shared_key_algorithm.import_key(
2059 cx,
2060 &subtle.global(),
2061 KeyFormat::Raw_secret,
2062 &decapsulated_bits,
2063 extractable,
2064 usages.clone(),
2065 );
2066 let shared_key = match shared_key_result {
2067 Ok(shared_key) => shared_key,
2068 Err(error) => {
2069 subtle.reject_promise_with_error(promise, error);
2070 return;
2071 },
2072 };
2073
2074
2075 subtle.resolve_promise_with_key(promise, shared_key);
2081 }));
2082 promise
2083 }
2084
2085 fn DecapsulateBits(
2087 &self,
2088 cx: &mut CurrentRealm,
2089 decapsulation_algorithm: AlgorithmIdentifier,
2090 decapsulation_key: &CryptoKey,
2091 ciphertext: ArrayBufferViewOrArrayBuffer,
2092 ) -> Rc<Promise> {
2093 let normalized_decapsulation_algorithm =
2101 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
2102 Ok(normalized_algorithm) => normalized_algorithm,
2103 Err(error) => {
2104 let promise = Promise::new_in_realm(cx);
2105 promise.reject_error_with_cx(cx, error);
2106 return promise;
2107 },
2108 };
2109
2110 let ciphertext = match ciphertext {
2113 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2114 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2115 };
2116
2117 let promise = Promise::new_in_realm(cx);
2120
2121 let trusted_subtle = Trusted::new(self);
2123 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2124 let trusted_promise = TrustedPromise::new(promise.clone());
2125 self.global()
2126 .task_manager()
2127 .dom_manipulation_task_source()
2128 .queue(task!(decapsulate_bits: move || {
2129 let subtle = trusted_subtle.root();
2130 let promise = trusted_promise.root();
2131 let decapsulation_key = trusted_decapsulation_key.root();
2132
2133 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2141 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2142 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2143 normalizedDecapsulationAlgorithm".to_string()
2144 )));
2145 return;
2146 }
2147
2148 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateBits) {
2151 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2152 "[[usages]] internal slot of decapsulationKey does not contain an \
2153 entry that is \"decapsulateBits\"".to_string(),
2154 )));
2155 return;
2156 }
2157
2158 let decapsulated_bits_result =
2164 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2165 let decapsulated_bits = match decapsulated_bits_result {
2166 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2167 Err(error) => {
2168 subtle.reject_promise_with_error(promise, error);
2169 return;
2170 },
2171 };
2172
2173 subtle.resolve_promise_with_data(promise, decapsulated_bits);
2179 }));
2180 promise
2181 }
2182
2183 fn GetPublicKey(
2185 &self,
2186 cx: &mut CurrentRealm,
2187 key: &CryptoKey,
2188 usages: Vec<KeyUsage>,
2189 ) -> Rc<Promise> {
2190 let algorithm = key.algorithm();
2195
2196 let get_public_key_algorithm = match normalize_algorithm::<GetPublicKeyOperation>(
2203 cx,
2204 &AlgorithmIdentifier::String(DOMString::from(algorithm.name().as_str())),
2205 ) {
2206 Ok(normalized_algorithm) => normalized_algorithm,
2207 Err(error) => {
2208 let promise = Promise::new_in_realm(cx);
2209 promise.reject_error_with_cx(cx, error);
2210 return promise;
2211 },
2212 };
2213
2214 let promise = Promise::new_in_realm(cx);
2217
2218 let trusted_subtle = Trusted::new(self);
2220 let trusted_promise = TrustedPromise::new(promise.clone());
2221 let trusted_key = Trusted::new(key);
2222 self.global()
2223 .task_manager()
2224 .dom_manipulation_task_source()
2225 .queue(task!(get_public_key: move |cx| {
2226 let subtle = trusted_subtle.root();
2227 let promise = trusted_promise.root();
2228 let key = trusted_key.root();
2229
2230 if key.Type() != KeyType::Private {
2237 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2238 "[[type]] internal slot of key is not \"private\"".to_string()
2239 )));
2240 return;
2241 }
2242
2243 let result = match get_public_key_algorithm.get_public_key(
2257 cx,
2258 &subtle.global(),
2259 &key,
2260 key.algorithm(),
2261 usages.clone(),
2262 ) {
2263 Ok(public_key) => public_key,
2264 Err(error) => {
2265 subtle.reject_promise_with_error(promise, error);
2266 return;
2267 },
2268 };
2269
2270 subtle.resolve_promise_with_key(promise, result);
2276 }));
2277 promise
2278 }
2279
2280 fn Supports(
2282 cx: &mut js::context::JSContext,
2283 _global: &GlobalScope,
2284 operation: DOMString,
2285 algorithm: AlgorithmIdentifier,
2286 length: Option<u32>,
2287 ) -> bool {
2288 let operation = &*operation.str();
2293 if !matches!(
2294 operation,
2295 "encrypt" |
2296 "decrypt" |
2297 "sign" |
2298 "verify" |
2299 "digest" |
2300 "generateKey" |
2301 "deriveKey" |
2302 "deriveBits" |
2303 "importKey" |
2304 "exportKey" |
2305 "wrapKey" |
2306 "unwrapKey" |
2307 "encapsulateKey" |
2308 "encapsulateBits" |
2309 "decapsulateKey" |
2310 "decapsulateBits" |
2311 "getPublicKey"
2312 ) {
2313 return false;
2314 }
2315
2316 check_support_for_algorithm(cx, operation, &algorithm, length)
2319 }
2320
2321 fn Supports_(
2323 cx: &mut js::context::JSContext,
2324 _global: &GlobalScope,
2325 operation: DOMString,
2326 algorithm: AlgorithmIdentifier,
2327 additional_algorithm: AlgorithmIdentifier,
2328 ) -> bool {
2329 let mut operation = &*operation.str();
2334 if !matches!(
2335 operation,
2336 "encrypt" |
2337 "decrypt" |
2338 "sign" |
2339 "verify" |
2340 "digest" |
2341 "generateKey" |
2342 "deriveKey" |
2343 "deriveBits" |
2344 "importKey" |
2345 "exportKey" |
2346 "wrapKey" |
2347 "unwrapKey" |
2348 "encapsulateKey" |
2349 "encapsulateBits" |
2350 "decapsulateKey" |
2351 "decapsulateBits" |
2352 "getPublicKey"
2353 ) {
2354 return false;
2355 }
2356
2357 if matches!(
2365 operation,
2366 "deriveKey" | "unwrapKey" | "encapsulateKey" | "decapsulateKey"
2367 ) && !check_support_for_algorithm(cx, "importKey", &additional_algorithm, None)
2368 {
2369 return false;
2370 }
2371 if operation == "wrapKey" &&
2372 !check_support_for_algorithm(cx, "exportKey", &additional_algorithm, None)
2373 {
2374 return false;
2375 }
2376
2377 let mut length = None;
2379
2380 if operation == "deriveKey" {
2382 if !check_support_for_algorithm(cx, "get key length", &additional_algorithm, None) {
2385 return false;
2386 }
2387
2388 let Ok(normalized_additional_algorithm) =
2391 normalize_algorithm::<GetKeyLengthOperation>(cx, &additional_algorithm)
2392 else {
2393 return false;
2394 };
2395
2396 match normalized_additional_algorithm.get_key_length() {
2399 Ok(key_length) => {
2400 length = key_length;
2401 },
2402 Err(_) => return false,
2403 };
2404
2405 operation = "deriveBits";
2407 }
2408
2409 check_support_for_algorithm(cx, operation, &algorithm, length)
2412 }
2413}
2414
2415pub(crate) fn check_support_for_algorithm(
2417 cx: &mut js::context::JSContext,
2418 mut operation: &str,
2419 algorithm: &AlgorithmIdentifier,
2420 length: Option<u32>,
2421) -> bool {
2422 if operation == "encapsulateKey" || operation == "encapsulateBits" {
2424 operation = "encapsulate";
2425 }
2426
2427 if operation == "decapsulateKey" || operation == "decapsulateBits" {
2429 operation = "decapsulate";
2430 }
2431
2432 if operation == "getPublicKey" {
2434 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2438 else {
2439 return false;
2440 };
2441
2442 return normalize_algorithm::<GetPublicKeyOperation>(
2449 cx,
2450 &AlgorithmIdentifier::String(DOMString::from(normalized_algorithm.name().as_str())),
2451 )
2452 .is_ok();
2453 }
2454
2455 match operation {
2494 "encrypt" => {
2495 let Ok(normalized_algorithm) = normalize_algorithm::<EncryptOperation>(cx, algorithm)
2496 else {
2497 return false;
2498 };
2499
2500 match normalized_algorithm {
2501 EncryptAlgorithm::RsaOaep(_) => true,
2502 EncryptAlgorithm::AesCtr(normalized_algorithm) => {
2503 normalized_algorithm.counter.len() == 16 &&
2504 normalized_algorithm.length != 0 &&
2505 normalized_algorithm.length <= 128
2506 },
2507 EncryptAlgorithm::AesCbc(normalized_algorithm) => {
2508 normalized_algorithm.iv.len() == 16
2509 },
2510 EncryptAlgorithm::AesGcm(normalized_algorithm) => {
2511 normalized_algorithm.iv.len() <= u32::MAX as usize &&
2512 normalized_algorithm.tag_length.is_none_or(|length| {
2513 matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)
2514 })
2515 },
2516 EncryptAlgorithm::AesOcb(normalized_algorithm) => {
2517 normalized_algorithm.iv.len() <= 15 &&
2518 normalized_algorithm
2519 .tag_length
2520 .is_none_or(|length| matches!(length, 64 | 96 | 128))
2521 },
2522 EncryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
2523 normalized_algorithm.iv.len() == 12 &&
2524 normalized_algorithm
2525 .tag_length
2526 .is_none_or(|length| length == 128)
2527 },
2528 }
2529 },
2530 "decrypt" => {
2531 let Ok(normalized_algorithm) = normalize_algorithm::<DecryptOperation>(cx, algorithm)
2532 else {
2533 return false;
2534 };
2535
2536 match normalized_algorithm {
2537 DecryptAlgorithm::RsaOaep(_) => true,
2538 DecryptAlgorithm::AesCtr(normalized_algorithm) => {
2539 normalized_algorithm.counter.len() == 16 &&
2540 normalized_algorithm.length != 0 &&
2541 normalized_algorithm.length <= 128
2542 },
2543 DecryptAlgorithm::AesCbc(normalized_algorithm) => {
2544 normalized_algorithm.iv.len() == 16
2545 },
2546 DecryptAlgorithm::AesGcm(normalized_algorithm) => {
2547 normalized_algorithm
2548 .tag_length
2549 .is_none_or(|length| matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)) &&
2550 normalized_algorithm.iv.len() <= u32::MAX as usize &&
2551 normalized_algorithm
2552 .additional_data
2553 .is_none_or(|data| data.len() <= u32::MAX as usize)
2554 },
2555 DecryptAlgorithm::AesOcb(normalized_algorithm) => {
2556 normalized_algorithm.iv.len() <= 15 &&
2557 normalized_algorithm
2558 .tag_length
2559 .is_none_or(|length| matches!(length, 64 | 96 | 128))
2560 },
2561 DecryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
2562 normalized_algorithm.iv.len() == 12 &&
2563 normalized_algorithm
2564 .tag_length
2565 .is_none_or(|length| length == 128)
2566 },
2567 }
2568 },
2569 "sign" => {
2570 let Ok(normalized_algorithm) = normalize_algorithm::<SignOperation>(cx, algorithm)
2571 else {
2572 return false;
2573 };
2574
2575 match normalized_algorithm {
2576 SignAlgorithm::RsassaPkcs1V1_5(_) |
2577 SignAlgorithm::RsaPss(_) |
2578 SignAlgorithm::Ecdsa(_) |
2579 SignAlgorithm::Ed25519(_) |
2580 SignAlgorithm::Hmac(_) |
2581 SignAlgorithm::MlDsa(_) => true,
2582 }
2583 },
2584 "verify" => {
2585 let Ok(normalized_algorithm) = normalize_algorithm::<VerifyOperation>(cx, algorithm)
2586 else {
2587 return false;
2588 };
2589
2590 match normalized_algorithm {
2591 VerifyAlgorithm::RsassaPkcs1V1_5(_) |
2592 VerifyAlgorithm::RsaPss(_) |
2593 VerifyAlgorithm::Ecdsa(_) |
2594 VerifyAlgorithm::Ed25519(_) |
2595 VerifyAlgorithm::Hmac(_) |
2596 VerifyAlgorithm::MlDsa(_) => true,
2597 }
2598 },
2599 "digest" => {
2600 let Ok(normalized_algorithm) = normalize_algorithm::<DigestOperation>(cx, algorithm)
2601 else {
2602 return false;
2603 };
2604
2605 match normalized_algorithm {
2606 DigestAlgorithm::Sha(_) |
2607 DigestAlgorithm::Sha3(_) |
2608 DigestAlgorithm::CShake(_) |
2609 DigestAlgorithm::TurboShake(_) => true,
2610 }
2611 },
2612 "deriveBits" => {
2613 let Ok(normalized_algorithm) =
2614 normalize_algorithm::<DeriveBitsOperation>(cx, algorithm)
2615 else {
2616 return false;
2617 };
2618
2619 match normalized_algorithm {
2620 DeriveBitsAlgorithm::Ecdh(normalized_algorithm) => length.is_none_or(|length| {
2621 ecdh_operation::secret_length(&normalized_algorithm)
2622 .is_ok_and(|secret_length| secret_length * 8 >= length)
2623 }),
2624 DeriveBitsAlgorithm::X25519(_) => {
2625 length.is_none_or(|length| x25519_operation::SECRET_LENGTH as u32 * 8 >= length)
2626 },
2627 DeriveBitsAlgorithm::Hkdf(_) => length.is_some_and(|length| length % 8 == 0),
2628 DeriveBitsAlgorithm::Pbkdf2(normalized_algorithm) => {
2629 length.is_some_and(|length| length % 8 == 0) &&
2630 normalized_algorithm.iterations != 0
2631 },
2632 DeriveBitsAlgorithm::Argon2(normalized_algorithm) => {
2633 length.is_some_and(|length| length >= 32 && length % 8 == 0) &&
2634 normalized_algorithm
2635 .version
2636 .is_none_or(|version| version == 19) &&
2637 normalized_algorithm.parallelism != 0 &&
2638 normalized_algorithm.parallelism <= 16777215 &&
2639 normalized_algorithm.memory >= 8 * normalized_algorithm.parallelism &&
2640 normalized_algorithm.passes != 0
2641 },
2642 }
2643 },
2644 "wrapKey" => {
2645 let Ok(normalized_algorithm) = normalize_algorithm::<WrapKeyOperation>(cx, algorithm)
2646 else {
2647 return check_support_for_algorithm(cx, "encrypt", algorithm, length);
2648 };
2649
2650 match normalized_algorithm {
2651 WrapKeyAlgorithm::AesKw(_) => true,
2652 }
2653 },
2654 "unwrapKey" => {
2655 let Ok(normalized_algorithm) = normalize_algorithm::<UnwrapKeyOperation>(cx, algorithm)
2656 else {
2657 return check_support_for_algorithm(cx, "decrypt", algorithm, length);
2658 };
2659
2660 match normalized_algorithm {
2661 UnwrapKeyAlgorithm::AesKw(_) => true,
2662 }
2663 },
2664 "generateKey" => {
2665 let Ok(normalized_algorithm) =
2666 normalize_algorithm::<GenerateKeyOperation>(cx, algorithm)
2667 else {
2668 return false;
2669 };
2670
2671 match normalized_algorithm {
2672 GenerateKeyAlgorithm::RsassaPkcs1V1_5(_) |
2673 GenerateKeyAlgorithm::RsaPss(_) |
2674 GenerateKeyAlgorithm::RsaOaep(_) => true,
2675 GenerateKeyAlgorithm::Ecdsa(normalized_algorithm) |
2676 GenerateKeyAlgorithm::Ecdh(normalized_algorithm) => {
2677 SUPPORTED_CURVES.contains(&normalized_algorithm.named_curve.as_str())
2678 },
2679 GenerateKeyAlgorithm::Ed25519(_) | GenerateKeyAlgorithm::X25519(_) => true,
2680 GenerateKeyAlgorithm::AesCtr(normalized_algorithm) |
2681 GenerateKeyAlgorithm::AesCbc(normalized_algorithm) |
2682 GenerateKeyAlgorithm::AesGcm(normalized_algorithm) |
2683 GenerateKeyAlgorithm::AesKw(normalized_algorithm) => {
2684 matches!(normalized_algorithm.length, 128 | 192 | 256)
2685 },
2686 GenerateKeyAlgorithm::Hmac(normalized_algorithm) => {
2687 normalized_algorithm.length.is_none_or(|length| length != 0)
2688 },
2689 GenerateKeyAlgorithm::MlKem(_) | GenerateKeyAlgorithm::MlDsa(_) => true,
2690 GenerateKeyAlgorithm::AesOcb(normalized_algorithm) => {
2691 matches!(normalized_algorithm.length, 128 | 192 | 256)
2692 },
2693 GenerateKeyAlgorithm::ChaCha20Poly1305(_) => true,
2694 }
2695 },
2696 "importKey" => {
2697 let Ok(normalized_algorithm) = normalize_algorithm::<ImportKeyOperation>(cx, algorithm)
2698 else {
2699 return false;
2700 };
2701
2702 match normalized_algorithm {
2703 ImportKeyAlgorithm::RsassaPkcs1V1_5(_) |
2704 ImportKeyAlgorithm::RsaPss(_) |
2705 ImportKeyAlgorithm::RsaOaep(_) |
2706 ImportKeyAlgorithm::Ecdsa(_) |
2707 ImportKeyAlgorithm::Ecdh(_) |
2708 ImportKeyAlgorithm::Ed25519(_) |
2709 ImportKeyAlgorithm::X25519(_) |
2710 ImportKeyAlgorithm::AesCtr(_) |
2711 ImportKeyAlgorithm::AesCbc(_) |
2712 ImportKeyAlgorithm::AesGcm(_) |
2713 ImportKeyAlgorithm::AesKw(_) |
2714 ImportKeyAlgorithm::Hmac(_) |
2715 ImportKeyAlgorithm::Hkdf(_) |
2716 ImportKeyAlgorithm::Pbkdf2(_) |
2717 ImportKeyAlgorithm::MlKem(_) |
2718 ImportKeyAlgorithm::MlDsa(_) |
2719 ImportKeyAlgorithm::AesOcb(_) |
2720 ImportKeyAlgorithm::ChaCha20Poly1305(_) |
2721 ImportKeyAlgorithm::Argon2(_) => true,
2722 }
2723 },
2724 "exportKey" => {
2725 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2726 else {
2727 return false;
2728 };
2729
2730 match normalized_algorithm {
2731 ExportKeyAlgorithm::RsassaPkcs1V1_5(_) |
2732 ExportKeyAlgorithm::RsaPss(_) |
2733 ExportKeyAlgorithm::RsaOaep(_) |
2734 ExportKeyAlgorithm::Ecdsa(_) |
2735 ExportKeyAlgorithm::Ecdh(_) |
2736 ExportKeyAlgorithm::Ed25519(_) |
2737 ExportKeyAlgorithm::X25519(_) |
2738 ExportKeyAlgorithm::AesCtr(_) |
2739 ExportKeyAlgorithm::AesCbc(_) |
2740 ExportKeyAlgorithm::AesGcm(_) |
2741 ExportKeyAlgorithm::AesKw(_) |
2742 ExportKeyAlgorithm::Hmac(_) |
2743 ExportKeyAlgorithm::MlKem(_) |
2744 ExportKeyAlgorithm::MlDsa(_) |
2745 ExportKeyAlgorithm::AesOcb(_) |
2746 ExportKeyAlgorithm::ChaCha20Poly1305(_) => true,
2747 }
2748 },
2749 "get key length" => {
2750 let Ok(normalized_algorithm) =
2751 normalize_algorithm::<GetKeyLengthOperation>(cx, algorithm)
2752 else {
2753 return false;
2754 };
2755
2756 match normalized_algorithm {
2757 GetKeyLengthAlgorithm::AesCtr(normalized_derived_key_algorithm) |
2758 GetKeyLengthAlgorithm::AesCbc(normalized_derived_key_algorithm) |
2759 GetKeyLengthAlgorithm::AesGcm(normalized_derived_key_algorithm) |
2760 GetKeyLengthAlgorithm::AesKw(normalized_derived_key_algorithm) => {
2761 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
2762 },
2763 GetKeyLengthAlgorithm::Hmac(normalized_derived_key_algorithm) => {
2764 normalized_derived_key_algorithm
2765 .length
2766 .is_none_or(|length| length != 0)
2767 },
2768 GetKeyLengthAlgorithm::Hkdf(_) | GetKeyLengthAlgorithm::Pbkdf2(_) => true,
2769 GetKeyLengthAlgorithm::AesOcb(normalized_derived_key_algorithm) => {
2770 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
2771 },
2772 GetKeyLengthAlgorithm::ChaCha20Poly1305(_) | GetKeyLengthAlgorithm::Argon2(_) => {
2773 true
2774 },
2775 }
2776 },
2777 "encapsulate" => {
2778 let Ok(normalized_algorithm) =
2779 normalize_algorithm::<EncapsulateOperation>(cx, algorithm)
2780 else {
2781 return false;
2782 };
2783
2784 match normalized_algorithm {
2785 EncapsulateAlgorithm::MlKem(_) => true,
2786 }
2787 },
2788 "decapsulate" => {
2789 let Ok(normalized_algorithm) =
2790 normalize_algorithm::<DecapsulateOperation>(cx, algorithm)
2791 else {
2792 return false;
2793 };
2794
2795 match normalized_algorithm {
2796 DecapsulateAlgorithm::MlKem(_) => true,
2797 }
2798 },
2799 _ => false,
2800 }
2801
2802 }
2806
2807trait TryFromWithCxAndName<T>: Sized {
2809 type Error;
2810
2811 fn try_from_with_cx_and_name(
2812 value: T,
2813 cx: &mut js::context::JSContext,
2814 algorithm_name: CryptoAlgorithm,
2815 ) -> Result<Self, Self::Error>;
2816}
2817
2818trait TryIntoWithCxAndName<T>: Sized {
2820 type Error;
2821
2822 fn try_into_with_cx_and_name(
2823 self,
2824 cx: &mut js::context::JSContext,
2825 algorithm_name: CryptoAlgorithm,
2826 ) -> Result<T, Self::Error>;
2827}
2828
2829impl<T, U> TryIntoWithCxAndName<U> for T
2830where
2831 U: TryFromWithCxAndName<T>,
2832{
2833 type Error = U::Error;
2834
2835 fn try_into_with_cx_and_name(
2836 self,
2837 cx: &mut js::context::JSContext,
2838 algorithm_name: CryptoAlgorithm,
2839 ) -> Result<U, Self::Error> {
2840 U::try_from_with_cx_and_name(self, cx, algorithm_name)
2841 }
2842}
2843
2844#[derive(Clone, MallocSizeOf)]
2849struct SubtleAlgorithm {
2850 name: CryptoAlgorithm,
2852}
2853
2854impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAlgorithm {
2855 type Error = Error;
2856
2857 fn try_from_with_cx_and_name(
2858 _object: HandleObject<'a>,
2859 _cx: &mut js::context::JSContext,
2860 algorithm_name: CryptoAlgorithm,
2861 ) -> Result<Self, Self::Error> {
2862 Ok(SubtleAlgorithm {
2863 name: algorithm_name,
2864 })
2865 }
2866}
2867
2868impl TryFrom<SerializableAlgorithm> for SubtleAlgorithm {
2869 type Error = ();
2870
2871 fn try_from(value: SerializableAlgorithm) -> Result<Self, Self::Error> {
2872 Ok(SubtleAlgorithm {
2873 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2874 })
2875 }
2876}
2877
2878impl From<&SubtleAlgorithm> for SerializableAlgorithm {
2879 fn from(value: &SubtleAlgorithm) -> Self {
2880 SerializableAlgorithm {
2881 name: value.name.as_str().into(),
2882 }
2883 }
2884}
2885
2886#[derive(Clone, MallocSizeOf)]
2888pub(crate) struct SubtleKeyAlgorithm {
2889 name: CryptoAlgorithm,
2891}
2892
2893impl SafeToJSValConvertible for SubtleKeyAlgorithm {
2894 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2895 let dictionary = KeyAlgorithm {
2896 name: self.name.as_str().into(),
2897 };
2898 dictionary.safe_to_jsval(cx, rval, can_gc);
2899 }
2900}
2901
2902impl TryFrom<SerializableKeyAlgorithm> for SubtleKeyAlgorithm {
2903 type Error = ();
2904
2905 fn try_from(value: SerializableKeyAlgorithm) -> Result<Self, Self::Error> {
2906 Ok(SubtleKeyAlgorithm {
2907 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2908 })
2909 }
2910}
2911
2912impl From<&SubtleKeyAlgorithm> for SerializableKeyAlgorithm {
2913 fn from(value: &SubtleKeyAlgorithm) -> Self {
2914 SerializableKeyAlgorithm {
2915 name: value.name.as_str().into(),
2916 }
2917 }
2918}
2919
2920#[derive(Clone, MallocSizeOf)]
2922pub(crate) struct SubtleRsaHashedKeyGenParams {
2923 name: CryptoAlgorithm,
2925
2926 modulus_length: u32,
2928
2929 public_exponent: Vec<u8>,
2931
2932 hash: DigestAlgorithm,
2934}
2935
2936impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaHashedKeyGenParams {
2937 type Error = Error;
2938
2939 fn try_from_with_cx_and_name(
2940 object: HandleObject,
2941 cx: &mut js::context::JSContext,
2942 algorithm_name: CryptoAlgorithm,
2943 ) -> Result<Self, Self::Error> {
2944 let hash = get_required_parameter(cx, object, c"hash", ())?;
2945
2946 Ok(SubtleRsaHashedKeyGenParams {
2947 name: algorithm_name,
2948 modulus_length: get_required_parameter(
2949 cx,
2950 object,
2951 c"modulusLength",
2952 ConversionBehavior::Default,
2953 )?,
2954 public_exponent: get_required_parameter_in_box::<HeapUint8Array>(
2955 cx,
2956 object,
2957 c"publicExponent",
2958 (),
2959 )?
2960 .to_vec(),
2961 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
2962 })
2963 }
2964}
2965
2966#[derive(Clone, MallocSizeOf)]
2968pub(crate) struct SubtleRsaHashedKeyAlgorithm {
2969 name: CryptoAlgorithm,
2971
2972 modulus_length: u32,
2974
2975 public_exponent: Vec<u8>,
2977
2978 hash: DigestAlgorithm,
2980}
2981
2982impl SafeToJSValConvertible for SubtleRsaHashedKeyAlgorithm {
2983 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2984 rooted!(in(*cx) let mut js_object = ptr::null_mut::<JSObject>());
2985 let public_exponent =
2986 create_buffer_source(cx, &self.public_exponent, js_object.handle_mut(), can_gc)
2987 .expect("Fail to convert publicExponent to Uint8Array");
2988 let key_algorithm = KeyAlgorithm {
2989 name: self.name.as_str().into(),
2990 };
2991 let rsa_key_algorithm = RootedTraceableBox::new(RsaKeyAlgorithm {
2992 parent: key_algorithm,
2993 modulusLength: self.modulus_length,
2994 publicExponent: public_exponent,
2995 });
2996 let rsa_hashed_key_algorithm = RootedTraceableBox::new(RsaHashedKeyAlgorithm {
2997 parent: rsa_key_algorithm,
2998 hash: KeyAlgorithm {
2999 name: self.hash.name().as_str().into(),
3000 },
3001 });
3002 rsa_hashed_key_algorithm.safe_to_jsval(cx, rval, can_gc);
3003 }
3004}
3005
3006impl TryFrom<SerializableRsaHashedKeyAlgorithm> for SubtleRsaHashedKeyAlgorithm {
3007 type Error = ();
3008
3009 fn try_from(value: SerializableRsaHashedKeyAlgorithm) -> Result<Self, Self::Error> {
3010 Ok(SubtleRsaHashedKeyAlgorithm {
3011 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3012 modulus_length: value.modulus_length,
3013 public_exponent: value.public_exponent,
3014 hash: value.hash.try_into()?,
3015 })
3016 }
3017}
3018
3019impl From<&SubtleRsaHashedKeyAlgorithm> for SerializableRsaHashedKeyAlgorithm {
3020 fn from(value: &SubtleRsaHashedKeyAlgorithm) -> Self {
3021 SerializableRsaHashedKeyAlgorithm {
3022 name: value.name.as_str().into(),
3023 modulus_length: value.modulus_length,
3024 public_exponent: value.public_exponent.clone(),
3025 hash: (&value.hash).into(),
3026 }
3027 }
3028}
3029
3030#[derive(Clone, MallocSizeOf)]
3032struct SubtleRsaHashedImportParams {
3033 name: CryptoAlgorithm,
3035
3036 hash: DigestAlgorithm,
3038}
3039
3040impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaHashedImportParams {
3041 type Error = Error;
3042
3043 fn try_from_with_cx_and_name(
3044 object: HandleObject,
3045 cx: &mut js::context::JSContext,
3046 algorithm_name: CryptoAlgorithm,
3047 ) -> Result<Self, Self::Error> {
3048 let hash = get_required_parameter(cx, object, c"hash", ())?;
3049
3050 Ok(SubtleRsaHashedImportParams {
3051 name: algorithm_name,
3052 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3053 })
3054 }
3055}
3056
3057#[derive(Clone, MallocSizeOf)]
3059struct SubtleRsaPssParams {
3060 name: CryptoAlgorithm,
3062
3063 salt_length: u32,
3065}
3066
3067impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaPssParams {
3068 type Error = Error;
3069
3070 fn try_from_with_cx_and_name(
3071 object: HandleObject,
3072 cx: &mut js::context::JSContext,
3073 algorithm_name: CryptoAlgorithm,
3074 ) -> Result<Self, Self::Error> {
3075 Ok(SubtleRsaPssParams {
3076 name: algorithm_name,
3077 salt_length: get_required_parameter(
3078 cx,
3079 object,
3080 c"saltLength",
3081 ConversionBehavior::EnforceRange,
3082 )?,
3083 })
3084 }
3085}
3086
3087#[derive(Clone, MallocSizeOf)]
3089struct SubtleRsaOaepParams {
3090 name: CryptoAlgorithm,
3092
3093 label: Option<Vec<u8>>,
3095}
3096
3097impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaOaepParams {
3098 type Error = Error;
3099
3100 fn try_from_with_cx_and_name(
3101 object: HandleObject<'a>,
3102 cx: &mut js::context::JSContext,
3103 algorithm_name: CryptoAlgorithm,
3104 ) -> Result<Self, Self::Error> {
3105 Ok(SubtleRsaOaepParams {
3106 name: algorithm_name,
3107 label: get_optional_buffer_source(cx, object, c"label")?,
3108 })
3109 }
3110}
3111
3112#[derive(Clone, MallocSizeOf)]
3114struct SubtleEcdsaParams {
3115 name: CryptoAlgorithm,
3117
3118 hash: DigestAlgorithm,
3120}
3121
3122impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcdsaParams {
3123 type Error = Error;
3124
3125 fn try_from_with_cx_and_name(
3126 object: HandleObject<'a>,
3127 cx: &mut js::context::JSContext,
3128 algorithm_name: CryptoAlgorithm,
3129 ) -> Result<Self, Self::Error> {
3130 let hash = get_required_parameter(cx, object, c"hash", ())?;
3131
3132 Ok(SubtleEcdsaParams {
3133 name: algorithm_name,
3134 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3135 })
3136 }
3137}
3138
3139#[derive(Clone, MallocSizeOf)]
3141struct SubtleEcKeyGenParams {
3142 name: CryptoAlgorithm,
3144
3145 named_curve: String,
3147}
3148
3149impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcKeyGenParams {
3150 type Error = Error;
3151
3152 fn try_from_with_cx_and_name(
3153 object: HandleObject<'a>,
3154 cx: &mut js::context::JSContext,
3155 algorithm_name: CryptoAlgorithm,
3156 ) -> Result<Self, Self::Error> {
3157 Ok(SubtleEcKeyGenParams {
3158 name: algorithm_name,
3159 named_curve: String::from(get_required_parameter::<DOMString>(
3160 cx,
3161 object,
3162 c"namedCurve",
3163 StringificationBehavior::Default,
3164 )?),
3165 })
3166 }
3167}
3168
3169#[derive(Clone, MallocSizeOf)]
3171pub(crate) struct SubtleEcKeyAlgorithm {
3172 name: CryptoAlgorithm,
3174
3175 named_curve: String,
3177}
3178
3179impl SafeToJSValConvertible for SubtleEcKeyAlgorithm {
3180 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3181 let parent = KeyAlgorithm {
3182 name: self.name.as_str().into(),
3183 };
3184 let dictionary = EcKeyAlgorithm {
3185 parent,
3186 namedCurve: self.named_curve.clone().into(),
3187 };
3188 dictionary.safe_to_jsval(cx, rval, can_gc);
3189 }
3190}
3191
3192impl TryFrom<SerializableEcKeyAlgorithm> for SubtleEcKeyAlgorithm {
3193 type Error = ();
3194
3195 fn try_from(value: SerializableEcKeyAlgorithm) -> Result<Self, Self::Error> {
3196 Ok(SubtleEcKeyAlgorithm {
3197 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3198 named_curve: value.named_curve,
3199 })
3200 }
3201}
3202
3203impl From<&SubtleEcKeyAlgorithm> for SerializableEcKeyAlgorithm {
3204 fn from(value: &SubtleEcKeyAlgorithm) -> Self {
3205 SerializableEcKeyAlgorithm {
3206 name: value.name.as_str().into(),
3207 named_curve: value.named_curve.clone(),
3208 }
3209 }
3210}
3211
3212#[derive(Clone, MallocSizeOf)]
3214struct SubtleEcKeyImportParams {
3215 name: CryptoAlgorithm,
3217
3218 named_curve: String,
3220}
3221
3222impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcKeyImportParams {
3223 type Error = Error;
3224
3225 fn try_from_with_cx_and_name(
3226 object: HandleObject<'a>,
3227 cx: &mut js::context::JSContext,
3228 algorithm_name: CryptoAlgorithm,
3229 ) -> Result<Self, Self::Error> {
3230 Ok(SubtleEcKeyImportParams {
3231 name: algorithm_name,
3232 named_curve: String::from(get_required_parameter::<DOMString>(
3233 cx,
3234 object,
3235 c"namedCurve",
3236 StringificationBehavior::Default,
3237 )?),
3238 })
3239 }
3240}
3241
3242#[derive(Clone, MallocSizeOf)]
3244struct SubtleEcdhKeyDeriveParams {
3245 name: CryptoAlgorithm,
3247
3248 public: Trusted<CryptoKey>,
3250}
3251
3252impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcdhKeyDeriveParams {
3253 type Error = Error;
3254
3255 fn try_from_with_cx_and_name(
3256 object: HandleObject<'a>,
3257 cx: &mut js::context::JSContext,
3258 algorithm_name: CryptoAlgorithm,
3259 ) -> Result<Self, Self::Error> {
3260 let public = get_required_parameter::<DomRoot<CryptoKey>>(cx, object, c"public", ())?;
3261
3262 Ok(SubtleEcdhKeyDeriveParams {
3263 name: algorithm_name,
3264 public: Trusted::new(&public),
3265 })
3266 }
3267}
3268
3269#[derive(Clone, MallocSizeOf)]
3271struct SubtleAesCtrParams {
3272 name: CryptoAlgorithm,
3274
3275 counter: Vec<u8>,
3277
3278 length: u8,
3280}
3281
3282impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesCtrParams {
3283 type Error = Error;
3284
3285 fn try_from_with_cx_and_name(
3286 object: HandleObject<'a>,
3287 cx: &mut js::context::JSContext,
3288 algorithm_name: CryptoAlgorithm,
3289 ) -> Result<Self, Self::Error> {
3290 Ok(SubtleAesCtrParams {
3291 name: algorithm_name,
3292 counter: get_required_buffer_source(cx, object, c"counter")?,
3293 length: get_required_parameter(
3294 cx,
3295 object,
3296 c"length",
3297 ConversionBehavior::EnforceRange,
3298 )?,
3299 })
3300 }
3301}
3302
3303#[derive(Clone, MallocSizeOf)]
3305pub(crate) struct SubtleAesKeyAlgorithm {
3306 name: CryptoAlgorithm,
3308
3309 length: u16,
3311}
3312
3313impl SafeToJSValConvertible for SubtleAesKeyAlgorithm {
3314 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3315 let parent = KeyAlgorithm {
3316 name: self.name.as_str().into(),
3317 };
3318 let dictionary = AesKeyAlgorithm {
3319 parent,
3320 length: self.length,
3321 };
3322 dictionary.safe_to_jsval(cx, rval, can_gc);
3323 }
3324}
3325
3326impl TryFrom<SerializableAesKeyAlgorithm> for SubtleAesKeyAlgorithm {
3327 type Error = ();
3328
3329 fn try_from(value: SerializableAesKeyAlgorithm) -> Result<Self, Self::Error> {
3330 Ok(SubtleAesKeyAlgorithm {
3331 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3332 length: value.length,
3333 })
3334 }
3335}
3336
3337impl From<&SubtleAesKeyAlgorithm> for SerializableAesKeyAlgorithm {
3338 fn from(value: &SubtleAesKeyAlgorithm) -> Self {
3339 SerializableAesKeyAlgorithm {
3340 name: value.name.as_str().into(),
3341 length: value.length,
3342 }
3343 }
3344}
3345
3346#[derive(Clone, MallocSizeOf)]
3348struct SubtleAesKeyGenParams {
3349 name: CryptoAlgorithm,
3351
3352 length: u16,
3354}
3355
3356impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesKeyGenParams {
3357 type Error = Error;
3358
3359 fn try_from_with_cx_and_name(
3360 object: HandleObject<'a>,
3361 cx: &mut js::context::JSContext,
3362 algorithm_name: CryptoAlgorithm,
3363 ) -> Result<Self, Self::Error> {
3364 Ok(SubtleAesKeyGenParams {
3365 name: algorithm_name,
3366 length: get_required_parameter(
3367 cx,
3368 object,
3369 c"length",
3370 ConversionBehavior::EnforceRange,
3371 )?,
3372 })
3373 }
3374}
3375
3376#[derive(Clone, MallocSizeOf)]
3378struct SubtleAesDerivedKeyParams {
3379 name: CryptoAlgorithm,
3381
3382 length: u16,
3384}
3385
3386impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesDerivedKeyParams {
3387 type Error = Error;
3388
3389 fn try_from_with_cx_and_name(
3390 object: HandleObject<'a>,
3391 cx: &mut js::context::JSContext,
3392 algorithm_name: CryptoAlgorithm,
3393 ) -> Result<Self, Self::Error> {
3394 Ok(SubtleAesDerivedKeyParams {
3395 name: algorithm_name,
3396 length: get_required_parameter(
3397 cx,
3398 object,
3399 c"length",
3400 ConversionBehavior::EnforceRange,
3401 )?,
3402 })
3403 }
3404}
3405
3406#[derive(Clone, MallocSizeOf)]
3408struct SubtleAesCbcParams {
3409 name: CryptoAlgorithm,
3411
3412 iv: Vec<u8>,
3414}
3415
3416impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesCbcParams {
3417 type Error = Error;
3418
3419 fn try_from_with_cx_and_name(
3420 object: HandleObject<'a>,
3421 cx: &mut js::context::JSContext,
3422 algorithm_name: CryptoAlgorithm,
3423 ) -> Result<Self, Self::Error> {
3424 Ok(SubtleAesCbcParams {
3425 name: algorithm_name,
3426 iv: get_required_buffer_source(cx, object, c"iv")?,
3427 })
3428 }
3429}
3430
3431#[derive(Clone, MallocSizeOf)]
3433struct SubtleAesGcmParams {
3434 name: CryptoAlgorithm,
3436
3437 iv: Vec<u8>,
3439
3440 additional_data: Option<Vec<u8>>,
3442
3443 tag_length: Option<u8>,
3445}
3446
3447impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesGcmParams {
3448 type Error = Error;
3449
3450 fn try_from_with_cx_and_name(
3451 object: HandleObject<'a>,
3452 cx: &mut js::context::JSContext,
3453 algorithm_name: CryptoAlgorithm,
3454 ) -> Result<Self, Self::Error> {
3455 Ok(SubtleAesGcmParams {
3456 name: algorithm_name,
3457 iv: get_required_buffer_source(cx, object, c"iv")?,
3458 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3459 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3460 })
3461 }
3462}
3463
3464#[derive(Clone, MallocSizeOf)]
3466struct SubtleHmacImportParams {
3467 name: CryptoAlgorithm,
3469
3470 hash: DigestAlgorithm,
3472
3473 length: Option<u32>,
3475}
3476
3477impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHmacImportParams {
3478 type Error = Error;
3479
3480 fn try_from_with_cx_and_name(
3481 object: HandleObject<'a>,
3482 cx: &mut js::context::JSContext,
3483 algorithm_name: CryptoAlgorithm,
3484 ) -> Result<Self, Self::Error> {
3485 let hash = get_required_parameter(cx, object, c"hash", ())?;
3486
3487 Ok(SubtleHmacImportParams {
3488 name: algorithm_name,
3489 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3490 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3491 })
3492 }
3493}
3494
3495#[derive(Clone, MallocSizeOf)]
3497pub(crate) struct SubtleHmacKeyAlgorithm {
3498 name: CryptoAlgorithm,
3500
3501 hash: DigestAlgorithm,
3503
3504 length: u32,
3506}
3507
3508impl SafeToJSValConvertible for SubtleHmacKeyAlgorithm {
3509 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3510 let parent = KeyAlgorithm {
3511 name: self.name.as_str().into(),
3512 };
3513 let hash = KeyAlgorithm {
3514 name: self.hash.name().as_str().into(),
3515 };
3516 let dictionary = HmacKeyAlgorithm {
3517 parent,
3518 hash,
3519 length: self.length,
3520 };
3521 dictionary.safe_to_jsval(cx, rval, can_gc);
3522 }
3523}
3524
3525impl TryFrom<SerializableHmacKeyAlgorithm> for SubtleHmacKeyAlgorithm {
3526 type Error = ();
3527
3528 fn try_from(value: SerializableHmacKeyAlgorithm) -> Result<Self, Self::Error> {
3529 Ok(SubtleHmacKeyAlgorithm {
3530 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3531 hash: value.hash.try_into()?,
3532 length: value.length,
3533 })
3534 }
3535}
3536
3537impl From<&SubtleHmacKeyAlgorithm> for SerializableHmacKeyAlgorithm {
3538 fn from(value: &SubtleHmacKeyAlgorithm) -> Self {
3539 SerializableHmacKeyAlgorithm {
3540 name: value.name.as_str().into(),
3541 hash: (&value.hash).into(),
3542 length: value.length,
3543 }
3544 }
3545}
3546
3547#[derive(Clone, MallocSizeOf)]
3549struct SubtleHmacKeyGenParams {
3550 name: CryptoAlgorithm,
3552
3553 hash: DigestAlgorithm,
3555
3556 length: Option<u32>,
3558}
3559
3560impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHmacKeyGenParams {
3561 type Error = Error;
3562
3563 fn try_from_with_cx_and_name(
3564 object: HandleObject<'a>,
3565 cx: &mut js::context::JSContext,
3566 algorithm_name: CryptoAlgorithm,
3567 ) -> Result<Self, Self::Error> {
3568 let hash = get_required_parameter(cx, object, c"hash", ())?;
3569
3570 Ok(SubtleHmacKeyGenParams {
3571 name: algorithm_name,
3572 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3573 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3574 })
3575 }
3576}
3577
3578#[derive(Clone, MallocSizeOf)]
3580pub(crate) struct SubtleHkdfParams {
3581 name: CryptoAlgorithm,
3583
3584 hash: DigestAlgorithm,
3586
3587 salt: Vec<u8>,
3589
3590 info: Vec<u8>,
3592}
3593
3594impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHkdfParams {
3595 type Error = Error;
3596
3597 fn try_from_with_cx_and_name(
3598 object: HandleObject<'a>,
3599 cx: &mut js::context::JSContext,
3600 algorithm_name: CryptoAlgorithm,
3601 ) -> Result<Self, Self::Error> {
3602 let hash = get_required_parameter(cx, object, c"hash", ())?;
3603
3604 Ok(SubtleHkdfParams {
3605 name: algorithm_name,
3606 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3607 salt: get_required_buffer_source(cx, object, c"salt")?,
3608 info: get_required_buffer_source(cx, object, c"info")?,
3609 })
3610 }
3611}
3612
3613#[derive(Clone, MallocSizeOf)]
3615pub(crate) struct SubtlePbkdf2Params {
3616 name: CryptoAlgorithm,
3618
3619 salt: Vec<u8>,
3621
3622 iterations: u32,
3624
3625 hash: DigestAlgorithm,
3627}
3628
3629impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtlePbkdf2Params {
3630 type Error = Error;
3631
3632 fn try_from_with_cx_and_name(
3633 object: HandleObject<'a>,
3634 cx: &mut js::context::JSContext,
3635 algorithm_name: CryptoAlgorithm,
3636 ) -> Result<Self, Self::Error> {
3637 let hash = get_required_parameter(cx, object, c"hash", ())?;
3638
3639 Ok(SubtlePbkdf2Params {
3640 name: algorithm_name,
3641 salt: get_required_buffer_source(cx, object, c"salt")?,
3642 iterations: get_required_parameter(
3643 cx,
3644 object,
3645 c"iterations",
3646 ConversionBehavior::EnforceRange,
3647 )?,
3648 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3649 })
3650 }
3651}
3652
3653#[derive(Clone, MallocSizeOf)]
3655struct SubtleContextParams {
3656 name: CryptoAlgorithm,
3658
3659 context: Option<Vec<u8>>,
3661}
3662
3663impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleContextParams {
3664 type Error = Error;
3665
3666 fn try_from_with_cx_and_name(
3667 object: HandleObject<'a>,
3668 cx: &mut js::context::JSContext,
3669 algorithm_name: CryptoAlgorithm,
3670 ) -> Result<Self, Self::Error> {
3671 Ok(SubtleContextParams {
3672 name: algorithm_name,
3673 context: get_optional_buffer_source(cx, object, c"context")?,
3674 })
3675 }
3676}
3677
3678#[derive(Clone, MallocSizeOf)]
3680struct SubtleAeadParams {
3681 name: CryptoAlgorithm,
3683
3684 iv: Vec<u8>,
3686
3687 additional_data: Option<Vec<u8>>,
3689
3690 tag_length: Option<u8>,
3692}
3693
3694impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAeadParams {
3695 type Error = Error;
3696
3697 fn try_from_with_cx_and_name(
3698 object: HandleObject<'a>,
3699 cx: &mut js::context::JSContext,
3700 algorithm_name: CryptoAlgorithm,
3701 ) -> Result<Self, Self::Error> {
3702 Ok(SubtleAeadParams {
3703 name: algorithm_name,
3704 iv: get_required_buffer_source(cx, object, c"iv")?,
3705 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3706 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3707 })
3708 }
3709}
3710
3711#[derive(Clone, MallocSizeOf)]
3713struct SubtleCShakeParams {
3714 name: CryptoAlgorithm,
3716
3717 output_length: u32,
3719
3720 function_name: Option<Vec<u8>>,
3722
3723 customization: Option<Vec<u8>>,
3725}
3726
3727impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleCShakeParams {
3728 type Error = Error;
3729
3730 fn try_from_with_cx_and_name(
3731 object: HandleObject<'a>,
3732 cx: &mut js::context::JSContext,
3733 algorithm_name: CryptoAlgorithm,
3734 ) -> Result<Self, Self::Error> {
3735 Ok(SubtleCShakeParams {
3736 name: algorithm_name,
3737 output_length: get_required_parameter(
3738 cx,
3739 object,
3740 c"outputLength",
3741 ConversionBehavior::EnforceRange,
3742 )?,
3743 function_name: get_optional_buffer_source(cx, object, c"functionName")?,
3744 customization: get_optional_buffer_source(cx, object, c"customization")?,
3745 })
3746 }
3747}
3748
3749impl TryFrom<SerializableCShakeParams> for SubtleCShakeParams {
3750 type Error = ();
3751
3752 fn try_from(value: SerializableCShakeParams) -> Result<Self, Self::Error> {
3753 Ok(SubtleCShakeParams {
3754 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3755 output_length: value.output_length,
3756 function_name: value.function_name,
3757 customization: value.customization,
3758 })
3759 }
3760}
3761
3762impl From<&SubtleCShakeParams> for SerializableCShakeParams {
3763 fn from(value: &SubtleCShakeParams) -> Self {
3764 SerializableCShakeParams {
3765 name: value.name.as_str().into(),
3766 output_length: value.output_length,
3767 function_name: value.function_name.clone(),
3768 customization: value.customization.clone(),
3769 }
3770 }
3771}
3772
3773#[derive(Clone, MallocSizeOf)]
3775struct SubtleTurboShakeParams {
3776 name: CryptoAlgorithm,
3778
3779 output_length: u32,
3781
3782 domain_separation: Option<u8>,
3784}
3785
3786impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleTurboShakeParams {
3787 type Error = Error;
3788
3789 fn try_from_with_cx_and_name(
3790 object: HandleObject<'a>,
3791 cx: &mut js::context::JSContext,
3792 algorithm_name: CryptoAlgorithm,
3793 ) -> Result<Self, Self::Error> {
3794 Ok(SubtleTurboShakeParams {
3795 name: algorithm_name,
3796 output_length: get_required_parameter(
3797 cx,
3798 object,
3799 c"outputLength",
3800 ConversionBehavior::EnforceRange,
3801 )?,
3802 domain_separation: get_property(
3803 cx,
3804 object,
3805 c"domainSeparation",
3806 ConversionBehavior::EnforceRange,
3807 )?,
3808 })
3809 }
3810}
3811
3812impl TryFrom<SerializableTurboShakeParams> for SubtleTurboShakeParams {
3813 type Error = ();
3814
3815 fn try_from(value: SerializableTurboShakeParams) -> Result<Self, Self::Error> {
3816 Ok(SubtleTurboShakeParams {
3817 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3818 output_length: value.output_length,
3819 domain_separation: value.domain_separation,
3820 })
3821 }
3822}
3823
3824impl From<&SubtleTurboShakeParams> for SerializableTurboShakeParams {
3825 fn from(value: &SubtleTurboShakeParams) -> Self {
3826 SerializableTurboShakeParams {
3827 name: value.name.as_str().into(),
3828 output_length: value.output_length,
3829 domain_separation: value.domain_separation,
3830 }
3831 }
3832}
3833
3834#[derive(Clone, MallocSizeOf)]
3836struct SubtleArgon2Params {
3837 name: CryptoAlgorithm,
3839
3840 nonce: Vec<u8>,
3842
3843 parallelism: u32,
3845
3846 memory: u32,
3848
3849 passes: u32,
3851
3852 version: Option<u8>,
3854
3855 secret_value: Option<Vec<u8>>,
3857
3858 associated_data: Option<Vec<u8>>,
3860}
3861
3862impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleArgon2Params {
3863 type Error = Error;
3864
3865 fn try_from_with_cx_and_name(
3866 object: HandleObject<'a>,
3867 cx: &mut js::context::JSContext,
3868 algorithm_name: CryptoAlgorithm,
3869 ) -> Result<Self, Self::Error> {
3870 Ok(SubtleArgon2Params {
3871 name: algorithm_name,
3872 nonce: get_required_buffer_source(cx, object, c"nonce")?,
3873 parallelism: get_required_parameter(
3874 cx,
3875 object,
3876 c"parallelism",
3877 ConversionBehavior::EnforceRange,
3878 )?,
3879 memory: get_required_parameter(
3880 cx,
3881 object,
3882 c"memory",
3883 ConversionBehavior::EnforceRange,
3884 )?,
3885 passes: get_required_parameter(
3886 cx,
3887 object,
3888 c"passes",
3889 ConversionBehavior::EnforceRange,
3890 )?,
3891 version: get_property(cx, object, c"version", ConversionBehavior::EnforceRange)?,
3892 secret_value: get_optional_buffer_source(cx, object, c"secretValue")?,
3893 associated_data: get_optional_buffer_source(cx, object, c"associatedData")?,
3894 })
3895 }
3896}
3897
3898struct SubtleEncapsulatedKey {
3900 shared_key: Option<Trusted<CryptoKey>>,
3902
3903 ciphertext: Option<Vec<u8>>,
3905}
3906
3907impl SafeToJSValConvertible for SubtleEncapsulatedKey {
3908 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3909 let shared_key = self.shared_key.as_ref().map(|shared_key| shared_key.root());
3910 let ciphertext = self.ciphertext.as_ref().map(|data| {
3911 rooted!(in(*cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
3912 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut(), can_gc)
3913 .expect("Failed to convert ciphertext to ArrayBufferU8")
3914 });
3915 let encapsulated_key = RootedTraceableBox::new(EncapsulatedKey {
3916 sharedKey: shared_key,
3917 ciphertext,
3918 });
3919 encapsulated_key.safe_to_jsval(cx, rval, can_gc);
3920 }
3921}
3922
3923struct SubtleEncapsulatedBits {
3925 shared_key: Option<Zeroizing<Vec<u8>>>,
3927
3928 ciphertext: Option<Vec<u8>>,
3930}
3931
3932impl SafeToJSValConvertible for SubtleEncapsulatedBits {
3933 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3934 let shared_key = self.shared_key.as_ref().map(|data| {
3935 rooted!(in(*cx) let mut shared_key_ptr = ptr::null_mut::<JSObject>());
3936 create_buffer_source::<ArrayBufferU8>(cx, data, shared_key_ptr.handle_mut(), can_gc)
3937 .expect("Failed to convert shared key to ArrayBufferU8")
3938 });
3939 let ciphertext = self.ciphertext.as_ref().map(|data| {
3940 rooted!(in(*cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
3941 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut(), can_gc)
3942 .expect("Failed to convert ciphertext to ArrayBufferU8")
3943 });
3944 let encapsulated_bits = RootedTraceableBox::new(EncapsulatedBits {
3945 sharedKey: shared_key,
3946 ciphertext,
3947 });
3948 encapsulated_bits.safe_to_jsval(cx, rval, can_gc);
3949 }
3950}
3951
3952fn get_required_parameter<T: FromJSValConvertible>(
3954 cx: &mut js::context::JSContext,
3955 object: HandleObject,
3956 parameter: &std::ffi::CStr,
3957 option: T::Config,
3958) -> Fallible<T> {
3959 get_property::<T>(cx, object, parameter, option)?
3960 .ok_or(Error::Type(c"Missing required parameter".into()))
3961}
3962
3963fn get_required_parameter_in_box<T: FromJSValConvertible + Trace>(
3965 cx: &mut js::context::JSContext,
3966 object: HandleObject,
3967 parameter: &std::ffi::CStr,
3968 option: T::Config,
3969) -> Fallible<RootedTraceableBox<T>> {
3970 get_property::<T>(cx, object, parameter, option)?
3971 .map(RootedTraceableBox::new)
3972 .ok_or(Error::Type(c"Missing required parameter".into()))
3973}
3974
3975fn get_optional_buffer_source(
3979 cx: &mut js::context::JSContext,
3980 object: HandleObject,
3981 parameter: &std::ffi::CStr,
3982) -> Fallible<Option<Vec<u8>>> {
3983 let buffer_source = get_property::<ArrayBufferViewOrArrayBuffer>(cx, object, parameter, ())?;
3984 match buffer_source {
3985 Some(ArrayBufferViewOrArrayBuffer::ArrayBufferView(view)) => Ok(Some(view.to_vec())),
3986 Some(ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer)) => Ok(Some(buffer.to_vec())),
3987 None => Ok(None),
3988 }
3989}
3990
3991fn get_required_buffer_source(
3995 cx: &mut js::context::JSContext,
3996 object: HandleObject,
3997 parameter: &std::ffi::CStr,
3998) -> Fallible<Vec<u8>> {
3999 get_optional_buffer_source(cx, object, parameter)?
4000 .ok_or(Error::Type(c"Missing required parameter".into()))
4001}
4002
4003enum ExportedKey {
4007 Bytes(Zeroizing<Vec<u8>>),
4008 Jwk(Box<JsonWebKey>),
4009}
4010
4011impl ExportedKey {
4012 fn new_bytes(bytes: Vec<u8>) -> ExportedKey {
4013 ExportedKey::Bytes(Zeroizing::new(bytes))
4014 }
4015
4016 fn new_jwk(jwk: JsonWebKey) -> ExportedKey {
4017 ExportedKey::Jwk(Box::new(jwk))
4018 }
4019}
4020
4021#[derive(Clone, MallocSizeOf)]
4025#[expect(clippy::enum_variant_names)]
4026pub(crate) enum KeyAlgorithmAndDerivatives {
4027 KeyAlgorithm(SubtleKeyAlgorithm),
4028 RsaHashedKeyAlgorithm(SubtleRsaHashedKeyAlgorithm),
4029 EcKeyAlgorithm(SubtleEcKeyAlgorithm),
4030 AesKeyAlgorithm(SubtleAesKeyAlgorithm),
4031 HmacKeyAlgorithm(SubtleHmacKeyAlgorithm),
4032}
4033
4034impl KeyAlgorithmAndDerivatives {
4035 fn name(&self) -> CryptoAlgorithm {
4036 match self {
4037 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => algorithm.name,
4038 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => algorithm.name,
4039 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => algorithm.name,
4040 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => algorithm.name,
4041 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => algorithm.name,
4042 }
4043 }
4044}
4045
4046impl SafeToJSValConvertible for KeyAlgorithmAndDerivatives {
4047 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
4048 match self {
4049 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval, can_gc),
4050 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => {
4051 algo.safe_to_jsval(cx, rval, can_gc)
4052 },
4053 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => {
4054 algo.safe_to_jsval(cx, rval, can_gc)
4055 },
4056 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => {
4057 algo.safe_to_jsval(cx, rval, can_gc)
4058 },
4059 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => {
4060 algo.safe_to_jsval(cx, rval, can_gc)
4061 },
4062 }
4063 }
4064}
4065
4066impl TryFrom<SerializableKeyAlgorithmAndDerivatives> for KeyAlgorithmAndDerivatives {
4067 type Error = ();
4068
4069 fn try_from(value: SerializableKeyAlgorithmAndDerivatives) -> Result<Self, Self::Error> {
4070 match value {
4071 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => Ok(
4072 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.try_into()?),
4073 ),
4074 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => Ok(
4075 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.try_into()?),
4076 ),
4077 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => Ok(
4078 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.try_into()?),
4079 ),
4080 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => Ok(
4081 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.try_into()?),
4082 ),
4083 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => Ok(
4084 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.try_into()?),
4085 ),
4086 }
4087 }
4088}
4089
4090impl From<&KeyAlgorithmAndDerivatives> for SerializableKeyAlgorithmAndDerivatives {
4091 fn from(value: &KeyAlgorithmAndDerivatives) -> Self {
4092 match value {
4093 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => {
4094 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.into())
4095 },
4096 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => {
4097 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.into())
4098 },
4099 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => {
4100 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.into())
4101 },
4102 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => {
4103 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.into())
4104 },
4105 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => {
4106 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.into())
4107 },
4108 }
4109 }
4110}
4111
4112#[derive(Clone, Copy)]
4113enum JwkStringField {
4114 X,
4115 Y,
4116 D,
4117 N,
4118 E,
4119 P,
4120 Q,
4121 DP,
4122 DQ,
4123 QI,
4124 K,
4125 Priv,
4126 Pub,
4127}
4128
4129impl Display for JwkStringField {
4130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4131 let field_name = match self {
4132 JwkStringField::X => "x",
4133 JwkStringField::Y => "y",
4134 JwkStringField::D => "d",
4135 JwkStringField::N => "n",
4136 JwkStringField::E => "e",
4137 JwkStringField::P => "q",
4138 JwkStringField::Q => "q",
4139 JwkStringField::DP => "dp",
4140 JwkStringField::DQ => "dq",
4141 JwkStringField::QI => "qi",
4142 JwkStringField::K => "k",
4143 JwkStringField::Priv => "priv",
4144 JwkStringField::Pub => "pub",
4145 };
4146 write!(f, "{}", field_name)
4147 }
4148}
4149
4150trait JsonWebKeyExt {
4151 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
4152 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error>;
4153 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
4154 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
4155 fn set_key_ops(&mut self, usages: Vec<KeyUsage>);
4156 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]);
4157 fn decode_optional_string_field(
4158 &self,
4159 field: JwkStringField,
4160 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error>;
4161 fn decode_required_string_field(
4162 &self,
4163 field: JwkStringField,
4164 ) -> Result<Zeroizing<Vec<u8>>, Error>;
4165 fn decode_primes_from_oth_field(
4166 &self,
4167 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4168 ) -> Result<(), Error>;
4169}
4170
4171impl JsonWebKeyExt for JsonWebKey {
4172 #[expect(unsafe_code)]
4174 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
4175 let json = String::from_utf8_lossy(data);
4180
4181 let json: Vec<_> = json.encode_utf16().collect();
4183
4184 rooted!(&in(cx) let mut result = UndefinedValue());
4188 unsafe {
4189 if !JS_ParseJSON(cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
4190 return Err(Error::JSFailed);
4191 }
4192 }
4193
4194 let key = match JsonWebKey::new(cx, result.handle()) {
4196 Ok(ConversionResult::Success(key)) => key,
4197 Ok(ConversionResult::Failure(error)) => {
4198 return Err(Error::Type(error.into_owned()));
4199 },
4200 Err(()) => {
4201 return Err(Error::JSFailed);
4202 },
4203 };
4204
4205 if key.kty.is_none() {
4207 return Err(Error::Data(None));
4208 }
4209
4210 Ok(key)
4212 }
4213
4214 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error> {
4220 rooted!(&in(cx) let mut data = UndefinedValue());
4221 self.safe_to_jsval(cx.into(), data.handle_mut(), CanGc::from_cx(cx));
4222 serialize_jsval_to_json_utf8(cx.into(), data.handle()).map(Zeroizing::new)
4223 }
4224
4225 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
4226 let mut usages = vec![];
4227 for op in self.key_ops.as_ref().ok_or(Error::Data(None))? {
4228 usages.push(KeyUsage::from_str(&op.str()).map_err(|_| Error::Data(None))?);
4229 }
4230 Ok(usages)
4231 }
4232
4233 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
4237 if let Some(ref key_ops) = self.key_ops {
4239 if key_ops
4242 .iter()
4243 .collect::<std::collections::HashSet<_>>()
4244 .len() <
4245 key_ops.len()
4246 {
4247 return Err(Error::Data(None));
4248 }
4249 if let Some(ref use_) = self.use_ &&
4252 key_ops.iter().any(|op| op != use_)
4253 {
4254 return Err(Error::Data(None));
4255 }
4256
4257 let key_ops_as_usages = self.get_usages_from_key_ops()?;
4259 if !specified_usages
4260 .iter()
4261 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
4262 {
4263 return Err(Error::Data(None));
4264 }
4265 }
4266
4267 Ok(())
4268 }
4269
4270 fn set_key_ops(&mut self, usages: Vec<KeyUsage>) {
4272 self.key_ops = Some(
4273 usages
4274 .into_iter()
4275 .map(|usage| DOMString::from(usage.as_str()))
4276 .collect(),
4277 );
4278 }
4279
4280 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]) {
4283 let encoded_data = DOMString::from(Base64UrlUnpadded::encode_string(data));
4284 match field {
4285 JwkStringField::X => self.x = Some(encoded_data),
4286 JwkStringField::Y => self.y = Some(encoded_data),
4287 JwkStringField::D => self.d = Some(encoded_data),
4288 JwkStringField::N => self.n = Some(encoded_data),
4289 JwkStringField::E => self.e = Some(encoded_data),
4290 JwkStringField::P => self.p = Some(encoded_data),
4291 JwkStringField::Q => self.q = Some(encoded_data),
4292 JwkStringField::DP => self.dp = Some(encoded_data),
4293 JwkStringField::DQ => self.dq = Some(encoded_data),
4294 JwkStringField::QI => self.qi = Some(encoded_data),
4295 JwkStringField::K => self.k = Some(encoded_data),
4296 JwkStringField::Priv => self.priv_ = Some(encoded_data),
4297 JwkStringField::Pub => self.pub_ = Some(encoded_data),
4298 }
4299 }
4300
4301 fn decode_optional_string_field(
4304 &self,
4305 field: JwkStringField,
4306 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error> {
4307 let field_string = match field {
4308 JwkStringField::X => &self.x,
4309 JwkStringField::Y => &self.y,
4310 JwkStringField::D => &self.d,
4311 JwkStringField::N => &self.n,
4312 JwkStringField::E => &self.e,
4313 JwkStringField::P => &self.p,
4314 JwkStringField::Q => &self.q,
4315 JwkStringField::DP => &self.dp,
4316 JwkStringField::DQ => &self.dq,
4317 JwkStringField::QI => &self.qi,
4318 JwkStringField::K => &self.k,
4319 JwkStringField::Priv => &self.priv_,
4320 JwkStringField::Pub => &self.pub_,
4321 };
4322
4323 field_string
4324 .as_ref()
4325 .map(|field_string| {
4326 Base64UrlUnpadded::decode_vec(&field_string.str()).map(Zeroizing::new)
4327 })
4328 .transpose()
4329 .map_err(|_| Error::Data(Some(format!("Failed to decode {} field in jwk", field))))
4330 }
4331
4332 fn decode_required_string_field(
4335 &self,
4336 field: JwkStringField,
4337 ) -> Result<Zeroizing<Vec<u8>>, Error> {
4338 self.decode_optional_string_field(field)?
4339 .ok_or(Error::Data(Some(format!(
4340 "The {} field is not present in jwk",
4341 field
4342 ))))
4343 }
4344
4345 fn decode_primes_from_oth_field(
4354 &self,
4355 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4356 ) -> Result<(), Error> {
4357 if self.oth.is_some() &&
4358 (self.p.is_none() ||
4359 self.q.is_none() ||
4360 self.dp.is_none() ||
4361 self.dq.is_none() ||
4362 self.qi.is_none())
4363 {
4364 return Err(Error::Data(Some(
4365 "The oth field is present while at least one of p, q, dp, dq, qi is missing, in jwk".to_string()
4366 )));
4367 }
4368
4369 for rsa_other_prime_info in self.oth.as_ref().unwrap_or(&Vec::new()) {
4370 let r = Base64UrlUnpadded::decode_vec(
4371 &rsa_other_prime_info
4372 .r
4373 .as_ref()
4374 .ok_or(Error::Data(Some(
4375 "The r field is not present in one of the entry of oth field in jwk"
4376 .to_string(),
4377 )))?
4378 .str(),
4379 )
4380 .map_err(|_| {
4381 Error::Data(Some(
4382 "Fail to decode r field in one of the entry of oth field in jwk".to_string(),
4383 ))
4384 })?;
4385 primes.push(Zeroizing::new(r));
4386
4387 let _d = Base64UrlUnpadded::decode_vec(
4388 &rsa_other_prime_info
4389 .d
4390 .as_ref()
4391 .ok_or(Error::Data(Some(
4392 "The d field is not present in one of the entry of oth field in jwk"
4393 .to_string(),
4394 )))?
4395 .str(),
4396 )
4397 .map_err(|_| {
4398 Error::Data(Some(
4399 "Fail to decode d field in one of the entry of oth field in jwk".to_string(),
4400 ))
4401 })?;
4402
4403 let _t = Base64UrlUnpadded::decode_vec(
4404 &rsa_other_prime_info
4405 .t
4406 .as_ref()
4407 .ok_or(Error::Data(Some(
4408 "The t field is not present in one of the entry of oth field in jwk"
4409 .to_string(),
4410 )))?
4411 .str(),
4412 )
4413 .map_err(|_| {
4414 Error::Data(Some(
4415 "Fail to decode t field in one of the entry of oth field in jwk".to_string(),
4416 ))
4417 })?;
4418 }
4419
4420 Ok(())
4421 }
4422}
4423
4424fn normalize_algorithm<Op: Operation>(
4426 cx: &mut js::context::JSContext,
4427 algorithm: &AlgorithmIdentifier,
4428) -> Result<Op::RegisteredAlgorithm, Error> {
4429 match algorithm {
4430 ObjectOrString::String(name) => {
4432 let algorithm = Algorithm {
4436 name: name.to_owned(),
4437 };
4438 rooted!(&in(cx) let mut algorithm_value = UndefinedValue());
4439 algorithm.safe_to_jsval(cx.into(), algorithm_value.handle_mut(), CanGc::from_cx(cx));
4440 let algorithm_object = RootedTraceableBox::new(Heap::default());
4441 algorithm_object.set(algorithm_value.to_object());
4442 normalize_algorithm::<Op>(cx, &ObjectOrString::Object(algorithm_object))
4443 },
4444 ObjectOrString::Object(object) => {
4446 let algorithm_name = get_required_parameter::<DOMString>(
4454 cx,
4455 object.handle(),
4456 c"name",
4457 StringificationBehavior::Default,
4458 )?;
4459
4460 let algorithm_name = CryptoAlgorithm::from_str_ignore_case(&algorithm_name.str())?;
4501 let normalized_algorithm =
4502 Op::RegisteredAlgorithm::from_object(cx, algorithm_name, object.handle())?;
4503
4504 Ok(normalized_algorithm)
4506 },
4507 }
4508}
4509
4510trait Operation {
4564 type RegisteredAlgorithm: NormalizedAlgorithm;
4565}
4566
4567trait NormalizedAlgorithm: Sized {
4568 fn from_object(
4570 cx: &mut js::context::JSContext,
4571 algorithm_name: CryptoAlgorithm,
4572 object: HandleObject,
4573 ) -> Fallible<Self>;
4574 fn name(&self) -> CryptoAlgorithm;
4575}
4576
4577struct EncryptOperation {}
4579
4580impl Operation for EncryptOperation {
4581 type RegisteredAlgorithm = EncryptAlgorithm;
4582}
4583
4584enum EncryptAlgorithm {
4587 RsaOaep(SubtleRsaOaepParams),
4588 AesCtr(SubtleAesCtrParams),
4589 AesCbc(SubtleAesCbcParams),
4590 AesGcm(SubtleAesGcmParams),
4591 AesOcb(SubtleAeadParams),
4592 ChaCha20Poly1305(SubtleAeadParams),
4593}
4594
4595impl NormalizedAlgorithm for EncryptAlgorithm {
4596 fn from_object(
4597 cx: &mut js::context::JSContext,
4598 algorithm_name: CryptoAlgorithm,
4599 object: HandleObject,
4600 ) -> Fallible<Self> {
4601 match algorithm_name {
4602 CryptoAlgorithm::RsaOaep => Ok(EncryptAlgorithm::RsaOaep(
4603 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4604 )),
4605 CryptoAlgorithm::AesCtr => Ok(EncryptAlgorithm::AesCtr(
4606 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4607 )),
4608 CryptoAlgorithm::AesCbc => Ok(EncryptAlgorithm::AesCbc(
4609 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4610 )),
4611 CryptoAlgorithm::AesGcm => Ok(EncryptAlgorithm::AesGcm(
4612 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4613 )),
4614 CryptoAlgorithm::AesOcb => Ok(EncryptAlgorithm::AesOcb(
4615 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4616 )),
4617 CryptoAlgorithm::ChaCha20Poly1305 => Ok(EncryptAlgorithm::ChaCha20Poly1305(
4618 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4619 )),
4620 _ => Err(Error::NotSupported(Some(format!(
4621 "{} does not support \"encrypt\" operation",
4622 algorithm_name.as_str()
4623 )))),
4624 }
4625 }
4626
4627 fn name(&self) -> CryptoAlgorithm {
4628 match self {
4629 EncryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
4630 EncryptAlgorithm::AesCtr(algorithm) => algorithm.name,
4631 EncryptAlgorithm::AesCbc(algorithm) => algorithm.name,
4632 EncryptAlgorithm::AesGcm(algorithm) => algorithm.name,
4633 EncryptAlgorithm::AesOcb(algorithm) => algorithm.name,
4634 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4635 }
4636 }
4637}
4638
4639impl EncryptAlgorithm {
4640 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
4641 match self {
4642 EncryptAlgorithm::RsaOaep(algorithm) => {
4643 rsa_oaep_operation::encrypt(algorithm, key, plaintext)
4644 },
4645 EncryptAlgorithm::AesCtr(algorithm) => {
4646 aes_ctr_operation::encrypt(algorithm, key, plaintext)
4647 },
4648 EncryptAlgorithm::AesCbc(algorithm) => {
4649 aes_cbc_operation::encrypt(algorithm, key, plaintext)
4650 },
4651 EncryptAlgorithm::AesGcm(algorithm) => {
4652 aes_gcm_operation::encrypt(algorithm, key, plaintext)
4653 },
4654 EncryptAlgorithm::AesOcb(algorithm) => {
4655 aes_ocb_operation::encrypt(algorithm, key, plaintext)
4656 },
4657 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => {
4658 chacha20_poly1305_operation::encrypt(algorithm, key, plaintext)
4659 },
4660 }
4661 }
4662}
4663
4664struct DecryptOperation {}
4666
4667impl Operation for DecryptOperation {
4668 type RegisteredAlgorithm = DecryptAlgorithm;
4669}
4670
4671enum DecryptAlgorithm {
4674 RsaOaep(SubtleRsaOaepParams),
4675 AesCtr(SubtleAesCtrParams),
4676 AesCbc(SubtleAesCbcParams),
4677 AesGcm(SubtleAesGcmParams),
4678 AesOcb(SubtleAeadParams),
4679 ChaCha20Poly1305(SubtleAeadParams),
4680}
4681
4682impl NormalizedAlgorithm for DecryptAlgorithm {
4683 fn from_object(
4684 cx: &mut js::context::JSContext,
4685 algorithm_name: CryptoAlgorithm,
4686 object: HandleObject,
4687 ) -> Fallible<Self> {
4688 match algorithm_name {
4689 CryptoAlgorithm::RsaOaep => Ok(DecryptAlgorithm::RsaOaep(
4690 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4691 )),
4692 CryptoAlgorithm::AesCtr => Ok(DecryptAlgorithm::AesCtr(
4693 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4694 )),
4695 CryptoAlgorithm::AesCbc => Ok(DecryptAlgorithm::AesCbc(
4696 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4697 )),
4698 CryptoAlgorithm::AesGcm => Ok(DecryptAlgorithm::AesGcm(
4699 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4700 )),
4701 CryptoAlgorithm::AesOcb => Ok(DecryptAlgorithm::AesOcb(
4702 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4703 )),
4704 CryptoAlgorithm::ChaCha20Poly1305 => Ok(DecryptAlgorithm::ChaCha20Poly1305(
4705 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4706 )),
4707 _ => Err(Error::NotSupported(Some(format!(
4708 "{} does not support \"decrypt\" operation",
4709 algorithm_name.as_str()
4710 )))),
4711 }
4712 }
4713
4714 fn name(&self) -> CryptoAlgorithm {
4715 match self {
4716 DecryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
4717 DecryptAlgorithm::AesCtr(algorithm) => algorithm.name,
4718 DecryptAlgorithm::AesCbc(algorithm) => algorithm.name,
4719 DecryptAlgorithm::AesGcm(algorithm) => algorithm.name,
4720 DecryptAlgorithm::AesOcb(algorithm) => algorithm.name,
4721 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4722 }
4723 }
4724}
4725
4726impl DecryptAlgorithm {
4727 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
4728 match self {
4729 DecryptAlgorithm::RsaOaep(algorithm) => {
4730 rsa_oaep_operation::decrypt(algorithm, key, ciphertext)
4731 },
4732 DecryptAlgorithm::AesCtr(algorithm) => {
4733 aes_ctr_operation::decrypt(algorithm, key, ciphertext)
4734 },
4735 DecryptAlgorithm::AesCbc(algorithm) => {
4736 aes_cbc_operation::decrypt(algorithm, key, ciphertext)
4737 },
4738 DecryptAlgorithm::AesGcm(algorithm) => {
4739 aes_gcm_operation::decrypt(algorithm, key, ciphertext)
4740 },
4741 DecryptAlgorithm::AesOcb(algorithm) => {
4742 aes_ocb_operation::decrypt(algorithm, key, ciphertext)
4743 },
4744 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => {
4745 chacha20_poly1305_operation::decrypt(algorithm, key, ciphertext)
4746 },
4747 }
4748 }
4749}
4750
4751struct SignOperation {}
4753
4754impl Operation for SignOperation {
4755 type RegisteredAlgorithm = SignAlgorithm;
4756}
4757
4758enum SignAlgorithm {
4761 RsassaPkcs1V1_5(SubtleAlgorithm),
4762 RsaPss(SubtleRsaPssParams),
4763 Ecdsa(SubtleEcdsaParams),
4764 Ed25519(SubtleAlgorithm),
4765 Hmac(SubtleAlgorithm),
4766 MlDsa(SubtleContextParams),
4767}
4768
4769impl NormalizedAlgorithm for SignAlgorithm {
4770 fn from_object(
4771 cx: &mut js::context::JSContext,
4772 algorithm_name: CryptoAlgorithm,
4773 object: HandleObject,
4774 ) -> Fallible<Self> {
4775 match algorithm_name {
4776 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(SignAlgorithm::RsassaPkcs1V1_5(
4777 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4778 )),
4779 CryptoAlgorithm::RsaPss => Ok(SignAlgorithm::RsaPss(
4780 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4781 )),
4782 CryptoAlgorithm::Ecdsa => Ok(SignAlgorithm::Ecdsa(
4783 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4784 )),
4785 CryptoAlgorithm::Ed25519 => Ok(SignAlgorithm::Ed25519(
4786 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4787 )),
4788 CryptoAlgorithm::Hmac => Ok(SignAlgorithm::Hmac(
4789 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4790 )),
4791 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
4792 SignAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
4793 ),
4794 _ => Err(Error::NotSupported(Some(format!(
4795 "{} does not support \"sign\" operation",
4796 algorithm_name.as_str()
4797 )))),
4798 }
4799 }
4800
4801 fn name(&self) -> CryptoAlgorithm {
4802 match self {
4803 SignAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
4804 SignAlgorithm::RsaPss(algorithm) => algorithm.name,
4805 SignAlgorithm::Ecdsa(algorithm) => algorithm.name,
4806 SignAlgorithm::Ed25519(algorithm) => algorithm.name,
4807 SignAlgorithm::Hmac(algorithm) => algorithm.name,
4808 SignAlgorithm::MlDsa(algorithm) => algorithm.name,
4809 }
4810 }
4811}
4812
4813impl SignAlgorithm {
4814 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
4815 match self {
4816 SignAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
4817 rsassa_pkcs1_v1_5_operation::sign(key, message)
4818 },
4819 SignAlgorithm::RsaPss(algorithm) => rsa_pss_operation::sign(algorithm, key, message),
4820 SignAlgorithm::Ecdsa(algorithm) => ecdsa_operation::sign(algorithm, key, message),
4821 SignAlgorithm::Ed25519(_algorithm) => ed25519_operation::sign(key, message),
4822 SignAlgorithm::Hmac(_algorithm) => hmac_operation::sign(key, message),
4823 SignAlgorithm::MlDsa(algorithm) => ml_dsa_operation::sign(algorithm, key, message),
4824 }
4825 }
4826}
4827
4828struct VerifyOperation {}
4830
4831impl Operation for VerifyOperation {
4832 type RegisteredAlgorithm = VerifyAlgorithm;
4833}
4834
4835enum VerifyAlgorithm {
4838 RsassaPkcs1V1_5(SubtleAlgorithm),
4839 RsaPss(SubtleRsaPssParams),
4840 Ecdsa(SubtleEcdsaParams),
4841 Ed25519(SubtleAlgorithm),
4842 Hmac(SubtleAlgorithm),
4843 MlDsa(SubtleContextParams),
4844}
4845
4846impl NormalizedAlgorithm for VerifyAlgorithm {
4847 fn from_object(
4848 cx: &mut js::context::JSContext,
4849 algorithm_name: CryptoAlgorithm,
4850 object: HandleObject,
4851 ) -> Fallible<Self> {
4852 match algorithm_name {
4853 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(VerifyAlgorithm::RsassaPkcs1V1_5(
4854 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4855 )),
4856 CryptoAlgorithm::RsaPss => Ok(VerifyAlgorithm::RsaPss(
4857 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4858 )),
4859 CryptoAlgorithm::Ecdsa => Ok(VerifyAlgorithm::Ecdsa(
4860 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4861 )),
4862 CryptoAlgorithm::Ed25519 => Ok(VerifyAlgorithm::Ed25519(
4863 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4864 )),
4865 CryptoAlgorithm::Hmac => Ok(VerifyAlgorithm::Hmac(
4866 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4867 )),
4868 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
4869 VerifyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
4870 ),
4871 _ => Err(Error::NotSupported(Some(format!(
4872 "{} does not support \"verify\" operation",
4873 algorithm_name.as_str()
4874 )))),
4875 }
4876 }
4877
4878 fn name(&self) -> CryptoAlgorithm {
4879 match self {
4880 VerifyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
4881 VerifyAlgorithm::RsaPss(algorithm) => algorithm.name,
4882 VerifyAlgorithm::Ecdsa(algorithm) => algorithm.name,
4883 VerifyAlgorithm::Ed25519(algorithm) => algorithm.name,
4884 VerifyAlgorithm::Hmac(algorithm) => algorithm.name,
4885 VerifyAlgorithm::MlDsa(algorithm) => algorithm.name,
4886 }
4887 }
4888}
4889
4890impl VerifyAlgorithm {
4891 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
4892 match self {
4893 VerifyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
4894 rsassa_pkcs1_v1_5_operation::verify(key, message, signature)
4895 },
4896 VerifyAlgorithm::RsaPss(algorithm) => {
4897 rsa_pss_operation::verify(algorithm, key, message, signature)
4898 },
4899 VerifyAlgorithm::Ecdsa(algorithm) => {
4900 ecdsa_operation::verify(algorithm, key, message, signature)
4901 },
4902 VerifyAlgorithm::Ed25519(_algorithm) => {
4903 ed25519_operation::verify(key, message, signature)
4904 },
4905 VerifyAlgorithm::Hmac(_algorithm) => hmac_operation::verify(key, message, signature),
4906 VerifyAlgorithm::MlDsa(algorithm) => {
4907 ml_dsa_operation::verify(algorithm, key, message, signature)
4908 },
4909 }
4910 }
4911}
4912
4913struct DigestOperation {}
4915
4916impl Operation for DigestOperation {
4917 type RegisteredAlgorithm = DigestAlgorithm;
4918}
4919
4920#[derive(Clone, MallocSizeOf)]
4923enum DigestAlgorithm {
4924 Sha(SubtleAlgorithm),
4925 Sha3(SubtleAlgorithm),
4926 CShake(SubtleCShakeParams),
4927 TurboShake(SubtleTurboShakeParams),
4928}
4929
4930impl NormalizedAlgorithm for DigestAlgorithm {
4931 fn from_object(
4932 cx: &mut js::context::JSContext,
4933 algorithm_name: CryptoAlgorithm,
4934 object: HandleObject,
4935 ) -> Fallible<Self> {
4936 match algorithm_name {
4937 CryptoAlgorithm::Sha1 |
4938 CryptoAlgorithm::Sha256 |
4939 CryptoAlgorithm::Sha384 |
4940 CryptoAlgorithm::Sha512 => Ok(DigestAlgorithm::Sha(
4941 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4942 )),
4943 CryptoAlgorithm::Sha3_256 | CryptoAlgorithm::Sha3_384 | CryptoAlgorithm::Sha3_512 => {
4944 Ok(DigestAlgorithm::Sha3(
4945 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4946 ))
4947 },
4948 CryptoAlgorithm::CShake128 | CryptoAlgorithm::CShake256 => Ok(DigestAlgorithm::CShake(
4949 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4950 )),
4951 CryptoAlgorithm::TurboShake128 | CryptoAlgorithm::TurboShake256 => Ok(
4952 DigestAlgorithm::TurboShake(object.try_into_with_cx_and_name(cx, algorithm_name)?),
4953 ),
4954 _ => Err(Error::NotSupported(Some(format!(
4955 "{} does not support \"digest\" operation",
4956 algorithm_name.as_str()
4957 )))),
4958 }
4959 }
4960
4961 fn name(&self) -> CryptoAlgorithm {
4962 match self {
4963 DigestAlgorithm::Sha(algorithm) => algorithm.name,
4964 DigestAlgorithm::Sha3(algorithm) => algorithm.name,
4965 DigestAlgorithm::CShake(algorithm) => algorithm.name,
4966 DigestAlgorithm::TurboShake(algorithm) => algorithm.name,
4967 }
4968 }
4969}
4970
4971impl DigestAlgorithm {
4972 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
4973 match self {
4974 DigestAlgorithm::Sha(algorithm) => sha_operation::digest(algorithm, message),
4975 DigestAlgorithm::Sha3(algorithm) => sha3_operation::digest(algorithm, message),
4976 DigestAlgorithm::CShake(algorithm) => cshake_operation::digest(algorithm, message),
4977 DigestAlgorithm::TurboShake(algorithm) => {
4978 turboshake_operation::digest(algorithm, message)
4979 },
4980 }
4981 }
4982}
4983
4984impl TryFrom<SerializableDigestAlgorithm> for DigestAlgorithm {
4985 type Error = ();
4986
4987 fn try_from(value: SerializableDigestAlgorithm) -> Result<Self, Self::Error> {
4988 match value {
4989 SerializableDigestAlgorithm::Sha(algorithm) => {
4990 Ok(DigestAlgorithm::Sha(algorithm.try_into()?))
4991 },
4992 SerializableDigestAlgorithm::Sha3(algorithm) => {
4993 Ok(DigestAlgorithm::Sha3(algorithm.try_into()?))
4994 },
4995 SerializableDigestAlgorithm::CShake(algorithm) => {
4996 Ok(DigestAlgorithm::CShake(algorithm.try_into()?))
4997 },
4998 SerializableDigestAlgorithm::TurboShake(algorithm) => {
4999 Ok(DigestAlgorithm::TurboShake(algorithm.try_into()?))
5000 },
5001 }
5002 }
5003}
5004
5005impl From<&DigestAlgorithm> for SerializableDigestAlgorithm {
5006 fn from(value: &DigestAlgorithm) -> Self {
5007 match value {
5008 DigestAlgorithm::Sha(algorithm) => SerializableDigestAlgorithm::Sha(algorithm.into()),
5009 DigestAlgorithm::Sha3(algorithm) => SerializableDigestAlgorithm::Sha3(algorithm.into()),
5010 DigestAlgorithm::CShake(algorithm) => {
5011 SerializableDigestAlgorithm::CShake(algorithm.into())
5012 },
5013 DigestAlgorithm::TurboShake(algorithm) => {
5014 SerializableDigestAlgorithm::TurboShake(algorithm.into())
5015 },
5016 }
5017 }
5018}
5019
5020struct DeriveBitsOperation {}
5022
5023impl Operation for DeriveBitsOperation {
5024 type RegisteredAlgorithm = DeriveBitsAlgorithm;
5025}
5026
5027enum DeriveBitsAlgorithm {
5030 Ecdh(SubtleEcdhKeyDeriveParams),
5031 X25519(SubtleEcdhKeyDeriveParams),
5032 Hkdf(SubtleHkdfParams),
5033 Pbkdf2(SubtlePbkdf2Params),
5034 Argon2(SubtleArgon2Params),
5035}
5036
5037impl NormalizedAlgorithm for DeriveBitsAlgorithm {
5038 fn from_object(
5039 cx: &mut js::context::JSContext,
5040 algorithm_name: CryptoAlgorithm,
5041 object: HandleObject,
5042 ) -> Fallible<Self> {
5043 match algorithm_name {
5044 CryptoAlgorithm::Ecdh => Ok(DeriveBitsAlgorithm::Ecdh(
5045 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5046 )),
5047 CryptoAlgorithm::X25519 => Ok(DeriveBitsAlgorithm::X25519(
5048 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5049 )),
5050 CryptoAlgorithm::Hkdf => Ok(DeriveBitsAlgorithm::Hkdf(
5051 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5052 )),
5053 CryptoAlgorithm::Pbkdf2 => Ok(DeriveBitsAlgorithm::Pbkdf2(
5054 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5055 )),
5056 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5057 DeriveBitsAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5058 ),
5059 _ => Err(Error::NotSupported(Some(format!(
5060 "{} does not support \"deriveBits\" operation",
5061 algorithm_name.as_str()
5062 )))),
5063 }
5064 }
5065
5066 fn name(&self) -> CryptoAlgorithm {
5067 match self {
5068 DeriveBitsAlgorithm::Ecdh(algorithm) => algorithm.name,
5069 DeriveBitsAlgorithm::X25519(algorithm) => algorithm.name,
5070 DeriveBitsAlgorithm::Hkdf(algorithm) => algorithm.name,
5071 DeriveBitsAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5072 DeriveBitsAlgorithm::Argon2(algorithm) => algorithm.name,
5073 }
5074 }
5075}
5076
5077impl DeriveBitsAlgorithm {
5078 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
5079 match self {
5080 DeriveBitsAlgorithm::Ecdh(algorithm) => {
5081 ecdh_operation::derive_bits(algorithm, key, length)
5082 },
5083 DeriveBitsAlgorithm::X25519(algorithm) => {
5084 x25519_operation::derive_bits(algorithm, key, length)
5085 },
5086 DeriveBitsAlgorithm::Hkdf(algorithm) => {
5087 hkdf_operation::derive_bits(algorithm, key, length)
5088 },
5089 DeriveBitsAlgorithm::Pbkdf2(algorithm) => {
5090 pbkdf2_operation::derive_bits(algorithm, key, length)
5091 },
5092 DeriveBitsAlgorithm::Argon2(algorithm) => {
5093 argon2_operation::derive_bits(algorithm, key, length)
5094 },
5095 }
5096 }
5097}
5098
5099struct WrapKeyOperation {}
5101
5102impl Operation for WrapKeyOperation {
5103 type RegisteredAlgorithm = WrapKeyAlgorithm;
5104}
5105
5106enum WrapKeyAlgorithm {
5109 AesKw(SubtleAlgorithm),
5110}
5111
5112impl NormalizedAlgorithm for WrapKeyAlgorithm {
5113 fn from_object(
5114 cx: &mut js::context::JSContext,
5115 algorithm_name: CryptoAlgorithm,
5116 object: HandleObject,
5117 ) -> Fallible<Self> {
5118 match algorithm_name {
5119 CryptoAlgorithm::AesKw => Ok(WrapKeyAlgorithm::AesKw(
5120 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5121 )),
5122 _ => Err(Error::NotSupported(Some(format!(
5123 "{} does not support \"wrapKey\" operation",
5124 algorithm_name.as_str()
5125 )))),
5126 }
5127 }
5128
5129 fn name(&self) -> CryptoAlgorithm {
5130 match self {
5131 WrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5132 }
5133 }
5134}
5135
5136impl WrapKeyAlgorithm {
5137 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
5138 match self {
5139 WrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::wrap_key(key, plaintext),
5140 }
5141 }
5142}
5143
5144struct UnwrapKeyOperation {}
5146
5147impl Operation for UnwrapKeyOperation {
5148 type RegisteredAlgorithm = UnwrapKeyAlgorithm;
5149}
5150
5151enum UnwrapKeyAlgorithm {
5154 AesKw(SubtleAlgorithm),
5155}
5156
5157impl NormalizedAlgorithm for UnwrapKeyAlgorithm {
5158 fn from_object(
5159 cx: &mut js::context::JSContext,
5160 algorithm_name: CryptoAlgorithm,
5161 object: HandleObject,
5162 ) -> Fallible<Self> {
5163 match algorithm_name {
5164 CryptoAlgorithm::AesKw => Ok(UnwrapKeyAlgorithm::AesKw(
5165 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5166 )),
5167 _ => Err(Error::NotSupported(Some(format!(
5168 "{} does not support \"unwrapKey\" operation",
5169 algorithm_name.as_str()
5170 )))),
5171 }
5172 }
5173
5174 fn name(&self) -> CryptoAlgorithm {
5175 match self {
5176 UnwrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5177 }
5178 }
5179}
5180
5181impl UnwrapKeyAlgorithm {
5182 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5183 match self {
5184 UnwrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::unwrap_key(key, ciphertext),
5185 }
5186 }
5187}
5188
5189struct GenerateKeyOperation {}
5191
5192impl Operation for GenerateKeyOperation {
5193 type RegisteredAlgorithm = GenerateKeyAlgorithm;
5194}
5195
5196enum GenerateKeyAlgorithm {
5199 RsassaPkcs1V1_5(SubtleRsaHashedKeyGenParams),
5200 RsaPss(SubtleRsaHashedKeyGenParams),
5201 RsaOaep(SubtleRsaHashedKeyGenParams),
5202 Ecdsa(SubtleEcKeyGenParams),
5203 Ecdh(SubtleEcKeyGenParams),
5204 Ed25519(SubtleAlgorithm),
5205 X25519(SubtleAlgorithm),
5206 AesCtr(SubtleAesKeyGenParams),
5207 AesCbc(SubtleAesKeyGenParams),
5208 AesGcm(SubtleAesKeyGenParams),
5209 AesKw(SubtleAesKeyGenParams),
5210 Hmac(SubtleHmacKeyGenParams),
5211 MlKem(SubtleAlgorithm),
5212 MlDsa(SubtleAlgorithm),
5213 AesOcb(SubtleAesKeyGenParams),
5214 ChaCha20Poly1305(SubtleAlgorithm),
5215}
5216
5217impl NormalizedAlgorithm for GenerateKeyAlgorithm {
5218 fn from_object(
5219 cx: &mut js::context::JSContext,
5220 algorithm_name: CryptoAlgorithm,
5221 object: HandleObject,
5222 ) -> Fallible<Self> {
5223 match algorithm_name {
5224 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GenerateKeyAlgorithm::RsassaPkcs1V1_5(
5225 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5226 )),
5227 CryptoAlgorithm::RsaPss => Ok(GenerateKeyAlgorithm::RsaPss(
5228 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5229 )),
5230 CryptoAlgorithm::RsaOaep => Ok(GenerateKeyAlgorithm::RsaOaep(
5231 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5232 )),
5233 CryptoAlgorithm::Ecdsa => Ok(GenerateKeyAlgorithm::Ecdsa(
5234 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5235 )),
5236 CryptoAlgorithm::Ecdh => Ok(GenerateKeyAlgorithm::Ecdh(
5237 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5238 )),
5239 CryptoAlgorithm::Ed25519 => Ok(GenerateKeyAlgorithm::Ed25519(
5240 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5241 )),
5242 CryptoAlgorithm::X25519 => Ok(GenerateKeyAlgorithm::X25519(
5243 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5244 )),
5245 CryptoAlgorithm::AesCtr => Ok(GenerateKeyAlgorithm::AesCtr(
5246 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5247 )),
5248 CryptoAlgorithm::AesCbc => Ok(GenerateKeyAlgorithm::AesCbc(
5249 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5250 )),
5251 CryptoAlgorithm::AesGcm => Ok(GenerateKeyAlgorithm::AesGcm(
5252 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5253 )),
5254 CryptoAlgorithm::AesKw => Ok(GenerateKeyAlgorithm::AesKw(
5255 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5256 )),
5257 CryptoAlgorithm::Hmac => Ok(GenerateKeyAlgorithm::Hmac(
5258 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5259 )),
5260 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5261 Ok(GenerateKeyAlgorithm::MlKem(
5262 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5263 ))
5264 },
5265 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5266 GenerateKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5267 ),
5268 CryptoAlgorithm::AesOcb => Ok(GenerateKeyAlgorithm::AesOcb(
5269 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5270 )),
5271 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GenerateKeyAlgorithm::ChaCha20Poly1305(
5272 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5273 )),
5274 _ => Err(Error::NotSupported(Some(format!(
5275 "{} does not support \"generateKey\" operation",
5276 algorithm_name.as_str()
5277 )))),
5278 }
5279 }
5280
5281 fn name(&self) -> CryptoAlgorithm {
5282 match self {
5283 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5284 GenerateKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5285 GenerateKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5286 GenerateKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5287 GenerateKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5288 GenerateKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5289 GenerateKeyAlgorithm::X25519(algorithm) => algorithm.name,
5290 GenerateKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5291 GenerateKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5292 GenerateKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5293 GenerateKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5294 GenerateKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5295 GenerateKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5296 GenerateKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5297 GenerateKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5298 GenerateKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5299 }
5300 }
5301}
5302
5303impl GenerateKeyAlgorithm {
5304 fn generate_key(
5305 &self,
5306 cx: &mut js::context::JSContext,
5307 global: &GlobalScope,
5308 extractable: bool,
5309 usages: Vec<KeyUsage>,
5310 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
5311 match self {
5312 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5313 rsassa_pkcs1_v1_5_operation::generate_key(
5314 cx,
5315 global,
5316 algorithm,
5317 extractable,
5318 usages,
5319 )
5320 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5321 },
5322 GenerateKeyAlgorithm::RsaPss(algorithm) => {
5323 rsa_pss_operation::generate_key(cx, global, algorithm, extractable, usages)
5324 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5325 },
5326 GenerateKeyAlgorithm::RsaOaep(algorithm) => {
5327 rsa_oaep_operation::generate_key(cx, global, algorithm, extractable, usages)
5328 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5329 },
5330 GenerateKeyAlgorithm::Ecdsa(algorithm) => {
5331 ecdsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5332 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5333 },
5334 GenerateKeyAlgorithm::Ecdh(algorithm) => {
5335 ecdh_operation::generate_key(cx, global, algorithm, extractable, usages)
5336 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5337 },
5338 GenerateKeyAlgorithm::Ed25519(_algorithm) => {
5339 ed25519_operation::generate_key(cx, global, extractable, usages)
5340 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5341 },
5342 GenerateKeyAlgorithm::X25519(_algorithm) => {
5343 x25519_operation::generate_key(cx, global, extractable, usages)
5344 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5345 },
5346 GenerateKeyAlgorithm::AesCtr(algorithm) => {
5347 aes_ctr_operation::generate_key(cx, global, algorithm, extractable, usages)
5348 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5349 },
5350 GenerateKeyAlgorithm::AesCbc(algorithm) => {
5351 aes_cbc_operation::generate_key(cx, global, algorithm, extractable, usages)
5352 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5353 },
5354 GenerateKeyAlgorithm::AesGcm(algorithm) => {
5355 aes_gcm_operation::generate_key(cx, global, algorithm, extractable, usages)
5356 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5357 },
5358 GenerateKeyAlgorithm::AesKw(algorithm) => {
5359 aes_kw_operation::generate_key(cx, global, algorithm, extractable, usages)
5360 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5361 },
5362 GenerateKeyAlgorithm::Hmac(algorithm) => {
5363 hmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5364 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5365 },
5366 GenerateKeyAlgorithm::MlKem(algorithm) => {
5367 ml_kem_operation::generate_key(cx, global, algorithm, extractable, usages)
5368 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5369 },
5370 GenerateKeyAlgorithm::MlDsa(algorithm) => {
5371 ml_dsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5372 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5373 },
5374 GenerateKeyAlgorithm::AesOcb(algorithm) => {
5375 aes_ocb_operation::generate_key(cx, global, algorithm, extractable, usages)
5376 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5377 },
5378 GenerateKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5379 chacha20_poly1305_operation::generate_key(cx, global, extractable, usages)
5380 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5381 },
5382 }
5383 }
5384}
5385
5386struct ImportKeyOperation {}
5388
5389impl Operation for ImportKeyOperation {
5390 type RegisteredAlgorithm = ImportKeyAlgorithm;
5391}
5392
5393enum ImportKeyAlgorithm {
5396 RsassaPkcs1V1_5(SubtleRsaHashedImportParams),
5397 RsaPss(SubtleRsaHashedImportParams),
5398 RsaOaep(SubtleRsaHashedImportParams),
5399 Ecdsa(SubtleEcKeyImportParams),
5400 Ecdh(SubtleEcKeyImportParams),
5401 Ed25519(SubtleAlgorithm),
5402 X25519(SubtleAlgorithm),
5403 AesCtr(SubtleAlgorithm),
5404 AesCbc(SubtleAlgorithm),
5405 AesGcm(SubtleAlgorithm),
5406 AesKw(SubtleAlgorithm),
5407 Hmac(SubtleHmacImportParams),
5408 Hkdf(SubtleAlgorithm),
5409 Pbkdf2(SubtleAlgorithm),
5410 MlKem(SubtleAlgorithm),
5411 MlDsa(SubtleAlgorithm),
5412 AesOcb(SubtleAlgorithm),
5413 ChaCha20Poly1305(SubtleAlgorithm),
5414 Argon2(SubtleAlgorithm),
5415}
5416
5417impl NormalizedAlgorithm for ImportKeyAlgorithm {
5418 fn from_object(
5419 cx: &mut js::context::JSContext,
5420 algorithm_name: CryptoAlgorithm,
5421 object: HandleObject,
5422 ) -> Fallible<Self> {
5423 match algorithm_name {
5424 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ImportKeyAlgorithm::RsassaPkcs1V1_5(
5425 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5426 )),
5427 CryptoAlgorithm::RsaPss => Ok(ImportKeyAlgorithm::RsaPss(
5428 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5429 )),
5430 CryptoAlgorithm::RsaOaep => Ok(ImportKeyAlgorithm::RsaOaep(
5431 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5432 )),
5433 CryptoAlgorithm::Ecdsa => Ok(ImportKeyAlgorithm::Ecdsa(
5434 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5435 )),
5436 CryptoAlgorithm::Ecdh => Ok(ImportKeyAlgorithm::Ecdh(
5437 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5438 )),
5439 CryptoAlgorithm::Ed25519 => Ok(ImportKeyAlgorithm::Ed25519(
5440 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5441 )),
5442 CryptoAlgorithm::X25519 => Ok(ImportKeyAlgorithm::X25519(
5443 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5444 )),
5445 CryptoAlgorithm::AesCtr => Ok(ImportKeyAlgorithm::AesCtr(
5446 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5447 )),
5448 CryptoAlgorithm::AesCbc => Ok(ImportKeyAlgorithm::AesCbc(
5449 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5450 )),
5451 CryptoAlgorithm::AesGcm => Ok(ImportKeyAlgorithm::AesGcm(
5452 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5453 )),
5454 CryptoAlgorithm::AesKw => Ok(ImportKeyAlgorithm::AesKw(
5455 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5456 )),
5457 CryptoAlgorithm::Hmac => Ok(ImportKeyAlgorithm::Hmac(
5458 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5459 )),
5460 CryptoAlgorithm::Hkdf => Ok(ImportKeyAlgorithm::Hkdf(
5461 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5462 )),
5463 CryptoAlgorithm::Pbkdf2 => Ok(ImportKeyAlgorithm::Pbkdf2(
5464 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5465 )),
5466 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5467 Ok(ImportKeyAlgorithm::MlKem(
5468 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5469 ))
5470 },
5471 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5472 ImportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5473 ),
5474 CryptoAlgorithm::AesOcb => Ok(ImportKeyAlgorithm::AesOcb(
5475 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5476 )),
5477 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ImportKeyAlgorithm::ChaCha20Poly1305(
5478 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5479 )),
5480 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5481 ImportKeyAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5482 ),
5483 _ => Err(Error::NotSupported(Some(format!(
5484 "{} does not support \"importKey\" operation",
5485 algorithm_name.as_str()
5486 )))),
5487 }
5488 }
5489
5490 fn name(&self) -> CryptoAlgorithm {
5491 match self {
5492 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5493 ImportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5494 ImportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5495 ImportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5496 ImportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5497 ImportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5498 ImportKeyAlgorithm::X25519(algorithm) => algorithm.name,
5499 ImportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5500 ImportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5501 ImportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5502 ImportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5503 ImportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5504 ImportKeyAlgorithm::Hkdf(algorithm) => algorithm.name,
5505 ImportKeyAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5506 ImportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5507 ImportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5508 ImportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5509 ImportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5510 ImportKeyAlgorithm::Argon2(algorithm) => algorithm.name,
5511 }
5512 }
5513}
5514
5515impl ImportKeyAlgorithm {
5516 fn import_key(
5517 &self,
5518 cx: &mut js::context::JSContext,
5519 global: &GlobalScope,
5520 format: KeyFormat,
5521 key_data: &[u8],
5522 extractable: bool,
5523 usages: Vec<KeyUsage>,
5524 ) -> Result<DomRoot<CryptoKey>, Error> {
5525 match self {
5526 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5527 rsassa_pkcs1_v1_5_operation::import_key(
5528 cx,
5529 global,
5530 algorithm,
5531 format,
5532 key_data,
5533 extractable,
5534 usages,
5535 )
5536 },
5537 ImportKeyAlgorithm::RsaPss(algorithm) => rsa_pss_operation::import_key(
5538 cx,
5539 global,
5540 algorithm,
5541 format,
5542 key_data,
5543 extractable,
5544 usages,
5545 ),
5546 ImportKeyAlgorithm::RsaOaep(algorithm) => rsa_oaep_operation::import_key(
5547 cx,
5548 global,
5549 algorithm,
5550 format,
5551 key_data,
5552 extractable,
5553 usages,
5554 ),
5555 ImportKeyAlgorithm::Ecdsa(algorithm) => ecdsa_operation::import_key(
5556 cx,
5557 global,
5558 algorithm,
5559 format,
5560 key_data,
5561 extractable,
5562 usages,
5563 ),
5564 ImportKeyAlgorithm::Ecdh(algorithm) => ecdh_operation::import_key(
5565 cx,
5566 global,
5567 algorithm,
5568 format,
5569 key_data,
5570 extractable,
5571 usages,
5572 ),
5573 ImportKeyAlgorithm::Ed25519(_algorithm) => {
5574 ed25519_operation::import_key(cx, global, format, key_data, extractable, usages)
5575 },
5576 ImportKeyAlgorithm::X25519(_algorithm) => {
5577 x25519_operation::import_key(cx, global, format, key_data, extractable, usages)
5578 },
5579 ImportKeyAlgorithm::AesCtr(_algorithm) => {
5580 aes_ctr_operation::import_key(cx, global, format, key_data, extractable, usages)
5581 },
5582 ImportKeyAlgorithm::AesCbc(_algorithm) => {
5583 aes_cbc_operation::import_key(cx, global, format, key_data, extractable, usages)
5584 },
5585 ImportKeyAlgorithm::AesGcm(_algorithm) => {
5586 aes_gcm_operation::import_key(cx, global, format, key_data, extractable, usages)
5587 },
5588 ImportKeyAlgorithm::AesKw(_algorithm) => {
5589 aes_kw_operation::import_key(cx, global, format, key_data, extractable, usages)
5590 },
5591 ImportKeyAlgorithm::Hmac(algorithm) => hmac_operation::import_key(
5592 cx,
5593 global,
5594 algorithm,
5595 format,
5596 key_data,
5597 extractable,
5598 usages,
5599 ),
5600 ImportKeyAlgorithm::Hkdf(_algorithm) => {
5601 hkdf_operation::import_key(cx, global, format, key_data, extractable, usages)
5602 },
5603 ImportKeyAlgorithm::Pbkdf2(_algorithm) => {
5604 pbkdf2_operation::import_key(cx, global, format, key_data, extractable, usages)
5605 },
5606 ImportKeyAlgorithm::MlKem(algorithm) => ml_kem_operation::import_key(
5607 cx,
5608 global,
5609 algorithm,
5610 format,
5611 key_data,
5612 extractable,
5613 usages,
5614 ),
5615 ImportKeyAlgorithm::MlDsa(algorithm) => ml_dsa_operation::import_key(
5616 cx,
5617 global,
5618 algorithm,
5619 format,
5620 key_data,
5621 extractable,
5622 usages,
5623 ),
5624 ImportKeyAlgorithm::AesOcb(_algorithm) => {
5625 aes_ocb_operation::import_key(cx, global, format, key_data, extractable, usages)
5626 },
5627 ImportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5628 chacha20_poly1305_operation::import_key(
5629 cx,
5630 global,
5631 format,
5632 key_data,
5633 extractable,
5634 usages,
5635 )
5636 },
5637 ImportKeyAlgorithm::Argon2(algorithm) => argon2_operation::import_key(
5638 cx,
5639 global,
5640 algorithm,
5641 format,
5642 key_data,
5643 extractable,
5644 usages,
5645 ),
5646 }
5647 }
5648}
5649
5650struct ExportKeyOperation {}
5652
5653impl Operation for ExportKeyOperation {
5654 type RegisteredAlgorithm = ExportKeyAlgorithm;
5655}
5656
5657enum ExportKeyAlgorithm {
5660 RsassaPkcs1V1_5(SubtleAlgorithm),
5661 RsaPss(SubtleAlgorithm),
5662 RsaOaep(SubtleAlgorithm),
5663 Ecdsa(SubtleAlgorithm),
5664 Ecdh(SubtleAlgorithm),
5665 Ed25519(SubtleAlgorithm),
5666 X25519(SubtleAlgorithm),
5667 AesCtr(SubtleAlgorithm),
5668 AesCbc(SubtleAlgorithm),
5669 AesGcm(SubtleAlgorithm),
5670 AesKw(SubtleAlgorithm),
5671 Hmac(SubtleAlgorithm),
5672 MlKem(SubtleAlgorithm),
5673 MlDsa(SubtleAlgorithm),
5674 AesOcb(SubtleAlgorithm),
5675 ChaCha20Poly1305(SubtleAlgorithm),
5676}
5677
5678impl NormalizedAlgorithm for ExportKeyAlgorithm {
5679 fn from_object(
5680 cx: &mut js::context::JSContext,
5681 algorithm_name: CryptoAlgorithm,
5682 object: HandleObject,
5683 ) -> Fallible<Self> {
5684 match algorithm_name {
5685 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ExportKeyAlgorithm::RsassaPkcs1V1_5(
5686 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5687 )),
5688 CryptoAlgorithm::RsaPss => Ok(ExportKeyAlgorithm::RsaPss(
5689 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5690 )),
5691 CryptoAlgorithm::RsaOaep => Ok(ExportKeyAlgorithm::RsaOaep(
5692 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5693 )),
5694 CryptoAlgorithm::Ecdsa => Ok(ExportKeyAlgorithm::Ecdsa(
5695 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5696 )),
5697 CryptoAlgorithm::Ecdh => Ok(ExportKeyAlgorithm::Ecdh(
5698 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5699 )),
5700 CryptoAlgorithm::Ed25519 => Ok(ExportKeyAlgorithm::Ed25519(
5701 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5702 )),
5703 CryptoAlgorithm::X25519 => Ok(ExportKeyAlgorithm::X25519(
5704 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5705 )),
5706 CryptoAlgorithm::AesCtr => Ok(ExportKeyAlgorithm::AesCtr(
5707 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5708 )),
5709 CryptoAlgorithm::AesCbc => Ok(ExportKeyAlgorithm::AesCbc(
5710 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5711 )),
5712 CryptoAlgorithm::AesGcm => Ok(ExportKeyAlgorithm::AesGcm(
5713 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5714 )),
5715 CryptoAlgorithm::AesKw => Ok(ExportKeyAlgorithm::AesKw(
5716 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5717 )),
5718 CryptoAlgorithm::Hmac => Ok(ExportKeyAlgorithm::Hmac(
5719 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5720 )),
5721 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5722 Ok(ExportKeyAlgorithm::MlKem(
5723 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5724 ))
5725 },
5726 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5727 ExportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5728 ),
5729 CryptoAlgorithm::AesOcb => Ok(ExportKeyAlgorithm::AesOcb(
5730 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5731 )),
5732 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ExportKeyAlgorithm::ChaCha20Poly1305(
5733 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5734 )),
5735 _ => Err(Error::NotSupported(Some(format!(
5736 "{} does not support \"exportKey\" operation",
5737 algorithm_name.as_str()
5738 )))),
5739 }
5740 }
5741
5742 fn name(&self) -> CryptoAlgorithm {
5743 match self {
5744 ExportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5745 ExportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5746 ExportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5747 ExportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5748 ExportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5749 ExportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5750 ExportKeyAlgorithm::X25519(algorithm) => algorithm.name,
5751 ExportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5752 ExportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5753 ExportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5754 ExportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5755 ExportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5756 ExportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5757 ExportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5758 ExportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5759 ExportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5760 }
5761 }
5762}
5763
5764impl ExportKeyAlgorithm {
5765 fn export_key(&self, format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
5766 match self {
5767 ExportKeyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5768 rsassa_pkcs1_v1_5_operation::export_key(format, key)
5769 },
5770 ExportKeyAlgorithm::RsaPss(_algorithm) => rsa_pss_operation::export_key(format, key),
5771 ExportKeyAlgorithm::RsaOaep(_algorithm) => rsa_oaep_operation::export_key(format, key),
5772 ExportKeyAlgorithm::Ecdsa(_algorithm) => ecdsa_operation::export_key(format, key),
5773 ExportKeyAlgorithm::Ecdh(_algorithm) => ecdh_operation::export_key(format, key),
5774 ExportKeyAlgorithm::Ed25519(_algorithm) => ed25519_operation::export_key(format, key),
5775 ExportKeyAlgorithm::X25519(_algorithm) => x25519_operation::export_key(format, key),
5776 ExportKeyAlgorithm::AesCtr(_algorithm) => aes_ctr_operation::export_key(format, key),
5777 ExportKeyAlgorithm::AesCbc(_algorithm) => aes_cbc_operation::export_key(format, key),
5778 ExportKeyAlgorithm::AesGcm(_algorithm) => aes_gcm_operation::export_key(format, key),
5779 ExportKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::export_key(format, key),
5780 ExportKeyAlgorithm::Hmac(_algorithm) => hmac_operation::export_key(format, key),
5781 ExportKeyAlgorithm::MlKem(_algorithm) => ml_kem_operation::export_key(format, key),
5782 ExportKeyAlgorithm::MlDsa(_algorithm) => ml_dsa_operation::export_key(format, key),
5783 ExportKeyAlgorithm::AesOcb(_algorithm) => aes_ocb_operation::export_key(format, key),
5784 ExportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5785 chacha20_poly1305_operation::export_key(format, key)
5786 },
5787 }
5788 }
5789}
5790
5791struct GetKeyLengthOperation {}
5793
5794impl Operation for GetKeyLengthOperation {
5795 type RegisteredAlgorithm = GetKeyLengthAlgorithm;
5796}
5797
5798enum GetKeyLengthAlgorithm {
5801 AesCtr(SubtleAesDerivedKeyParams),
5802 AesCbc(SubtleAesDerivedKeyParams),
5803 AesGcm(SubtleAesDerivedKeyParams),
5804 AesKw(SubtleAesDerivedKeyParams),
5805 Hmac(SubtleHmacImportParams),
5806 Hkdf(SubtleAlgorithm),
5807 Pbkdf2(SubtleAlgorithm),
5808 AesOcb(SubtleAesDerivedKeyParams),
5809 ChaCha20Poly1305(SubtleAlgorithm),
5810 Argon2(SubtleAlgorithm),
5811}
5812
5813impl NormalizedAlgorithm for GetKeyLengthAlgorithm {
5814 fn from_object(
5815 cx: &mut js::context::JSContext,
5816 algorithm_name: CryptoAlgorithm,
5817 object: HandleObject,
5818 ) -> Fallible<Self> {
5819 match algorithm_name {
5820 CryptoAlgorithm::AesCtr => Ok(GetKeyLengthAlgorithm::AesCtr(
5821 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5822 )),
5823 CryptoAlgorithm::AesCbc => Ok(GetKeyLengthAlgorithm::AesCbc(
5824 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5825 )),
5826 CryptoAlgorithm::AesGcm => Ok(GetKeyLengthAlgorithm::AesGcm(
5827 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5828 )),
5829 CryptoAlgorithm::AesKw => Ok(GetKeyLengthAlgorithm::AesKw(
5830 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5831 )),
5832 CryptoAlgorithm::Hmac => Ok(GetKeyLengthAlgorithm::Hmac(
5833 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5834 )),
5835 CryptoAlgorithm::Hkdf => Ok(GetKeyLengthAlgorithm::Hkdf(
5836 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5837 )),
5838 CryptoAlgorithm::Pbkdf2 => Ok(GetKeyLengthAlgorithm::Pbkdf2(
5839 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5840 )),
5841 CryptoAlgorithm::AesOcb => Ok(GetKeyLengthAlgorithm::AesOcb(
5842 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5843 )),
5844 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GetKeyLengthAlgorithm::ChaCha20Poly1305(
5845 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5846 )),
5847 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => {
5848 Ok(GetKeyLengthAlgorithm::Argon2(
5849 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5850 ))
5851 },
5852 _ => Err(Error::NotSupported(Some(format!(
5853 "{} does not support \"get key length\" operation",
5854 algorithm_name.as_str()
5855 )))),
5856 }
5857 }
5858
5859 fn name(&self) -> CryptoAlgorithm {
5860 match self {
5861 GetKeyLengthAlgorithm::AesCtr(algorithm) => algorithm.name,
5862 GetKeyLengthAlgorithm::AesCbc(algorithm) => algorithm.name,
5863 GetKeyLengthAlgorithm::AesGcm(algorithm) => algorithm.name,
5864 GetKeyLengthAlgorithm::AesKw(algorithm) => algorithm.name,
5865 GetKeyLengthAlgorithm::Hmac(algorithm) => algorithm.name,
5866 GetKeyLengthAlgorithm::Hkdf(algorithm) => algorithm.name,
5867 GetKeyLengthAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5868 GetKeyLengthAlgorithm::AesOcb(algorithm) => algorithm.name,
5869 GetKeyLengthAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5870 GetKeyLengthAlgorithm::Argon2(algorithm) => algorithm.name,
5871 }
5872 }
5873}
5874
5875impl GetKeyLengthAlgorithm {
5876 fn get_key_length(&self) -> Result<Option<u32>, Error> {
5877 match self {
5878 GetKeyLengthAlgorithm::AesCtr(algorithm) => {
5879 aes_ctr_operation::get_key_length(algorithm)
5880 },
5881 GetKeyLengthAlgorithm::AesCbc(algorithm) => {
5882 aes_cbc_operation::get_key_length(algorithm)
5883 },
5884 GetKeyLengthAlgorithm::AesGcm(algorithm) => {
5885 aes_gcm_operation::get_key_length(algorithm)
5886 },
5887 GetKeyLengthAlgorithm::AesKw(algorithm) => aes_kw_operation::get_key_length(algorithm),
5888 GetKeyLengthAlgorithm::Hmac(algorithm) => hmac_operation::get_key_length(algorithm),
5889 GetKeyLengthAlgorithm::Hkdf(_algorithm) => hkdf_operation::get_key_length(),
5890 GetKeyLengthAlgorithm::Pbkdf2(_algorithm) => pbkdf2_operation::get_key_length(),
5891 GetKeyLengthAlgorithm::AesOcb(algorithm) => {
5892 aes_ocb_operation::get_key_length(algorithm)
5893 },
5894 GetKeyLengthAlgorithm::ChaCha20Poly1305(_algorithm) => {
5895 chacha20_poly1305_operation::get_key_length()
5896 },
5897 GetKeyLengthAlgorithm::Argon2(_algorithm) => argon2_operation::get_key_length(),
5898 }
5899 }
5900}
5901
5902struct EncapsulateOperation {}
5904
5905impl Operation for EncapsulateOperation {
5906 type RegisteredAlgorithm = EncapsulateAlgorithm;
5907}
5908
5909enum EncapsulateAlgorithm {
5912 MlKem(SubtleAlgorithm),
5913}
5914
5915impl NormalizedAlgorithm for EncapsulateAlgorithm {
5916 fn from_object(
5917 cx: &mut js::context::JSContext,
5918 algorithm_name: CryptoAlgorithm,
5919 object: HandleObject,
5920 ) -> Fallible<Self> {
5921 match algorithm_name {
5922 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5923 Ok(EncapsulateAlgorithm::MlKem(
5924 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5925 ))
5926 },
5927 _ => Err(Error::NotSupported(Some(format!(
5928 "{} does not support \"encapsulate\" operation",
5929 algorithm_name.as_str()
5930 )))),
5931 }
5932 }
5933
5934 fn name(&self) -> CryptoAlgorithm {
5935 match self {
5936 EncapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
5937 }
5938 }
5939}
5940
5941impl EncapsulateAlgorithm {
5942 fn encapsulate(&self, key: &CryptoKey) -> Result<SubtleEncapsulatedBits, Error> {
5943 match self {
5944 EncapsulateAlgorithm::MlKem(algorithm) => ml_kem_operation::encapsulate(algorithm, key),
5945 }
5946 }
5947}
5948
5949struct DecapsulateOperation {}
5951
5952impl Operation for DecapsulateOperation {
5953 type RegisteredAlgorithm = DecapsulateAlgorithm;
5954}
5955
5956enum DecapsulateAlgorithm {
5959 MlKem(SubtleAlgorithm),
5960}
5961
5962impl NormalizedAlgorithm for DecapsulateAlgorithm {
5963 fn from_object(
5964 cx: &mut js::context::JSContext,
5965 algorithm_name: CryptoAlgorithm,
5966 object: HandleObject,
5967 ) -> Fallible<Self> {
5968 match algorithm_name {
5969 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5970 Ok(DecapsulateAlgorithm::MlKem(
5971 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5972 ))
5973 },
5974 _ => Err(Error::NotSupported(Some(format!(
5975 "{} does not support \"decapsulate\" operation",
5976 algorithm_name.as_str()
5977 )))),
5978 }
5979 }
5980
5981 fn name(&self) -> CryptoAlgorithm {
5982 match self {
5983 DecapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
5984 }
5985 }
5986}
5987
5988impl DecapsulateAlgorithm {
5989 fn decapsulate(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5990 match self {
5991 DecapsulateAlgorithm::MlKem(algorithm) => {
5992 ml_kem_operation::decapsulate(algorithm, key, ciphertext)
5993 },
5994 }
5995 }
5996}
5997
5998struct GetPublicKeyOperation {}
6000
6001impl Operation for GetPublicKeyOperation {
6002 type RegisteredAlgorithm = GetPublicKeyAlgorithm;
6003}
6004
6005enum GetPublicKeyAlgorithm {
6008 RsassaPkcs1v1_5(SubtleAlgorithm),
6009 RsaPss(SubtleAlgorithm),
6010 RsaOaep(SubtleAlgorithm),
6011 Ecdsa(SubtleAlgorithm),
6012 Ecdh(SubtleAlgorithm),
6013 Ed25519(SubtleAlgorithm),
6014 X25519(SubtleAlgorithm),
6015 MlKem(SubtleAlgorithm),
6016 MlDsa(SubtleAlgorithm),
6017}
6018
6019impl NormalizedAlgorithm for GetPublicKeyAlgorithm {
6020 fn from_object(
6021 cx: &mut js::context::JSContext,
6022 algorithm_name: CryptoAlgorithm,
6023 object: HandleObject,
6024 ) -> Fallible<Self> {
6025 match algorithm_name {
6026 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GetPublicKeyAlgorithm::RsassaPkcs1v1_5(
6027 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6028 )),
6029 CryptoAlgorithm::RsaPss => Ok(GetPublicKeyAlgorithm::RsaPss(
6030 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6031 )),
6032 CryptoAlgorithm::RsaOaep => Ok(GetPublicKeyAlgorithm::RsaOaep(
6033 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6034 )),
6035 CryptoAlgorithm::Ecdsa => Ok(GetPublicKeyAlgorithm::Ecdsa(
6036 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6037 )),
6038 CryptoAlgorithm::Ecdh => Ok(GetPublicKeyAlgorithm::Ecdh(
6039 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6040 )),
6041 CryptoAlgorithm::Ed25519 => Ok(GetPublicKeyAlgorithm::Ed25519(
6042 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6043 )),
6044 CryptoAlgorithm::X25519 => Ok(GetPublicKeyAlgorithm::X25519(
6045 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6046 )),
6047 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6048 Ok(GetPublicKeyAlgorithm::MlKem(
6049 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6050 ))
6051 },
6052 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6053 GetPublicKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6054 ),
6055 _ => Err(Error::NotSupported(Some(format!(
6056 "{} does not support \"getPublicKey\" operation",
6057 algorithm_name.as_str()
6058 )))),
6059 }
6060 }
6061
6062 fn name(&self) -> CryptoAlgorithm {
6063 match self {
6064 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(algorithm) => algorithm.name,
6065 GetPublicKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6066 GetPublicKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6067 GetPublicKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6068 GetPublicKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6069 GetPublicKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6070 GetPublicKeyAlgorithm::X25519(algorithm) => algorithm.name,
6071 GetPublicKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6072 GetPublicKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6073 }
6074 }
6075}
6076
6077impl GetPublicKeyAlgorithm {
6078 fn get_public_key(
6079 &self,
6080 cx: &mut js::context::JSContext,
6081 global: &GlobalScope,
6082 key: &CryptoKey,
6083 algorithm: &KeyAlgorithmAndDerivatives,
6084 usages: Vec<KeyUsage>,
6085 ) -> Result<DomRoot<CryptoKey>, Error> {
6086 match self {
6087 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(_algorithm) => {
6088 rsassa_pkcs1_v1_5_operation::get_public_key(cx, global, key, algorithm, usages)
6089 },
6090 GetPublicKeyAlgorithm::RsaPss(_algorithm) => {
6091 rsa_pss_operation::get_public_key(cx, global, key, algorithm, usages)
6092 },
6093 GetPublicKeyAlgorithm::RsaOaep(_algorithm) => {
6094 rsa_oaep_operation::get_public_key(cx, global, key, algorithm, usages)
6095 },
6096 GetPublicKeyAlgorithm::Ecdsa(_algorithm) => {
6097 ecdsa_operation::get_public_key(cx, global, key, algorithm, usages)
6098 },
6099 GetPublicKeyAlgorithm::Ecdh(_algorithm) => {
6100 ecdh_operation::get_public_key(cx, global, key, algorithm, usages)
6101 },
6102 GetPublicKeyAlgorithm::Ed25519(_algorithm) => {
6103 ed25519_operation::get_public_key(cx, global, key, algorithm, usages)
6104 },
6105 GetPublicKeyAlgorithm::X25519(_algorithm) => {
6106 x25519_operation::get_public_key(cx, global, key, algorithm, usages)
6107 },
6108 GetPublicKeyAlgorithm::MlKem(_algorithm) => {
6109 ml_kem_operation::get_public_key(cx, global, key, algorithm, usages)
6110 },
6111 GetPublicKeyAlgorithm::MlDsa(_algorithm) => {
6112 ml_dsa_operation::get_public_key(cx, global, key, algorithm, usages)
6113 },
6114 }
6115 }
6116}