1mod aes_operation;
6mod hkdf_operation;
7mod hmac_operation;
8mod pbkdf2_operation;
9mod sha_operation;
10
11use std::ptr;
12use std::rc::Rc;
13use std::str::FromStr;
14
15use dom_struct::dom_struct;
16use js::conversions::ConversionResult;
17use js::jsapi::{Heap, JSObject};
18use js::jsval::{ObjectValue, UndefinedValue};
19use js::rust::wrappers::JS_ParseJSON;
20use js::rust::{HandleValue, MutableHandleValue};
21use js::typedarray::ArrayBufferU8;
22use servo_rand::ServoRng;
23
24use crate::dom::bindings::buffer_source::create_buffer_source;
25use crate::dom::bindings::cell::DomRefCell;
26use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
27 CryptoKeyMethods, KeyType, KeyUsage,
28};
29use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
30 AesCbcParams, AesCtrParams, AesDerivedKeyParams, AesGcmParams, AesKeyAlgorithm,
31 AesKeyGenParams, Algorithm, AlgorithmIdentifier, HkdfParams, HmacImportParams,
32 HmacKeyAlgorithm, HmacKeyGenParams, JsonWebKey, KeyAlgorithm, KeyFormat, Pbkdf2Params,
33 RsaOtherPrimesInfo, SubtleCryptoMethods,
34};
35use crate::dom::bindings::codegen::UnionTypes::{
36 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey, ObjectOrString,
37};
38use crate::dom::bindings::conversions::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";
68
69static SUPPORTED_ALGORITHMS: &[&str] = &[
70 ALG_AES_CBC,
71 ALG_AES_CTR,
72 ALG_AES_GCM,
73 ALG_AES_KW,
74 ALG_SHA1,
75 ALG_SHA256,
76 ALG_SHA384,
77 ALG_SHA512,
78 ALG_HMAC,
79 ALG_HKDF,
80 ALG_PBKDF2,
81 ALG_RSASSA_PKCS1,
82 ALG_RSA_OAEP,
83 ALG_RSA_PSS,
84 ALG_ECDH,
85 ALG_ECDSA,
86];
87
88const NAMED_CURVE_P256: &str = "P-256";
89const NAMED_CURVE_P384: &str = "P-384";
90const NAMED_CURVE_P521: &str = "P-521";
91#[allow(dead_code)]
92static SUPPORTED_CURVES: &[&str] = &[NAMED_CURVE_P256, NAMED_CURVE_P384, NAMED_CURVE_P521];
93
94#[allow(dead_code)]
96enum Operation {
97 Encrypt,
98 Decrypt,
99 Sign,
100 Verify,
101 Digest,
102 GenerateKey,
103 DeriveKey,
104 DeriveBits,
105 ImportKey,
106 ExportKey,
107 WrapKey,
108 UnwrapKey,
109 GetKeyLength,
110}
111
112#[dom_struct]
113pub(crate) struct SubtleCrypto {
114 reflector_: Reflector,
115 #[no_trace]
116 rng: DomRefCell<ServoRng>,
117}
118
119impl SubtleCrypto {
120 fn new_inherited() -> SubtleCrypto {
121 SubtleCrypto {
122 reflector_: Reflector::new(),
123 rng: DomRefCell::new(ServoRng::default()),
124 }
125 }
126
127 pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<SubtleCrypto> {
128 reflect_dom_object(Box::new(SubtleCrypto::new_inherited()), global, can_gc)
129 }
130
131 fn resolve_promise_with_data(&self, promise: Rc<Promise>, data: Vec<u8>) {
135 let trusted_promise = TrustedPromise::new(promise);
136 self.global().task_manager().crypto_task_source().queue(
137 task!(resolve_data: move || {
138 let promise = trusted_promise.root();
139
140 let cx = GlobalScope::get_cx();
141 rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
142 match create_buffer_source::<ArrayBufferU8>(cx, &data, array_buffer_ptr.handle_mut(), CanGc::note()) {
143 Ok(_) => promise.resolve_native(&*array_buffer_ptr, CanGc::note()),
144 Err(_) => promise.reject_error(Error::JSFailed, CanGc::note()),
145 }
146 }),
147 );
148 }
149
150 fn resolve_promise_with_jwk(&self, promise: Rc<Promise>, jwk: Box<JsonWebKey>) {
154 let cx = GlobalScope::get_cx();
157 let stringified_jwk = match jwk.stringify(cx) {
158 Ok(stringified_jwk) => stringified_jwk.to_string(),
159 Err(error) => {
160 self.reject_promise_with_error(promise, error);
161 return;
162 },
163 };
164
165 let trusted_subtle = Trusted::new(self);
166 let trusted_promise = TrustedPromise::new(promise);
167 self.global()
168 .task_manager()
169 .crypto_task_source()
170 .queue(task!(resolve_jwk: move || {
171 let subtle = trusted_subtle.root();
172 let promise = trusted_promise.root();
173
174 let cx = GlobalScope::get_cx();
175 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
176 Ok(jwk) => {
177 rooted!(in(*cx) let mut rval = UndefinedValue());
178 jwk.safe_to_jsval(cx, rval.handle_mut());
179 rooted!(in(*cx) let mut object = rval.to_object());
180 promise.resolve_native(&*object, CanGc::note());
181 },
182 Err(error) => {
183 subtle.reject_promise_with_error(promise, error);
184 return;
185 },
186 }
187 }));
188 }
189
190 fn resolve_promise_with_key(&self, promise: Rc<Promise>, key: DomRoot<CryptoKey>) {
193 let trusted_key = Trusted::new(&*key);
194 let trusted_promise = TrustedPromise::new(promise);
195 self.global()
196 .task_manager()
197 .crypto_task_source()
198 .queue(task!(resolve_key: move || {
199 let key = trusted_key.root();
200 let promise = trusted_promise.root();
201 promise.resolve_native(&key, CanGc::note());
202 }));
203 }
204
205 fn resolve_promise_with_bool(&self, promise: Rc<Promise>, result: bool) {
208 let trusted_promise = TrustedPromise::new(promise);
209 self.global().task_manager().crypto_task_source().queue(
210 task!(generate_key_result: move || {
211 let promise = trusted_promise.root();
212 promise.resolve_native(&result, CanGc::note());
213 }),
214 );
215 }
216
217 fn reject_promise_with_error(&self, promise: Rc<Promise>, error: Error) {
220 let trusted_promise = TrustedPromise::new(promise);
221 self.global()
222 .task_manager()
223 .crypto_task_source()
224 .queue(task!(reject_error: move || {
225 let promise = trusted_promise.root();
226 promise.reject_error(error, CanGc::note());
227 }));
228 }
229}
230
231impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
232 fn Encrypt(
234 &self,
235 cx: JSContext,
236 algorithm: AlgorithmIdentifier,
237 key: &CryptoKey,
238 data: ArrayBufferViewOrArrayBuffer,
239 comp: InRealm,
240 can_gc: CanGc,
241 ) -> Rc<Promise> {
242 let data = match data {
249 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
250 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
251 };
252
253 let promise = Promise::new_in_current_realm(comp, can_gc);
257 let normalized_algorithm =
258 match normalize_algorithm(cx, &Operation::Encrypt, &algorithm, can_gc) {
259 Ok(normalized_algorithm) => normalized_algorithm,
260 Err(error) => {
261 promise.reject_error(error, can_gc);
262 return promise;
263 },
264 };
265
266 let this = Trusted::new(self);
272 let trusted_promise = TrustedPromise::new(promise.clone());
273 let trusted_key = Trusted::new(key);
274 self.global()
275 .task_manager()
276 .dom_manipulation_task_source()
277 .queue(task!(encrypt: move || {
278 let subtle = this.root();
279 let promise = trusted_promise.root();
280 let key = trusted_key.root();
281
282 if normalized_algorithm.name() != key.algorithm().name() {
290 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
291 return;
292 }
293
294 if !key.usages().contains(&KeyUsage::Encrypt) {
297 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
298 return;
299 }
300
301 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
305 Ok(ciphertext) => ciphertext,
306 Err(error) => {
307 subtle.reject_promise_with_error(promise, error);
308 return;
309 },
310 };
311
312 subtle.resolve_promise_with_data(promise, ciphertext);
318 }));
319 promise
320 }
321
322 fn Decrypt(
324 &self,
325 cx: JSContext,
326 algorithm: AlgorithmIdentifier,
327 key: &CryptoKey,
328 data: ArrayBufferViewOrArrayBuffer,
329 comp: InRealm,
330 can_gc: CanGc,
331 ) -> Rc<Promise> {
332 let data = match data {
339 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
340 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
341 };
342
343 let promise = Promise::new_in_current_realm(comp, can_gc);
347 let normalized_algorithm =
348 match normalize_algorithm(cx, &Operation::Decrypt, &algorithm, can_gc) {
349 Ok(normalized_algorithm) => normalized_algorithm,
350 Err(error) => {
351 promise.reject_error(error, can_gc);
352 return promise;
353 },
354 };
355
356 let this = Trusted::new(self);
362 let trusted_promise = TrustedPromise::new(promise.clone());
363 let trusted_key = Trusted::new(key);
364 self.global()
365 .task_manager()
366 .dom_manipulation_task_source()
367 .queue(task!(decrypt: move || {
368 let subtle = this.root();
369 let promise = trusted_promise.root();
370 let key = trusted_key.root();
371
372 if normalized_algorithm.name() != key.algorithm().name() {
380 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
381 return;
382 }
383
384 if !key.usages().contains(&KeyUsage::Decrypt) {
387 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
388 return;
389 }
390
391 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
395 Ok(plaintext) => plaintext,
396 Err(error) => {
397 subtle.reject_promise_with_error(promise, error);
398 return;
399 },
400 };
401
402 subtle.resolve_promise_with_data(promise, plaintext);
408 }));
409 promise
410 }
411
412 fn Sign(
414 &self,
415 cx: JSContext,
416 algorithm: AlgorithmIdentifier,
417 key: &CryptoKey,
418 data: ArrayBufferViewOrArrayBuffer,
419 comp: InRealm,
420 can_gc: CanGc,
421 ) -> Rc<Promise> {
422 let data = match &data {
429 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
430 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
431 };
432
433 let promise = Promise::new_in_current_realm(comp, can_gc);
437 let normalized_algorithm =
438 match normalize_algorithm(cx, &Operation::Sign, &algorithm, can_gc) {
439 Ok(normalized_algorithm) => normalized_algorithm,
440 Err(error) => {
441 promise.reject_error(error, can_gc);
442 return promise;
443 },
444 };
445
446 let this = Trusted::new(self);
452 let trusted_promise = TrustedPromise::new(promise.clone());
453 let trusted_key = Trusted::new(key);
454 self.global()
455 .task_manager()
456 .dom_manipulation_task_source()
457 .queue(task!(sign: move || {
458 let subtle = this.root();
459 let promise = trusted_promise.root();
460 let key = trusted_key.root();
461
462 if normalized_algorithm.name() != key.algorithm().name() {
470 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
471 return;
472 }
473
474 if !key.usages().contains(&KeyUsage::Sign) {
477 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
478 return;
479 }
480
481 let signature = match normalized_algorithm.sign(&key, &data, CanGc::note()) {
484 Ok(signature) => signature,
485 Err(error) => {
486 subtle.reject_promise_with_error(promise, error);
487 return;
488 },
489 };
490
491 subtle.resolve_promise_with_data(promise, signature);
497 }));
498 promise
499 }
500
501 fn Verify(
503 &self,
504 cx: JSContext,
505 algorithm: AlgorithmIdentifier,
506 key: &CryptoKey,
507 signature: ArrayBufferViewOrArrayBuffer,
508 data: ArrayBufferViewOrArrayBuffer,
509 comp: InRealm,
510 can_gc: CanGc,
511 ) -> Rc<Promise> {
512 let signature = match &signature {
519 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
520 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
521 };
522
523 let data = match &data {
526 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
527 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
528 };
529
530 let promise = Promise::new_in_current_realm(comp, can_gc);
534 let normalized_algorithm =
535 match normalize_algorithm(cx, &Operation::Verify, &algorithm, can_gc) {
536 Ok(algorithm) => algorithm,
537 Err(error) => {
538 promise.reject_error(error, can_gc);
539 return promise;
540 },
541 };
542
543 let this = Trusted::new(self);
549 let trusted_promise = TrustedPromise::new(promise.clone());
550 let trusted_key = Trusted::new(key);
551 self.global()
552 .task_manager()
553 .dom_manipulation_task_source()
554 .queue(task!(sign: move || {
555 let subtle = this.root();
556 let promise = trusted_promise.root();
557 let key = trusted_key.root();
558
559 if normalized_algorithm.name() != key.algorithm().name() {
567 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
568 return;
569 }
570
571 if !key.usages().contains(&KeyUsage::Verify) {
574 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
575 return;
576 }
577
578 let result = match normalized_algorithm.verify(&key, &data, &signature, CanGc::note()) {
582 Ok(result) => result,
583 Err(error) => {
584 subtle.reject_promise_with_error(promise, error);
585 return;
586 },
587 };
588
589 subtle.resolve_promise_with_bool(promise, result);
593 }));
594 promise
595 }
596
597 fn Digest(
599 &self,
600 cx: JSContext,
601 algorithm: AlgorithmIdentifier,
602 data: ArrayBufferViewOrArrayBuffer,
603 comp: InRealm,
604 can_gc: CanGc,
605 ) -> Rc<Promise> {
606 let data = match data {
612 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
613 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
614 };
615
616 let promise = Promise::new_in_current_realm(comp, can_gc);
620 let normalized_algorithm =
621 match normalize_algorithm(cx, &Operation::Digest, &algorithm, can_gc) {
622 Ok(normalized_algorithm) => normalized_algorithm,
623 Err(error) => {
624 promise.reject_error(error, can_gc);
625 return promise;
626 },
627 };
628
629 let this = Trusted::new(self);
635 let trusted_promise = TrustedPromise::new(promise.clone());
636 self.global()
637 .task_manager()
638 .dom_manipulation_task_source()
639 .queue(task!(generate_key: move || {
640 let subtle = this.root();
641 let promise = trusted_promise.root();
642
643 let digest = match normalized_algorithm.digest(&data) {
650 Ok(digest) => digest,
651 Err(error) => {
652 subtle.reject_promise_with_error(promise, error);
653 return;
654 }
655 };
656
657 subtle.resolve_promise_with_data(promise, digest);
663 }));
664 promise
665 }
666
667 fn GenerateKey(
669 &self,
670 cx: JSContext,
671 algorithm: AlgorithmIdentifier,
672 extractable: bool,
673 key_usages: Vec<KeyUsage>,
674 comp: InRealm,
675 can_gc: CanGc,
676 ) -> Rc<Promise> {
677 let promise = Promise::new_in_current_realm(comp, can_gc);
684 let normalized_algorithm =
685 match normalize_algorithm(cx, &Operation::GenerateKey, &algorithm, can_gc) {
686 Ok(normalized_algorithm) => normalized_algorithm,
687 Err(error) => {
688 promise.reject_error(error, can_gc);
689 return promise;
690 },
691 };
692
693 let trusted_subtle = Trusted::new(self);
699 let trusted_promise = TrustedPromise::new(promise.clone());
700 self.global()
701 .task_manager()
702 .dom_manipulation_task_source()
703 .queue(task!(generate_key: move || {
704 let subtle = trusted_subtle.root();
705 let promise = trusted_promise.root();
706
707 let result = match normalized_algorithm.generate_key(
714 &subtle.global(),
715 extractable,
716 key_usages,
717 &subtle.rng,
718 CanGc::note(),
719 ) {
720 Ok(result) => result,
721 Err(error) => {
722 subtle.reject_promise_with_error(promise, error);
723 return;
724 }
725 };
726
727 match &result {
736 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
737 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
738 && crpyto_key.usages().is_empty()
739 {
740 subtle.reject_promise_with_error(promise, Error::Syntax(None));
741 return;
742 }
743 },
744 };
745
746 match result {
752 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
753 subtle.resolve_promise_with_key(promise, key);
754 },
755 }
756 }));
757
758 promise
759 }
760
761 fn DeriveKey(
763 &self,
764 cx: JSContext,
765 algorithm: AlgorithmIdentifier,
766 base_key: &CryptoKey,
767 derived_key_type: AlgorithmIdentifier,
768 extractable: bool,
769 usages: Vec<KeyUsage>,
770 comp: InRealm,
771 can_gc: CanGc,
772 ) -> Rc<Promise> {
773 let promise = Promise::new_in_current_realm(comp, can_gc);
782 let normalized_algorithm =
783 match normalize_algorithm(cx, &Operation::DeriveBits, &algorithm, can_gc) {
784 Ok(normalized_algorithm) => normalized_algorithm,
785 Err(error) => {
786 promise.reject_error(error, can_gc);
787 return promise;
788 },
789 };
790
791 let normalized_derived_key_algorithm_import =
796 match normalize_algorithm(cx, &Operation::ImportKey, &derived_key_type, can_gc) {
797 Ok(normalized_algorithm) => normalized_algorithm,
798 Err(error) => {
799 promise.reject_error(error, can_gc);
800 return promise;
801 },
802 };
803
804 let normalized_derived_key_algorithm_length =
809 match normalize_algorithm(cx, &Operation::GetKeyLength, &derived_key_type, can_gc) {
810 Ok(normalized_algorithm) => normalized_algorithm,
811 Err(error) => {
812 promise.reject_error(error, can_gc);
813 return promise;
814 },
815 };
816
817 let trusted_subtle = Trusted::new(self);
823 let trusted_base_key = Trusted::new(base_key);
824 let trusted_promise = TrustedPromise::new(promise.clone());
825 self.global().task_manager().dom_manipulation_task_source().queue(
826 task!(derive_key: move || {
827 let subtle = trusted_subtle.root();
828 let base_key = trusted_base_key.root();
829 let promise = trusted_promise.root();
830
831 if normalized_algorithm.name() != base_key.algorithm().name() {
839 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
840 return;
841 }
842
843 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
846 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
847 return;
848 }
849
850 let length = match normalized_derived_key_algorithm_length.get_key_length() {
853 Ok(length) => length,
854 Err(error) => {
855 subtle.reject_promise_with_error(promise, error);
856 return;
857 }
858 };
859
860 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
863 Ok(secret) => secret,
864 Err(error) => {
865 subtle.reject_promise_with_error(promise, error);
866 return;
867 }
868 };
869
870 let result = match normalized_derived_key_algorithm_import.import_key(
874 &subtle.global(),
875 KeyFormat::Raw,
876 &secret,
877 extractable,
878 usages.clone(),
879 CanGc::note(),
880 ) {
881 Ok(algorithm) => algorithm,
882 Err(error) => {
883 subtle.reject_promise_with_error(promise, error);
884 return;
885 },
886 };
887
888 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
891 subtle.reject_promise_with_error(promise, Error::Syntax(None));
892 return;
893 }
894
895 subtle.resolve_promise_with_key(promise, result);
906 }),
907 );
908 promise
909 }
910
911 fn DeriveBits(
913 &self,
914 cx: JSContext,
915 algorithm: AlgorithmIdentifier,
916 base_key: &CryptoKey,
917 length: Option<u32>,
918 comp: InRealm,
919 can_gc: CanGc,
920 ) -> Rc<Promise> {
921 let promise = Promise::new_in_current_realm(comp, can_gc);
929 let normalized_algorithm =
930 match normalize_algorithm(cx, &Operation::DeriveBits, &algorithm, can_gc) {
931 Ok(normalized_algorithm) => normalized_algorithm,
932 Err(error) => {
933 promise.reject_error(error, can_gc);
934 return promise;
935 },
936 };
937
938 let trsuted_subtle = Trusted::new(self);
944 let trusted_base_key = Trusted::new(base_key);
945 let trusted_promise = TrustedPromise::new(promise.clone());
946 self.global()
947 .task_manager()
948 .dom_manipulation_task_source()
949 .queue(task!(import_key: move || {
950 let subtle = trsuted_subtle.root();
951 let base_key = trusted_base_key.root();
952 let promise = trusted_promise.root();
953
954 if normalized_algorithm.name() != base_key.algorithm().name() {
962 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
963 return;
964 }
965
966 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
969 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
970 return;
971 }
972
973 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
976 Ok(bits) => bits,
977 Err(error) => {
978 subtle.reject_promise_with_error(promise, error);
979 return;
980 }
981 };
982
983 subtle.resolve_promise_with_data(promise, bits);
989 }));
990 promise
991 }
992
993 fn ImportKey(
995 &self,
996 cx: JSContext,
997 format: KeyFormat,
998 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
999 algorithm: AlgorithmIdentifier,
1000 extractable: bool,
1001 key_usages: Vec<KeyUsage>,
1002 comp: InRealm,
1003 can_gc: CanGc,
1004 ) -> Rc<Promise> {
1005 let promise = Promise::new_in_current_realm(comp, can_gc);
1011
1012 let key_data = match format {
1014 KeyFormat::Raw | KeyFormat::Pkcs8 | KeyFormat::Spki => {
1016 match key_data {
1017 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1020 promise.reject_error(
1021 Error::Type("The keyData type does not match the format".to_string()),
1022 can_gc,
1023 );
1024 return promise;
1025 },
1026
1027 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1030 view.to_vec()
1031 },
1032 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1033 buffer.to_vec()
1034 },
1035 }
1036 },
1037 KeyFormat::Jwk => {
1039 match key_data {
1040 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1041 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1042 promise.reject_error(
1045 Error::Type("The keyData type does not match the format".to_string()),
1046 can_gc,
1047 );
1048 return promise;
1049 },
1050
1051 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1052 match jwk.stringify(cx) {
1059 Ok(stringified) => stringified.as_bytes().to_vec(),
1060 Err(error) => {
1061 promise.reject_error(error, can_gc);
1062 return promise;
1063 },
1064 }
1065 },
1066 }
1067 },
1068 };
1069
1070 let normalized_algorithm =
1074 match normalize_algorithm(cx, &Operation::ImportKey, &algorithm, can_gc) {
1075 Ok(algorithm) => algorithm,
1076 Err(error) => {
1077 promise.reject_error(error, can_gc);
1078 return promise;
1079 },
1080 };
1081
1082 let this = Trusted::new(self);
1084 let trusted_promise = TrustedPromise::new(promise.clone());
1085 self.global()
1086 .task_manager()
1087 .dom_manipulation_task_source()
1088 .queue(task!(import_key: move || {
1089 let subtle = this.root();
1090 let promise = trusted_promise.root();
1091
1092 let result = match normalized_algorithm.import_key(
1100 &subtle.global(),
1101 format,
1102 &key_data,
1103 extractable,
1104 key_usages.clone(),
1105 CanGc::note()
1106 ) {
1107 Ok(key) => key,
1108 Err(error) => {
1109 subtle.reject_promise_with_error(promise, error);
1110 return;
1111 },
1112 };
1113
1114 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && key_usages.is_empty() {
1117 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1118 return;
1119 }
1120
1121 result.set_extractable(extractable);
1123
1124 result.set_usages(&key_usages);
1126
1127 subtle.resolve_promise_with_key(promise, result);
1133 }));
1134
1135 promise
1136 }
1137
1138 fn ExportKey(
1140 &self,
1141 format: KeyFormat,
1142 key: &CryptoKey,
1143 comp: InRealm,
1144 can_gc: CanGc,
1145 ) -> Rc<Promise> {
1146 let promise = Promise::new_in_current_realm(comp, can_gc);
1153
1154 let trusted_subtle = Trusted::new(self);
1156 let trusted_promise = TrustedPromise::new(promise.clone());
1157 let trusted_key = Trusted::new(key);
1158 self.global()
1159 .task_manager()
1160 .dom_manipulation_task_source()
1161 .queue(task!(export_key: move || {
1162 let subtle = trusted_subtle.root();
1163 let promise = trusted_promise.root();
1164 let key = trusted_key.root();
1165
1166 if matches!(
1174 key.algorithm().name(),
1175 ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 | ALG_HKDF | ALG_PBKDF2
1176 ) {
1177 subtle.reject_promise_with_error(promise, Error::NotSupported);
1178 return;
1179 }
1180
1181 if !key.Extractable() {
1184 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1185 return;
1186 }
1187
1188 let result = match perform_export_key_operation(format, &key) {
1191 Ok(exported_key) => exported_key,
1192 Err(error) => {
1193 subtle.reject_promise_with_error(promise, error);
1194 return;
1195 },
1196 };
1197
1198 match result {
1209 ExportedKey::Raw(raw) => {
1210 subtle.resolve_promise_with_data(promise, raw);
1211 },
1212 ExportedKey::Jwk(jwk) => {
1213 subtle.resolve_promise_with_jwk(promise, jwk);
1214 },
1215 }
1216 }));
1217 promise
1218 }
1219
1220 fn WrapKey(
1222 &self,
1223 cx: JSContext,
1224 format: KeyFormat,
1225 key: &CryptoKey,
1226 wrapping_key: &CryptoKey,
1227 algorithm: AlgorithmIdentifier,
1228 comp: InRealm,
1229 can_gc: CanGc,
1230 ) -> Rc<Promise> {
1231 let mut normalized_algorithm_result =
1238 normalize_algorithm(cx, &Operation::WrapKey, &algorithm, can_gc);
1239
1240 if normalized_algorithm_result.is_err() {
1243 normalized_algorithm_result =
1244 normalize_algorithm(cx, &Operation::Encrypt, &algorithm, can_gc);
1245 }
1246
1247 let promise = Promise::new_in_current_realm(comp, can_gc);
1249 let normalized_algorithm = match normalized_algorithm_result {
1250 Ok(normalized_algorithm) => normalized_algorithm,
1251 Err(error) => {
1252 promise.reject_error(error, can_gc);
1253 return promise;
1254 },
1255 };
1256
1257 let trusted_subtle = Trusted::new(self);
1263 let trusted_key = Trusted::new(key);
1264 let trusted_wrapping_key = Trusted::new(wrapping_key);
1265 let trusted_promise = TrustedPromise::new(promise.clone());
1266 self.global()
1267 .task_manager()
1268 .dom_manipulation_task_source()
1269 .queue(task!(wrap_key: move || {
1270 let subtle = trusted_subtle.root();
1271 let key = trusted_key.root();
1272 let wrapping_key = trusted_wrapping_key.root();
1273 let promise = trusted_promise.root();
1274
1275 if normalized_algorithm.name() != wrapping_key.algorithm().name() {
1283 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1284 return;
1285 }
1286
1287 if !wrapping_key.usages().contains(&KeyUsage::WrapKey) {
1290 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1291 return;
1292 }
1293
1294 if matches!(
1298 key.algorithm().name(),
1299 ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 | ALG_HKDF | ALG_PBKDF2
1300 ) {
1301 subtle.reject_promise_with_error(promise, Error::NotSupported);
1302 return;
1303 }
1304
1305
1306 if !key.Extractable() {
1309 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1310 return;
1311 }
1312
1313 let exported_key = match perform_export_key_operation(format, &key) {
1316 Ok(exported_key) => exported_key,
1317 Err(error) => {
1318 subtle.reject_promise_with_error(promise, error);
1319 return;
1320 },
1321 };
1322
1323 let cx = GlobalScope::get_cx();
1333 let bytes = match exported_key {
1334 ExportedKey::Raw(raw) => raw,
1335 ExportedKey::Jwk(jwk) => match jwk.stringify(cx) {
1336 Ok(stringified_jwk) => stringified_jwk.as_bytes().to_vec(),
1337 Err(error) => {
1338 subtle.reject_promise_with_error(promise, error);
1339 return;
1340 },
1341 },
1342 };
1343
1344 let mut result = normalized_algorithm.wrap_key(&wrapping_key, &bytes);
1356 if result.is_err() {
1357 result = normalized_algorithm.encrypt(&wrapping_key, &bytes);
1358 }
1359 let result = match result {
1360 Ok(result) => result,
1361 Err(error) => {
1362 subtle.reject_promise_with_error(promise, error);
1363 return;
1364 },
1365 };
1366
1367 subtle.resolve_promise_with_data(promise, result);
1373 }));
1374 promise
1375 }
1376
1377 fn UnwrapKey(
1379 &self,
1380 cx: JSContext,
1381 format: KeyFormat,
1382 wrapped_key: ArrayBufferViewOrArrayBuffer,
1383 unwrapping_key: &CryptoKey,
1384 algorithm: AlgorithmIdentifier,
1385 unwrapped_key_algorithm: AlgorithmIdentifier,
1386 extractable: bool,
1387 usages: Vec<KeyUsage>,
1388 comp: InRealm,
1389 can_gc: CanGc,
1390 ) -> Rc<Promise> {
1391 let wrapped_key = match wrapped_key {
1399 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1400 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1401 };
1402
1403 let mut normalized_algorithm =
1406 normalize_algorithm(cx, &Operation::UnwrapKey, &algorithm, can_gc);
1407
1408 if normalized_algorithm.is_err() {
1411 normalized_algorithm = normalize_algorithm(cx, &Operation::Decrypt, &algorithm, can_gc);
1412 }
1413
1414 let promise = Promise::new_in_current_realm(comp, can_gc);
1416 let normalized_algorithm = match normalized_algorithm {
1417 Ok(algorithm) => algorithm,
1418 Err(error) => {
1419 promise.reject_error(error, can_gc);
1420 return promise;
1421 },
1422 };
1423
1424 let normalized_key_algorithm = match normalize_algorithm(
1428 cx,
1429 &Operation::ImportKey,
1430 &unwrapped_key_algorithm,
1431 can_gc,
1432 ) {
1433 Ok(algorithm) => algorithm,
1434 Err(error) => {
1435 promise.reject_error(error, can_gc);
1436 return promise;
1437 },
1438 };
1439
1440 let trusted_subtle = Trusted::new(self);
1446 let trusted_unwrapping_key = Trusted::new(unwrapping_key);
1447 let trusted_promise = TrustedPromise::new(promise.clone());
1448 self.global().task_manager().dom_manipulation_task_source().queue(
1449 task!(unwrap_key: move || {
1450 let subtle = trusted_subtle.root();
1451 let unwrapping_key = trusted_unwrapping_key.root();
1452 let promise = trusted_promise.root();
1453
1454 if normalized_algorithm.name() != unwrapping_key.algorithm().name() {
1462 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1463 return;
1464 }
1465
1466 if !unwrapping_key.usages().contains(&KeyUsage::UnwrapKey) {
1469 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1470 return;
1471 }
1472
1473 let mut bytes = normalized_algorithm.unwrap_key(&unwrapping_key, &wrapped_key);
1485 if bytes.is_err() {
1486 bytes = normalized_algorithm.decrypt(&unwrapping_key, &wrapped_key);
1487 }
1488 let bytes = match bytes {
1489 Ok(bytes) => bytes,
1490 Err(error) => {
1491 subtle.reject_promise_with_error(promise, error);
1492 return;
1493 },
1494 };
1495
1496 let cx = GlobalScope::get_cx();
1506 if format == KeyFormat::Jwk {
1507 if let Err(error) = JsonWebKey::parse(cx, &bytes) {
1508 subtle.reject_promise_with_error(promise, error);
1509 return;
1510 }
1511 }
1512 let key = bytes;
1513
1514 let result = match normalized_key_algorithm.import_key(
1518 &subtle.global(),
1519 format,
1520 &key,
1521 extractable,
1522 usages.clone(),
1523 CanGc::note(),
1524 ) {
1525 Ok(result) => result,
1526 Err(error) => {
1527 subtle.reject_promise_with_error(promise, error);
1528 return;
1529 },
1530 };
1531
1532 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1535 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1536 return;
1537 }
1538
1539 subtle.resolve_promise_with_key(promise, result);
1550 }),
1551 );
1552 promise
1553 }
1554}
1555
1556#[derive(Clone, Debug, MallocSizeOf)]
1561struct SubtleAlgorithm {
1562 name: String,
1564}
1565
1566impl From<Algorithm> for SubtleAlgorithm {
1567 fn from(params: Algorithm) -> Self {
1568 SubtleAlgorithm {
1569 name: params.name.to_string(),
1570 }
1571 }
1572}
1573
1574#[derive(Clone, Debug, MallocSizeOf)]
1576pub(crate) struct SubtleKeyAlgorithm {
1577 name: String,
1579}
1580
1581impl SubtleKeyAlgorithm {
1582 fn block_size_in_bits(&self) -> Result<u32, Error> {
1583 let size = match self.name.as_str() {
1584 ALG_SHA1 => 160,
1585 ALG_SHA256 => 256,
1586 ALG_SHA384 => 384,
1587 ALG_SHA512 => 512,
1588 _ => {
1589 return Err(Error::NotSupported);
1590 },
1591 };
1592
1593 Ok(size)
1594 }
1595}
1596
1597impl From<NormalizedAlgorithm> for SubtleKeyAlgorithm {
1598 fn from(value: NormalizedAlgorithm) -> Self {
1599 SubtleKeyAlgorithm {
1600 name: value.name().to_string(),
1601 }
1602 }
1603}
1604
1605impl SafeToJSValConvertible for SubtleKeyAlgorithm {
1606 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue) {
1607 let dictionary = KeyAlgorithm {
1608 name: self.name.clone().into(),
1609 };
1610 dictionary.safe_to_jsval(cx, rval);
1611 }
1612}
1613
1614#[derive(Clone, Debug, MallocSizeOf)]
1615pub(crate) struct SubtleAesCbcParams {
1616 pub(crate) name: String,
1617 pub(crate) iv: Vec<u8>,
1618}
1619
1620impl From<RootedTraceableBox<AesCbcParams>> for SubtleAesCbcParams {
1621 fn from(params: RootedTraceableBox<AesCbcParams>) -> Self {
1622 let iv = match ¶ms.iv {
1623 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1624 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1625 };
1626 SubtleAesCbcParams {
1627 name: params.parent.name.to_string(),
1628 iv,
1629 }
1630 }
1631}
1632
1633#[derive(Clone, Debug, MallocSizeOf)]
1634pub(crate) struct SubtleAesCtrParams {
1635 pub(crate) name: String,
1636 pub(crate) counter: Vec<u8>,
1637 pub(crate) length: u8,
1638}
1639
1640impl From<RootedTraceableBox<AesCtrParams>> for SubtleAesCtrParams {
1641 fn from(params: RootedTraceableBox<AesCtrParams>) -> Self {
1642 let counter = match ¶ms.counter {
1643 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1644 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1645 };
1646 SubtleAesCtrParams {
1647 name: params.parent.name.to_string(),
1648 counter,
1649 length: params.length,
1650 }
1651 }
1652}
1653
1654#[derive(Clone, Debug, MallocSizeOf)]
1655pub(crate) struct SubtleAesGcmParams {
1656 pub(crate) name: String,
1657 pub(crate) iv: Vec<u8>,
1658 pub(crate) additional_data: Option<Vec<u8>>,
1659 pub(crate) tag_length: Option<u8>,
1660}
1661
1662impl From<RootedTraceableBox<AesGcmParams>> for SubtleAesGcmParams {
1663 fn from(params: RootedTraceableBox<AesGcmParams>) -> Self {
1664 let iv = match ¶ms.iv {
1665 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1666 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1667 };
1668 let additional_data = params.additionalData.as_ref().map(|data| match data {
1669 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1670 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1671 });
1672
1673 SubtleAesGcmParams {
1674 name: params.parent.name.to_string(),
1675 iv,
1676 additional_data,
1677 tag_length: params.tagLength,
1678 }
1679 }
1680}
1681
1682#[derive(Clone, Debug, MallocSizeOf)]
1684pub(crate) struct SubtleAesKeyAlgorithm {
1685 name: String,
1687
1688 length: u16,
1690}
1691
1692impl SafeToJSValConvertible for SubtleAesKeyAlgorithm {
1693 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue) {
1694 let parent = KeyAlgorithm {
1695 name: self.name.clone().into(),
1696 };
1697 let dictionary = AesKeyAlgorithm {
1698 parent,
1699 length: self.length,
1700 };
1701 dictionary.safe_to_jsval(cx, rval);
1702 }
1703}
1704
1705#[derive(Clone, Debug, MallocSizeOf)]
1707struct SubtleAesKeyGenParams {
1708 name: String,
1710
1711 length: u16,
1713}
1714
1715impl From<AesKeyGenParams> for SubtleAesKeyGenParams {
1716 fn from(params: AesKeyGenParams) -> Self {
1717 SubtleAesKeyGenParams {
1718 name: params.parent.name.to_string(),
1719 length: params.length,
1720 }
1721 }
1722}
1723
1724#[derive(Clone, Debug, MallocSizeOf)]
1726struct SubtleAesDerivedKeyParams {
1727 name: String,
1729
1730 length: u16,
1732}
1733
1734impl From<AesDerivedKeyParams> for SubtleAesDerivedKeyParams {
1735 fn from(params: AesDerivedKeyParams) -> Self {
1736 SubtleAesDerivedKeyParams {
1737 name: params.parent.name.to_string(),
1738 length: params.length,
1739 }
1740 }
1741}
1742
1743#[derive(Clone, Debug, MallocSizeOf)]
1745struct SubtleHmacImportParams {
1746 name: String,
1748
1749 hash: SubtleKeyAlgorithm,
1751
1752 length: Option<u32>,
1754}
1755
1756impl TryFrom<RootedTraceableBox<HmacImportParams>> for SubtleHmacImportParams {
1757 type Error = Error;
1758
1759 fn try_from(params: RootedTraceableBox<HmacImportParams>) -> Result<Self, Error> {
1760 let cx = GlobalScope::get_cx();
1761 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash, CanGc::note())?;
1762 Ok(SubtleHmacImportParams {
1763 name: params.parent.name.to_string(),
1764 hash: hash.into(),
1765 length: params.length,
1766 })
1767 }
1768}
1769
1770#[derive(Clone, Debug, MallocSizeOf)]
1772pub(crate) struct SubtleHmacKeyAlgorithm {
1773 name: String,
1775
1776 hash: SubtleKeyAlgorithm,
1778
1779 length: u32,
1781}
1782
1783impl SafeToJSValConvertible for SubtleHmacKeyAlgorithm {
1784 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue) {
1785 let parent = KeyAlgorithm {
1786 name: self.name.clone().into(),
1787 };
1788 let hash = KeyAlgorithm {
1789 name: self.hash.name.clone().into(),
1790 };
1791 let dictionary = HmacKeyAlgorithm {
1792 parent,
1793 hash,
1794 length: self.length,
1795 };
1796 dictionary.safe_to_jsval(cx, rval);
1797 }
1798}
1799
1800#[derive(Clone, Debug, MallocSizeOf)]
1802struct SubtleHmacKeyGenParams {
1803 name: String,
1805
1806 hash: SubtleKeyAlgorithm,
1808
1809 length: Option<u32>,
1811}
1812
1813impl TryFrom<RootedTraceableBox<HmacKeyGenParams>> for SubtleHmacKeyGenParams {
1814 type Error = Error;
1815
1816 fn try_from(params: RootedTraceableBox<HmacKeyGenParams>) -> Result<Self, Error> {
1817 let cx = GlobalScope::get_cx();
1818 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash, CanGc::note())?;
1819 Ok(SubtleHmacKeyGenParams {
1820 name: params.parent.name.to_string(),
1821 hash: hash.into(),
1822 length: params.length,
1823 })
1824 }
1825}
1826
1827#[derive(Clone, Debug, MallocSizeOf)]
1829pub(crate) struct SubtleHkdfParams {
1830 name: String,
1832
1833 hash: SubtleKeyAlgorithm,
1835
1836 salt: Vec<u8>,
1838
1839 info: Vec<u8>,
1841}
1842
1843impl TryFrom<RootedTraceableBox<HkdfParams>> for SubtleHkdfParams {
1844 type Error = Error;
1845
1846 fn try_from(params: RootedTraceableBox<HkdfParams>) -> Result<Self, Error> {
1847 let cx = GlobalScope::get_cx();
1848 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash, CanGc::note())?;
1849 let salt = match ¶ms.salt {
1850 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1851 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1852 };
1853 let info = match ¶ms.info {
1854 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1855 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1856 };
1857 Ok(SubtleHkdfParams {
1858 name: params.parent.name.to_string(),
1859 hash: hash.into(),
1860 salt,
1861 info,
1862 })
1863 }
1864}
1865
1866#[derive(Clone, Debug, MallocSizeOf)]
1868pub(crate) struct SubtlePbkdf2Params {
1869 name: String,
1871
1872 salt: Vec<u8>,
1874
1875 iterations: u32,
1877
1878 hash: SubtleKeyAlgorithm,
1880}
1881
1882impl TryFrom<RootedTraceableBox<Pbkdf2Params>> for SubtlePbkdf2Params {
1883 type Error = Error;
1884
1885 fn try_from(params: RootedTraceableBox<Pbkdf2Params>) -> Result<Self, Error> {
1886 let cx = GlobalScope::get_cx();
1887 let salt = match ¶ms.salt {
1888 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1889 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1890 };
1891 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash, CanGc::note())?;
1892 Ok(SubtlePbkdf2Params {
1893 name: params.parent.name.to_string(),
1894 salt,
1895 iterations: params.iterations,
1896 hash: hash.into(),
1897 })
1898 }
1899}
1900
1901trait DictionaryFromJSVal: Sized {
1903 fn create(
1904 cx: JSContext,
1905 value: HandleValue,
1906 can_gc: CanGc,
1907 ) -> Result<ConversionResult<Self>, ()>;
1908}
1909
1910impl DictionaryFromJSVal for Algorithm {
1911 fn create(
1912 cx: JSContext,
1913 value: HandleValue,
1914 can_gc: CanGc,
1915 ) -> Result<ConversionResult<Self>, ()> {
1916 Self::new(cx, value, can_gc)
1917 }
1918}
1919
1920impl DictionaryFromJSVal for AesDerivedKeyParams {
1921 fn create(
1922 cx: JSContext,
1923 value: HandleValue,
1924 can_gc: CanGc,
1925 ) -> Result<ConversionResult<Self>, ()> {
1926 Self::new(cx, value, can_gc)
1927 }
1928}
1929
1930impl DictionaryFromJSVal for AesKeyGenParams {
1931 fn create(
1932 cx: JSContext,
1933 value: HandleValue,
1934 can_gc: CanGc,
1935 ) -> Result<ConversionResult<Self>, ()> {
1936 Self::new(cx, value, can_gc)
1937 }
1938}
1939
1940impl DictionaryFromJSVal for RootedTraceableBox<HmacImportParams> {
1941 fn create(
1942 cx: JSContext,
1943 value: HandleValue,
1944 can_gc: CanGc,
1945 ) -> Result<ConversionResult<Self>, ()> {
1946 HmacImportParams::new(cx, value, can_gc)
1947 }
1948}
1949
1950impl DictionaryFromJSVal for RootedTraceableBox<HmacKeyGenParams> {
1951 fn create(
1952 cx: JSContext,
1953 value: HandleValue,
1954 can_gc: CanGc,
1955 ) -> Result<ConversionResult<Self>, ()> {
1956 HmacKeyGenParams::new(cx, value, can_gc)
1957 }
1958}
1959
1960impl DictionaryFromJSVal for HmacKeyAlgorithm {
1961 fn create(
1962 cx: JSContext,
1963 value: HandleValue,
1964 can_gc: CanGc,
1965 ) -> Result<ConversionResult<Self>, ()> {
1966 Self::new(cx, value, can_gc)
1967 }
1968}
1969
1970impl DictionaryFromJSVal for RootedTraceableBox<AesCbcParams> {
1971 fn create(
1972 cx: JSContext,
1973 value: HandleValue,
1974 can_gc: CanGc,
1975 ) -> Result<ConversionResult<Self>, ()> {
1976 AesCbcParams::new(cx, value, can_gc)
1977 }
1978}
1979
1980impl DictionaryFromJSVal for RootedTraceableBox<AesCtrParams> {
1981 fn create(
1982 cx: JSContext,
1983 value: HandleValue,
1984 can_gc: CanGc,
1985 ) -> Result<ConversionResult<Self>, ()> {
1986 AesCtrParams::new(cx, value, can_gc)
1987 }
1988}
1989
1990impl DictionaryFromJSVal for RootedTraceableBox<AesGcmParams> {
1991 fn create(
1992 cx: JSContext,
1993 value: HandleValue,
1994 can_gc: CanGc,
1995 ) -> Result<ConversionResult<Self>, ()> {
1996 AesGcmParams::new(cx, value, can_gc)
1997 }
1998}
1999
2000impl DictionaryFromJSVal for RootedTraceableBox<Pbkdf2Params> {
2001 fn create(
2002 cx: JSContext,
2003 value: HandleValue,
2004 can_gc: CanGc,
2005 ) -> Result<ConversionResult<Self>, ()> {
2006 Pbkdf2Params::new(cx, value, can_gc)
2007 }
2008}
2009
2010impl DictionaryFromJSVal for RootedTraceableBox<HkdfParams> {
2011 fn create(
2012 cx: JSContext,
2013 value: HandleValue,
2014 can_gc: CanGc,
2015 ) -> Result<ConversionResult<Self>, ()> {
2016 HkdfParams::new(cx, value, can_gc)
2017 }
2018}
2019
2020fn extract_native_dict<T>(converted: Result<ConversionResult<T>, ()>) -> Fallible<T> {
2021 let params_result = converted.map_err(|_| Error::JSFailed)?;
2022 let ConversionResult::Success(params) = params_result else {
2023 return Err(Error::Syntax(None));
2024 };
2025 Ok(params)
2026}
2027
2028fn value_from_js_object<T: DictionaryFromJSVal>(
2029 cx: JSContext,
2030 value: HandleValue,
2031 can_gc: CanGc,
2032) -> Fallible<T> {
2033 extract_native_dict(T::create(cx, value, can_gc))
2034}
2035
2036trait DictionaryFromJSValType: crate::JSTraceable {}
2037impl<T: crate::JSTraceable + 'static> DictionaryFromJSValType for T where
2038 RootedTraceableBox<T>: DictionaryFromJSVal
2039{
2040}
2041
2042fn boxed_value_from_js_object<T: DictionaryFromJSValType>(
2043 cx: JSContext,
2044 value: HandleValue,
2045 can_gc: CanGc,
2046) -> Fallible<RootedTraceableBox<T>>
2047where
2048 RootedTraceableBox<T>: DictionaryFromJSVal,
2049{
2050 extract_native_dict(<RootedTraceableBox<T>>::create(cx, value, can_gc))
2051}
2052
2053pub(crate) enum ExportedKey {
2054 Raw(Vec<u8>),
2055 Jwk(Box<JsonWebKey>),
2056}
2057
2058#[derive(Clone, Debug, MallocSizeOf)]
2062#[allow(clippy::enum_variant_names)]
2063pub(crate) enum KeyAlgorithmAndDerivatives {
2064 KeyAlgorithm(SubtleKeyAlgorithm),
2065 AesKeyAlgorithm(SubtleAesKeyAlgorithm),
2066 HmacKeyAlgorithm(SubtleHmacKeyAlgorithm),
2067}
2068
2069impl KeyAlgorithmAndDerivatives {
2070 fn name(&self) -> &str {
2071 match self {
2072 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => &algo.name,
2073 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => &algo.name,
2074 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => &algo.name,
2075 }
2076 }
2077}
2078
2079impl From<NormalizedAlgorithm> for KeyAlgorithmAndDerivatives {
2080 fn from(value: NormalizedAlgorithm) -> Self {
2081 KeyAlgorithmAndDerivatives::KeyAlgorithm(SubtleKeyAlgorithm {
2082 name: value.name().to_string(),
2083 })
2084 }
2085}
2086
2087impl SafeToJSValConvertible for KeyAlgorithmAndDerivatives {
2088 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue) {
2089 match self {
2090 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
2091 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
2092 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
2093 }
2094 }
2095}
2096
2097#[expect(unused)]
2098trait RsaOtherPrimesInfoExt {
2099 fn from_value(value: &serde_json::Value) -> Result<RsaOtherPrimesInfo, Error>;
2100}
2101
2102impl RsaOtherPrimesInfoExt for RsaOtherPrimesInfo {
2103 fn from_value(value: &serde_json::Value) -> Result<RsaOtherPrimesInfo, Error> {
2104 let serde_json::Value::Object(object) = value else {
2105 return Err(Error::Data);
2106 };
2107
2108 let mut rsa_other_primes_info: RsaOtherPrimesInfo = Default::default();
2109 for (key, value) in object {
2110 match key.as_str() {
2111 "r" => {
2112 rsa_other_primes_info.r =
2113 Some(DOMString::from(value.as_str().ok_or(Error::Data)?))
2114 },
2115 "d" => {
2116 rsa_other_primes_info.d =
2117 Some(DOMString::from(value.as_str().ok_or(Error::Data)?))
2118 },
2119 "t" => {
2120 rsa_other_primes_info.t =
2121 Some(DOMString::from(value.as_str().ok_or(Error::Data)?))
2122 },
2123 _ => {
2124 },
2127 }
2128 }
2129
2130 Ok(rsa_other_primes_info)
2131 }
2132}
2133
2134trait JsonWebKeyExt {
2135 fn parse(cx: JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
2136 fn stringify(&self, cx: JSContext) -> Result<DOMString, Error>;
2137 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
2138 #[expect(unused)]
2139 fn get_rsa_other_primes_info_from_oth(&self) -> Result<&[RsaOtherPrimesInfo], Error>;
2140 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
2141}
2142
2143impl JsonWebKeyExt for JsonWebKey {
2144 #[allow(unsafe_code)]
2146 fn parse(cx: JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
2147 let json = String::from_utf8_lossy(data);
2152
2153 let json: Vec<_> = json.encode_utf16().collect();
2155
2156 rooted!(in(*cx) let mut result = UndefinedValue());
2160 unsafe {
2161 if !JS_ParseJSON(*cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
2162 return Err(Error::JSFailed);
2163 }
2164 }
2165
2166 let key = match JsonWebKey::new(cx, result.handle(), CanGc::note()) {
2168 Ok(ConversionResult::Success(key)) => key,
2169 Ok(ConversionResult::Failure(error)) => {
2170 return Err(Error::Type(error.to_string()));
2171 },
2172 Err(()) => {
2173 return Err(Error::JSFailed);
2174 },
2175 };
2176
2177 if key.kty.is_none() {
2179 return Err(Error::Data);
2180 }
2181
2182 Ok(key)
2184 }
2185
2186 fn stringify(&self, cx: JSContext) -> Result<DOMString, Error> {
2192 rooted!(in(*cx) let mut data = UndefinedValue());
2193 self.safe_to_jsval(cx, data.handle_mut());
2194 serialize_jsval_to_json_utf8(cx, data.handle())
2195 }
2196
2197 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
2198 let mut usages = vec![];
2199 for op in self.key_ops.as_ref().ok_or(Error::Data)? {
2200 usages.push(KeyUsage::from_str(&op.str()).map_err(|_| Error::Data)?);
2201 }
2202 Ok(usages)
2203 }
2204
2205 fn get_rsa_other_primes_info_from_oth(&self) -> Result<&[RsaOtherPrimesInfo], Error> {
2206 self.oth.as_deref().ok_or(Error::Data)
2207 }
2208
2209 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
2213 if let Some(ref key_ops) = self.key_ops {
2215 if key_ops
2218 .iter()
2219 .collect::<std::collections::HashSet<_>>()
2220 .len() <
2221 key_ops.len()
2222 {
2223 return Err(Error::Data);
2224 }
2225 if let Some(ref use_) = self.use_ {
2228 if key_ops.iter().any(|op| op != use_) {
2229 return Err(Error::Data);
2230 }
2231 }
2232
2233 let key_ops_as_usages = self.get_usages_from_key_ops()?;
2235 if !specified_usages
2236 .iter()
2237 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
2238 {
2239 return Err(Error::Data);
2240 }
2241 }
2242
2243 Ok(())
2244 }
2245}
2246
2247#[derive(Clone, Debug, MallocSizeOf)]
2252enum NormalizedAlgorithm {
2253 Algorithm(SubtleAlgorithm),
2254 AesCtrParams(SubtleAesCtrParams),
2255 AesKeyGenParams(SubtleAesKeyGenParams),
2256 AesDerivedKeyParams(SubtleAesDerivedKeyParams),
2257 AesCbcParams(SubtleAesCbcParams),
2258 AesGcmParams(SubtleAesGcmParams),
2259 HmacImportParams(SubtleHmacImportParams),
2260 HmacKeyGenParams(SubtleHmacKeyGenParams),
2261 HkdfParams(SubtleHkdfParams),
2262 Pbkdf2Params(SubtlePbkdf2Params),
2263}
2264
2265fn normalize_algorithm(
2267 cx: JSContext,
2268 op: &Operation,
2269 alg: &AlgorithmIdentifier,
2270 can_gc: CanGc,
2271) -> Result<NormalizedAlgorithm, Error> {
2272 match alg {
2273 ObjectOrString::String(name) => {
2275 let alg = Algorithm {
2279 name: name.to_owned(),
2280 };
2281 rooted!(in(*cx) let mut alg_value = UndefinedValue());
2282 alg.safe_to_jsval(cx, alg_value.handle_mut());
2283 let alg_obj = RootedTraceableBox::new(Heap::default());
2284 alg_obj.set(alg_value.to_object());
2285 normalize_algorithm(cx, op, &ObjectOrString::Object(alg_obj), can_gc)
2286 },
2287 ObjectOrString::Object(obj) => {
2289 rooted!(in(*cx) let value = ObjectValue(obj.get()));
2298 let initial_alg = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2299
2300 let Some(&alg_name) = SUPPORTED_ALGORITHMS.iter().find(|supported_algorithm| {
2308 supported_algorithm.eq_ignore_ascii_case(&initial_alg.name.str())
2309 }) else {
2310 return Err(Error::NotSupported);
2311 };
2312
2313 let normalized_algorithm = match (alg_name, op) {
2349 (ALG_AES_CTR, Operation::Encrypt) => {
2351 let mut params =
2352 boxed_value_from_js_object::<AesCtrParams>(cx, value.handle(), can_gc)?;
2353 params.parent.name = DOMString::from(alg_name);
2354 NormalizedAlgorithm::AesCtrParams(params.into())
2355 },
2356 (ALG_AES_CTR, Operation::Decrypt) => {
2357 let mut params =
2358 boxed_value_from_js_object::<AesCtrParams>(cx, value.handle(), can_gc)?;
2359 params.parent.name = DOMString::from(alg_name);
2360 NormalizedAlgorithm::AesCtrParams(params.into())
2361 },
2362 (ALG_AES_CTR, Operation::GenerateKey) => {
2363 let mut params =
2364 value_from_js_object::<AesKeyGenParams>(cx, value.handle(), can_gc)?;
2365 params.parent.name = DOMString::from(alg_name);
2366 NormalizedAlgorithm::AesKeyGenParams(params.into())
2367 },
2368 (ALG_AES_CTR, Operation::ImportKey) => {
2369 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2370 params.name = DOMString::from(alg_name);
2371 NormalizedAlgorithm::Algorithm(params.into())
2372 },
2373 (ALG_AES_CTR, Operation::ExportKey) => {
2374 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2375 params.name = DOMString::from(alg_name);
2376 NormalizedAlgorithm::Algorithm(params.into())
2377 },
2378 (ALG_AES_CTR, Operation::GetKeyLength) => {
2379 let mut params =
2380 value_from_js_object::<AesDerivedKeyParams>(cx, value.handle(), can_gc)?;
2381 params.parent.name = DOMString::from(alg_name);
2382 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2383 },
2384
2385 (ALG_AES_CBC, Operation::Encrypt) => {
2387 let mut params =
2388 boxed_value_from_js_object::<AesCbcParams>(cx, value.handle(), can_gc)?;
2389 params.parent.name = DOMString::from(alg_name);
2390 NormalizedAlgorithm::AesCbcParams(params.into())
2391 },
2392 (ALG_AES_CBC, Operation::Decrypt) => {
2393 let mut params =
2394 boxed_value_from_js_object::<AesCbcParams>(cx, value.handle(), can_gc)?;
2395 params.parent.name = DOMString::from(alg_name);
2396 NormalizedAlgorithm::AesCbcParams(params.into())
2397 },
2398 (ALG_AES_CBC, Operation::GenerateKey) => {
2399 let mut params =
2400 value_from_js_object::<AesKeyGenParams>(cx, value.handle(), can_gc)?;
2401 params.parent.name = DOMString::from(alg_name);
2402 NormalizedAlgorithm::AesKeyGenParams(params.into())
2403 },
2404 (ALG_AES_CBC, Operation::ImportKey) => {
2405 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2406 params.name = DOMString::from(alg_name);
2407 NormalizedAlgorithm::Algorithm(params.into())
2408 },
2409 (ALG_AES_CBC, Operation::ExportKey) => {
2410 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2411 params.name = DOMString::from(alg_name);
2412 NormalizedAlgorithm::Algorithm(params.into())
2413 },
2414 (ALG_AES_CBC, Operation::GetKeyLength) => {
2415 let mut params =
2416 value_from_js_object::<AesDerivedKeyParams>(cx, value.handle(), can_gc)?;
2417 params.parent.name = DOMString::from(alg_name);
2418 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2419 },
2420
2421 (ALG_AES_GCM, Operation::Encrypt) => {
2423 let mut params =
2424 boxed_value_from_js_object::<AesGcmParams>(cx, value.handle(), can_gc)?;
2425 params.parent.name = DOMString::from(alg_name);
2426 NormalizedAlgorithm::AesGcmParams(params.into())
2427 },
2428 (ALG_AES_GCM, Operation::Decrypt) => {
2429 let mut params =
2430 boxed_value_from_js_object::<AesGcmParams>(cx, value.handle(), can_gc)?;
2431 params.parent.name = DOMString::from(alg_name);
2432 NormalizedAlgorithm::AesGcmParams(params.into())
2433 },
2434 (ALG_AES_GCM, Operation::GenerateKey) => {
2435 let mut params =
2436 value_from_js_object::<AesKeyGenParams>(cx, value.handle(), can_gc)?;
2437 params.parent.name = DOMString::from(alg_name);
2438 NormalizedAlgorithm::AesKeyGenParams(params.into())
2439 },
2440 (ALG_AES_GCM, Operation::ImportKey) => {
2441 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2442 params.name = DOMString::from(alg_name);
2443 NormalizedAlgorithm::Algorithm(params.into())
2444 },
2445 (ALG_AES_GCM, Operation::ExportKey) => {
2446 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2447 params.name = DOMString::from(alg_name);
2448 NormalizedAlgorithm::Algorithm(params.into())
2449 },
2450 (ALG_AES_GCM, Operation::GetKeyLength) => {
2451 let mut params =
2452 value_from_js_object::<AesDerivedKeyParams>(cx, value.handle(), can_gc)?;
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 = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2460 params.name = DOMString::from(alg_name);
2461 NormalizedAlgorithm::Algorithm(params.into())
2462 },
2463 (ALG_AES_KW, Operation::UnwrapKey) => {
2464 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2465 params.name = DOMString::from(alg_name);
2466 NormalizedAlgorithm::Algorithm(params.into())
2467 },
2468 (ALG_AES_KW, Operation::GenerateKey) => {
2469 let mut params =
2470 value_from_js_object::<AesKeyGenParams>(cx, value.handle(), can_gc)?;
2471 params.parent.name = DOMString::from(alg_name);
2472 NormalizedAlgorithm::AesKeyGenParams(params.into())
2473 },
2474 (ALG_AES_KW, Operation::ImportKey) => {
2475 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2476 params.name = DOMString::from(alg_name);
2477 NormalizedAlgorithm::Algorithm(params.into())
2478 },
2479 (ALG_AES_KW, Operation::ExportKey) => {
2480 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2481 params.name = DOMString::from(alg_name);
2482 NormalizedAlgorithm::Algorithm(params.into())
2483 },
2484 (ALG_HMAC, Operation::Sign) => {
2488 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2489 params.name = DOMString::from(alg_name);
2490 NormalizedAlgorithm::Algorithm(params.into())
2491 },
2492 (ALG_HMAC, Operation::Verify) => {
2493 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2494 params.name = DOMString::from(alg_name);
2495 NormalizedAlgorithm::Algorithm(params.into())
2496 },
2497 (ALG_HMAC, Operation::GenerateKey) => {
2498 let mut params =
2499 boxed_value_from_js_object::<HmacKeyGenParams>(cx, value.handle(), can_gc)?;
2500 params.parent.name = DOMString::from(alg_name);
2501 NormalizedAlgorithm::HmacKeyGenParams(params.try_into()?)
2502 },
2503 (ALG_HMAC, Operation::ImportKey) => {
2504 let mut params =
2505 boxed_value_from_js_object::<HmacImportParams>(cx, value.handle(), can_gc)?;
2506 params.parent.name = DOMString::from(alg_name);
2507 NormalizedAlgorithm::HmacImportParams(params.try_into()?)
2508 },
2509 (ALG_HMAC, Operation::ExportKey) => {
2510 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2511 params.name = DOMString::from(alg_name);
2512 NormalizedAlgorithm::Algorithm(params.into())
2513 },
2514 (ALG_HMAC, Operation::GetKeyLength) => {
2515 let mut params =
2516 boxed_value_from_js_object::<HmacImportParams>(cx, value.handle(), can_gc)?;
2517 params.parent.name = DOMString::from(alg_name);
2518 NormalizedAlgorithm::HmacImportParams(params.try_into()?)
2519 },
2520
2521 (ALG_SHA1, Operation::Digest) => {
2523 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2524 params.name = DOMString::from(alg_name);
2525 NormalizedAlgorithm::Algorithm(params.into())
2526 },
2527 (ALG_SHA256, Operation::Digest) => {
2528 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2529 params.name = DOMString::from(alg_name);
2530 NormalizedAlgorithm::Algorithm(params.into())
2531 },
2532 (ALG_SHA384, Operation::Digest) => {
2533 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2534 params.name = DOMString::from(alg_name);
2535 NormalizedAlgorithm::Algorithm(params.into())
2536 },
2537 (ALG_SHA512, Operation::Digest) => {
2538 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2539 params.name = DOMString::from(alg_name);
2540 NormalizedAlgorithm::Algorithm(params.into())
2541 },
2542
2543 (ALG_HKDF, Operation::DeriveBits) => {
2545 let mut params =
2546 boxed_value_from_js_object::<HkdfParams>(cx, value.handle(), can_gc)?;
2547 params.parent.name = DOMString::from(alg_name);
2548 NormalizedAlgorithm::HkdfParams(params.try_into()?)
2549 },
2550 (ALG_HKDF, Operation::ImportKey) => {
2551 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2552 params.name = DOMString::from(alg_name);
2553 NormalizedAlgorithm::Algorithm(params.into())
2554 },
2555 (ALG_HKDF, Operation::GetKeyLength) => {
2556 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2557 params.name = DOMString::from(alg_name);
2558 NormalizedAlgorithm::Algorithm(params.into())
2559 },
2560
2561 (ALG_PBKDF2, Operation::DeriveBits) => {
2563 let mut params =
2564 boxed_value_from_js_object::<Pbkdf2Params>(cx, value.handle(), can_gc)?;
2565 params.parent.name = DOMString::from(alg_name);
2566 NormalizedAlgorithm::Pbkdf2Params(params.try_into()?)
2567 },
2568 (ALG_PBKDF2, Operation::ImportKey) => {
2569 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2570 params.name = DOMString::from(alg_name);
2571 NormalizedAlgorithm::Algorithm(params.into())
2572 },
2573 (ALG_PBKDF2, Operation::GetKeyLength) => {
2574 let mut params = value_from_js_object::<Algorithm>(cx, value.handle(), can_gc)?;
2575 params.name = DOMString::from(alg_name);
2576 NormalizedAlgorithm::Algorithm(params.into())
2577 },
2578
2579 _ => return Err(Error::NotSupported),
2580 };
2581
2582 Ok(normalized_algorithm)
2584 },
2585 }
2586}
2587
2588impl NormalizedAlgorithm {
2589 fn name(&self) -> &str {
2591 match self {
2592 NormalizedAlgorithm::Algorithm(algo) => &algo.name,
2593 NormalizedAlgorithm::AesCtrParams(algo) => &algo.name,
2594 NormalizedAlgorithm::AesKeyGenParams(algo) => &algo.name,
2595 NormalizedAlgorithm::AesDerivedKeyParams(algo) => &algo.name,
2596 NormalizedAlgorithm::AesCbcParams(algo) => &algo.name,
2597 NormalizedAlgorithm::AesGcmParams(algo) => &algo.name,
2598 NormalizedAlgorithm::HmacImportParams(algo) => &algo.name,
2599 NormalizedAlgorithm::HmacKeyGenParams(algo) => &algo.name,
2600 NormalizedAlgorithm::HkdfParams(algo) => &algo.name,
2601 NormalizedAlgorithm::Pbkdf2Params(algo) => &algo.name,
2602 }
2603 }
2604
2605 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
2606 match self {
2607 NormalizedAlgorithm::AesCtrParams(algo) => {
2608 aes_operation::encrypt_aes_ctr(algo, key, plaintext)
2609 },
2610 NormalizedAlgorithm::AesCbcParams(algo) => {
2611 aes_operation::encrypt_aes_cbc(algo, key, plaintext)
2612 },
2613 NormalizedAlgorithm::AesGcmParams(algo) => {
2614 aes_operation::encrypt_aes_gcm(algo, key, plaintext)
2615 },
2616 _ => Err(Error::NotSupported),
2617 }
2618 }
2619
2620 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
2621 match self {
2622 NormalizedAlgorithm::AesCtrParams(algo) => {
2623 aes_operation::decrypt_aes_ctr(algo, key, ciphertext)
2624 },
2625 NormalizedAlgorithm::AesCbcParams(algo) => {
2626 aes_operation::decrypt_aes_cbc(algo, key, ciphertext)
2627 },
2628 NormalizedAlgorithm::AesGcmParams(algo) => {
2629 aes_operation::decrypt_aes_gcm(algo, key, ciphertext)
2630 },
2631 _ => Err(Error::NotSupported),
2632 }
2633 }
2634
2635 fn sign(&self, key: &CryptoKey, message: &[u8], can_gc: CanGc) -> Result<Vec<u8>, Error> {
2636 match self {
2637 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2638 ALG_HMAC => hmac_operation::sign(key, message, can_gc),
2639 _ => Err(Error::NotSupported),
2640 },
2641 _ => Err(Error::NotSupported),
2642 }
2643 }
2644
2645 fn verify(
2646 &self,
2647 key: &CryptoKey,
2648 message: &[u8],
2649 signature: &[u8],
2650 can_gc: CanGc,
2651 ) -> Result<bool, Error> {
2652 match self {
2653 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2654 ALG_HMAC => hmac_operation::verify(key, message, signature, can_gc),
2655 _ => Err(Error::NotSupported),
2656 },
2657 _ => Err(Error::NotSupported),
2658 }
2659 }
2660
2661 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
2662 match self {
2663 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2664 ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 => {
2665 sha_operation::digest(algo, message)
2666 },
2667 _ => Err(Error::NotSupported),
2668 },
2669 _ => Err(Error::NotSupported),
2670 }
2671 }
2672
2673 fn generate_key(
2674 &self,
2675 global: &GlobalScope,
2676 extractable: bool,
2677 usages: Vec<KeyUsage>,
2678 rng: &DomRefCell<ServoRng>,
2679 can_gc: CanGc,
2680 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
2681 match self {
2682 NormalizedAlgorithm::AesKeyGenParams(algo) => match algo.name.as_str() {
2683 ALG_AES_CTR => aes_operation::generate_key_aes_ctr(
2684 global,
2685 algo,
2686 extractable,
2687 usages,
2688 rng,
2689 can_gc,
2690 )
2691 .map(CryptoKeyOrCryptoKeyPair::CryptoKey),
2692 ALG_AES_CBC => aes_operation::generate_key_aes_cbc(
2693 global,
2694 algo,
2695 extractable,
2696 usages,
2697 rng,
2698 can_gc,
2699 )
2700 .map(CryptoKeyOrCryptoKeyPair::CryptoKey),
2701 ALG_AES_GCM => aes_operation::generate_key_aes_gcm(
2702 global,
2703 algo,
2704 extractable,
2705 usages,
2706 rng,
2707 can_gc,
2708 )
2709 .map(CryptoKeyOrCryptoKeyPair::CryptoKey),
2710 ALG_AES_KW => aes_operation::generate_key_aes_kw(
2711 global,
2712 algo,
2713 extractable,
2714 usages,
2715 rng,
2716 can_gc,
2717 )
2718 .map(CryptoKeyOrCryptoKeyPair::CryptoKey),
2719 _ => Err(Error::NotSupported),
2720 },
2721 NormalizedAlgorithm::HmacKeyGenParams(algo) => {
2722 hmac_operation::generate_key(global, algo, extractable, usages, rng, can_gc)
2723 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
2724 },
2725 _ => Err(Error::NotSupported),
2726 }
2727 }
2728
2729 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
2730 match self {
2731 NormalizedAlgorithm::HkdfParams(algo) => hkdf_operation::derive_bits(algo, key, length),
2732 NormalizedAlgorithm::Pbkdf2Params(algo) => {
2733 pbkdf2_operation::derive_bits(algo, key, length)
2734 },
2735 _ => Err(Error::NotSupported),
2736 }
2737 }
2738
2739 fn import_key(
2740 &self,
2741 global: &GlobalScope,
2742 format: KeyFormat,
2743 key_data: &[u8],
2744 extractable: bool,
2745 usages: Vec<KeyUsage>,
2746 can_gc: CanGc,
2747 ) -> Result<DomRoot<CryptoKey>, Error> {
2748 match self {
2749 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2750 ALG_AES_CTR => aes_operation::import_key_aes_ctr(
2751 global,
2752 format,
2753 key_data,
2754 extractable,
2755 usages,
2756 can_gc,
2757 ),
2758 ALG_AES_CBC => aes_operation::import_key_aes_cbc(
2759 global,
2760 format,
2761 key_data,
2762 extractable,
2763 usages,
2764 can_gc,
2765 ),
2766 ALG_AES_GCM => aes_operation::import_key_aes_gcm(
2767 global,
2768 format,
2769 key_data,
2770 extractable,
2771 usages,
2772 can_gc,
2773 ),
2774 ALG_AES_KW => aes_operation::import_key_aes_kw(
2775 global,
2776 format,
2777 key_data,
2778 extractable,
2779 usages,
2780 can_gc,
2781 ),
2782 ALG_HKDF => {
2783 hkdf_operation::import(global, format, key_data, extractable, usages, can_gc)
2784 },
2785 ALG_PBKDF2 => {
2786 pbkdf2_operation::import(global, format, key_data, extractable, usages, can_gc)
2787 },
2788 _ => Err(Error::NotSupported),
2789 },
2790 NormalizedAlgorithm::HmacImportParams(algo) => hmac_operation::import_key(
2791 global,
2792 algo,
2793 format,
2794 key_data,
2795 extractable,
2796 usages,
2797 can_gc,
2798 ),
2799 _ => Err(Error::NotSupported),
2800 }
2801 }
2802
2803 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
2804 match self {
2805 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2806 ALG_AES_KW => aes_operation::wrap_key_aes_kw(key, plaintext),
2807 _ => Err(Error::NotSupported),
2808 },
2809 _ => Err(Error::NotSupported),
2810 }
2811 }
2812
2813 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
2814 match self {
2815 NormalizedAlgorithm::Algorithm(algo) => match algo.name.as_str() {
2816 ALG_AES_KW => aes_operation::unwrap_key_aes_kw(key, ciphertext),
2817 _ => Err(Error::NotSupported),
2818 },
2819 _ => Err(Error::NotSupported),
2820 }
2821 }
2822
2823 fn get_key_length(&self) -> Result<Option<u32>, Error> {
2824 match self {
2825 NormalizedAlgorithm::AesDerivedKeyParams(algo) => match algo.name.as_str() {
2826 ALG_AES_CTR => aes_operation::get_key_length_aes_ctr(algo),
2827 ALG_AES_CBC => aes_operation::get_key_length_aes_cbc(algo),
2828 ALG_AES_GCM => aes_operation::get_key_length_aes_gcm(algo),
2829 ALG_AES_KW => aes_operation::get_key_length_aes_kw(algo),
2830 _ => Err(Error::NotSupported),
2831 },
2832 NormalizedAlgorithm::HmacImportParams(algo) => hmac_operation::get_key_length(algo),
2833 NormalizedAlgorithm::HkdfParams(_algo) => hkdf_operation::get_key_length(),
2834 NormalizedAlgorithm::Pbkdf2Params(_algo) => pbkdf2_operation::get_key_length(),
2835 _ => Err(Error::NotSupported),
2836 }
2837 }
2838}
2839
2840fn perform_export_key_operation(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
2847 match key.algorithm().name() {
2848 ALG_AES_CTR => aes_operation::export_key_aes_ctr(format, key),
2849 ALG_AES_CBC => aes_operation::export_key_aes_cbc(format, key),
2850 ALG_AES_GCM => aes_operation::export_key_aes_gcm(format, key),
2851 ALG_AES_KW => aes_operation::export_key_aes_kw(format, key),
2852 ALG_HMAC => hmac_operation::export(format, key),
2853 _ => Err(Error::NotSupported),
2854 }
2855}