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