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    Pbkdf2Password(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::Hmac(bytes) => bytes,
321            _ => unreachable!(),
322        }
323    }
324}
325
326impl MallocSizeOf for Handle {
327    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
328        match self {
329            Handle::RsaPrivateKey(private_key) => private_key.size_of(ops),
330            Handle::RsaPublicKey(public_key) => public_key.size_of(ops),
331            Handle::P256PrivateKey(private_key) => private_key.size_of(ops),
332            Handle::P384PrivateKey(private_key) => private_key.size_of(ops),
333            Handle::P521PrivateKey(private_key) => private_key.size_of(ops),
334            Handle::P256PublicKey(public_key) => public_key.size_of(ops),
335            Handle::P384PublicKey(public_key) => public_key.size_of(ops),
336            Handle::P521PublicKey(public_key) => public_key.size_of(ops),
337            Handle::Ed25519PrivateKey(bytes) => bytes.size_of(ops),
338            Handle::Ed25519PublicKey(bytes) => bytes.size_of(ops),
339            Handle::X25519PrivateKey(private_key) => private_key.size_of(ops),
340            Handle::X25519PublicKey(public_key) => public_key.size_of(ops),
341            Handle::Ed448PrivateKey(private_key) => private_key.size_of(ops),
342            Handle::Ed448PublicKey(public_key) => public_key.size_of(ops),
343            Handle::X448PrivateKey(private_key) => private_key.size_of(ops),
344            Handle::X448PublicKey(public_key) => public_key.size_of(ops),
345            Handle::Aes128Key(key) => key.size_of(ops),
346            Handle::Aes192Key(key) => key.size_of(ops),
347            Handle::Aes256Key(key) => key.size_of(ops),
348            Handle::HkdfSecret(secret) => secret.size_of(ops),
349            Handle::Pbkdf2Password(password) => password.size_of(ops),
350            Handle::Hmac(bytes) => bytes.size_of(ops),
351            Handle::MlKem512PrivateKey(private_key) => private_key.size_of(ops),
352            Handle::MlKem768PrivateKey(private_key) => private_key.size_of(ops),
353            Handle::MlKem1024PrivateKey(private_key) => private_key.size_of(ops),
354            Handle::MlKem512PublicKey(public_key) => public_key.size_of(ops),
355            Handle::MlKem768PublicKey(public_key) => public_key.size_of(ops),
356            Handle::MlKem1024PublicKey(public_key) => public_key.size_of(ops),
357            Handle::MlKem768X25519PrivateKey(private_key) => private_key.size_of(ops),
358            Handle::MlKem768X25519PublicKey(public_key) => public_key.size_of(ops),
359            Handle::MlDsa44PrivateKey(private_key) => private_key.size_of(ops),
360            Handle::MlDsa65PrivateKey(private_key) => private_key.size_of(ops),
361            Handle::MlDsa87PrivateKey(private_key) => private_key.size_of(ops),
362            Handle::MlDsa44PublicKey(public_key) => public_key.size_of(ops),
363            Handle::MlDsa65PublicKey(public_key) => public_key.size_of(ops),
364            Handle::MlDsa87PublicKey(public_key) => public_key.size_of(ops),
365            Handle::ChaCha20Poly1305Key(key) => key.size_of(ops),
366            Handle::KmacKey(key) => key.size_of(ops),
367            Handle::Argon2Password(password) => password.size_of(ops),
368        }
369    }
370}
371
372impl TryFrom<SerializableCryptoKeyHandle> for Handle {
373    type Error = ();
374
375    fn try_from(value: SerializableCryptoKeyHandle) -> Result<Self, Self::Error> {
376        match &value {
377            SerializableCryptoKeyHandle::RsaPrivateKey(private_key) => Ok(Handle::RsaPrivateKey(
378                rsa::pkcs8::DecodePrivateKey::from_pkcs8_der(private_key).map_err(|_| ())?,
379            )),
380            SerializableCryptoKeyHandle::RsaPublicKey(public_key) => Ok(Handle::RsaPublicKey(
381                rsa::pkcs8::spki::DecodePublicKey::from_public_key_der(public_key)
382                    .map_err(|_| ())?,
383            )),
384            SerializableCryptoKeyHandle::P256PrivateKey(private_key) => Ok(Handle::P256PrivateKey(
385                p256::SecretKey::from_slice(private_key).map_err(|_| ())?,
386            )),
387            SerializableCryptoKeyHandle::P384PrivateKey(private_key) => Ok(Handle::P384PrivateKey(
388                p384::SecretKey::from_slice(private_key).map_err(|_| ())?,
389            )),
390            SerializableCryptoKeyHandle::P521PrivateKey(private_key) => Ok(Handle::P521PrivateKey(
391                p521::SecretKey::from_slice(private_key).map_err(|_| ())?,
392            )),
393            SerializableCryptoKeyHandle::P256PublicKey(public_key) => Ok(Handle::P256PublicKey(
394                p256::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
395            )),
396            SerializableCryptoKeyHandle::P384PublicKey(public_key) => Ok(Handle::P384PublicKey(
397                p384::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
398            )),
399            SerializableCryptoKeyHandle::P521PublicKey(public_key) => Ok(Handle::P521PublicKey(
400                p521::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
401            )),
402            SerializableCryptoKeyHandle::Ed25519PrivateKey(private_key) => Ok(
403                Handle::Ed25519PrivateKey(ed25519_dalek::SigningKey::from_bytes(private_key)),
404            ),
405            SerializableCryptoKeyHandle::Ed25519PublicKey(public_key) => {
406                Ok(Handle::Ed25519PublicKey(
407                    ed25519_dalek::VerifyingKey::from_bytes(public_key).map_err(|_| ())?,
408                ))
409            },
410            SerializableCryptoKeyHandle::X25519PrivateKey(private_key) => {
411                Ok(Handle::X25519PrivateKey((*private_key).into()))
412            },
413            SerializableCryptoKeyHandle::X25519PublicKey(public_key) => {
414                Ok(Handle::X25519PublicKey((*public_key).into()))
415            },
416            SerializableCryptoKeyHandle::Ed448PrivateKey(private_key) => {
417                Ok(Handle::Ed448PrivateKey(
418                    ed448_goldilocks::SigningKey::try_from(private_key).map_err(|_| ())?,
419                ))
420            },
421            SerializableCryptoKeyHandle::Ed448PublicKey(public_key) => Ok(Handle::Ed448PublicKey(
422                ed448_goldilocks::VerifyingKey::from_bytes(
423                    public_key.as_slice().try_into().map_err(|_| ())?,
424                )
425                .map_err(|_| ())?,
426            )),
427            SerializableCryptoKeyHandle::X448PrivateKey(private_key) => {
428                Ok(Handle::X448PrivateKey(x448::StaticSecret::from(
429                    <[u8; 56]>::try_from(private_key.as_slice()).map_err(|_| ())?,
430                )))
431            },
432            SerializableCryptoKeyHandle::X448PublicKey(public_key) => Ok(Handle::X448PublicKey(
433                x448::PublicKey::from_bytes_unchecked(public_key).ok_or(())?,
434            )),
435            SerializableCryptoKeyHandle::Aes128Key(key) => Ok(Handle::Aes128Key(
436                aes::cipher::common::Key::<aes::Aes128>::try_from(key).map_err(|_| ())?,
437            )),
438            SerializableCryptoKeyHandle::Aes192Key(key) => Ok(Handle::Aes192Key(
439                aes::cipher::common::Key::<aes::Aes192>::try_from(key).map_err(|_| ())?,
440            )),
441            SerializableCryptoKeyHandle::Aes256Key(key) => Ok(Handle::Aes256Key(
442                aes::cipher::common::Key::<aes::Aes256>::try_from(key).map_err(|_| ())?,
443            )),
444            SerializableCryptoKeyHandle::Hmac(bytes) => Ok(Handle::Hmac(bytes.clone().into())),
445            SerializableCryptoKeyHandle::HkdfSecret(bytes) => {
446                Ok(Handle::HkdfSecret(bytes.clone().into()))
447            },
448            SerializableCryptoKeyHandle::Pbkdf2Password(password) => {
449                Ok(Handle::Pbkdf2Password(password.clone().into()))
450            },
451            SerializableCryptoKeyHandle::MlKem512PrivateKey(private_key) => {
452                Ok(Handle::MlKem512PrivateKey(
453                    ml_kem::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
454                ))
455            },
456            SerializableCryptoKeyHandle::MlKem768PrivateKey(private_key) => {
457                Ok(Handle::MlKem768PrivateKey(
458                    ml_kem::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
459                ))
460            },
461            SerializableCryptoKeyHandle::MlKem1024PrivateKey(private_key) => {
462                Ok(Handle::MlKem1024PrivateKey(
463                    ml_kem::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
464                ))
465            },
466            SerializableCryptoKeyHandle::MlKem512PublicKey(public_key) => {
467                Ok(Handle::MlKem512PublicKey(
468                    ml_kem::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
469                ))
470            },
471            SerializableCryptoKeyHandle::MlKem768PublicKey(public_key) => {
472                Ok(Handle::MlKem768PublicKey(
473                    ml_kem::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
474                ))
475            },
476            SerializableCryptoKeyHandle::MlKem1024PublicKey(public_key) => {
477                Ok(Handle::MlKem1024PublicKey(
478                    ml_kem::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
479                ))
480            },
481            SerializableCryptoKeyHandle::MlKem768X25519PrivateKey(private_key) => {
482                Ok(Handle::MlKem768X25519PrivateKey(
483                    x_wing::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
484                ))
485            },
486            SerializableCryptoKeyHandle::MlKem768X25519PublicKey(public_key) => {
487                Ok(Handle::MlKem768X25519PublicKey(
488                    x_wing::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
489                ))
490            },
491            SerializableCryptoKeyHandle::MlDsa44PrivateKey(private_key) => {
492                Ok(Handle::MlDsa44PrivateKey(
493                    ml_dsa::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
494                ))
495            },
496            SerializableCryptoKeyHandle::MlDsa65PrivateKey(private_key) => {
497                Ok(Handle::MlDsa65PrivateKey(
498                    ml_dsa::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
499                ))
500            },
501            SerializableCryptoKeyHandle::MlDsa87PrivateKey(private_key) => {
502                Ok(Handle::MlDsa87PrivateKey(
503                    ml_dsa::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
504                ))
505            },
506            SerializableCryptoKeyHandle::MlDsa44PublicKey(public_key) => {
507                Ok(Handle::MlDsa44PublicKey(
508                    ml_dsa::KeyInit::new_from_slice(public_key).map_err(|_| ())?,
509                ))
510            },
511            SerializableCryptoKeyHandle::MlDsa65PublicKey(public_key) => {
512                Ok(Handle::MlDsa65PublicKey(
513                    ml_dsa::KeyInit::new_from_slice(public_key).map_err(|_| ())?,
514                ))
515            },
516            SerializableCryptoKeyHandle::MlDsa87PublicKey(public_key) => {
517                Ok(Handle::MlDsa87PublicKey(
518                    ml_dsa::KeyInit::new_from_slice(public_key).map_err(|_| ())?,
519                ))
520            },
521            SerializableCryptoKeyHandle::ChaCha20Poly1305Key(key) => Ok(
522                Handle::ChaCha20Poly1305Key(chacha20poly1305::Key::try_from(key).map_err(|_| ())?),
523            ),
524            SerializableCryptoKeyHandle::KmacKey(key) => Ok(Handle::KmacKey(key.clone().into())),
525            SerializableCryptoKeyHandle::Argon2Password(password) => {
526                Ok(Handle::Argon2Password(password.clone().into()))
527            },
528        }
529    }
530}
531
532/// To serialize the key in the `Handle`, we convert the key into byte sequences. For most
533/// cryptographic algorithms, this conversion is straightforward since the key can natually be
534/// expressed as a byte sequence. However, some cryptographic algorithms require preprocessing
535/// before their key can be represented in byte sequences. For example, an RSA private key needs to
536/// be first converted into DER-encoded PKCS#8 format before it can be expressed as a byte sequence.
537impl TryFrom<&Handle> for SerializableCryptoKeyHandle {
538    type Error = ();
539
540    fn try_from(value: &Handle) -> Result<Self, Self::Error> {
541        match value {
542            Handle::RsaPrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::RsaPrivateKey(
543                rsa::pkcs8::EncodePrivateKey::to_pkcs8_der(private_key)
544                    .map_err(|_| ())?
545                    .as_bytes()
546                    .to_vec(),
547            )),
548            Handle::RsaPublicKey(public_key) => Ok(SerializableCryptoKeyHandle::RsaPublicKey(
549                rsa::pkcs8::spki::EncodePublicKey::to_public_key_der(public_key)
550                    .map_err(|_| ())?
551                    .into_vec(),
552            )),
553            Handle::P256PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P256PrivateKey(
554                private_key.to_bytes().as_slice().to_vec(),
555            )),
556            Handle::P384PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P384PrivateKey(
557                private_key.to_bytes().as_slice().to_vec(),
558            )),
559            Handle::P521PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P521PrivateKey(
560                private_key.to_bytes().as_slice().to_vec(),
561            )),
562            Handle::P256PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P256PublicKey(
563                public_key.to_sec1_bytes().to_vec(),
564            )),
565            Handle::P384PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P384PublicKey(
566                public_key.to_sec1_bytes().to_vec(),
567            )),
568            Handle::P521PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P521PublicKey(
569                public_key.to_sec1_bytes().to_vec(),
570            )),
571            Handle::Ed25519PrivateKey(private_key) => Ok(
572                SerializableCryptoKeyHandle::Ed25519PrivateKey(private_key.to_bytes()),
573            ),
574            Handle::Ed25519PublicKey(public_key) => Ok(
575                SerializableCryptoKeyHandle::Ed25519PublicKey(public_key.to_bytes()),
576            ),
577            Handle::X25519PrivateKey(private_key) => Ok(
578                SerializableCryptoKeyHandle::X25519PrivateKey(private_key.to_bytes()),
579            ),
580            Handle::X25519PublicKey(public_key) => Ok(
581                SerializableCryptoKeyHandle::X25519PublicKey(public_key.to_bytes()),
582            ),
583            Handle::Ed448PrivateKey(private_key) => Ok(
584                SerializableCryptoKeyHandle::Ed448PrivateKey(private_key.as_bytes().to_vec()),
585            ),
586            Handle::Ed448PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::Ed448PublicKey(
587                public_key.as_bytes().to_vec(),
588            )),
589            Handle::X448PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::X448PrivateKey(
590                private_key.as_bytes().to_vec(),
591            )),
592            Handle::X448PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::X448PublicKey(
593                public_key.as_bytes().to_vec(),
594            )),
595            Handle::Aes128Key(key) => Ok(SerializableCryptoKeyHandle::Aes128Key(key.to_vec())),
596            Handle::Aes192Key(key) => Ok(SerializableCryptoKeyHandle::Aes192Key(key.to_vec())),
597            Handle::Aes256Key(key) => Ok(SerializableCryptoKeyHandle::Aes256Key(key.to_vec())),
598            Handle::Hmac(bytes) => Ok(SerializableCryptoKeyHandle::Hmac(bytes.to_vec())),
599            Handle::HkdfSecret(bytes) => {
600                Ok(SerializableCryptoKeyHandle::HkdfSecret(bytes.to_vec()))
601            },
602            Handle::Pbkdf2Password(password) => Ok(SerializableCryptoKeyHandle::Pbkdf2Password(
603                password.to_vec(),
604            )),
605            Handle::MlKem512PrivateKey(private_key) => {
606                Ok(SerializableCryptoKeyHandle::MlKem512PrivateKey(
607                    private_key
608                        .to_seed()
609                        .expect("This decapsulation key should contain seed value")
610                        .as_slice()
611                        .to_vec(),
612                ))
613            },
614            Handle::MlKem768PrivateKey(private_key) => {
615                Ok(SerializableCryptoKeyHandle::MlKem768PrivateKey(
616                    private_key
617                        .to_seed()
618                        .expect("This decapsulation key should contain seed value")
619                        .as_slice()
620                        .to_vec(),
621                ))
622            },
623            Handle::MlKem1024PrivateKey(private_key) => {
624                Ok(SerializableCryptoKeyHandle::MlKem1024PrivateKey(
625                    private_key
626                        .to_seed()
627                        .expect("This decapsulation key should contain seed value")
628                        .as_slice()
629                        .to_vec(),
630                ))
631            },
632            Handle::MlKem512PublicKey(public_key) => {
633                Ok(SerializableCryptoKeyHandle::MlKem512PublicKey(
634                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
635                ))
636            },
637            Handle::MlKem768PublicKey(public_key) => {
638                Ok(SerializableCryptoKeyHandle::MlKem768PublicKey(
639                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
640                ))
641            },
642            Handle::MlKem1024PublicKey(public_key) => {
643                Ok(SerializableCryptoKeyHandle::MlKem1024PublicKey(
644                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
645                ))
646            },
647            Handle::MlKem768X25519PrivateKey(private_key) => {
648                Ok(SerializableCryptoKeyHandle::MlKem768X25519PrivateKey(
649                    private_key.as_bytes().to_vec(),
650                ))
651            },
652            Handle::MlKem768X25519PublicKey(public_key) => {
653                Ok(SerializableCryptoKeyHandle::MlKem768X25519PublicKey(
654                    x_wing::KeyExport::to_bytes(public_key).to_vec(),
655                ))
656            },
657            Handle::MlDsa44PrivateKey(private_key) => {
658                Ok(SerializableCryptoKeyHandle::MlDsa44PrivateKey(
659                    private_key.as_seed().as_slice().to_vec(),
660                ))
661            },
662            Handle::MlDsa65PrivateKey(private_key) => {
663                Ok(SerializableCryptoKeyHandle::MlDsa65PrivateKey(
664                    private_key.as_seed().as_slice().to_vec(),
665                ))
666            },
667            Handle::MlDsa87PrivateKey(private_key) => {
668                Ok(SerializableCryptoKeyHandle::MlDsa87PrivateKey(
669                    private_key.as_seed().as_slice().to_vec(),
670                ))
671            },
672            Handle::MlDsa44PublicKey(public_key) => {
673                Ok(SerializableCryptoKeyHandle::MlDsa44PublicKey(
674                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
675                ))
676            },
677            Handle::MlDsa65PublicKey(public_key) => {
678                Ok(SerializableCryptoKeyHandle::MlDsa65PublicKey(
679                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
680                ))
681            },
682            Handle::MlDsa87PublicKey(public_key) => {
683                Ok(SerializableCryptoKeyHandle::MlDsa87PublicKey(
684                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
685                ))
686            },
687            Handle::ChaCha20Poly1305Key(key) => Ok(
688                SerializableCryptoKeyHandle::ChaCha20Poly1305Key(key.as_slice().to_vec()),
689            ),
690            Handle::KmacKey(key) => Ok(SerializableCryptoKeyHandle::KmacKey(key.to_vec())),
691            Handle::Argon2Password(password) => Ok(SerializableCryptoKeyHandle::Argon2Password(
692                password.to_vec(),
693            )),
694        }
695    }
696}
697
698/// The trait providing helper functions for `&[KeyUsage]`
699pub(crate) trait KeyUsageSliceHelper {
700    /// <https://w3c.github.io/webcrypto/#concept-usage-intersection>
701    fn usage_intersection(&self, other: &[KeyUsage]) -> Vec<KeyUsage>;
702
703    /// <https://w3c.github.io/webcrypto/#concept-normalized-usages>
704    fn normalized_value(&self) -> Vec<KeyUsage>;
705
706    /// Ensure that the key usage list only contains entries which are in `allowed`. If the key
707    /// usage list contains an entry which is not in `allowed`, then throw a SyntaxError. Note that,
708    /// if `allowed` is set to empty, it throws a SyntaxError when the key usage list is not empty.
709    fn ensure_only_contain_entries_from(&self, allowed: &[KeyUsage]) -> ErrorResult;
710}
711
712impl KeyUsageSliceHelper for [KeyUsage] {
713    fn usage_intersection(&self, other: &[KeyUsage]) -> Vec<KeyUsage> {
714        // When this specification says to calculate the usage intersection of two sequences, a and
715        // b the result shall be a sequence containing each recognized key usage value that appears
716        // in both a and b, in the order listed in the list of recognized key usage values, where a
717        // value is said to appear in a sequence if an element of the sequence exists that is a
718        // case-sensitive string match for that value.
719        let mut intersection = self
720            .iter()
721            .filter(|usage| other.contains(usage))
722            .cloned()
723            .collect::<Vec<KeyUsage>>();
724        intersection.sort();
725        intersection.dedup();
726
727        intersection
728    }
729
730    fn normalized_value(&self) -> Vec<KeyUsage> {
731        // When this specification says to calculate the normalized value of a usages list, usages
732        // the result shall be the usage intersection of usages and a sequence containing all
733        // recognized key usage values.
734        self.usage_intersection(KeyUsage::VARIANTS)
735    }
736
737    fn ensure_only_contain_entries_from(&self, allowed: &[KeyUsage]) -> ErrorResult {
738        if self.iter().all(|usage| allowed.contains(usage)) {
739            Ok(())
740        } else {
741            Err(Error::Syntax(Some(if allowed.is_empty() {
742                "Usages is not empty".into()
743            } else {
744                format!(
745                    "Usages contains an entry which is not {}",
746                    allowed.iter().map(|usage| usage.as_ref()).join(" or "),
747                )
748            })))
749        }
750    }
751}