Skip to main content

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