Skip to main content

script/dom/webcrypto/
cryptokey.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::str::FromStr;
6
7use dom_struct::dom_struct;
8use js::context::NoGC;
9use js::conversions::ToJSValConvertible;
10use js::jsapi::{Heap, JSObject, Value};
11use js::rust::MutableHandleObject;
12use malloc_size_of::MallocSizeOf;
13use rustc_hash::FxHashMap;
14use script_bindings::reflector::{Reflector, reflect_dom_object};
15use servo_base::id::{CryptoKeyId, CryptoKeyIndex};
16use servo_constellation_traits::{SerializableCryptoKey, SerializableCryptoKeyHandle};
17use strum::VariantArray;
18use zeroize::Zeroizing;
19
20use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
21    CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
22};
23use crate::dom::bindings::root::DomRoot;
24use crate::dom::bindings::serializable::Serializable;
25use crate::dom::bindings::structuredclone::StructuredData;
26use crate::dom::globalscope::GlobalScope;
27use crate::dom::subtlecrypto::KeyAlgorithmAndDerivatives;
28
29pub(crate) enum CryptoKeyOrCryptoKeyPair {
30    CryptoKey(DomRoot<CryptoKey>),
31    CryptoKeyPair(CryptoKeyPair),
32}
33
34/// The underlying cryptographic data this key represents.
35///
36/// Please make sure the inner types for secret variants implement the `zeroize::ZeroizeOnDrop`
37/// trait, which signifies that the type will call `Zeroize::zeroize` on `Drop` to securely erase
38/// the secret from memory.
39pub(crate) enum Handle {
40    RsaPrivateKey(rsa::RsaPrivateKey),
41    RsaPublicKey(rsa::RsaPublicKey),
42    P256PrivateKey(p256::SecretKey),
43    P384PrivateKey(p384::SecretKey),
44    P521PrivateKey(p521::SecretKey),
45    P256PublicKey(p256::PublicKey),
46    P384PublicKey(p384::PublicKey),
47    P521PublicKey(p521::PublicKey),
48    Ed25519PrivateKey(ed25519_dalek::SigningKey),
49    Ed25519PublicKey(ed25519_dalek::VerifyingKey),
50    X25519PrivateKey(x25519_dalek::StaticSecret),
51    X25519PublicKey(x25519_dalek::PublicKey),
52    Ed448PrivateKey(ed448_goldilocks::SigningKey),
53    Ed448PublicKey(ed448_goldilocks::VerifyingKey),
54    X448PrivateKey(x448::StaticSecret),
55    X448PublicKey(x448::PublicKey),
56    Aes128Key(aes::cipher::common::Key<aes::Aes128>),
57    Aes192Key(aes::cipher::common::Key<aes::Aes192>),
58    Aes256Key(aes::cipher::common::Key<aes::Aes256>),
59    HkdfSecret(Zeroizing<Vec<u8>>),
60    Pbkdf2(Zeroizing<Vec<u8>>),
61    Hmac(Zeroizing<Vec<u8>>),
62    MlKem512PrivateKey(ml_kem::DecapsulationKey<ml_kem::MlKem512>),
63    MlKem768PrivateKey(ml_kem::DecapsulationKey<ml_kem::MlKem768>),
64    MlKem1024PrivateKey(ml_kem::DecapsulationKey<ml_kem::MlKem1024>),
65    MlKem512PublicKey(ml_kem::EncapsulationKey<ml_kem::MlKem512>),
66    MlKem768PublicKey(ml_kem::EncapsulationKey<ml_kem::MlKem768>),
67    MlKem1024PublicKey(ml_kem::EncapsulationKey<ml_kem::MlKem1024>),
68    MlKem768X25519PrivateKey(x_wing::DecapsulationKey),
69    MlKem768X25519PublicKey(x_wing::EncapsulationKey),
70    MlDsa44PrivateKey(ml_dsa::SigningKey<ml_dsa::MlDsa44>),
71    MlDsa65PrivateKey(ml_dsa::SigningKey<ml_dsa::MlDsa65>),
72    MlDsa87PrivateKey(ml_dsa::SigningKey<ml_dsa::MlDsa87>),
73    MlDsa44PublicKey(ml_dsa::VerifyingKey<ml_dsa::MlDsa44>),
74    MlDsa65PublicKey(ml_dsa::VerifyingKey<ml_dsa::MlDsa65>),
75    MlDsa87PublicKey(ml_dsa::VerifyingKey<ml_dsa::MlDsa87>),
76    ChaCha20Poly1305Key(chacha20poly1305::Key),
77    KmacKey(Zeroizing<Vec<u8>>),
78    Argon2Password(Zeroizing<Vec<u8>>),
79}
80
81/// <https://w3c.github.io/webcrypto/#cryptokey-interface>
82#[dom_struct]
83pub(crate) struct CryptoKey {
84    reflector_: Reflector,
85
86    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-type>
87    key_type: KeyType,
88
89    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-extractable>
90    extractable: bool,
91
92    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-algorithm>
93    ///
94    /// The contents of the [[algorithm]] internal slot shall be, or be derived from, a
95    /// KeyAlgorithm.
96    #[no_trace]
97    algorithm: KeyAlgorithmAndDerivatives,
98
99    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-algorithm_cached>
100    #[ignore_malloc_size_of = "Defined in mozjs"]
101    algorithm_cached: Heap<*mut JSObject>,
102
103    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-usages>
104    ///
105    /// The contents of the [[usages]] internal slot shall be of type Sequence<KeyUsage>.
106    usages: Vec<KeyUsage>,
107
108    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-usages_cached>
109    #[ignore_malloc_size_of = "Defined in mozjs"]
110    usages_cached: Heap<*mut JSObject>,
111
112    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-handle>
113    #[no_trace]
114    handle: Handle,
115}
116
117impl CryptoKey {
118    fn new_inherited(
119        key_type: KeyType,
120        extractable: bool,
121        algorithm: KeyAlgorithmAndDerivatives,
122        usages: Vec<KeyUsage>,
123        handle: Handle,
124    ) -> CryptoKey {
125        CryptoKey {
126            reflector_: Reflector::new(),
127            key_type,
128            extractable,
129            algorithm,
130            algorithm_cached: Heap::default(),
131            usages,
132            usages_cached: Heap::default(),
133            handle,
134        }
135    }
136
137    pub(crate) fn new(
138        cx: &mut js::context::JSContext,
139        global: &GlobalScope,
140        key_type: KeyType,
141        extractable: bool,
142        algorithm: KeyAlgorithmAndDerivatives,
143        usages: Vec<KeyUsage>,
144        handle: Handle,
145    ) -> DomRoot<CryptoKey> {
146        let crypto_key = reflect_dom_object(
147            cx,
148            Box::new(CryptoKey::new_inherited(
149                key_type,
150                extractable,
151                algorithm.clone(),
152                usages.clone(),
153                handle,
154            )),
155            global,
156        );
157
158        // Create and store a cached object of algorithm
159        rooted!(&in(cx) let mut algorithm_object_value: Value);
160        algorithm.to_jsval(cx, algorithm_object_value.handle_mut());
161        crypto_key
162            .algorithm_cached
163            .set(algorithm_object_value.to_object());
164
165        // Create and store a cached object of usages
166        rooted!(&in(cx) let mut usages_object_value: Value);
167        usages.to_jsval(cx, usages_object_value.handle_mut());
168        crypto_key
169            .usages_cached
170            .set(usages_object_value.to_object());
171
172        crypto_key
173    }
174
175    pub(crate) fn algorithm(&self) -> &KeyAlgorithmAndDerivatives {
176        &self.algorithm
177    }
178
179    pub(crate) fn usages(&self) -> &[KeyUsage] {
180        &self.usages
181    }
182
183    pub(crate) fn handle(&self) -> &Handle {
184        &self.handle
185    }
186}
187
188impl CryptoKeyMethods<crate::DomTypeHolder> for CryptoKey {
189    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-type>
190    fn Type(&self) -> KeyType {
191        // Reflects the [[type]] internal slot, which contains the type of the underlying key.
192        self.key_type
193    }
194
195    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-extractable>
196    fn Extractable(&self) -> bool {
197        // Reflects the [[extractable]] internal slot, which indicates whether or not the raw
198        // keying material may be exported by the application.
199        self.extractable
200    }
201
202    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-algorithm>
203    fn Algorithm(&self, mut return_value: MutableHandleObject) {
204        // Returns the cached ECMAScript object associated with the [[algorithm]] internal slot.
205        return_value.set(self.algorithm_cached.get())
206    }
207
208    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
209    fn Usages(&self, mut return_value: MutableHandleObject) {
210        // Returns the cached ECMAScript object associated with the [[usages]] internal slot, which
211        // indicates which cryptographic operations are permissible to be used with this key.
212        return_value.set(self.usages_cached.get())
213    }
214}
215
216impl Serializable for CryptoKey {
217    type Index = CryptoKeyIndex;
218    type Data = SerializableCryptoKey;
219
220    /// <https://w3c.github.io/webcrypto/#cryptokey-interface-serializable>
221    fn serialize(&self, _no_gc: &NoGC) -> Result<(CryptoKeyId, Self::Data), ()> {
222        // Step 1. Set serialized.[[Type]] to the [[type]] internal slot of value.
223        // Step 2. Set serialized.[[Extractable]] to the [[extractable]] internal slot of value.
224        // Step 3. Set serialized.[[Algorithm]] to the sub-serialization of the [[algorithm]]
225        // internal slot of value.
226        // Step 4. Set serialized.[[Usages]] to the sub-serialization of the [[usages]] internal
227        // slot of value.
228        // Step 5. Set serialized.[[Handle]] to the [[handle]] internal slot of value.
229        let serialized = SerializableCryptoKey {
230            key_type: self.key_type.as_str().into(),
231            extractable: self.extractable,
232            algorithm: (&self.algorithm).into(),
233            usages: self
234                .usages
235                .iter()
236                .map(|usage| usage.as_str().into())
237                .collect(),
238            handle: (&self.handle).try_into()?,
239        };
240        Ok((CryptoKeyId::new(), serialized))
241    }
242
243    /// <https://w3c.github.io/webcrypto/#cryptokey-interface-serializable>
244    fn deserialize(
245        cx: &mut js::context::JSContext,
246        owner: &GlobalScope,
247        serialized: Self::Data,
248    ) -> Result<DomRoot<Self>, ()> {
249        // Step 1. Initialize the [[type]] internal slot of value to serialized.[[Type]].
250        // Step 2. Initialize the [[extractable]] internal slot of value to
251        // serialized.[[Extractable]].
252        // Step 3. Initialize the [[algorithm]] internal slot of value to the sub-deserialization of
253        // serialized.[[Algorithm]].
254        // Step 4. Initialize the [[usages]] internal slot of value to the sub-deserialization of
255        // serialized.[[Usages]].
256        // Step 5. Initialize the [[handle]] internal slot of value to serialized.[[Handle]].
257        Ok(CryptoKey::new(
258            cx,
259            owner,
260            KeyType::from_str(&serialized.key_type)?,
261            serialized.extractable,
262            serialized.algorithm.try_into()?,
263            serialized
264                .usages
265                .iter()
266                .map(|usage| KeyUsage::from_str(usage))
267                .collect::<Result<Vec<_>, _>>()?,
268            serialized.handle.try_into()?,
269        ))
270    }
271
272    fn serialized_storage<'a>(
273        reader: StructuredData<'a, '_>,
274    ) -> &'a mut Option<FxHashMap<CryptoKeyId, Self::Data>> {
275        match reader {
276            StructuredData::Reader(reader) => &mut reader.crypto_keys,
277            StructuredData::Writer(writer) => &mut writer.crypto_keys,
278        }
279    }
280}
281
282impl Handle {
283    pub(crate) fn as_bytes(&self) -> &[u8] {
284        match self {
285            Self::Pbkdf2(bytes) => bytes,
286            Self::Hmac(bytes) => bytes,
287            _ => unreachable!(),
288        }
289    }
290}
291
292impl MallocSizeOf for Handle {
293    fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
294        match self {
295            Handle::RsaPrivateKey(private_key) => private_key.size_of(ops),
296            Handle::RsaPublicKey(public_key) => public_key.size_of(ops),
297            Handle::P256PrivateKey(private_key) => private_key.size_of(ops),
298            Handle::P384PrivateKey(private_key) => private_key.size_of(ops),
299            Handle::P521PrivateKey(private_key) => private_key.size_of(ops),
300            Handle::P256PublicKey(public_key) => public_key.size_of(ops),
301            Handle::P384PublicKey(public_key) => public_key.size_of(ops),
302            Handle::P521PublicKey(public_key) => public_key.size_of(ops),
303            Handle::Ed25519PrivateKey(bytes) => bytes.size_of(ops),
304            Handle::Ed25519PublicKey(bytes) => bytes.size_of(ops),
305            Handle::X25519PrivateKey(private_key) => private_key.size_of(ops),
306            Handle::X25519PublicKey(public_key) => public_key.size_of(ops),
307            Handle::Ed448PrivateKey(private_key) => private_key.size_of(ops),
308            Handle::Ed448PublicKey(public_key) => public_key.size_of(ops),
309            Handle::X448PrivateKey(private_key) => private_key.size_of(ops),
310            Handle::X448PublicKey(public_key) => public_key.size_of(ops),
311            Handle::Aes128Key(key) => key.size_of(ops),
312            Handle::Aes192Key(key) => key.size_of(ops),
313            Handle::Aes256Key(key) => key.size_of(ops),
314            Handle::HkdfSecret(secret) => secret.size_of(ops),
315            Handle::Pbkdf2(bytes) => bytes.size_of(ops),
316            Handle::Hmac(bytes) => bytes.size_of(ops),
317            Handle::MlKem512PrivateKey(private_key) => private_key.size_of(ops),
318            Handle::MlKem768PrivateKey(private_key) => private_key.size_of(ops),
319            Handle::MlKem1024PrivateKey(private_key) => private_key.size_of(ops),
320            Handle::MlKem512PublicKey(public_key) => public_key.size_of(ops),
321            Handle::MlKem768PublicKey(public_key) => public_key.size_of(ops),
322            Handle::MlKem1024PublicKey(public_key) => public_key.size_of(ops),
323            Handle::MlKem768X25519PrivateKey(private_key) => private_key.size_of(ops),
324            Handle::MlKem768X25519PublicKey(public_key) => public_key.size_of(ops),
325            Handle::MlDsa44PrivateKey(private_key) => private_key.size_of(ops),
326            Handle::MlDsa65PrivateKey(private_key) => private_key.size_of(ops),
327            Handle::MlDsa87PrivateKey(private_key) => private_key.size_of(ops),
328            Handle::MlDsa44PublicKey(public_key) => public_key.size_of(ops),
329            Handle::MlDsa65PublicKey(public_key) => public_key.size_of(ops),
330            Handle::MlDsa87PublicKey(public_key) => public_key.size_of(ops),
331            Handle::ChaCha20Poly1305Key(key) => key.size_of(ops),
332            Handle::KmacKey(key) => key.size_of(ops),
333            Handle::Argon2Password(password) => password.size_of(ops),
334        }
335    }
336}
337
338impl TryFrom<SerializableCryptoKeyHandle> for Handle {
339    type Error = ();
340
341    fn try_from(value: SerializableCryptoKeyHandle) -> Result<Self, Self::Error> {
342        match &value {
343            SerializableCryptoKeyHandle::RsaPrivateKey(private_key) => Ok(Handle::RsaPrivateKey(
344                rsa::pkcs8::DecodePrivateKey::from_pkcs8_der(private_key).map_err(|_| ())?,
345            )),
346            SerializableCryptoKeyHandle::RsaPublicKey(public_key) => Ok(Handle::RsaPublicKey(
347                rsa::pkcs8::spki::DecodePublicKey::from_public_key_der(public_key)
348                    .map_err(|_| ())?,
349            )),
350            SerializableCryptoKeyHandle::P256PrivateKey(private_key) => Ok(Handle::P256PrivateKey(
351                p256::SecretKey::from_slice(private_key).map_err(|_| ())?,
352            )),
353            SerializableCryptoKeyHandle::P384PrivateKey(private_key) => Ok(Handle::P384PrivateKey(
354                p384::SecretKey::from_slice(private_key).map_err(|_| ())?,
355            )),
356            SerializableCryptoKeyHandle::P521PrivateKey(private_key) => Ok(Handle::P521PrivateKey(
357                p521::SecretKey::from_slice(private_key).map_err(|_| ())?,
358            )),
359            SerializableCryptoKeyHandle::P256PublicKey(public_key) => Ok(Handle::P256PublicKey(
360                p256::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
361            )),
362            SerializableCryptoKeyHandle::P384PublicKey(public_key) => Ok(Handle::P384PublicKey(
363                p384::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
364            )),
365            SerializableCryptoKeyHandle::P521PublicKey(public_key) => Ok(Handle::P521PublicKey(
366                p521::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
367            )),
368            SerializableCryptoKeyHandle::Ed25519PrivateKey(private_key) => Ok(
369                Handle::Ed25519PrivateKey(ed25519_dalek::SigningKey::from_bytes(private_key)),
370            ),
371            SerializableCryptoKeyHandle::Ed25519PublicKey(public_key) => {
372                Ok(Handle::Ed25519PublicKey(
373                    ed25519_dalek::VerifyingKey::from_bytes(public_key).map_err(|_| ())?,
374                ))
375            },
376            SerializableCryptoKeyHandle::X25519PrivateKey(private_key) => {
377                Ok(Handle::X25519PrivateKey((*private_key).into()))
378            },
379            SerializableCryptoKeyHandle::X25519PublicKey(public_key) => {
380                Ok(Handle::X25519PublicKey((*public_key).into()))
381            },
382            SerializableCryptoKeyHandle::Ed448PrivateKey(private_key) => {
383                Ok(Handle::Ed448PrivateKey(
384                    ed448_goldilocks::SigningKey::try_from(private_key).map_err(|_| ())?,
385                ))
386            },
387            SerializableCryptoKeyHandle::Ed448PublicKey(public_key) => Ok(Handle::Ed448PublicKey(
388                ed448_goldilocks::VerifyingKey::from_bytes(
389                    public_key.as_slice().try_into().map_err(|_| ())?,
390                )
391                .map_err(|_| ())?,
392            )),
393            SerializableCryptoKeyHandle::X448PrivateKey(private_key) => {
394                Ok(Handle::X448PrivateKey(x448::StaticSecret::from(
395                    <[u8; 56]>::try_from(private_key.as_slice()).map_err(|_| ())?,
396                )))
397            },
398            SerializableCryptoKeyHandle::X448PublicKey(public_key) => Ok(Handle::X448PublicKey(
399                x448::PublicKey::from_bytes_unchecked(public_key).ok_or(())?,
400            )),
401            SerializableCryptoKeyHandle::Aes128Key(key) => Ok(Handle::Aes128Key(
402                aes::cipher::common::Key::<aes::Aes128>::try_from(key).map_err(|_| ())?,
403            )),
404            SerializableCryptoKeyHandle::Aes192Key(key) => Ok(Handle::Aes192Key(
405                aes::cipher::common::Key::<aes::Aes192>::try_from(key).map_err(|_| ())?,
406            )),
407            SerializableCryptoKeyHandle::Aes256Key(key) => Ok(Handle::Aes256Key(
408                aes::cipher::common::Key::<aes::Aes256>::try_from(key).map_err(|_| ())?,
409            )),
410            SerializableCryptoKeyHandle::Hmac(bytes) => Ok(Handle::Hmac(bytes.clone().into())),
411            SerializableCryptoKeyHandle::HkdfSecret(bytes) => {
412                Ok(Handle::HkdfSecret(bytes.clone().into()))
413            },
414            SerializableCryptoKeyHandle::Pbkdf2(bytes) => Ok(Handle::Pbkdf2(bytes.clone().into())),
415            SerializableCryptoKeyHandle::MlKem512PrivateKey(private_key) => {
416                Ok(Handle::MlKem512PrivateKey(
417                    ml_kem::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
418                ))
419            },
420            SerializableCryptoKeyHandle::MlKem768PrivateKey(private_key) => {
421                Ok(Handle::MlKem768PrivateKey(
422                    ml_kem::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
423                ))
424            },
425            SerializableCryptoKeyHandle::MlKem1024PrivateKey(private_key) => {
426                Ok(Handle::MlKem1024PrivateKey(
427                    ml_kem::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
428                ))
429            },
430            SerializableCryptoKeyHandle::MlKem512PublicKey(public_key) => {
431                Ok(Handle::MlKem512PublicKey(
432                    ml_kem::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
433                ))
434            },
435            SerializableCryptoKeyHandle::MlKem768PublicKey(public_key) => {
436                Ok(Handle::MlKem768PublicKey(
437                    ml_kem::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
438                ))
439            },
440            SerializableCryptoKeyHandle::MlKem1024PublicKey(public_key) => {
441                Ok(Handle::MlKem1024PublicKey(
442                    ml_kem::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
443                ))
444            },
445            SerializableCryptoKeyHandle::MlKem768X25519PrivateKey(private_key) => {
446                Ok(Handle::MlKem768X25519PrivateKey(
447                    x_wing::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
448                ))
449            },
450            SerializableCryptoKeyHandle::MlKem768X25519PublicKey(public_key) => {
451                Ok(Handle::MlKem768X25519PublicKey(
452                    x_wing::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
453                ))
454            },
455            SerializableCryptoKeyHandle::MlDsa44PrivateKey(private_key) => {
456                Ok(Handle::MlDsa44PrivateKey(
457                    ml_dsa::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
458                ))
459            },
460            SerializableCryptoKeyHandle::MlDsa65PrivateKey(private_key) => {
461                Ok(Handle::MlDsa65PrivateKey(
462                    ml_dsa::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
463                ))
464            },
465            SerializableCryptoKeyHandle::MlDsa87PrivateKey(private_key) => {
466                Ok(Handle::MlDsa87PrivateKey(
467                    ml_dsa::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
468                ))
469            },
470            SerializableCryptoKeyHandle::MlDsa44PublicKey(public_key) => {
471                Ok(Handle::MlDsa44PublicKey(
472                    ml_dsa::KeyInit::new_from_slice(public_key).map_err(|_| ())?,
473                ))
474            },
475            SerializableCryptoKeyHandle::MlDsa65PublicKey(public_key) => {
476                Ok(Handle::MlDsa65PublicKey(
477                    ml_dsa::KeyInit::new_from_slice(public_key).map_err(|_| ())?,
478                ))
479            },
480            SerializableCryptoKeyHandle::MlDsa87PublicKey(public_key) => {
481                Ok(Handle::MlDsa87PublicKey(
482                    ml_dsa::KeyInit::new_from_slice(public_key).map_err(|_| ())?,
483                ))
484            },
485            SerializableCryptoKeyHandle::ChaCha20Poly1305Key(key) => Ok(
486                Handle::ChaCha20Poly1305Key(chacha20poly1305::Key::try_from(key).map_err(|_| ())?),
487            ),
488            SerializableCryptoKeyHandle::KmacKey(key) => Ok(Handle::KmacKey(key.clone().into())),
489            SerializableCryptoKeyHandle::Argon2Password(password) => {
490                Ok(Handle::Argon2Password(password.clone().into()))
491            },
492        }
493    }
494}
495
496/// To serialize the key in the `Handle`, we convert the key into byte sequences. For most
497/// cryptographic algorithms, this conversion is straightforward since the key can natually be
498/// expressed as a byte sequence. However, some cryptographic algorithms require preprocessing
499/// before their key can be represented in byte sequences. For example, an RSA private key needs to
500/// be first converted into DER-encoded PKCS#8 format before it can be expressed as a byte sequence.
501impl TryFrom<&Handle> for SerializableCryptoKeyHandle {
502    type Error = ();
503
504    fn try_from(value: &Handle) -> Result<Self, Self::Error> {
505        match value {
506            Handle::RsaPrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::RsaPrivateKey(
507                rsa::pkcs8::EncodePrivateKey::to_pkcs8_der(private_key)
508                    .map_err(|_| ())?
509                    .as_bytes()
510                    .to_vec(),
511            )),
512            Handle::RsaPublicKey(public_key) => Ok(SerializableCryptoKeyHandle::RsaPublicKey(
513                rsa::pkcs8::spki::EncodePublicKey::to_public_key_der(public_key)
514                    .map_err(|_| ())?
515                    .into_vec(),
516            )),
517            Handle::P256PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P256PrivateKey(
518                private_key.to_bytes().as_slice().to_vec(),
519            )),
520            Handle::P384PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P384PrivateKey(
521                private_key.to_bytes().as_slice().to_vec(),
522            )),
523            Handle::P521PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P521PrivateKey(
524                private_key.to_bytes().as_slice().to_vec(),
525            )),
526            Handle::P256PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P256PublicKey(
527                public_key.to_sec1_bytes().to_vec(),
528            )),
529            Handle::P384PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P384PublicKey(
530                public_key.to_sec1_bytes().to_vec(),
531            )),
532            Handle::P521PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P521PublicKey(
533                public_key.to_sec1_bytes().to_vec(),
534            )),
535            Handle::Ed25519PrivateKey(private_key) => Ok(
536                SerializableCryptoKeyHandle::Ed25519PrivateKey(private_key.to_bytes()),
537            ),
538            Handle::Ed25519PublicKey(public_key) => Ok(
539                SerializableCryptoKeyHandle::Ed25519PublicKey(public_key.to_bytes()),
540            ),
541            Handle::X25519PrivateKey(private_key) => Ok(
542                SerializableCryptoKeyHandle::X25519PrivateKey(private_key.to_bytes()),
543            ),
544            Handle::X25519PublicKey(public_key) => Ok(
545                SerializableCryptoKeyHandle::X25519PublicKey(public_key.to_bytes()),
546            ),
547            Handle::Ed448PrivateKey(private_key) => Ok(
548                SerializableCryptoKeyHandle::Ed448PrivateKey(private_key.as_bytes().to_vec()),
549            ),
550            Handle::Ed448PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::Ed448PublicKey(
551                public_key.as_bytes().to_vec(),
552            )),
553            Handle::X448PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::X448PrivateKey(
554                private_key.as_bytes().to_vec(),
555            )),
556            Handle::X448PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::X448PublicKey(
557                public_key.as_bytes().to_vec(),
558            )),
559            Handle::Aes128Key(key) => Ok(SerializableCryptoKeyHandle::Aes128Key(key.to_vec())),
560            Handle::Aes192Key(key) => Ok(SerializableCryptoKeyHandle::Aes192Key(key.to_vec())),
561            Handle::Aes256Key(key) => Ok(SerializableCryptoKeyHandle::Aes256Key(key.to_vec())),
562            Handle::Hmac(bytes) => Ok(SerializableCryptoKeyHandle::Hmac(bytes.to_vec())),
563            Handle::HkdfSecret(bytes) => {
564                Ok(SerializableCryptoKeyHandle::HkdfSecret(bytes.to_vec()))
565            },
566            Handle::Pbkdf2(bytes) => Ok(SerializableCryptoKeyHandle::Pbkdf2(bytes.to_vec())),
567            Handle::MlKem512PrivateKey(private_key) => {
568                Ok(SerializableCryptoKeyHandle::MlKem512PrivateKey(
569                    private_key
570                        .to_seed()
571                        .expect("This decapsulation key should contain seed value")
572                        .as_slice()
573                        .to_vec(),
574                ))
575            },
576            Handle::MlKem768PrivateKey(private_key) => {
577                Ok(SerializableCryptoKeyHandle::MlKem768PrivateKey(
578                    private_key
579                        .to_seed()
580                        .expect("This decapsulation key should contain seed value")
581                        .as_slice()
582                        .to_vec(),
583                ))
584            },
585            Handle::MlKem1024PrivateKey(private_key) => {
586                Ok(SerializableCryptoKeyHandle::MlKem1024PrivateKey(
587                    private_key
588                        .to_seed()
589                        .expect("This decapsulation key should contain seed value")
590                        .as_slice()
591                        .to_vec(),
592                ))
593            },
594            Handle::MlKem512PublicKey(public_key) => {
595                Ok(SerializableCryptoKeyHandle::MlKem512PublicKey(
596                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
597                ))
598            },
599            Handle::MlKem768PublicKey(public_key) => {
600                Ok(SerializableCryptoKeyHandle::MlKem768PublicKey(
601                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
602                ))
603            },
604            Handle::MlKem1024PublicKey(public_key) => {
605                Ok(SerializableCryptoKeyHandle::MlKem1024PublicKey(
606                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
607                ))
608            },
609            Handle::MlKem768X25519PrivateKey(private_key) => {
610                Ok(SerializableCryptoKeyHandle::MlKem768X25519PrivateKey(
611                    private_key.as_bytes().to_vec(),
612                ))
613            },
614            Handle::MlKem768X25519PublicKey(public_key) => {
615                Ok(SerializableCryptoKeyHandle::MlKem768X25519PublicKey(
616                    x_wing::KeyExport::to_bytes(public_key).to_vec(),
617                ))
618            },
619            Handle::MlDsa44PrivateKey(private_key) => {
620                Ok(SerializableCryptoKeyHandle::MlDsa44PrivateKey(
621                    private_key.as_seed().as_slice().to_vec(),
622                ))
623            },
624            Handle::MlDsa65PrivateKey(private_key) => {
625                Ok(SerializableCryptoKeyHandle::MlDsa65PrivateKey(
626                    private_key.as_seed().as_slice().to_vec(),
627                ))
628            },
629            Handle::MlDsa87PrivateKey(private_key) => {
630                Ok(SerializableCryptoKeyHandle::MlDsa87PrivateKey(
631                    private_key.as_seed().as_slice().to_vec(),
632                ))
633            },
634            Handle::MlDsa44PublicKey(public_key) => {
635                Ok(SerializableCryptoKeyHandle::MlDsa44PublicKey(
636                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
637                ))
638            },
639            Handle::MlDsa65PublicKey(public_key) => {
640                Ok(SerializableCryptoKeyHandle::MlDsa65PublicKey(
641                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
642                ))
643            },
644            Handle::MlDsa87PublicKey(public_key) => {
645                Ok(SerializableCryptoKeyHandle::MlDsa87PublicKey(
646                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
647                ))
648            },
649            Handle::ChaCha20Poly1305Key(key) => Ok(
650                SerializableCryptoKeyHandle::ChaCha20Poly1305Key(key.as_slice().to_vec()),
651            ),
652            Handle::KmacKey(key) => Ok(SerializableCryptoKeyHandle::KmacKey(key.to_vec())),
653            Handle::Argon2Password(password) => Ok(SerializableCryptoKeyHandle::Argon2Password(
654                password.to_vec(),
655            )),
656        }
657    }
658}
659
660/// The trait providing helper functions for [`Vec<KeyUsage>`]
661pub(crate) trait KeyUsageVecHelper {
662    /// <https://w3c.github.io/webcrypto/#concept-usage-intersection>
663    fn usage_intersection(&self, other: &[KeyUsage]) -> Vec<KeyUsage>;
664
665    /// <https://w3c.github.io/webcrypto/#concept-normalized-usages>
666    fn normalized_value(&self) -> Vec<KeyUsage>;
667}
668
669impl KeyUsageVecHelper for Vec<KeyUsage> {
670    fn usage_intersection(&self, other: &[KeyUsage]) -> Vec<KeyUsage> {
671        // When this specification says to calculate the usage intersection of two sequences, a and
672        // b the result shall be a sequence containing each recognized key usage value that appears
673        // in both a and b, in the order listed in the list of recognized key usage values, where a
674        // value is said to appear in a sequence if an element of the sequence exists that is a
675        // case-sensitive string match for that value.
676        let mut intersection = self
677            .iter()
678            .filter(|usage| other.contains(usage))
679            .cloned()
680            .collect::<Vec<KeyUsage>>();
681        intersection.sort();
682        intersection.dedup();
683
684        intersection
685    }
686
687    fn normalized_value(&self) -> Vec<KeyUsage> {
688        // When this specification says to calculate the normalized value of a usages list, usages
689        // the result shall be the usage intersection of usages and a sequence containing all
690        // recognized key usage values.
691        self.usage_intersection(KeyUsage::VARIANTS)
692    }
693}