1use std::cell::Cell;
6use std::ptr::NonNull;
7
8use dom_struct::dom_struct;
9use js::jsapi::{Heap, JSObject, Value};
10use malloc_size_of::MallocSizeOf;
11use script_bindings::conversions::SafeToJSValConvertible;
12
13use crate::dom::bindings::cell::DomRefCell;
14use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
15 CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
16};
17use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
18use crate::dom::bindings::root::DomRoot;
19use crate::dom::globalscope::GlobalScope;
20use crate::dom::subtlecrypto::KeyAlgorithmAndDerivatives;
21use crate::script_runtime::{CanGc, JSContext};
22
23pub(crate) enum CryptoKeyOrCryptoKeyPair {
24 CryptoKey(DomRoot<CryptoKey>),
25 CryptoKeyPair(CryptoKeyPair),
26}
27
28pub(crate) enum Handle {
30 P256PrivateKey(p256::SecretKey),
31 P384PrivateKey(p384::SecretKey),
32 P521PrivateKey(p521::SecretKey),
33 P256PublicKey(p256::PublicKey),
34 P384PublicKey(p384::PublicKey),
35 P521PublicKey(p521::PublicKey),
36 X25519PrivateKey(x25519_dalek::StaticSecret),
37 X25519PublicKey(x25519_dalek::PublicKey),
38 Aes128(Vec<u8>),
39 Aes192(Vec<u8>),
40 Aes256(Vec<u8>),
41 Pbkdf2(Vec<u8>),
42 Hkdf(Vec<u8>),
43 Hmac(Vec<u8>),
44 Ed25519(Vec<u8>),
45}
46
47#[dom_struct]
49pub(crate) struct CryptoKey {
50 reflector_: Reflector,
51
52 key_type: KeyType,
54
55 extractable: Cell<bool>,
57
58 #[no_trace]
63 algorithm: KeyAlgorithmAndDerivatives,
64
65 #[ignore_malloc_size_of = "Defined in mozjs"]
67 algorithm_cached: Heap<*mut JSObject>,
68
69 usages: DomRefCell<Vec<KeyUsage>>,
73
74 #[ignore_malloc_size_of = "Defined in mozjs"]
76 usages_cached: Heap<*mut JSObject>,
77
78 #[no_trace]
80 handle: Handle,
81}
82
83impl CryptoKey {
84 fn new_inherited(
85 key_type: KeyType,
86 extractable: bool,
87 algorithm: KeyAlgorithmAndDerivatives,
88 usages: Vec<KeyUsage>,
89 handle: Handle,
90 ) -> CryptoKey {
91 CryptoKey {
92 reflector_: Reflector::new(),
93 key_type,
94 extractable: Cell::new(extractable),
95 algorithm,
96 algorithm_cached: Heap::default(),
97 usages: DomRefCell::new(usages),
98 usages_cached: Heap::default(),
99 handle,
100 }
101 }
102
103 pub(crate) fn new(
104 global: &GlobalScope,
105 key_type: KeyType,
106 extractable: bool,
107 algorithm: KeyAlgorithmAndDerivatives,
108 usages: Vec<KeyUsage>,
109 handle: Handle,
110 can_gc: CanGc,
111 ) -> DomRoot<CryptoKey> {
112 let crypto_key = reflect_dom_object(
113 Box::new(CryptoKey::new_inherited(
114 key_type,
115 extractable,
116 algorithm.clone(),
117 usages.clone(),
118 handle,
119 )),
120 global,
121 can_gc,
122 );
123
124 let cx = GlobalScope::get_cx();
125
126 rooted!(in(*cx) let mut algorithm_object_value: Value);
128 algorithm.safe_to_jsval(cx, algorithm_object_value.handle_mut(), can_gc);
129 crypto_key
130 .algorithm_cached
131 .set(algorithm_object_value.to_object());
132
133 rooted!(in(*cx) let mut usages_object_value: Value);
135 usages.safe_to_jsval(cx, usages_object_value.handle_mut(), can_gc);
136 crypto_key
137 .usages_cached
138 .set(usages_object_value.to_object());
139
140 crypto_key
141 }
142
143 pub(crate) fn algorithm(&self) -> &KeyAlgorithmAndDerivatives {
144 &self.algorithm
145 }
146
147 pub(crate) fn usages(&self) -> Vec<KeyUsage> {
148 self.usages.borrow().clone()
149 }
150
151 pub(crate) fn handle(&self) -> &Handle {
152 &self.handle
153 }
154
155 pub(crate) fn set_extractable(&self, extractable: bool) {
156 self.extractable.set(extractable);
157 }
158
159 pub(crate) fn set_usages(&self, usages: &[KeyUsage]) {
160 *self.usages.borrow_mut() = usages.to_owned();
161
162 let cx = GlobalScope::get_cx();
164 rooted!(in(*cx) let mut usages_object_value: Value);
165 usages.safe_to_jsval(cx, usages_object_value.handle_mut(), CanGc::note());
166 self.usages_cached.set(usages_object_value.to_object());
167 }
168}
169
170impl CryptoKeyMethods<crate::DomTypeHolder> for CryptoKey {
171 fn Type(&self) -> KeyType {
173 self.key_type
175 }
176
177 fn Extractable(&self) -> bool {
179 self.extractable.get()
182 }
183
184 fn Algorithm(&self, _cx: JSContext) -> NonNull<JSObject> {
186 NonNull::new(self.algorithm_cached.get()).unwrap()
188 }
189
190 fn Usages(&self, _cx: JSContext) -> NonNull<JSObject> {
192 NonNull::new(self.usages_cached.get()).unwrap()
195 }
196}
197
198impl Handle {
199 pub(crate) fn as_bytes(&self) -> &[u8] {
200 match self {
201 Self::Aes128(bytes) => bytes,
202 Self::Aes192(bytes) => bytes,
203 Self::Aes256(bytes) => bytes,
204 Self::Pbkdf2(bytes) => bytes,
205 Self::Hkdf(bytes) => bytes,
206 Self::Hmac(bytes) => bytes,
207 Self::Ed25519(bytes) => bytes,
208 _ => unreachable!(),
209 }
210 }
211}
212
213impl MallocSizeOf for Handle {
214 fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
215 match self {
216 Handle::P256PrivateKey(private_key) => private_key.size_of(ops),
217 Handle::P384PrivateKey(private_key) => private_key.size_of(ops),
218 Handle::P521PrivateKey(private_key) => private_key.size_of(ops),
219 Handle::P256PublicKey(public_key) => public_key.size_of(ops),
220 Handle::P384PublicKey(public_key) => public_key.size_of(ops),
221 Handle::P521PublicKey(public_key) => public_key.size_of(ops),
222 Handle::X25519PrivateKey(private_key) => private_key.size_of(ops),
223 Handle::X25519PublicKey(public_key) => public_key.size_of(ops),
224 Handle::Aes128(bytes) => bytes.size_of(ops),
225 Handle::Aes192(bytes) => bytes.size_of(ops),
226 Handle::Aes256(bytes) => bytes.size_of(ops),
227 Handle::Pbkdf2(bytes) => bytes.size_of(ops),
228 Handle::Hkdf(bytes) => bytes.size_of(ops),
229 Handle::Hmac(bytes) => bytes.size_of(ops),
230 Handle::Ed25519(bytes) => bytes.size_of(ops),
231 }
232 }
233}