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_with_cx};
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 RsaPrivateKey(rsa::RsaPrivateKey),
31 RsaPublicKey(rsa::RsaPublicKey),
32 P256PrivateKey(p256::SecretKey),
33 P384PrivateKey(p384::SecretKey),
34 P521PrivateKey(p521::SecretKey),
35 P256PublicKey(p256::PublicKey),
36 P384PublicKey(p384::PublicKey),
37 P521PublicKey(p521::PublicKey),
38 X25519PrivateKey(x25519_dalek::StaticSecret),
39 X25519PublicKey(x25519_dalek::PublicKey),
40 Aes128Key(aes::cipher::crypto_common::Key<aes::Aes128>),
41 Aes192Key(aes::cipher::crypto_common::Key<aes::Aes192>),
42 Aes256Key(aes::cipher::crypto_common::Key<aes::Aes256>),
43 HkdfSecret(Vec<u8>),
44 Pbkdf2(Vec<u8>),
45 Hmac(Vec<u8>),
46 Ed25519(Vec<u8>),
47 MlKem512PrivateKey((ml_kem::B32, ml_kem::B32)),
48 MlKem768PrivateKey((ml_kem::B32, ml_kem::B32)),
49 MlKem1024PrivateKey((ml_kem::B32, ml_kem::B32)),
50 MlKem512PublicKey(Box<ml_kem::Encoded<ml_kem::kem::EncapsulationKey<ml_kem::MlKem512Params>>>),
51 MlKem768PublicKey(Box<ml_kem::Encoded<ml_kem::kem::EncapsulationKey<ml_kem::MlKem768Params>>>),
52 MlKem1024PublicKey(
53 Box<ml_kem::Encoded<ml_kem::kem::EncapsulationKey<ml_kem::MlKem1024Params>>>,
54 ),
55 MlDsa44PrivateKey(ml_dsa::B32),
56 MlDsa65PrivateKey(ml_dsa::B32),
57 MlDsa87PrivateKey(ml_dsa::B32),
58 MlDsa44PublicKey(Box<ml_dsa::EncodedVerifyingKey<ml_dsa::MlDsa44>>),
59 MlDsa65PublicKey(Box<ml_dsa::EncodedVerifyingKey<ml_dsa::MlDsa65>>),
60 MlDsa87PublicKey(Box<ml_dsa::EncodedVerifyingKey<ml_dsa::MlDsa87>>),
61 ChaCha20Poly1305Key(chacha20poly1305::Key),
62 Argon2Password(Vec<u8>),
63}
64
65#[dom_struct]
67pub(crate) struct CryptoKey {
68 reflector_: Reflector,
69
70 key_type: KeyType,
72
73 extractable: Cell<bool>,
75
76 #[no_trace]
81 algorithm: KeyAlgorithmAndDerivatives,
82
83 #[ignore_malloc_size_of = "Defined in mozjs"]
85 algorithm_cached: Heap<*mut JSObject>,
86
87 usages: DomRefCell<Vec<KeyUsage>>,
91
92 #[ignore_malloc_size_of = "Defined in mozjs"]
94 usages_cached: Heap<*mut JSObject>,
95
96 #[no_trace]
98 handle: Handle,
99}
100
101impl CryptoKey {
102 fn new_inherited(
103 key_type: KeyType,
104 extractable: bool,
105 algorithm: KeyAlgorithmAndDerivatives,
106 usages: Vec<KeyUsage>,
107 handle: Handle,
108 ) -> CryptoKey {
109 CryptoKey {
110 reflector_: Reflector::new(),
111 key_type,
112 extractable: Cell::new(extractable),
113 algorithm,
114 algorithm_cached: Heap::default(),
115 usages: DomRefCell::new(usages),
116 usages_cached: Heap::default(),
117 handle,
118 }
119 }
120
121 pub(crate) fn new(
122 cx: &mut js::context::JSContext,
123 global: &GlobalScope,
124 key_type: KeyType,
125 extractable: bool,
126 algorithm: KeyAlgorithmAndDerivatives,
127 usages: Vec<KeyUsage>,
128 handle: Handle,
129 ) -> DomRoot<CryptoKey> {
130 let crypto_key = reflect_dom_object_with_cx(
131 Box::new(CryptoKey::new_inherited(
132 key_type,
133 extractable,
134 algorithm.clone(),
135 usages.clone(),
136 handle,
137 )),
138 global,
139 cx,
140 );
141
142 rooted!(&in(cx) let mut algorithm_object_value: Value);
144 algorithm.safe_to_jsval(
145 cx.into(),
146 algorithm_object_value.handle_mut(),
147 CanGc::from_cx(cx),
148 );
149 crypto_key
150 .algorithm_cached
151 .set(algorithm_object_value.to_object());
152
153 rooted!(&in(cx) let mut usages_object_value: Value);
155 usages.safe_to_jsval(
156 cx.into(),
157 usages_object_value.handle_mut(),
158 CanGc::from_cx(cx),
159 );
160 crypto_key
161 .usages_cached
162 .set(usages_object_value.to_object());
163
164 crypto_key
165 }
166
167 pub(crate) fn algorithm(&self) -> &KeyAlgorithmAndDerivatives {
168 &self.algorithm
169 }
170
171 pub(crate) fn usages(&self) -> Vec<KeyUsage> {
172 self.usages.borrow().clone()
173 }
174
175 pub(crate) fn handle(&self) -> &Handle {
176 &self.handle
177 }
178
179 pub(crate) fn set_extractable(&self, extractable: bool) {
180 self.extractable.set(extractable);
181 }
182
183 pub(crate) fn set_usages(&self, cx: &mut js::context::JSContext, usages: &[KeyUsage]) {
184 *self.usages.borrow_mut() = usages.to_owned();
185
186 rooted!(&in(cx) let mut usages_object_value: Value);
188 usages.safe_to_jsval(
189 cx.into(),
190 usages_object_value.handle_mut(),
191 CanGc::from_cx(cx),
192 );
193 self.usages_cached.set(usages_object_value.to_object());
194 }
195}
196
197impl CryptoKeyMethods<crate::DomTypeHolder> for CryptoKey {
198 fn Type(&self) -> KeyType {
200 self.key_type
202 }
203
204 fn Extractable(&self) -> bool {
206 self.extractable.get()
209 }
210
211 fn Algorithm(&self, _cx: JSContext) -> NonNull<JSObject> {
213 NonNull::new(self.algorithm_cached.get()).unwrap()
215 }
216
217 fn Usages(&self, _cx: JSContext) -> NonNull<JSObject> {
219 NonNull::new(self.usages_cached.get()).unwrap()
222 }
223}
224
225impl Handle {
226 pub(crate) fn as_bytes(&self) -> &[u8] {
227 match self {
228 Self::Pbkdf2(bytes) => bytes,
229 Self::Hmac(bytes) => bytes,
230 Self::Ed25519(bytes) => bytes,
231 _ => unreachable!(),
232 }
233 }
234}
235
236impl MallocSizeOf for Handle {
237 fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
238 match self {
239 Handle::RsaPrivateKey(private_key) => private_key.size_of(ops),
240 Handle::RsaPublicKey(public_key) => public_key.size_of(ops),
241 Handle::P256PrivateKey(private_key) => private_key.size_of(ops),
242 Handle::P384PrivateKey(private_key) => private_key.size_of(ops),
243 Handle::P521PrivateKey(private_key) => private_key.size_of(ops),
244 Handle::P256PublicKey(public_key) => public_key.size_of(ops),
245 Handle::P384PublicKey(public_key) => public_key.size_of(ops),
246 Handle::P521PublicKey(public_key) => public_key.size_of(ops),
247 Handle::X25519PrivateKey(private_key) => private_key.size_of(ops),
248 Handle::X25519PublicKey(public_key) => public_key.size_of(ops),
249 Handle::Aes128Key(key) => key.size_of(ops),
250 Handle::Aes192Key(key) => key.size_of(ops),
251 Handle::Aes256Key(key) => key.size_of(ops),
252 Handle::HkdfSecret(secret) => secret.size_of(ops),
253 Handle::Pbkdf2(bytes) => bytes.size_of(ops),
254 Handle::Hmac(bytes) => bytes.size_of(ops),
255 Handle::Ed25519(bytes) => bytes.size_of(ops),
256 Handle::MlKem512PrivateKey(seed) => seed.0.size_of(ops) + seed.1.size_of(ops),
257 Handle::MlKem768PrivateKey(seed) => seed.0.size_of(ops) + seed.1.size_of(ops),
258 Handle::MlKem1024PrivateKey(seed) => seed.0.size_of(ops) + seed.1.size_of(ops),
259 Handle::MlKem512PublicKey(public_key) => public_key.size_of(ops),
260 Handle::MlKem768PublicKey(public_key) => public_key.size_of(ops),
261 Handle::MlKem1024PublicKey(public_key) => public_key.size_of(ops),
262 Handle::MlDsa44PrivateKey(seed) => seed.size_of(ops),
263 Handle::MlDsa65PrivateKey(seed) => seed.size_of(ops),
264 Handle::MlDsa87PrivateKey(seed) => seed.size_of(ops),
265 Handle::MlDsa44PublicKey(public_key) => public_key.size_of(ops),
266 Handle::MlDsa65PublicKey(public_key) => public_key.size_of(ops),
267 Handle::MlDsa87PublicKey(public_key) => public_key.size_of(ops),
268 Handle::ChaCha20Poly1305Key(key) => key.size_of(ops),
269 Handle::Argon2Password(password) => password.size_of(ops),
270 }
271 }
272}