1use std::cell::Cell;
6use std::ptr::NonNull;
7
8use dom_struct::dom_struct;
9use js::jsapi::{Heap, JSObject, Value};
10use script_bindings::conversions::SafeToJSValConvertible;
11
12use crate::dom::bindings::cell::DomRefCell;
13use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
14 CryptoKeyMethods, KeyType, KeyUsage,
15};
16use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
17use crate::dom::bindings::root::DomRoot;
18use crate::dom::globalscope::GlobalScope;
19use crate::dom::subtlecrypto::KeyAlgorithmAndDerivatives;
20use crate::script_runtime::{CanGc, JSContext};
21
22pub(crate) enum CryptoKeyOrCryptoKeyPair {
23 CryptoKey(DomRoot<CryptoKey>),
24 }
26
27#[allow(dead_code)]
29#[derive(MallocSizeOf)]
30pub(crate) enum Handle {
31 Aes128(Vec<u8>),
32 Aes192(Vec<u8>),
33 Aes256(Vec<u8>),
34 Pbkdf2(Vec<u8>),
35 Hkdf(Vec<u8>),
36 Hmac(Vec<u8>),
37}
38
39#[dom_struct]
41pub(crate) struct CryptoKey {
42 reflector_: Reflector,
43
44 key_type: KeyType,
46
47 extractable: Cell<bool>,
49
50 #[no_trace]
55 algorithm: KeyAlgorithmAndDerivatives,
56
57 #[ignore_malloc_size_of = "Defined in mozjs"]
59 algorithm_cached: Heap<*mut JSObject>,
60
61 usages: DomRefCell<Vec<KeyUsage>>,
65
66 #[ignore_malloc_size_of = "Defined in mozjs"]
68 usages_cached: Heap<*mut JSObject>,
69
70 #[no_trace]
72 handle: Handle,
73}
74
75impl CryptoKey {
76 fn new_inherited(
77 key_type: KeyType,
78 extractable: bool,
79 algorithm: KeyAlgorithmAndDerivatives,
80 usages: Vec<KeyUsage>,
81 handle: Handle,
82 ) -> CryptoKey {
83 CryptoKey {
84 reflector_: Reflector::new(),
85 key_type,
86 extractable: Cell::new(extractable),
87 algorithm,
88 algorithm_cached: Heap::default(),
89 usages: DomRefCell::new(usages),
90 usages_cached: Heap::default(),
91 handle,
92 }
93 }
94
95 #[allow(clippy::too_many_arguments)]
96 pub(crate) fn new(
97 global: &GlobalScope,
98 key_type: KeyType,
99 extractable: bool,
100 algorithm: KeyAlgorithmAndDerivatives,
101 usages: Vec<KeyUsage>,
102 handle: Handle,
103 can_gc: CanGc,
104 ) -> DomRoot<CryptoKey> {
105 let crypto_key = reflect_dom_object(
106 Box::new(CryptoKey::new_inherited(
107 key_type,
108 extractable,
109 algorithm.clone(),
110 usages.clone(),
111 handle,
112 )),
113 global,
114 can_gc,
115 );
116
117 let cx = GlobalScope::get_cx();
118
119 rooted!(in(*cx) let mut algorithm_object_value: Value);
121 algorithm.safe_to_jsval(cx, algorithm_object_value.handle_mut());
122 crypto_key
123 .algorithm_cached
124 .set(algorithm_object_value.to_object());
125
126 rooted!(in(*cx) let mut usages_object_value: Value);
128 usages.safe_to_jsval(cx, usages_object_value.handle_mut());
129 crypto_key
130 .usages_cached
131 .set(usages_object_value.to_object());
132
133 crypto_key
134 }
135
136 pub(crate) fn algorithm(&self) -> &KeyAlgorithmAndDerivatives {
137 &self.algorithm
138 }
139
140 pub(crate) fn usages(&self) -> Vec<KeyUsage> {
141 self.usages.borrow().clone()
142 }
143
144 pub(crate) fn handle(&self) -> &Handle {
145 &self.handle
146 }
147
148 pub(crate) fn set_extractable(&self, extractable: bool) {
149 self.extractable.set(extractable);
150 }
151
152 pub(crate) fn set_usages(&self, usages: &[KeyUsage]) {
153 *self.usages.borrow_mut() = usages.to_owned();
154
155 let cx = GlobalScope::get_cx();
157 rooted!(in(*cx) let mut usages_object_value: Value);
158 usages.safe_to_jsval(cx, usages_object_value.handle_mut());
159 self.usages_cached.set(usages_object_value.to_object());
160 }
161}
162
163impl CryptoKeyMethods<crate::DomTypeHolder> for CryptoKey {
164 fn Type(&self) -> KeyType {
166 self.key_type
168 }
169
170 fn Extractable(&self) -> bool {
172 self.extractable.get()
175 }
176
177 fn Algorithm(&self, _cx: JSContext) -> NonNull<JSObject> {
179 NonNull::new(self.algorithm_cached.get()).unwrap()
181 }
182
183 fn Usages(&self, _cx: JSContext) -> NonNull<JSObject> {
185 NonNull::new(self.usages_cached.get()).unwrap()
188 }
189}
190
191impl Handle {
192 pub(crate) fn as_bytes(&self) -> &[u8] {
193 match self {
194 Self::Aes128(bytes) => bytes,
195 Self::Aes192(bytes) => bytes,
196 Self::Aes256(bytes) => bytes,
197 Self::Pbkdf2(bytes) => bytes,
198 Self::Hkdf(bytes) => bytes,
199 Self::Hmac(bytes) => bytes,
200 }
201 }
202}