1mod aes_operation;
6mod ecdh_operation;
7mod ed25519_operation;
8mod hkdf_operation;
9mod hmac_operation;
10mod pbkdf2_operation;
11mod sha_operation;
12
13use std::ptr;
14use std::rc::Rc;
15use std::str::FromStr;
16
17use dom_struct::dom_struct;
18use js::conversions::ConversionResult;
19use js::jsapi::{Heap, JSObject};
20use js::jsval::{ObjectValue, UndefinedValue};
21use js::rust::wrappers::JS_ParseJSON;
22use js::rust::{HandleValue, MutableHandleValue};
23use js::typedarray::ArrayBufferU8;
24
25use crate::dom::bindings::buffer_source::create_buffer_source;
26use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
27 CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
28};
29use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
30 AesCbcParams, AesCtrParams, AesDerivedKeyParams, AesGcmParams, AesKeyAlgorithm,
31 AesKeyGenParams, Algorithm, AlgorithmIdentifier, EcKeyAlgorithm, EcKeyGenParams,
32 EcKeyImportParams, HkdfParams, HmacImportParams, HmacKeyAlgorithm, HmacKeyGenParams,
33 JsonWebKey, KeyAlgorithm, KeyFormat, Pbkdf2Params, RsaOtherPrimesInfo, SubtleCryptoMethods,
34};
35use crate::dom::bindings::codegen::UnionTypes::{
36 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey, ObjectOrString,
37};
38use crate::dom::bindings::conversions::{SafeFromJSValConvertible, SafeToJSValConvertible};
39use crate::dom::bindings::error::{Error, Fallible};
40use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
41use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
42use crate::dom::bindings::root::DomRoot;
43use crate::dom::bindings::str::{DOMString, serialize_jsval_to_json_utf8};
44use crate::dom::bindings::trace::RootedTraceableBox;
45use crate::dom::cryptokey::{CryptoKey, CryptoKeyOrCryptoKeyPair};
46use crate::dom::globalscope::GlobalScope;
47use crate::dom::promise::Promise;
48use crate::realms::InRealm;
49use crate::script_runtime::{CanGc, JSContext};
50
51const ALG_AES_CBC: &str = "AES-CBC";
53const ALG_AES_CTR: &str = "AES-CTR";
54const ALG_AES_GCM: &str = "AES-GCM";
55const ALG_AES_KW: &str = "AES-KW";
56const ALG_SHA1: &str = "SHA-1";
57const ALG_SHA256: &str = "SHA-256";
58const ALG_SHA384: &str = "SHA-384";
59const ALG_SHA512: &str = "SHA-512";
60const ALG_HMAC: &str = "HMAC";
61const ALG_HKDF: &str = "HKDF";
62const ALG_PBKDF2: &str = "PBKDF2";
63const ALG_RSASSA_PKCS1: &str = "RSASSA-PKCS1-v1_5";
64const ALG_RSA_OAEP: &str = "RSA-OAEP";
65const ALG_RSA_PSS: &str = "RSA-PSS";
66const ALG_ECDH: &str = "ECDH";
67const ALG_ECDSA: &str = "ECDSA";
68const ALG_ED25519: &str = "Ed25519";
69
70static SUPPORTED_ALGORITHMS: &[&str] = &[
71 ALG_AES_CBC,
72 ALG_AES_CTR,
73 ALG_AES_GCM,
74 ALG_AES_KW,
75 ALG_SHA1,
76 ALG_SHA256,
77 ALG_SHA384,
78 ALG_SHA512,
79 ALG_HMAC,
80 ALG_HKDF,
81 ALG_PBKDF2,
82 ALG_RSASSA_PKCS1,
83 ALG_RSA_OAEP,
84 ALG_RSA_PSS,
85 ALG_ECDH,
86 ALG_ECDSA,
87 ALG_ED25519,
88];
89
90const NAMED_CURVE_P256: &str = "P-256";
91const NAMED_CURVE_P384: &str = "P-384";
92const NAMED_CURVE_P521: &str = "P-521";
93
94static SUPPORTED_CURVES: &[&str] = &[NAMED_CURVE_P256, NAMED_CURVE_P384, NAMED_CURVE_P521];
95
96#[allow(dead_code)]
98enum Operation {
99 Encrypt,
100 Decrypt,
101 Sign,
102 Verify,
103 Digest,
104 GenerateKey,
105 DeriveKey,
106 DeriveBits,
107 ImportKey,
108 ExportKey,
109 WrapKey,
110 UnwrapKey,
111 GetKeyLength,
112}
113
114#[dom_struct]
115pub(crate) struct SubtleCrypto {
116 reflector_: Reflector,
117}
118
119impl SubtleCrypto {
120 fn new_inherited() -> SubtleCrypto {
121 SubtleCrypto {
122 reflector_: Reflector::new(),
123 }
124 }
125
126 pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<SubtleCrypto> {
127 reflect_dom_object(Box::new(SubtleCrypto::new_inherited()), global, can_gc)
128 }
129
130 fn resolve_promise_with_data(&self, promise: Rc<Promise>, data: Vec<u8>) {
134 let trusted_promise = TrustedPromise::new(promise);
135 self.global().task_manager().crypto_task_source().queue(
136 task!(resolve_data: move || {
137 let promise = trusted_promise.root();
138
139 let cx = GlobalScope::get_cx();
140 rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
141 match create_buffer_source::<ArrayBufferU8>(cx, &data, array_buffer_ptr.handle_mut(), CanGc::note()) {
142 Ok(_) => promise.resolve_native(&*array_buffer_ptr, CanGc::note()),
143 Err(_) => promise.reject_error(Error::JSFailed, CanGc::note()),
144 }
145 }),
146 );
147 }
148
149 fn resolve_promise_with_jwk(&self, promise: Rc<Promise>, jwk: Box<JsonWebKey>) {
153 let cx = GlobalScope::get_cx();
156 let stringified_jwk = match jwk.stringify(cx) {
157 Ok(stringified_jwk) => stringified_jwk.to_string(),
158 Err(error) => {
159 self.reject_promise_with_error(promise, error);
160 return;
161 },
162 };
163
164 let trusted_subtle = Trusted::new(self);
165 let trusted_promise = TrustedPromise::new(promise);
166 self.global()
167 .task_manager()
168 .crypto_task_source()
169 .queue(task!(resolve_jwk: move || {
170 let subtle = trusted_subtle.root();
171 let promise = trusted_promise.root();
172
173 let cx = GlobalScope::get_cx();
174 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
175 Ok(jwk) => {
176 rooted!(in(*cx) let mut rval = UndefinedValue());
177 jwk.safe_to_jsval(cx, rval.handle_mut(), CanGc::note());
178 rooted!(in(*cx) let mut object = rval.to_object());
179 promise.resolve_native(&*object, CanGc::note());
180 },
181 Err(error) => {
182 subtle.reject_promise_with_error(promise, error);
183 return;
184 },
185 }
186 }));
187 }
188
189 fn resolve_promise_with_key(&self, promise: Rc<Promise>, key: DomRoot<CryptoKey>) {
192 let trusted_key = Trusted::new(&*key);
193 let trusted_promise = TrustedPromise::new(promise);
194 self.global()
195 .task_manager()
196 .crypto_task_source()
197 .queue(task!(resolve_key: move || {
198 let key = trusted_key.root();
199 let promise = trusted_promise.root();
200 promise.resolve_native(&key, CanGc::note());
201 }));
202 }
203
204 fn resolve_promise_with_key_pair(&self, promise: Rc<Promise>, key_pair: CryptoKeyPair) {
207 let trusted_private_key = key_pair.privateKey.map(|key| Trusted::new(&*key));
208 let trusted_public_key = key_pair.publicKey.map(|key| Trusted::new(&*key));
209 let trusted_promise = TrustedPromise::new(promise);
210 self.global()
211 .task_manager()
212 .crypto_task_source()
213 .queue(task!(resolve_key: move || {
214 let key_pair = CryptoKeyPair {
215 privateKey: trusted_private_key.map(|trusted_key| trusted_key.root()),
216 publicKey: trusted_public_key.map(|trusted_key| trusted_key.root()),
217 };
218 let promise = trusted_promise.root();
219 promise.resolve_native(&key_pair, CanGc::note());
220 }));
221 }
222
223 fn resolve_promise_with_bool(&self, promise: Rc<Promise>, result: bool) {
226 let trusted_promise = TrustedPromise::new(promise);
227 self.global().task_manager().crypto_task_source().queue(
228 task!(generate_key_result: move || {
229 let promise = trusted_promise.root();
230 promise.resolve_native(&result, CanGc::note());
231 }),
232 );
233 }
234
235 fn reject_promise_with_error(&self, promise: Rc<Promise>, error: Error) {
238 let trusted_promise = TrustedPromise::new(promise);
239 self.global()
240 .task_manager()
241 .crypto_task_source()
242 .queue(task!(reject_error: move || {
243 let promise = trusted_promise.root();
244 promise.reject_error(error, CanGc::note());
245 }));
246 }
247}
248
249impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
250 fn Encrypt(
252 &self,
253 cx: JSContext,
254 algorithm: AlgorithmIdentifier,
255 key: &CryptoKey,
256 data: ArrayBufferViewOrArrayBuffer,
257 comp: InRealm,
258 can_gc: CanGc,
259 ) -> Rc<Promise> {
260 let data = match data {
267 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
268 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
269 };
270
271 let promise = Promise::new_in_current_realm(comp, can_gc);
275 let normalized_algorithm = match normalize_algorithm(cx, &Operation::Encrypt, &algorithm) {
276 Ok(normalized_algorithm) => normalized_algorithm,
277 Err(error) => {
278 promise.reject_error(error, can_gc);
279 return promise;
280 },
281 };
282
283 let this = Trusted::new(self);
289 let trusted_promise = TrustedPromise::new(promise.clone());
290 let trusted_key = Trusted::new(key);
291 self.global()
292 .task_manager()
293 .dom_manipulation_task_source()
294 .queue(task!(encrypt: move || {
295 let subtle = this.root();
296 let promise = trusted_promise.root();
297 let key = trusted_key.root();
298
299 if normalized_algorithm.name() != key.algorithm().name() {
307 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
308 return;
309 }
310
311 if !key.usages().contains(&KeyUsage::Encrypt) {
314 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
315 return;
316 }
317
318 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
322 Ok(ciphertext) => ciphertext,
323 Err(error) => {
324 subtle.reject_promise_with_error(promise, error);
325 return;
326 },
327 };
328
329 subtle.resolve_promise_with_data(promise, ciphertext);
335 }));
336 promise
337 }
338
339 fn Decrypt(
341 &self,
342 cx: JSContext,
343 algorithm: AlgorithmIdentifier,
344 key: &CryptoKey,
345 data: ArrayBufferViewOrArrayBuffer,
346 comp: InRealm,
347 can_gc: CanGc,
348 ) -> Rc<Promise> {
349 let data = match data {
356 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
357 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
358 };
359
360 let promise = Promise::new_in_current_realm(comp, can_gc);
364 let normalized_algorithm = match normalize_algorithm(cx, &Operation::Decrypt, &algorithm) {
365 Ok(normalized_algorithm) => normalized_algorithm,
366 Err(error) => {
367 promise.reject_error(error, can_gc);
368 return promise;
369 },
370 };
371
372 let this = Trusted::new(self);
378 let trusted_promise = TrustedPromise::new(promise.clone());
379 let trusted_key = Trusted::new(key);
380 self.global()
381 .task_manager()
382 .dom_manipulation_task_source()
383 .queue(task!(decrypt: move || {
384 let subtle = this.root();
385 let promise = trusted_promise.root();
386 let key = trusted_key.root();
387
388 if normalized_algorithm.name() != key.algorithm().name() {
396 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
397 return;
398 }
399
400 if !key.usages().contains(&KeyUsage::Decrypt) {
403 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
404 return;
405 }
406
407 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
411 Ok(plaintext) => plaintext,
412 Err(error) => {
413 subtle.reject_promise_with_error(promise, error);
414 return;
415 },
416 };
417
418 subtle.resolve_promise_with_data(promise, plaintext);
424 }));
425 promise
426 }
427
428 fn Sign(
430 &self,
431 cx: JSContext,
432 algorithm: AlgorithmIdentifier,
433 key: &CryptoKey,
434 data: ArrayBufferViewOrArrayBuffer,
435 comp: InRealm,
436 can_gc: CanGc,
437 ) -> Rc<Promise> {
438 let data = match &data {
445 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
446 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
447 };
448
449 let promise = Promise::new_in_current_realm(comp, can_gc);
453 let normalized_algorithm = match normalize_algorithm(cx, &Operation::Sign, &algorithm) {
454 Ok(normalized_algorithm) => normalized_algorithm,
455 Err(error) => {
456 promise.reject_error(error, can_gc);
457 return promise;
458 },
459 };
460
461 let this = Trusted::new(self);
467 let trusted_promise = TrustedPromise::new(promise.clone());
468 let trusted_key = Trusted::new(key);
469 self.global()
470 .task_manager()
471 .dom_manipulation_task_source()
472 .queue(task!(sign: move || {
473 let subtle = this.root();
474 let promise = trusted_promise.root();
475 let key = trusted_key.root();
476
477 if normalized_algorithm.name() != key.algorithm().name() {
485 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
486 return;
487 }
488
489 if !key.usages().contains(&KeyUsage::Sign) {
492 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
493 return;
494 }
495
496 let signature = match normalized_algorithm.sign(&key, &data) {
499 Ok(signature) => signature,
500 Err(error) => {
501 subtle.reject_promise_with_error(promise, error);
502 return;
503 },
504 };
505
506 subtle.resolve_promise_with_data(promise, signature);
512 }));
513 promise
514 }
515
516 fn Verify(
518 &self,
519 cx: JSContext,
520 algorithm: AlgorithmIdentifier,
521 key: &CryptoKey,
522 signature: ArrayBufferViewOrArrayBuffer,
523 data: ArrayBufferViewOrArrayBuffer,
524 comp: InRealm,
525 can_gc: CanGc,
526 ) -> Rc<Promise> {
527 let signature = match &signature {
534 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
535 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
536 };
537
538 let data = match &data {
541 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
542 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
543 };
544
545 let promise = Promise::new_in_current_realm(comp, can_gc);
549 let normalized_algorithm = match normalize_algorithm(cx, &Operation::Verify, &algorithm) {
550 Ok(algorithm) => algorithm,
551 Err(error) => {
552 promise.reject_error(error, can_gc);
553 return promise;
554 },
555 };
556
557 let this = Trusted::new(self);
563 let trusted_promise = TrustedPromise::new(promise.clone());
564 let trusted_key = Trusted::new(key);
565 self.global()
566 .task_manager()
567 .dom_manipulation_task_source()
568 .queue(task!(sign: move || {
569 let subtle = this.root();
570 let promise = trusted_promise.root();
571 let key = trusted_key.root();
572
573 if normalized_algorithm.name() != key.algorithm().name() {
581 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
582 return;
583 }
584
585 if !key.usages().contains(&KeyUsage::Verify) {
588 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
589 return;
590 }
591
592 let result = match normalized_algorithm.verify(&key, &data, &signature) {
596 Ok(result) => result,
597 Err(error) => {
598 subtle.reject_promise_with_error(promise, error);
599 return;
600 },
601 };
602
603 subtle.resolve_promise_with_bool(promise, result);
607 }));
608 promise
609 }
610
611 fn Digest(
613 &self,
614 cx: JSContext,
615 algorithm: AlgorithmIdentifier,
616 data: ArrayBufferViewOrArrayBuffer,
617 comp: InRealm,
618 can_gc: CanGc,
619 ) -> Rc<Promise> {
620 let data = match data {
626 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
627 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
628 };
629
630 let promise = Promise::new_in_current_realm(comp, can_gc);
634 let normalized_algorithm = match normalize_algorithm(cx, &Operation::Digest, &algorithm) {
635 Ok(normalized_algorithm) => normalized_algorithm,
636 Err(error) => {
637 promise.reject_error(error, can_gc);
638 return promise;
639 },
640 };
641
642 let this = Trusted::new(self);
648 let trusted_promise = TrustedPromise::new(promise.clone());
649 self.global()
650 .task_manager()
651 .dom_manipulation_task_source()
652 .queue(task!(generate_key: move || {
653 let subtle = this.root();
654 let promise = trusted_promise.root();
655
656 let digest = match normalized_algorithm.digest(&data) {
663 Ok(digest) => digest,
664 Err(error) => {
665 subtle.reject_promise_with_error(promise, error);
666 return;
667 }
668 };
669
670 subtle.resolve_promise_with_data(promise, digest);
676 }));
677 promise
678 }
679
680 fn GenerateKey(
682 &self,
683 cx: JSContext,
684 algorithm: AlgorithmIdentifier,
685 extractable: bool,
686 key_usages: Vec<KeyUsage>,
687 comp: InRealm,
688 can_gc: CanGc,
689 ) -> Rc<Promise> {
690 let promise = Promise::new_in_current_realm(comp, can_gc);
697 let normalized_algorithm =
698 match normalize_algorithm(cx, &Operation::GenerateKey, &algorithm) {
699 Ok(normalized_algorithm) => normalized_algorithm,
700 Err(error) => {
701 promise.reject_error(error, can_gc);
702 return promise;
703 },
704 };
705
706 let trusted_subtle = Trusted::new(self);
712 let trusted_promise = TrustedPromise::new(promise.clone());
713 self.global()
714 .task_manager()
715 .dom_manipulation_task_source()
716 .queue(task!(generate_key: move || {
717 let subtle = trusted_subtle.root();
718 let promise = trusted_promise.root();
719
720 let result = match normalized_algorithm.generate_key(
727 &subtle.global(),
728 extractable,
729 key_usages,
730 CanGc::note(),
731 ) {
732 Ok(result) => result,
733 Err(error) => {
734 subtle.reject_promise_with_error(promise, error);
735 return;
736 }
737 };
738
739 match &result {
748 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
749 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
750 && crpyto_key.usages().is_empty()
751 {
752 subtle.reject_promise_with_error(promise, Error::Syntax(None));
753 return;
754 }
755 },
756 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(crypto_key_pair) => {
757 if crypto_key_pair.privateKey.as_ref().is_none_or(|private_key| private_key.usages().is_empty()) {
758 subtle.reject_promise_with_error(promise, Error::Syntax(None));
759 return;
760 }
761 }
762 };
763
764 match result {
770 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
771 subtle.resolve_promise_with_key(promise, key);
772 },
773 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(key_pair) => {
774 subtle.resolve_promise_with_key_pair(promise, key_pair);
775 },
776 }
777 }));
778
779 promise
780 }
781
782 fn DeriveKey(
784 &self,
785 cx: JSContext,
786 algorithm: AlgorithmIdentifier,
787 base_key: &CryptoKey,
788 derived_key_type: AlgorithmIdentifier,
789 extractable: bool,
790 usages: Vec<KeyUsage>,
791 comp: InRealm,
792 can_gc: CanGc,
793 ) -> Rc<Promise> {
794 let promise = Promise::new_in_current_realm(comp, can_gc);
803 let normalized_algorithm = match normalize_algorithm(cx, &Operation::DeriveBits, &algorithm)
804 {
805 Ok(normalized_algorithm) => normalized_algorithm,
806 Err(error) => {
807 promise.reject_error(error, can_gc);
808 return promise;
809 },
810 };
811
812 let normalized_derived_key_algorithm_import =
817 match normalize_algorithm(cx, &Operation::ImportKey, &derived_key_type) {
818 Ok(normalized_algorithm) => normalized_algorithm,
819 Err(error) => {
820 promise.reject_error(error, can_gc);
821 return promise;
822 },
823 };
824
825 let normalized_derived_key_algorithm_length =
830 match normalize_algorithm(cx, &Operation::GetKeyLength, &derived_key_type) {
831 Ok(normalized_algorithm) => normalized_algorithm,
832 Err(error) => {
833 promise.reject_error(error, can_gc);
834 return promise;
835 },
836 };
837
838 let trusted_subtle = Trusted::new(self);
844 let trusted_base_key = Trusted::new(base_key);
845 let trusted_promise = TrustedPromise::new(promise.clone());
846 self.global().task_manager().dom_manipulation_task_source().queue(
847 task!(derive_key: move || {
848 let subtle = trusted_subtle.root();
849 let base_key = trusted_base_key.root();
850 let promise = trusted_promise.root();
851
852 if normalized_algorithm.name() != base_key.algorithm().name() {
860 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
861 return;
862 }
863
864 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
867 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
868 return;
869 }
870
871 let length = match normalized_derived_key_algorithm_length.get_key_length() {
874 Ok(length) => length,
875 Err(error) => {
876 subtle.reject_promise_with_error(promise, error);
877 return;
878 }
879 };
880
881 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
884 Ok(secret) => secret,
885 Err(error) => {
886 subtle.reject_promise_with_error(promise, error);
887 return;
888 }
889 };
890
891 let result = match normalized_derived_key_algorithm_import.import_key(
895 &subtle.global(),
896 KeyFormat::Raw,
897 &secret,
898 extractable,
899 usages.clone(),
900 CanGc::note(),
901 ) {
902 Ok(algorithm) => algorithm,
903 Err(error) => {
904 subtle.reject_promise_with_error(promise, error);
905 return;
906 },
907 };
908
909 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
912 subtle.reject_promise_with_error(promise, Error::Syntax(None));
913 return;
914 }
915
916 subtle.resolve_promise_with_key(promise, result);
927 }),
928 );
929 promise
930 }
931
932 fn DeriveBits(
934 &self,
935 cx: JSContext,
936 algorithm: AlgorithmIdentifier,
937 base_key: &CryptoKey,
938 length: Option<u32>,
939 comp: InRealm,
940 can_gc: CanGc,
941 ) -> Rc<Promise> {
942 let promise = Promise::new_in_current_realm(comp, can_gc);
950 let normalized_algorithm = match normalize_algorithm(cx, &Operation::DeriveBits, &algorithm)
951 {
952 Ok(normalized_algorithm) => normalized_algorithm,
953 Err(error) => {
954 promise.reject_error(error, can_gc);
955 return promise;
956 },
957 };
958
959 let trsuted_subtle = Trusted::new(self);
965 let trusted_base_key = Trusted::new(base_key);
966 let trusted_promise = TrustedPromise::new(promise.clone());
967 self.global()
968 .task_manager()
969 .dom_manipulation_task_source()
970 .queue(task!(import_key: move || {
971 let subtle = trsuted_subtle.root();
972 let base_key = trusted_base_key.root();
973 let promise = trusted_promise.root();
974
975 if normalized_algorithm.name() != base_key.algorithm().name() {
983 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
984 return;
985 }
986
987 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
990 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
991 return;
992 }
993
994 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
997 Ok(bits) => bits,
998 Err(error) => {
999 subtle.reject_promise_with_error(promise, error);
1000 return;
1001 }
1002 };
1003
1004 subtle.resolve_promise_with_data(promise, bits);
1010 }));
1011 promise
1012 }
1013
1014 fn ImportKey(
1016 &self,
1017 cx: JSContext,
1018 format: KeyFormat,
1019 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
1020 algorithm: AlgorithmIdentifier,
1021 extractable: bool,
1022 key_usages: Vec<KeyUsage>,
1023 comp: InRealm,
1024 can_gc: CanGc,
1025 ) -> Rc<Promise> {
1026 let promise = Promise::new_in_current_realm(comp, can_gc);
1032
1033 let key_data = match format {
1035 KeyFormat::Raw | KeyFormat::Pkcs8 | KeyFormat::Spki => {
1037 match key_data {
1038 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1041 promise.reject_error(
1042 Error::Type("The keyData type does not match the format".to_string()),
1043 can_gc,
1044 );
1045 return promise;
1046 },
1047
1048 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1051 view.to_vec()
1052 },
1053 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1054 buffer.to_vec()
1055 },
1056 }
1057 },
1058 KeyFormat::Jwk => {
1060 match key_data {
1061 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1062 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1063 promise.reject_error(
1066 Error::Type("The keyData type does not match the format".to_string()),
1067 can_gc,
1068 );
1069 return promise;
1070 },
1071
1072 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1073 match jwk.stringify(cx) {
1080 Ok(stringified) => stringified.as_bytes().to_vec(),
1081 Err(error) => {
1082 promise.reject_error(error, can_gc);
1083 return promise;
1084 },
1085 }
1086 },
1087 }
1088 },
1089 };
1090
1091 let normalized_algorithm = match normalize_algorithm(cx, &Operation::ImportKey, &algorithm)
1095 {
1096 Ok(algorithm) => algorithm,
1097 Err(error) => {
1098 promise.reject_error(error, can_gc);
1099 return promise;
1100 },
1101 };
1102
1103 let this = Trusted::new(self);
1105 let trusted_promise = TrustedPromise::new(promise.clone());
1106 self.global()
1107 .task_manager()
1108 .dom_manipulation_task_source()
1109 .queue(task!(import_key: move || {
1110 let subtle = this.root();
1111 let promise = trusted_promise.root();
1112
1113 let result = match normalized_algorithm.import_key(
1121 &subtle.global(),
1122 format,
1123 &key_data,
1124 extractable,
1125 key_usages.clone(),
1126 CanGc::note()
1127 ) {
1128 Ok(key) => key,
1129 Err(error) => {
1130 subtle.reject_promise_with_error(promise, error);
1131 return;
1132 },
1133 };
1134
1135 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && key_usages.is_empty() {
1138 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1139 return;
1140 }
1141
1142 result.set_extractable(extractable);
1144
1145 result.set_usages(&key_usages);
1147
1148 subtle.resolve_promise_with_key(promise, result);
1154 }));
1155
1156 promise
1157 }
1158
1159 fn ExportKey(
1161 &self,
1162 format: KeyFormat,
1163 key: &CryptoKey,
1164 comp: InRealm,
1165 can_gc: CanGc,
1166 ) -> Rc<Promise> {
1167 let promise = Promise::new_in_current_realm(comp, can_gc);
1174
1175 let trusted_subtle = Trusted::new(self);
1177 let trusted_promise = TrustedPromise::new(promise.clone());
1178 let trusted_key = Trusted::new(key);
1179 self.global()
1180 .task_manager()
1181 .dom_manipulation_task_source()
1182 .queue(task!(export_key: move || {
1183 let subtle = trusted_subtle.root();
1184 let promise = trusted_promise.root();
1185 let key = trusted_key.root();
1186
1187 if matches!(
1195 key.algorithm().name(),
1196 ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 | ALG_HKDF | ALG_PBKDF2
1197 ) {
1198 subtle.reject_promise_with_error(promise, Error::NotSupported);
1199 return;
1200 }
1201
1202 if !key.Extractable() {
1205 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1206 return;
1207 }
1208
1209 let result = match perform_export_key_operation(format, &key) {
1212 Ok(exported_key) => exported_key,
1213 Err(error) => {
1214 subtle.reject_promise_with_error(promise, error);
1215 return;
1216 },
1217 };
1218
1219 match result {
1230 ExportedKey::Raw(raw) => {
1231 subtle.resolve_promise_with_data(promise, raw);
1232 },
1233 ExportedKey::Jwk(jwk) => {
1234 subtle.resolve_promise_with_jwk(promise, jwk);
1235 },
1236 }
1237 }));
1238 promise
1239 }
1240
1241 fn WrapKey(
1243 &self,
1244 cx: JSContext,
1245 format: KeyFormat,
1246 key: &CryptoKey,
1247 wrapping_key: &CryptoKey,
1248 algorithm: AlgorithmIdentifier,
1249 comp: InRealm,
1250 can_gc: CanGc,
1251 ) -> Rc<Promise> {
1252 let mut normalized_algorithm_result =
1259 normalize_algorithm(cx, &Operation::WrapKey, &algorithm);
1260
1261 if normalized_algorithm_result.is_err() {
1264 normalized_algorithm_result = normalize_algorithm(cx, &Operation::Encrypt, &algorithm);
1265 }
1266
1267 let promise = Promise::new_in_current_realm(comp, can_gc);
1269 let normalized_algorithm = match normalized_algorithm_result {
1270 Ok(normalized_algorithm) => normalized_algorithm,
1271 Err(error) => {
1272 promise.reject_error(error, can_gc);
1273 return promise;
1274 },
1275 };
1276
1277 let trusted_subtle = Trusted::new(self);
1283 let trusted_key = Trusted::new(key);
1284 let trusted_wrapping_key = Trusted::new(wrapping_key);
1285 let trusted_promise = TrustedPromise::new(promise.clone());
1286 self.global()
1287 .task_manager()
1288 .dom_manipulation_task_source()
1289 .queue(task!(wrap_key: move || {
1290 let subtle = trusted_subtle.root();
1291 let key = trusted_key.root();
1292 let wrapping_key = trusted_wrapping_key.root();
1293 let promise = trusted_promise.root();
1294
1295 if normalized_algorithm.name() != wrapping_key.algorithm().name() {
1303 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1304 return;
1305 }
1306
1307 if !wrapping_key.usages().contains(&KeyUsage::WrapKey) {
1310 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1311 return;
1312 }
1313
1314 if matches!(
1318 key.algorithm().name(),
1319 ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 | ALG_HKDF | ALG_PBKDF2
1320 ) {
1321 subtle.reject_promise_with_error(promise, Error::NotSupported);
1322 return;
1323 }
1324
1325
1326 if !key.Extractable() {
1329 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1330 return;
1331 }
1332
1333 let exported_key = match perform_export_key_operation(format, &key) {
1336 Ok(exported_key) => exported_key,
1337 Err(error) => {
1338 subtle.reject_promise_with_error(promise, error);
1339 return;
1340 },
1341 };
1342
1343 let cx = GlobalScope::get_cx();
1353 let bytes = match exported_key {
1354 ExportedKey::Raw(raw) => raw,
1355 ExportedKey::Jwk(jwk) => match jwk.stringify(cx) {
1356 Ok(stringified_jwk) => stringified_jwk.as_bytes().to_vec(),
1357 Err(error) => {
1358 subtle.reject_promise_with_error(promise, error);
1359 return;
1360 },
1361 },
1362 };
1363
1364 let mut result = normalized_algorithm.wrap_key(&wrapping_key, &bytes);
1376 if result.is_err() {
1377 result = normalized_algorithm.encrypt(&wrapping_key, &bytes);
1378 }
1379 let result = match result {
1380 Ok(result) => result,
1381 Err(error) => {
1382 subtle.reject_promise_with_error(promise, error);
1383 return;
1384 },
1385 };
1386
1387 subtle.resolve_promise_with_data(promise, result);
1393 }));
1394 promise
1395 }
1396
1397 fn UnwrapKey(
1399 &self,
1400 cx: JSContext,
1401 format: KeyFormat,
1402 wrapped_key: ArrayBufferViewOrArrayBuffer,
1403 unwrapping_key: &CryptoKey,
1404 algorithm: AlgorithmIdentifier,
1405 unwrapped_key_algorithm: AlgorithmIdentifier,
1406 extractable: bool,
1407 usages: Vec<KeyUsage>,
1408 comp: InRealm,
1409 can_gc: CanGc,
1410 ) -> Rc<Promise> {
1411 let wrapped_key = match wrapped_key {
1419 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1420 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1421 };
1422
1423 let mut normalized_algorithm = normalize_algorithm(cx, &Operation::UnwrapKey, &algorithm);
1426
1427 if normalized_algorithm.is_err() {
1430 normalized_algorithm = normalize_algorithm(cx, &Operation::Decrypt, &algorithm);
1431 }
1432
1433 let promise = Promise::new_in_current_realm(comp, can_gc);
1435 let normalized_algorithm = match normalized_algorithm {
1436 Ok(algorithm) => algorithm,
1437 Err(error) => {
1438 promise.reject_error(error, can_gc);
1439 return promise;
1440 },
1441 };
1442
1443 let normalized_key_algorithm =
1447 match normalize_algorithm(cx, &Operation::ImportKey, &unwrapped_key_algorithm) {
1448 Ok(algorithm) => algorithm,
1449 Err(error) => {
1450 promise.reject_error(error, can_gc);
1451 return promise;
1452 },
1453 };
1454
1455 let trusted_subtle = Trusted::new(self);
1461 let trusted_unwrapping_key = Trusted::new(unwrapping_key);
1462 let trusted_promise = TrustedPromise::new(promise.clone());
1463 self.global().task_manager().dom_manipulation_task_source().queue(
1464 task!(unwrap_key: move || {
1465 let subtle = trusted_subtle.root();
1466 let unwrapping_key = trusted_unwrapping_key.root();
1467 let promise = trusted_promise.root();
1468
1469 if normalized_algorithm.name() != unwrapping_key.algorithm().name() {
1477 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1478 return;
1479 }
1480
1481 if !unwrapping_key.usages().contains(&KeyUsage::UnwrapKey) {
1484 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1485 return;
1486 }
1487
1488 let mut bytes = normalized_algorithm.unwrap_key(&unwrapping_key, &wrapped_key);
1500 if bytes.is_err() {
1501 bytes = normalized_algorithm.decrypt(&unwrapping_key, &wrapped_key);
1502 }
1503 let bytes = match bytes {
1504 Ok(bytes) => bytes,
1505 Err(error) => {
1506 subtle.reject_promise_with_error(promise, error);
1507 return;
1508 },
1509 };
1510
1511 let cx = GlobalScope::get_cx();
1521 if format == KeyFormat::Jwk {
1522 if let Err(error) = JsonWebKey::parse(cx, &bytes) {
1523 subtle.reject_promise_with_error(promise, error);
1524 return;
1525 }
1526 }
1527 let key = bytes;
1528
1529 let result = match normalized_key_algorithm.import_key(
1533 &subtle.global(),
1534 format,
1535 &key,
1536 extractable,
1537 usages.clone(),
1538 CanGc::note(),
1539 ) {
1540 Ok(result) => result,
1541 Err(error) => {
1542 subtle.reject_promise_with_error(promise, error);
1543 return;
1544 },
1545 };
1546
1547 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1550 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1551 return;
1552 }
1553
1554 subtle.resolve_promise_with_key(promise, result);
1565 }),
1566 );
1567 promise
1568 }
1569}
1570
1571#[derive(Clone, Debug, MallocSizeOf)]
1576struct SubtleAlgorithm {
1577 name: String,
1579}
1580
1581impl From<Algorithm> for SubtleAlgorithm {
1582 fn from(params: Algorithm) -> Self {
1583 SubtleAlgorithm {
1584 name: params.name.to_string(),
1585 }
1586 }
1587}
1588
1589#[derive(Clone, Debug, MallocSizeOf)]
1591pub(crate) struct SubtleKeyAlgorithm {
1592 name: String,
1594}
1595
1596impl SubtleKeyAlgorithm {
1597 fn block_size_in_bits(&self) -> Result<u32, Error> {
1598 let size = match self.name.as_str() {
1599 ALG_SHA1 => 512,
1600 ALG_SHA256 => 512,
1601 ALG_SHA384 => 1024,
1602 ALG_SHA512 => 1024,
1603 _ => {
1604 return Err(Error::NotSupported);
1605 },
1606 };
1607
1608 Ok(size)
1609 }
1610}
1611
1612impl From<NormalizedAlgorithm> for SubtleKeyAlgorithm {
1613 fn from(value: NormalizedAlgorithm) -> Self {
1614 SubtleKeyAlgorithm {
1615 name: value.name().to_string(),
1616 }
1617 }
1618}
1619
1620impl SafeToJSValConvertible for SubtleKeyAlgorithm {
1621 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
1622 let dictionary = KeyAlgorithm {
1623 name: self.name.clone().into(),
1624 };
1625 dictionary.safe_to_jsval(cx, rval, can_gc);
1626 }
1627}
1628
1629#[derive(Clone, Debug, MallocSizeOf)]
1631struct SubtleEcKeyGenParams {
1632 name: String,
1634
1635 named_curve: String,
1637}
1638
1639impl From<EcKeyGenParams> for SubtleEcKeyGenParams {
1640 fn from(value: EcKeyGenParams) -> Self {
1641 SubtleEcKeyGenParams {
1642 name: value.parent.name.to_string(),
1643 named_curve: value.namedCurve.to_string(),
1644 }
1645 }
1646}
1647
1648#[derive(Clone, Debug, MallocSizeOf)]
1650pub(crate) struct SubtleEcKeyAlgorithm {
1651 name: String,
1653
1654 named_curve: String,
1656}
1657
1658impl SafeToJSValConvertible for SubtleEcKeyAlgorithm {
1659 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
1660 let parent = KeyAlgorithm {
1661 name: self.name.clone().into(),
1662 };
1663 let dictionary = EcKeyAlgorithm {
1664 parent,
1665 namedCurve: self.named_curve.clone().into(),
1666 };
1667 dictionary.safe_to_jsval(cx, rval, can_gc);
1668 }
1669}
1670
1671#[derive(Clone, Debug, MallocSizeOf)]
1673struct SubtleEcKeyImportParams {
1674 name: String,
1676
1677 named_curve: String,
1679}
1680
1681impl From<EcKeyImportParams> for SubtleEcKeyImportParams {
1682 fn from(value: EcKeyImportParams) -> Self {
1683 SubtleEcKeyImportParams {
1684 name: value.parent.name.to_string(),
1685 named_curve: value.namedCurve.to_string(),
1686 }
1687 }
1688}
1689
1690#[derive(Clone, Debug, MallocSizeOf)]
1691pub(crate) struct SubtleAesCbcParams {
1692 pub(crate) name: String,
1693 pub(crate) iv: Vec<u8>,
1694}
1695
1696impl From<RootedTraceableBox<AesCbcParams>> for SubtleAesCbcParams {
1697 fn from(params: RootedTraceableBox<AesCbcParams>) -> Self {
1698 let iv = match ¶ms.iv {
1699 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1700 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1701 };
1702 SubtleAesCbcParams {
1703 name: params.parent.name.to_string(),
1704 iv,
1705 }
1706 }
1707}
1708
1709#[derive(Clone, Debug, MallocSizeOf)]
1710pub(crate) struct SubtleAesCtrParams {
1711 pub(crate) name: String,
1712 pub(crate) counter: Vec<u8>,
1713 pub(crate) length: u8,
1714}
1715
1716impl From<RootedTraceableBox<AesCtrParams>> for SubtleAesCtrParams {
1717 fn from(params: RootedTraceableBox<AesCtrParams>) -> Self {
1718 let counter = match ¶ms.counter {
1719 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1720 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1721 };
1722 SubtleAesCtrParams {
1723 name: params.parent.name.to_string(),
1724 counter,
1725 length: params.length,
1726 }
1727 }
1728}
1729
1730#[derive(Clone, Debug, MallocSizeOf)]
1731pub(crate) struct SubtleAesGcmParams {
1732 pub(crate) name: String,
1733 pub(crate) iv: Vec<u8>,
1734 pub(crate) additional_data: Option<Vec<u8>>,
1735 pub(crate) tag_length: Option<u8>,
1736}
1737
1738impl From<RootedTraceableBox<AesGcmParams>> for SubtleAesGcmParams {
1739 fn from(params: RootedTraceableBox<AesGcmParams>) -> Self {
1740 let iv = match ¶ms.iv {
1741 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1742 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1743 };
1744 let additional_data = params.additionalData.as_ref().map(|data| match data {
1745 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1746 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1747 });
1748
1749 SubtleAesGcmParams {
1750 name: params.parent.name.to_string(),
1751 iv,
1752 additional_data,
1753 tag_length: params.tagLength,
1754 }
1755 }
1756}
1757
1758#[derive(Clone, Debug, MallocSizeOf)]
1760pub(crate) struct SubtleAesKeyAlgorithm {
1761 name: String,
1763
1764 length: u16,
1766}
1767
1768impl SafeToJSValConvertible for SubtleAesKeyAlgorithm {
1769 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
1770 let parent = KeyAlgorithm {
1771 name: self.name.clone().into(),
1772 };
1773 let dictionary = AesKeyAlgorithm {
1774 parent,
1775 length: self.length,
1776 };
1777 dictionary.safe_to_jsval(cx, rval, can_gc);
1778 }
1779}
1780
1781#[derive(Clone, Debug, MallocSizeOf)]
1783struct SubtleAesKeyGenParams {
1784 name: String,
1786
1787 length: u16,
1789}
1790
1791impl From<AesKeyGenParams> for SubtleAesKeyGenParams {
1792 fn from(params: AesKeyGenParams) -> Self {
1793 SubtleAesKeyGenParams {
1794 name: params.parent.name.to_string(),
1795 length: params.length,
1796 }
1797 }
1798}
1799
1800#[derive(Clone, Debug, MallocSizeOf)]
1802struct SubtleAesDerivedKeyParams {
1803 name: String,
1805
1806 length: u16,
1808}
1809
1810impl From<AesDerivedKeyParams> for SubtleAesDerivedKeyParams {
1811 fn from(params: AesDerivedKeyParams) -> Self {
1812 SubtleAesDerivedKeyParams {
1813 name: params.parent.name.to_string(),
1814 length: params.length,
1815 }
1816 }
1817}
1818
1819#[derive(Clone, Debug, MallocSizeOf)]
1821struct SubtleHmacImportParams {
1822 name: String,
1824
1825 hash: SubtleKeyAlgorithm,
1827
1828 length: Option<u32>,
1830}
1831
1832impl TryFrom<RootedTraceableBox<HmacImportParams>> for SubtleHmacImportParams {
1833 type Error = Error;
1834
1835 fn try_from(params: RootedTraceableBox<HmacImportParams>) -> Result<Self, Error> {
1836 let cx = GlobalScope::get_cx();
1837 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash)?;
1838 Ok(SubtleHmacImportParams {
1839 name: params.parent.name.to_string(),
1840 hash: hash.into(),
1841 length: params.length,
1842 })
1843 }
1844}
1845
1846#[derive(Clone, Debug, MallocSizeOf)]
1848pub(crate) struct SubtleHmacKeyAlgorithm {
1849 name: String,
1851
1852 hash: SubtleKeyAlgorithm,
1854
1855 length: u32,
1857}
1858
1859impl SafeToJSValConvertible for SubtleHmacKeyAlgorithm {
1860 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
1861 let parent = KeyAlgorithm {
1862 name: self.name.clone().into(),
1863 };
1864 let hash = KeyAlgorithm {
1865 name: self.hash.name.clone().into(),
1866 };
1867 let dictionary = HmacKeyAlgorithm {
1868 parent,
1869 hash,
1870 length: self.length,
1871 };
1872 dictionary.safe_to_jsval(cx, rval, can_gc);
1873 }
1874}
1875
1876#[derive(Clone, Debug, MallocSizeOf)]
1878struct SubtleHmacKeyGenParams {
1879 name: String,
1881
1882 hash: SubtleKeyAlgorithm,
1884
1885 length: Option<u32>,
1887}
1888
1889impl TryFrom<RootedTraceableBox<HmacKeyGenParams>> for SubtleHmacKeyGenParams {
1890 type Error = Error;
1891
1892 fn try_from(params: RootedTraceableBox<HmacKeyGenParams>) -> Result<Self, Error> {
1893 let cx = GlobalScope::get_cx();
1894 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash)?;
1895 Ok(SubtleHmacKeyGenParams {
1896 name: params.parent.name.to_string(),
1897 hash: hash.into(),
1898 length: params.length,
1899 })
1900 }
1901}
1902
1903#[derive(Clone, Debug, MallocSizeOf)]
1905pub(crate) struct SubtleHkdfParams {
1906 name: String,
1908
1909 hash: SubtleKeyAlgorithm,
1911
1912 salt: Vec<u8>,
1914
1915 info: Vec<u8>,
1917}
1918
1919impl TryFrom<RootedTraceableBox<HkdfParams>> for SubtleHkdfParams {
1920 type Error = Error;
1921
1922 fn try_from(params: RootedTraceableBox<HkdfParams>) -> Result<Self, Error> {
1923 let cx = GlobalScope::get_cx();
1924 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash)?;
1925 let salt = match ¶ms.salt {
1926 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1927 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1928 };
1929 let info = match ¶ms.info {
1930 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1931 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1932 };
1933 Ok(SubtleHkdfParams {
1934 name: params.parent.name.to_string(),
1935 hash: hash.into(),
1936 salt,
1937 info,
1938 })
1939 }
1940}
1941
1942#[derive(Clone, Debug, MallocSizeOf)]
1944pub(crate) struct SubtlePbkdf2Params {
1945 name: String,
1947
1948 salt: Vec<u8>,
1950
1951 iterations: u32,
1953
1954 hash: SubtleKeyAlgorithm,
1956}
1957
1958impl TryFrom<RootedTraceableBox<Pbkdf2Params>> for SubtlePbkdf2Params {
1959 type Error = Error;
1960
1961 fn try_from(params: RootedTraceableBox<Pbkdf2Params>) -> Result<Self, Error> {
1962 let cx = GlobalScope::get_cx();
1963 let salt = match ¶ms.salt {
1964 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1965 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1966 };
1967 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash)?;
1968 Ok(SubtlePbkdf2Params {
1969 name: params.parent.name.to_string(),
1970 salt,
1971 iterations: params.iterations,
1972 hash: hash.into(),
1973 })
1974 }
1975}
1976
1977fn dictionary_from_jsval<T>(cx: JSContext, value: HandleValue) -> Fallible<T>
1979where
1980 T: SafeFromJSValConvertible<Config = ()>,
1981{
1982 let conversion = T::safe_from_jsval(cx, value, ()).map_err(|_| Error::JSFailed)?;
1983 match conversion {
1984 ConversionResult::Success(dictionary) => Ok(dictionary),
1985 ConversionResult::Failure(error) => Err(Error::Type(error.into())),
1986 }
1987}
1988
1989pub(crate) enum ExportedKey {
1990 Raw(Vec<u8>),
1991 Jwk(Box<JsonWebKey>),
1992}
1993
1994#[derive(Clone, Debug, MallocSizeOf)]
1998#[allow(clippy::enum_variant_names)]
1999pub(crate) enum KeyAlgorithmAndDerivatives {
2000 KeyAlgorithm(SubtleKeyAlgorithm),
2001 EcKeyAlgorithm(SubtleEcKeyAlgorithm),
2002 AesKeyAlgorithm(SubtleAesKeyAlgorithm),
2003 HmacKeyAlgorithm(SubtleHmacKeyAlgorithm),
2004}
2005
2006impl KeyAlgorithmAndDerivatives {
2007 fn name(&self) -> &str {
2008 match self {
2009 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => &algo.name,
2010 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => &algo.name,
2011 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => &algo.name,
2012 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => &algo.name,
2013 }
2014 }
2015}
2016
2017impl From<NormalizedAlgorithm> for KeyAlgorithmAndDerivatives {
2018 fn from(value: NormalizedAlgorithm) -> Self {
2019 KeyAlgorithmAndDerivatives::KeyAlgorithm(SubtleKeyAlgorithm {
2020 name: value.name().to_string(),
2021 })
2022 }
2023}
2024
2025impl SafeToJSValConvertible for KeyAlgorithmAndDerivatives {
2026 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2027 match self {
2028 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval, can_gc),
2029 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => {
2030 algo.safe_to_jsval(cx, rval, can_gc)
2031 },
2032 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => {
2033 algo.safe_to_jsval(cx, rval, can_gc)
2034 },
2035 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => {
2036 algo.safe_to_jsval(cx, rval, can_gc)
2037 },
2038 }
2039 }
2040}
2041
2042#[expect(unused)]
2043trait RsaOtherPrimesInfoExt {
2044 fn from_value(value: &serde_json::Value) -> Result<RsaOtherPrimesInfo, Error>;
2045}
2046
2047impl RsaOtherPrimesInfoExt for RsaOtherPrimesInfo {
2048 fn from_value(value: &serde_json::Value) -> Result<RsaOtherPrimesInfo, Error> {
2049 let serde_json::Value::Object(object) = value else {
2050 return Err(Error::Data);
2051 };
2052
2053 let mut rsa_other_primes_info: RsaOtherPrimesInfo = Default::default();
2054 for (key, value) in object {
2055 match key.as_str() {
2056 "r" => {
2057 rsa_other_primes_info.r =
2058 Some(DOMString::from(value.as_str().ok_or(Error::Data)?))
2059 },
2060 "d" => {
2061 rsa_other_primes_info.d =
2062 Some(DOMString::from(value.as_str().ok_or(Error::Data)?))
2063 },
2064 "t" => {
2065 rsa_other_primes_info.t =
2066 Some(DOMString::from(value.as_str().ok_or(Error::Data)?))
2067 },
2068 _ => {
2069 },
2072 }
2073 }
2074
2075 Ok(rsa_other_primes_info)
2076 }
2077}
2078
2079trait JsonWebKeyExt {
2080 fn parse(cx: JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
2081 fn stringify(&self, cx: JSContext) -> Result<DOMString, Error>;
2082 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
2083 #[expect(unused)]
2084 fn get_rsa_other_primes_info_from_oth(&self) -> Result<&[RsaOtherPrimesInfo], Error>;
2085 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
2086}
2087
2088impl JsonWebKeyExt for JsonWebKey {
2089 #[allow(unsafe_code)]
2091 fn parse(cx: JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
2092 let json = String::from_utf8_lossy(data);
2097
2098 let json: Vec<_> = json.encode_utf16().collect();
2100
2101 rooted!(in(*cx) let mut result = UndefinedValue());
2105 unsafe {
2106 if !JS_ParseJSON(*cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
2107 return Err(Error::JSFailed);
2108 }
2109 }
2110
2111 let key = match JsonWebKey::new(cx, result.handle(), CanGc::note()) {
2113 Ok(ConversionResult::Success(key)) => key,
2114 Ok(ConversionResult::Failure(error)) => {
2115 return Err(Error::Type(error.to_string()));
2116 },
2117 Err(()) => {
2118 return Err(Error::JSFailed);
2119 },
2120 };
2121
2122 if key.kty.is_none() {
2124 return Err(Error::Data);
2125 }
2126
2127 Ok(key)
2129 }
2130
2131 fn stringify(&self, cx: JSContext) -> Result<DOMString, Error> {
2137 rooted!(in(*cx) let mut data = UndefinedValue());
2138 self.safe_to_jsval(cx, data.handle_mut(), CanGc::note());
2139 serialize_jsval_to_json_utf8(cx, data.handle())
2140 }
2141
2142 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
2143 let mut usages = vec![];
2144 for op in self.key_ops.as_ref().ok_or(Error::Data)? {
2145 usages.push(KeyUsage::from_str(&op.str()).map_err(|_| Error::Data)?);
2146 }
2147 Ok(usages)
2148 }
2149
2150 fn get_rsa_other_primes_info_from_oth(&self) -> Result<&[RsaOtherPrimesInfo], Error> {
2151 self.oth.as_deref().ok_or(Error::Data)
2152 }
2153
2154 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
2158 if let Some(ref key_ops) = self.key_ops {
2160 if key_ops
2163 .iter()
2164 .collect::<std::collections::HashSet<_>>()
2165 .len() <
2166 key_ops.len()
2167 {
2168 return Err(Error::Data);
2169 }
2170 if let Some(ref use_) = self.use_ {
2173 if key_ops.iter().any(|op| op != use_) {
2174 return Err(Error::Data);
2175 }
2176 }
2177
2178 let key_ops_as_usages = self.get_usages_from_key_ops()?;
2180 if !specified_usages
2181 .iter()
2182 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
2183 {
2184 return Err(Error::Data);
2185 }
2186 }
2187
2188 Ok(())
2189 }
2190}
2191
2192#[derive(Clone, Debug, MallocSizeOf)]
2197enum NormalizedAlgorithm {
2198 Algorithm(SubtleAlgorithm),
2199 EcKeyGenParams(SubtleEcKeyGenParams),
2200 EcKeyImportParams(SubtleEcKeyImportParams),
2201 AesCtrParams(SubtleAesCtrParams),
2202 AesKeyGenParams(SubtleAesKeyGenParams),
2203 AesDerivedKeyParams(SubtleAesDerivedKeyParams),
2204 AesCbcParams(SubtleAesCbcParams),
2205 AesGcmParams(SubtleAesGcmParams),
2206 HmacImportParams(SubtleHmacImportParams),
2207 HmacKeyGenParams(SubtleHmacKeyGenParams),
2208 HkdfParams(SubtleHkdfParams),
2209 Pbkdf2Params(SubtlePbkdf2Params),
2210}
2211
2212fn normalize_algorithm(
2214 cx: JSContext,
2215 op: &Operation,
2216 alg: &AlgorithmIdentifier,
2217) -> Result<NormalizedAlgorithm, Error> {
2218 match alg {
2219 ObjectOrString::String(name) => {
2221 let alg = Algorithm {
2225 name: name.to_owned(),
2226 };
2227 rooted!(in(*cx) let mut alg_value = UndefinedValue());
2228 alg.safe_to_jsval(cx, alg_value.handle_mut(), CanGc::note());
2229 let alg_obj = RootedTraceableBox::new(Heap::default());
2230 alg_obj.set(alg_value.to_object());
2231 normalize_algorithm(cx, op, &ObjectOrString::Object(alg_obj))
2232 },
2233 ObjectOrString::Object(obj) => {
2235 rooted!(in(*cx) let value = ObjectValue(obj.get()));
2244 let initial_alg = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2245
2246 let Some(&alg_name) = SUPPORTED_ALGORITHMS.iter().find(|supported_algorithm| {
2254 supported_algorithm.eq_ignore_ascii_case(&initial_alg.name.str())
2255 }) else {
2256 return Err(Error::NotSupported);
2257 };
2258
2259 let normalized_algorithm = match (alg_name, op) {
2295 (ALG_ECDH, Operation::GenerateKey) => {
2297 let mut params = dictionary_from_jsval::<EcKeyGenParams>(cx, value.handle())?;
2298 params.parent.name = DOMString::from(alg_name);
2299 NormalizedAlgorithm::EcKeyGenParams(params.into())
2300 },
2301 (ALG_ECDH, Operation::ImportKey) => {
2302 let mut params =
2303 dictionary_from_jsval::<EcKeyImportParams>(cx, value.handle())?;
2304 params.parent.name = DOMString::from(alg_name);
2305 NormalizedAlgorithm::EcKeyImportParams(params.into())
2306 },
2307 (ALG_ECDH, Operation::ExportKey) => {
2308 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2309 params.name = DOMString::from(alg_name);
2310 NormalizedAlgorithm::Algorithm(params.into())
2311 },
2312
2313 (ALG_ED25519, Operation::Sign) => {
2315 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2316 params.name = DOMString::from(alg_name);
2317 NormalizedAlgorithm::Algorithm(params.into())
2318 },
2319 (ALG_ED25519, Operation::Verify) => {
2320 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2321 params.name = DOMString::from(alg_name);
2322 NormalizedAlgorithm::Algorithm(params.into())
2323 },
2324 (ALG_ED25519, Operation::GenerateKey) => {
2325 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2326 params.name = DOMString::from(alg_name);
2327 NormalizedAlgorithm::Algorithm(params.into())
2328 },
2329 (ALG_ED25519, Operation::ImportKey) => {
2330 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2331 params.name = DOMString::from(alg_name);
2332 NormalizedAlgorithm::Algorithm(params.into())
2333 },
2334 (ALG_ED25519, Operation::ExportKey) => {
2335 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2336 params.name = DOMString::from(alg_name);
2337 NormalizedAlgorithm::Algorithm(params.into())
2338 },
2339
2340 (ALG_AES_CTR, Operation::Encrypt) => {
2342 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesCtrParams>>(
2343 cx,
2344 value.handle(),
2345 )?;
2346 params.parent.name = DOMString::from(alg_name);
2347 NormalizedAlgorithm::AesCtrParams(params.into())
2348 },
2349 (ALG_AES_CTR, Operation::Decrypt) => {
2350 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesCtrParams>>(
2351 cx,
2352 value.handle(),
2353 )?;
2354 params.parent.name = DOMString::from(alg_name);
2355 NormalizedAlgorithm::AesCtrParams(params.into())
2356 },
2357 (ALG_AES_CTR, Operation::GenerateKey) => {
2358 let mut params = dictionary_from_jsval::<AesKeyGenParams>(cx, value.handle())?;
2359 params.parent.name = DOMString::from(alg_name);
2360 NormalizedAlgorithm::AesKeyGenParams(params.into())
2361 },
2362 (ALG_AES_CTR, Operation::ImportKey) => {
2363 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2364 params.name = DOMString::from(alg_name);
2365 NormalizedAlgorithm::Algorithm(params.into())
2366 },
2367 (ALG_AES_CTR, Operation::ExportKey) => {
2368 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2369 params.name = DOMString::from(alg_name);
2370 NormalizedAlgorithm::Algorithm(params.into())
2371 },
2372 (ALG_AES_CTR, Operation::GetKeyLength) => {
2373 let mut params =
2374 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value.handle())?;
2375 params.parent.name = DOMString::from(alg_name);
2376 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2377 },
2378
2379 (ALG_AES_CBC, Operation::Encrypt) => {
2381 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesCbcParams>>(
2382 cx,
2383 value.handle(),
2384 )?;
2385 params.parent.name = DOMString::from(alg_name);
2386 NormalizedAlgorithm::AesCbcParams(params.into())
2387 },
2388 (ALG_AES_CBC, Operation::Decrypt) => {
2389 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesCbcParams>>(
2390 cx,
2391 value.handle(),
2392 )?;
2393 params.parent.name = DOMString::from(alg_name);
2394 NormalizedAlgorithm::AesCbcParams(params.into())
2395 },
2396 (ALG_AES_CBC, Operation::GenerateKey) => {
2397 let mut params = dictionary_from_jsval::<AesKeyGenParams>(cx, value.handle())?;
2398 params.parent.name = DOMString::from(alg_name);
2399 NormalizedAlgorithm::AesKeyGenParams(params.into())
2400 },
2401 (ALG_AES_CBC, Operation::ImportKey) => {
2402 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2403 params.name = DOMString::from(alg_name);
2404 NormalizedAlgorithm::Algorithm(params.into())
2405 },
2406 (ALG_AES_CBC, Operation::ExportKey) => {
2407 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2408 params.name = DOMString::from(alg_name);
2409 NormalizedAlgorithm::Algorithm(params.into())
2410 },
2411 (ALG_AES_CBC, Operation::GetKeyLength) => {
2412 let mut params =
2413 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value.handle())?;
2414 params.parent.name = DOMString::from(alg_name);
2415 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2416 },
2417
2418 (ALG_AES_GCM, Operation::Encrypt) => {
2420 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesGcmParams>>(
2421 cx,
2422 value.handle(),
2423 )?;
2424 params.parent.name = DOMString::from(alg_name);
2425 NormalizedAlgorithm::AesGcmParams(params.into())
2426 },
2427 (ALG_AES_GCM, Operation::Decrypt) => {
2428 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesGcmParams>>(
2429 cx,
2430 value.handle(),
2431 )?;
2432 params.parent.name = DOMString::from(alg_name);
2433 NormalizedAlgorithm::AesGcmParams(params.into())
2434 },
2435 (ALG_AES_GCM, Operation::GenerateKey) => {
2436 let mut params = dictionary_from_jsval::<AesKeyGenParams>(cx, value.handle())?;
2437 params.parent.name = DOMString::from(alg_name);
2438 NormalizedAlgorithm::AesKeyGenParams(params.into())
2439 },
2440 (ALG_AES_GCM, Operation::ImportKey) => {
2441 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2442 params.name = DOMString::from(alg_name);
2443 NormalizedAlgorithm::Algorithm(params.into())
2444 },
2445 (ALG_AES_GCM, Operation::ExportKey) => {
2446 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2447 params.name = DOMString::from(alg_name);
2448 NormalizedAlgorithm::Algorithm(params.into())
2449 },
2450 (ALG_AES_GCM, Operation::GetKeyLength) => {
2451 let mut params =
2452 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value.handle())?;
2453 params.parent.name = DOMString::from(alg_name);
2454 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2455 },
2456
2457 (ALG_AES_KW, Operation::WrapKey) => {
2459 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2460 params.name = DOMString::from(alg_name);
2461 NormalizedAlgorithm::Algorithm(params.into())
2462 },
2463 (ALG_AES_KW, Operation::UnwrapKey) => {
2464 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2465 params.name = DOMString::from(alg_name);
2466 NormalizedAlgorithm::Algorithm(params.into())
2467 },
2468 (ALG_AES_KW, Operation::GenerateKey) => {
2469 let mut params = dictionary_from_jsval::<AesKeyGenParams>(cx, value.handle())?;
2470 params.parent.name = DOMString::from(alg_name);
2471 NormalizedAlgorithm::AesKeyGenParams(params.into())
2472 },
2473 (ALG_AES_KW, Operation::ImportKey) => {
2474 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2475 params.name = DOMString::from(alg_name);
2476 NormalizedAlgorithm::Algorithm(params.into())
2477 },
2478 (ALG_AES_KW, Operation::ExportKey) => {
2479 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2480 params.name = DOMString::from(alg_name);
2481 NormalizedAlgorithm::Algorithm(params.into())
2482 },
2483 (ALG_AES_KW, Operation::GetKeyLength) => {
2484 let mut params =
2485 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value.handle())?;
2486 params.parent.name = DOMString::from(alg_name);
2487 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2488 },
2489
2490 (ALG_HMAC, Operation::Sign) => {
2492 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2493 params.name = DOMString::from(alg_name);
2494 NormalizedAlgorithm::Algorithm(params.into())
2495 },
2496 (ALG_HMAC, Operation::Verify) => {
2497 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2498 params.name = DOMString::from(alg_name);
2499 NormalizedAlgorithm::Algorithm(params.into())
2500 },
2501 (ALG_HMAC, Operation::GenerateKey) => {
2502 let mut params = dictionary_from_jsval::<RootedTraceableBox<HmacKeyGenParams>>(
2503 cx,
2504 value.handle(),
2505 )?;
2506 params.parent.name = DOMString::from(alg_name);
2507 NormalizedAlgorithm::HmacKeyGenParams(params.try_into()?)
2508 },
2509 (ALG_HMAC, Operation::ImportKey) => {
2510 let mut params = dictionary_from_jsval::<RootedTraceableBox<HmacImportParams>>(
2511 cx,
2512 value.handle(),
2513 )?;
2514 params.parent.name = DOMString::from(alg_name);
2515 NormalizedAlgorithm::HmacImportParams(params.try_into()?)
2516 },
2517 (ALG_HMAC, Operation::ExportKey) => {
2518 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2519 params.name = DOMString::from(alg_name);
2520 NormalizedAlgorithm::Algorithm(params.into())
2521 },
2522 (ALG_HMAC, Operation::GetKeyLength) => {
2523 let mut params = dictionary_from_jsval::<RootedTraceableBox<HmacImportParams>>(
2524 cx,
2525 value.handle(),
2526 )?;
2527 params.parent.name = DOMString::from(alg_name);
2528 NormalizedAlgorithm::HmacImportParams(params.try_into()?)
2529 },
2530
2531 (ALG_SHA1, Operation::Digest) => {
2533 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2534 params.name = DOMString::from(alg_name);
2535 NormalizedAlgorithm::Algorithm(params.into())
2536 },
2537 (ALG_SHA256, Operation::Digest) => {
2538 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2539 params.name = DOMString::from(alg_name);
2540 NormalizedAlgorithm::Algorithm(params.into())
2541 },
2542 (ALG_SHA384, Operation::Digest) => {
2543 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2544 params.name = DOMString::from(alg_name);
2545 NormalizedAlgorithm::Algorithm(params.into())
2546 },
2547 (ALG_SHA512, Operation::Digest) => {
2548 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2549 params.name = DOMString::from(alg_name);
2550 NormalizedAlgorithm::Algorithm(params.into())
2551 },
2552
2553 (ALG_HKDF, Operation::DeriveBits) => {
2555 let mut params = dictionary_from_jsval::<RootedTraceableBox<HkdfParams>>(
2556 cx,
2557 value.handle(),
2558 )?;
2559 params.parent.name = DOMString::from(alg_name);
2560 NormalizedAlgorithm::HkdfParams(params.try_into()?)
2561 },
2562 (ALG_HKDF, Operation::ImportKey) => {
2563 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2564 params.name = DOMString::from(alg_name);
2565 NormalizedAlgorithm::Algorithm(params.into())
2566 },
2567 (ALG_HKDF, Operation::GetKeyLength) => {
2568 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2569 params.name = DOMString::from(alg_name);
2570 NormalizedAlgorithm::Algorithm(params.into())
2571 },
2572
2573 (ALG_PBKDF2, Operation::DeriveBits) => {
2575 let mut params = dictionary_from_jsval::<RootedTraceableBox<Pbkdf2Params>>(
2576 cx,
2577 value.handle(),
2578 )?;
2579 params.parent.name = DOMString::from(alg_name);
2580 NormalizedAlgorithm::Pbkdf2Params(params.try_into()?)
2581 },
2582 (ALG_PBKDF2, Operation::ImportKey) => {
2583 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2584 params.name = DOMString::from(alg_name);
2585 NormalizedAlgorithm::Algorithm(params.into())
2586 },
2587 (ALG_PBKDF2, Operation::GetKeyLength) => {
2588 let mut params = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
2589 params.name = DOMString::from(alg_name);
2590 NormalizedAlgorithm::Algorithm(params.into())
2591 },
2592
2593 _ => return Err(Error::NotSupported),
2594 };
2595
2596 Ok(normalized_algorithm)
2598 },
2599 }
2600}
2601
2602impl NormalizedAlgorithm {
2603 fn name(&self) -> &str {
2605 match self {
2606 NormalizedAlgorithm::Algorithm(algo) => &algo.name,
2607 NormalizedAlgorithm::EcKeyGenParams(algo) => &algo.name,
2608 NormalizedAlgorithm::EcKeyImportParams(algo) => &algo.name,
2609 NormalizedAlgorithm::AesCtrParams(algo) => &algo.name,
2610 NormalizedAlgorithm::AesKeyGenParams(algo) => &algo.name,
2611 NormalizedAlgorithm::AesDerivedKeyParams(algo) => &algo.name,
2612 NormalizedAlgorithm::AesCbcParams(algo) => &algo.name,
2613 NormalizedAlgorithm::AesGcmParams(algo) => &algo.name,
2614 NormalizedAlgorithm::HmacImportParams(algo) => &algo.name,
2615 NormalizedAlgorithm::HmacKeyGenParams(algo) => &algo.name,
2616 NormalizedAlgorithm::HkdfParams(algo) => &algo.name,
2617 NormalizedAlgorithm::Pbkdf2Params(algo) => &algo.name,
2618 }
2619 }
2620
2621 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
2622 match self {
2623 NormalizedAlgorithm::AesCtrParams(algo) => {
2624 aes_operation::encrypt_aes_ctr(algo, key, plaintext)
2625 },
2626 NormalizedAlgorithm::AesCbcParams(algo) => {
2627 aes_operation::encrypt_aes_cbc(algo, key, plaintext)
2628 },
2629 NormalizedAlgorithm::AesGcmParams(algo) => {
2630 aes_operation::encrypt_aes_gcm(algo, key, plaintext)
2631 },
2632 _ => Err(Error::NotSupported),
2633 }
2634 }
2635
2636 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
2637 match self {
2638 NormalizedAlgorithm::AesCtrParams(algo) => {
2639 aes_operation::decrypt_aes_ctr(algo, key, ciphertext)
2640 },
2641 NormalizedAlgorithm::AesCbcParams(algo) => {
2642 aes_operation::decrypt_aes_cbc(algo, key, ciphertext)
2643 },
2644 NormalizedAlgorithm::AesGcmParams(algo) => {
2645 aes_operation::decrypt_aes_gcm(algo, key, ciphertext)
2646 },
2647 _ => Err(Error::NotSupported),
2648 }
2649 }
2650
2651 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
2652 match self {
2653 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2654 ALG_ED25519 => ed25519_operation::sign(key, message),
2655 ALG_HMAC => hmac_operation::sign(key, message),
2656 _ => Err(Error::NotSupported),
2657 },
2658 _ => Err(Error::NotSupported),
2659 }
2660 }
2661
2662 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
2663 match self {
2664 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2665 ALG_ED25519 => ed25519_operation::verify(key, message, signature),
2666 ALG_HMAC => hmac_operation::verify(key, message, signature),
2667 _ => Err(Error::NotSupported),
2668 },
2669 _ => Err(Error::NotSupported),
2670 }
2671 }
2672
2673 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
2674 match self {
2675 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2676 ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 => {
2677 sha_operation::digest(algo, message)
2678 },
2679 _ => Err(Error::NotSupported),
2680 },
2681 _ => Err(Error::NotSupported),
2682 }
2683 }
2684
2685 fn generate_key(
2686 &self,
2687 global: &GlobalScope,
2688 extractable: bool,
2689 usages: Vec<KeyUsage>,
2690 can_gc: CanGc,
2691 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
2692 match self {
2693 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2694 ALG_ED25519 => ed25519_operation::generate_key(global, extractable, usages, can_gc)
2695 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair),
2696 _ => Err(Error::NotSupported),
2697 },
2698 NormalizedAlgorithm::EcKeyGenParams(algo) => match algo.name.as_str() {
2699 ALG_ECDH => ecdh_operation::generate_key(global, algo, extractable, usages, can_gc)
2700 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair),
2701 _ => Err(Error::NotSupported),
2702 },
2703 NormalizedAlgorithm::AesKeyGenParams(algo) => match algo.name.as_str() {
2704 ALG_AES_CTR => {
2705 aes_operation::generate_key_aes_ctr(global, algo, extractable, usages, can_gc)
2706 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
2707 },
2708 ALG_AES_CBC => {
2709 aes_operation::generate_key_aes_cbc(global, algo, extractable, usages, can_gc)
2710 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
2711 },
2712 ALG_AES_GCM => {
2713 aes_operation::generate_key_aes_gcm(global, algo, extractable, usages, can_gc)
2714 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
2715 },
2716 ALG_AES_KW => {
2717 aes_operation::generate_key_aes_kw(global, algo, extractable, usages, can_gc)
2718 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
2719 },
2720 _ => Err(Error::NotSupported),
2721 },
2722 NormalizedAlgorithm::HmacKeyGenParams(algo) => {
2723 hmac_operation::generate_key(global, algo, extractable, usages, can_gc)
2724 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
2725 },
2726 _ => Err(Error::NotSupported),
2727 }
2728 }
2729
2730 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
2731 match self {
2732 NormalizedAlgorithm::HkdfParams(algo) => hkdf_operation::derive_bits(algo, key, length),
2733 NormalizedAlgorithm::Pbkdf2Params(algo) => {
2734 pbkdf2_operation::derive_bits(algo, key, length)
2735 },
2736 _ => Err(Error::NotSupported),
2737 }
2738 }
2739
2740 fn import_key(
2741 &self,
2742 global: &GlobalScope,
2743 format: KeyFormat,
2744 key_data: &[u8],
2745 extractable: bool,
2746 usages: Vec<KeyUsage>,
2747 can_gc: CanGc,
2748 ) -> Result<DomRoot<CryptoKey>, Error> {
2749 match self {
2750 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2751 ALG_ED25519 => ed25519_operation::import_key(
2752 global,
2753 format,
2754 key_data,
2755 extractable,
2756 usages,
2757 can_gc,
2758 ),
2759 ALG_AES_CTR => aes_operation::import_key_aes_ctr(
2760 global,
2761 format,
2762 key_data,
2763 extractable,
2764 usages,
2765 can_gc,
2766 ),
2767 ALG_AES_CBC => aes_operation::import_key_aes_cbc(
2768 global,
2769 format,
2770 key_data,
2771 extractable,
2772 usages,
2773 can_gc,
2774 ),
2775 ALG_AES_GCM => aes_operation::import_key_aes_gcm(
2776 global,
2777 format,
2778 key_data,
2779 extractable,
2780 usages,
2781 can_gc,
2782 ),
2783 ALG_AES_KW => aes_operation::import_key_aes_kw(
2784 global,
2785 format,
2786 key_data,
2787 extractable,
2788 usages,
2789 can_gc,
2790 ),
2791 ALG_HKDF => {
2792 hkdf_operation::import(global, format, key_data, extractable, usages, can_gc)
2793 },
2794 ALG_PBKDF2 => {
2795 pbkdf2_operation::import(global, format, key_data, extractable, usages, can_gc)
2796 },
2797 _ => Err(Error::NotSupported),
2798 },
2799 NormalizedAlgorithm::EcKeyImportParams(algo) => ecdh_operation::import_key(
2800 global,
2801 algo,
2802 format,
2803 key_data,
2804 extractable,
2805 usages,
2806 can_gc,
2807 ),
2808 NormalizedAlgorithm::HmacImportParams(algo) => hmac_operation::import_key(
2809 global,
2810 algo,
2811 format,
2812 key_data,
2813 extractable,
2814 usages,
2815 can_gc,
2816 ),
2817 _ => Err(Error::NotSupported),
2818 }
2819 }
2820
2821 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
2822 match self {
2823 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2824 ALG_AES_KW => aes_operation::wrap_key_aes_kw(key, plaintext),
2825 _ => Err(Error::NotSupported),
2826 },
2827 _ => Err(Error::NotSupported),
2828 }
2829 }
2830
2831 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
2832 match self {
2833 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2834 ALG_AES_KW => aes_operation::unwrap_key_aes_kw(key, ciphertext),
2835 _ => Err(Error::NotSupported),
2836 },
2837 _ => Err(Error::NotSupported),
2838 }
2839 }
2840
2841 fn get_key_length(&self) -> Result<Option<u32>, Error> {
2842 match self {
2843 NormalizedAlgorithm::AesDerivedKeyParams(algo) => match algo.name.as_str() {
2844 ALG_AES_CTR => aes_operation::get_key_length_aes_ctr(algo),
2845 ALG_AES_CBC => aes_operation::get_key_length_aes_cbc(algo),
2846 ALG_AES_GCM => aes_operation::get_key_length_aes_gcm(algo),
2847 ALG_AES_KW => aes_operation::get_key_length_aes_kw(algo),
2848 _ => Err(Error::NotSupported),
2849 },
2850 NormalizedAlgorithm::HmacImportParams(algo) => hmac_operation::get_key_length(algo),
2851 NormalizedAlgorithm::HkdfParams(_algo) => hkdf_operation::get_key_length(),
2852 NormalizedAlgorithm::Pbkdf2Params(_algo) => pbkdf2_operation::get_key_length(),
2853 _ => Err(Error::NotSupported),
2854 }
2855 }
2856}
2857
2858fn perform_export_key_operation(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
2865 match key.algorithm().name() {
2866 ALG_ECDH => ecdh_operation::export_key(format, key),
2867 ALG_ED25519 => ed25519_operation::export_key(format, key),
2868 ALG_AES_CTR => aes_operation::export_key_aes_ctr(format, key),
2869 ALG_AES_CBC => aes_operation::export_key_aes_cbc(format, key),
2870 ALG_AES_GCM => aes_operation::export_key_aes_gcm(format, key),
2871 ALG_AES_KW => aes_operation::export_key_aes_kw(format, key),
2872 ALG_HMAC => hmac_operation::export(format, key),
2873 _ => Err(Error::NotSupported),
2874 }
2875}