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