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::cell::Cell;
6use std::str::FromStr;
7
8use dom_struct::dom_struct;
9use js::context::NoGC;
10use js::conversions::ToJSValConvertible;
11use js::jsapi::{Heap, JSObject, Value};
12use js::rust::MutableHandleObject;
13use malloc_size_of::MallocSizeOf;
14use rustc_hash::FxHashMap;
15use script_bindings::cell::{DomRefCell, Ref};
16use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
17use servo_base::id::{CryptoKeyId, CryptoKeyIndex};
18use servo_constellation_traits::{SerializableCryptoKey, SerializableCryptoKeyHandle};
19use strum::VariantArray;
20use zeroize::Zeroizing;
21
22use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
23    CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
24};
25use crate::dom::bindings::root::DomRoot;
26use crate::dom::bindings::serializable::Serializable;
27use crate::dom::bindings::structuredclone::StructuredData;
28use crate::dom::globalscope::GlobalScope;
29use crate::dom::subtlecrypto::KeyAlgorithmAndDerivatives;
30
31pub(crate) enum CryptoKeyOrCryptoKeyPair {
32    CryptoKey(DomRoot<CryptoKey>),
33    CryptoKeyPair(CryptoKeyPair),
34}
35
36/// The underlying cryptographic data this key represents.
37///
38/// Please make sure the inner types for secret variants implement the `zeroize::ZeroizeOnDrop`
39/// trait, which signifies that the type will call `Zeroize::zeroize` on `Drop` to securely erase
40/// the secret from memory.
41pub(crate) enum Handle {
42    RsaPrivateKey(rsa::RsaPrivateKey),
43    RsaPublicKey(rsa::RsaPublicKey),
44    P256PrivateKey(p256::SecretKey),
45    P384PrivateKey(p384::SecretKey),
46    P521PrivateKey(p521::SecretKey),
47    P256PublicKey(p256::PublicKey),
48    P384PublicKey(p384::PublicKey),
49    P521PublicKey(p521::PublicKey),
50    Ed25519PrivateKey(ed25519_dalek::SigningKey),
51    Ed25519PublicKey(ed25519_dalek::VerifyingKey),
52    X25519PrivateKey(x25519_dalek::StaticSecret),
53    X25519PublicKey(x25519_dalek::PublicKey),
54    Ed448PrivateKey(ed448_goldilocks::SigningKey),
55    Ed448PublicKey(ed448_goldilocks::VerifyingKey),
56    X448PrivateKey(x448::StaticSecret),
57    X448PublicKey(x448::PublicKey),
58    Aes128Key(aes::cipher::common::Key<aes::Aes128>),
59    Aes192Key(aes::cipher::common::Key<aes::Aes192>),
60    Aes256Key(aes::cipher::common::Key<aes::Aes256>),
61    HkdfSecret(Zeroizing<Vec<u8>>),
62    Pbkdf2(Zeroizing<Vec<u8>>),
63    Hmac(Zeroizing<Vec<u8>>),
64    MlKem512PrivateKey(ml_kem::DecapsulationKey<ml_kem::MlKem512>),
65    MlKem768PrivateKey(ml_kem::DecapsulationKey<ml_kem::MlKem768>),
66    MlKem1024PrivateKey(ml_kem::DecapsulationKey<ml_kem::MlKem1024>),
67    MlKem512PublicKey(ml_kem::EncapsulationKey<ml_kem::MlKem512>),
68    MlKem768PublicKey(ml_kem::EncapsulationKey<ml_kem::MlKem768>),
69    MlKem1024PublicKey(ml_kem::EncapsulationKey<ml_kem::MlKem1024>),
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: Cell<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: DomRefCell<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: Cell::new(extractable),
129            algorithm,
130            algorithm_cached: Heap::default(),
131            usages: DomRefCell::new(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_with_cx(
147            Box::new(CryptoKey::new_inherited(
148                key_type,
149                extractable,
150                algorithm.clone(),
151                usages.clone(),
152                handle,
153            )),
154            global,
155            cx,
156        );
157
158        // Create and store a cached object of algorithm
159        rooted!(&in(cx) let mut algorithm_object_value: Value);
160        algorithm.safe_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.safe_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) -> Ref<'_, Vec<KeyUsage>> {
180        self.usages.borrow()
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.get()
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.get(),
232            algorithm: (&self.algorithm).into(),
233            usages: self
234                .usages
235                .borrow()
236                .iter()
237                .map(|usage| usage.as_str().into())
238                .collect(),
239            handle: (&self.handle).try_into()?,
240        };
241        Ok((CryptoKeyId::new(), serialized))
242    }
243
244    /// <https://w3c.github.io/webcrypto/#cryptokey-interface-serializable>
245    fn deserialize(
246        cx: &mut js::context::JSContext,
247        owner: &GlobalScope,
248        serialized: Self::Data,
249    ) -> Result<DomRoot<Self>, ()> {
250        // Step 1. Initialize the [[type]] internal slot of value to serialized.[[Type]].
251        // Step 2. Initialize the [[extractable]] internal slot of value to
252        // serialized.[[Extractable]].
253        // Step 3. Initialize the [[algorithm]] internal slot of value to the sub-deserialization of
254        // serialized.[[Algorithm]].
255        // Step 4. Initialize the [[usages]] internal slot of value to the sub-deserialization of
256        // serialized.[[Usages]].
257        // Step 5. Initialize the [[handle]] internal slot of value to serialized.[[Handle]].
258        Ok(CryptoKey::new(
259            cx,
260            owner,
261            KeyType::from_str(&serialized.key_type)?,
262            serialized.extractable,
263            serialized.algorithm.try_into()?,
264            serialized
265                .usages
266                .iter()
267                .map(|usage| KeyUsage::from_str(usage))
268                .collect::<Result<Vec<_>, _>>()?,
269            serialized.handle.try_into()?,
270        ))
271    }
272
273    fn serialized_storage<'a>(
274        reader: StructuredData<'a, '_>,
275    ) -> &'a mut Option<FxHashMap<CryptoKeyId, Self::Data>> {
276        match reader {
277            StructuredData::Reader(reader) => &mut reader.crypto_keys,
278            StructuredData::Writer(writer) => &mut writer.crypto_keys,
279        }
280    }
281}
282
283impl Handle {
284    pub(crate) fn as_bytes(&self) -> &[u8] {
285        match self {
286            Self::Pbkdf2(bytes) => bytes,
287            Self::Hmac(bytes) => bytes,
288            _ => unreachable!(),
289        }
290    }
291}
292
293impl MallocSizeOf for Handle {
294    fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
295        match self {
296            Handle::RsaPrivateKey(private_key) => private_key.size_of(ops),
297            Handle::RsaPublicKey(public_key) => public_key.size_of(ops),
298            Handle::P256PrivateKey(private_key) => private_key.size_of(ops),
299            Handle::P384PrivateKey(private_key) => private_key.size_of(ops),
300            Handle::P521PrivateKey(private_key) => private_key.size_of(ops),
301            Handle::P256PublicKey(public_key) => public_key.size_of(ops),
302            Handle::P384PublicKey(public_key) => public_key.size_of(ops),
303            Handle::P521PublicKey(public_key) => public_key.size_of(ops),
304            Handle::Ed25519PrivateKey(bytes) => bytes.size_of(ops),
305            Handle::Ed25519PublicKey(bytes) => bytes.size_of(ops),
306            Handle::X25519PrivateKey(private_key) => private_key.size_of(ops),
307            Handle::X25519PublicKey(public_key) => public_key.size_of(ops),
308            Handle::Ed448PrivateKey(private_key) => private_key.size_of(ops),
309            Handle::Ed448PublicKey(public_key) => public_key.size_of(ops),
310            Handle::X448PrivateKey(private_key) => private_key.size_of(ops),
311            Handle::X448PublicKey(public_key) => public_key.size_of(ops),
312            Handle::Aes128Key(key) => key.size_of(ops),
313            Handle::Aes192Key(key) => key.size_of(ops),
314            Handle::Aes256Key(key) => key.size_of(ops),
315            Handle::HkdfSecret(secret) => secret.size_of(ops),
316            Handle::Pbkdf2(bytes) => bytes.size_of(ops),
317            Handle::Hmac(bytes) => bytes.size_of(ops),
318            Handle::MlKem512PrivateKey(private_key) => private_key.size_of(ops),
319            Handle::MlKem768PrivateKey(private_key) => private_key.size_of(ops),
320            Handle::MlKem1024PrivateKey(private_key) => private_key.size_of(ops),
321            Handle::MlKem512PublicKey(public_key) => public_key.size_of(ops),
322            Handle::MlKem768PublicKey(public_key) => public_key.size_of(ops),
323            Handle::MlKem1024PublicKey(public_key) => public_key.size_of(ops),
324            Handle::MlDsa44PrivateKey(private_key) => private_key.size_of(ops),
325            Handle::MlDsa65PrivateKey(private_key) => private_key.size_of(ops),
326            Handle::MlDsa87PrivateKey(private_key) => private_key.size_of(ops),
327            Handle::MlDsa44PublicKey(public_key) => public_key.size_of(ops),
328            Handle::MlDsa65PublicKey(public_key) => public_key.size_of(ops),
329            Handle::MlDsa87PublicKey(public_key) => public_key.size_of(ops),
330            Handle::ChaCha20Poly1305Key(key) => key.size_of(ops),
331            Handle::KmacKey(key) => key.size_of(ops),
332            Handle::Argon2Password(password) => password.size_of(ops),
333        }
334    }
335}
336
337impl TryFrom<SerializableCryptoKeyHandle> for Handle {
338    type Error = ();
339
340    fn try_from(value: SerializableCryptoKeyHandle) -> Result<Self, Self::Error> {
341        match &value {
342            SerializableCryptoKeyHandle::RsaPrivateKey(private_key) => Ok(Handle::RsaPrivateKey(
343                rsa::pkcs8::DecodePrivateKey::from_pkcs8_der(private_key).map_err(|_| ())?,
344            )),
345            SerializableCryptoKeyHandle::RsaPublicKey(public_key) => Ok(Handle::RsaPublicKey(
346                rsa::pkcs8::spki::DecodePublicKey::from_public_key_der(public_key)
347                    .map_err(|_| ())?,
348            )),
349            SerializableCryptoKeyHandle::P256PrivateKey(private_key) => Ok(Handle::P256PrivateKey(
350                p256::SecretKey::from_slice(private_key).map_err(|_| ())?,
351            )),
352            SerializableCryptoKeyHandle::P384PrivateKey(private_key) => Ok(Handle::P384PrivateKey(
353                p384::SecretKey::from_slice(private_key).map_err(|_| ())?,
354            )),
355            SerializableCryptoKeyHandle::P521PrivateKey(private_key) => Ok(Handle::P521PrivateKey(
356                p521::SecretKey::from_slice(private_key).map_err(|_| ())?,
357            )),
358            SerializableCryptoKeyHandle::P256PublicKey(public_key) => Ok(Handle::P256PublicKey(
359                p256::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
360            )),
361            SerializableCryptoKeyHandle::P384PublicKey(public_key) => Ok(Handle::P384PublicKey(
362                p384::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
363            )),
364            SerializableCryptoKeyHandle::P521PublicKey(public_key) => Ok(Handle::P521PublicKey(
365                p521::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
366            )),
367            SerializableCryptoKeyHandle::Ed25519PrivateKey(private_key) => Ok(
368                Handle::Ed25519PrivateKey(ed25519_dalek::SigningKey::from_bytes(private_key)),
369            ),
370            SerializableCryptoKeyHandle::Ed25519PublicKey(public_key) => {
371                Ok(Handle::Ed25519PublicKey(
372                    ed25519_dalek::VerifyingKey::from_bytes(public_key).map_err(|_| ())?,
373                ))
374            },
375            SerializableCryptoKeyHandle::X25519PrivateKey(private_key) => {
376                Ok(Handle::X25519PrivateKey((*private_key).into()))
377            },
378            SerializableCryptoKeyHandle::X25519PublicKey(public_key) => {
379                Ok(Handle::X25519PublicKey((*public_key).into()))
380            },
381            SerializableCryptoKeyHandle::Ed448PrivateKey(private_key) => {
382                Ok(Handle::Ed448PrivateKey(
383                    ed448_goldilocks::SigningKey::try_from(private_key).map_err(|_| ())?,
384                ))
385            },
386            SerializableCryptoKeyHandle::Ed448PublicKey(public_key) => Ok(Handle::Ed448PublicKey(
387                ed448_goldilocks::VerifyingKey::from_bytes(
388                    public_key.as_slice().try_into().map_err(|_| ())?,
389                )
390                .map_err(|_| ())?,
391            )),
392            SerializableCryptoKeyHandle::X448PrivateKey(private_key) => {
393                Ok(Handle::X448PrivateKey(x448::StaticSecret::from(
394                    <[u8; 56]>::try_from(private_key.as_slice()).map_err(|_| ())?,
395                )))
396            },
397            SerializableCryptoKeyHandle::X448PublicKey(public_key) => Ok(Handle::X448PublicKey(
398                x448::PublicKey::from_bytes_unchecked(public_key).ok_or(())?,
399            )),
400            SerializableCryptoKeyHandle::Aes128Key(key) => Ok(Handle::Aes128Key(
401                aes::cipher::common::Key::<aes::Aes128>::try_from(key).map_err(|_| ())?,
402            )),
403            SerializableCryptoKeyHandle::Aes192Key(key) => Ok(Handle::Aes192Key(
404                aes::cipher::common::Key::<aes::Aes192>::try_from(key).map_err(|_| ())?,
405            )),
406            SerializableCryptoKeyHandle::Aes256Key(key) => Ok(Handle::Aes256Key(
407                aes::cipher::common::Key::<aes::Aes256>::try_from(key).map_err(|_| ())?,
408            )),
409            SerializableCryptoKeyHandle::Hmac(bytes) => Ok(Handle::Hmac(bytes.clone().into())),
410            SerializableCryptoKeyHandle::HkdfSecret(bytes) => {
411                Ok(Handle::HkdfSecret(bytes.clone().into()))
412            },
413            SerializableCryptoKeyHandle::Pbkdf2(bytes) => Ok(Handle::Pbkdf2(bytes.clone().into())),
414            SerializableCryptoKeyHandle::MlKem512PrivateKey(private_key) => {
415                Ok(Handle::MlKem512PrivateKey(
416                    ml_kem::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
417                ))
418            },
419            SerializableCryptoKeyHandle::MlKem768PrivateKey(private_key) => {
420                Ok(Handle::MlKem768PrivateKey(
421                    ml_kem::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
422                ))
423            },
424            SerializableCryptoKeyHandle::MlKem1024PrivateKey(private_key) => {
425                Ok(Handle::MlKem1024PrivateKey(
426                    ml_kem::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
427                ))
428            },
429            SerializableCryptoKeyHandle::MlKem512PublicKey(public_key) => {
430                Ok(Handle::MlKem512PublicKey(
431                    ml_kem::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
432                ))
433            },
434            SerializableCryptoKeyHandle::MlKem768PublicKey(public_key) => {
435                Ok(Handle::MlKem768PublicKey(
436                    ml_kem::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
437                ))
438            },
439            SerializableCryptoKeyHandle::MlKem1024PublicKey(public_key) => {
440                Ok(Handle::MlKem1024PublicKey(
441                    ml_kem::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
442                ))
443            },
444            SerializableCryptoKeyHandle::MlDsa44PrivateKey(private_key) => {
445                Ok(Handle::MlDsa44PrivateKey(
446                    ml_dsa::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
447                ))
448            },
449            SerializableCryptoKeyHandle::MlDsa65PrivateKey(private_key) => {
450                Ok(Handle::MlDsa65PrivateKey(
451                    ml_dsa::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
452                ))
453            },
454            SerializableCryptoKeyHandle::MlDsa87PrivateKey(private_key) => {
455                Ok(Handle::MlDsa87PrivateKey(
456                    ml_dsa::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
457                ))
458            },
459            SerializableCryptoKeyHandle::MlDsa44PublicKey(public_key) => {
460                Ok(Handle::MlDsa44PublicKey(
461                    ml_dsa::KeyInit::new_from_slice(public_key).map_err(|_| ())?,
462                ))
463            },
464            SerializableCryptoKeyHandle::MlDsa65PublicKey(public_key) => {
465                Ok(Handle::MlDsa65PublicKey(
466                    ml_dsa::KeyInit::new_from_slice(public_key).map_err(|_| ())?,
467                ))
468            },
469            SerializableCryptoKeyHandle::MlDsa87PublicKey(public_key) => {
470                Ok(Handle::MlDsa87PublicKey(
471                    ml_dsa::KeyInit::new_from_slice(public_key).map_err(|_| ())?,
472                ))
473            },
474            SerializableCryptoKeyHandle::ChaCha20Poly1305Key(key) => Ok(
475                Handle::ChaCha20Poly1305Key(chacha20poly1305::Key::try_from(key).map_err(|_| ())?),
476            ),
477            SerializableCryptoKeyHandle::KmacKey(key) => Ok(Handle::KmacKey(key.clone().into())),
478            SerializableCryptoKeyHandle::Argon2Password(password) => {
479                Ok(Handle::Argon2Password(password.clone().into()))
480            },
481        }
482    }
483}
484
485/// To serialize the key in the `Handle`, we convert the key into byte sequences. For most
486/// cryptographic algorithms, this conversion is straightforward since the key can natually be
487/// expressed as a byte sequence. However, some cryptographic algorithms require preprocessing
488/// before their key can be represented in byte sequences. For example, an RSA private key needs to
489/// be first converted into DER-encoded PKCS#8 format before it can be expressed as a byte sequence.
490impl TryFrom<&Handle> for SerializableCryptoKeyHandle {
491    type Error = ();
492
493    fn try_from(value: &Handle) -> Result<Self, Self::Error> {
494        match value {
495            Handle::RsaPrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::RsaPrivateKey(
496                rsa::pkcs8::EncodePrivateKey::to_pkcs8_der(private_key)
497                    .map_err(|_| ())?
498                    .as_bytes()
499                    .to_vec(),
500            )),
501            Handle::RsaPublicKey(public_key) => Ok(SerializableCryptoKeyHandle::RsaPublicKey(
502                rsa::pkcs8::spki::EncodePublicKey::to_public_key_der(public_key)
503                    .map_err(|_| ())?
504                    .into_vec(),
505            )),
506            Handle::P256PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P256PrivateKey(
507                private_key.to_bytes().as_slice().to_vec(),
508            )),
509            Handle::P384PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P384PrivateKey(
510                private_key.to_bytes().as_slice().to_vec(),
511            )),
512            Handle::P521PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P521PrivateKey(
513                private_key.to_bytes().as_slice().to_vec(),
514            )),
515            Handle::P256PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P256PublicKey(
516                public_key.to_sec1_bytes().to_vec(),
517            )),
518            Handle::P384PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P384PublicKey(
519                public_key.to_sec1_bytes().to_vec(),
520            )),
521            Handle::P521PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P521PublicKey(
522                public_key.to_sec1_bytes().to_vec(),
523            )),
524            Handle::Ed25519PrivateKey(private_key) => Ok(
525                SerializableCryptoKeyHandle::Ed25519PrivateKey(private_key.to_bytes()),
526            ),
527            Handle::Ed25519PublicKey(public_key) => Ok(
528                SerializableCryptoKeyHandle::Ed25519PublicKey(public_key.to_bytes()),
529            ),
530            Handle::X25519PrivateKey(private_key) => Ok(
531                SerializableCryptoKeyHandle::X25519PrivateKey(private_key.to_bytes()),
532            ),
533            Handle::X25519PublicKey(public_key) => Ok(
534                SerializableCryptoKeyHandle::X25519PublicKey(public_key.to_bytes()),
535            ),
536            Handle::Ed448PrivateKey(private_key) => Ok(
537                SerializableCryptoKeyHandle::Ed448PrivateKey(private_key.as_bytes().to_vec()),
538            ),
539            Handle::Ed448PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::Ed448PublicKey(
540                public_key.as_bytes().to_vec(),
541            )),
542            Handle::X448PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::X448PrivateKey(
543                private_key.as_bytes().to_vec(),
544            )),
545            Handle::X448PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::X448PublicKey(
546                public_key.as_bytes().to_vec(),
547            )),
548            Handle::Aes128Key(key) => Ok(SerializableCryptoKeyHandle::Aes128Key(key.to_vec())),
549            Handle::Aes192Key(key) => Ok(SerializableCryptoKeyHandle::Aes192Key(key.to_vec())),
550            Handle::Aes256Key(key) => Ok(SerializableCryptoKeyHandle::Aes256Key(key.to_vec())),
551            Handle::Hmac(bytes) => Ok(SerializableCryptoKeyHandle::Hmac(bytes.to_vec())),
552            Handle::HkdfSecret(bytes) => {
553                Ok(SerializableCryptoKeyHandle::HkdfSecret(bytes.to_vec()))
554            },
555            Handle::Pbkdf2(bytes) => Ok(SerializableCryptoKeyHandle::Pbkdf2(bytes.to_vec())),
556            Handle::MlKem512PrivateKey(private_key) => {
557                Ok(SerializableCryptoKeyHandle::MlKem512PrivateKey(
558                    private_key
559                        .to_seed()
560                        .expect("This decapsulation key should contain seed value")
561                        .as_slice()
562                        .to_vec(),
563                ))
564            },
565            Handle::MlKem768PrivateKey(private_key) => {
566                Ok(SerializableCryptoKeyHandle::MlKem768PrivateKey(
567                    private_key
568                        .to_seed()
569                        .expect("This decapsulation key should contain seed value")
570                        .as_slice()
571                        .to_vec(),
572                ))
573            },
574            Handle::MlKem1024PrivateKey(private_key) => {
575                Ok(SerializableCryptoKeyHandle::MlKem1024PrivateKey(
576                    private_key
577                        .to_seed()
578                        .expect("This decapsulation key should contain seed value")
579                        .as_slice()
580                        .to_vec(),
581                ))
582            },
583            Handle::MlKem512PublicKey(public_key) => {
584                Ok(SerializableCryptoKeyHandle::MlKem512PublicKey(
585                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
586                ))
587            },
588            Handle::MlKem768PublicKey(public_key) => {
589                Ok(SerializableCryptoKeyHandle::MlKem768PublicKey(
590                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
591                ))
592            },
593            Handle::MlKem1024PublicKey(public_key) => {
594                Ok(SerializableCryptoKeyHandle::MlKem1024PublicKey(
595                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
596                ))
597            },
598            Handle::MlDsa44PrivateKey(private_key) => {
599                Ok(SerializableCryptoKeyHandle::MlDsa44PrivateKey(
600                    private_key.as_seed().as_slice().to_vec(),
601                ))
602            },
603            Handle::MlDsa65PrivateKey(private_key) => {
604                Ok(SerializableCryptoKeyHandle::MlDsa65PrivateKey(
605                    private_key.as_seed().as_slice().to_vec(),
606                ))
607            },
608            Handle::MlDsa87PrivateKey(private_key) => {
609                Ok(SerializableCryptoKeyHandle::MlDsa87PrivateKey(
610                    private_key.as_seed().as_slice().to_vec(),
611                ))
612            },
613            Handle::MlDsa44PublicKey(public_key) => {
614                Ok(SerializableCryptoKeyHandle::MlDsa44PublicKey(
615                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
616                ))
617            },
618            Handle::MlDsa65PublicKey(public_key) => {
619                Ok(SerializableCryptoKeyHandle::MlDsa65PublicKey(
620                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
621                ))
622            },
623            Handle::MlDsa87PublicKey(public_key) => {
624                Ok(SerializableCryptoKeyHandle::MlDsa87PublicKey(
625                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
626                ))
627            },
628            Handle::ChaCha20Poly1305Key(key) => Ok(
629                SerializableCryptoKeyHandle::ChaCha20Poly1305Key(key.as_slice().to_vec()),
630            ),
631            Handle::KmacKey(key) => Ok(SerializableCryptoKeyHandle::KmacKey(key.to_vec())),
632            Handle::Argon2Password(password) => Ok(SerializableCryptoKeyHandle::Argon2Password(
633                password.to_vec(),
634            )),
635        }
636    }
637}
638
639/// The trait providing helper functions for [`Vec<KeyUsage>`]
640pub(crate) trait KeyUsageVecHelper {
641    /// <https://w3c.github.io/webcrypto/#concept-usage-intersection>
642    fn usage_intersection(&self, other: &[KeyUsage]) -> Vec<KeyUsage>;
643
644    /// <https://w3c.github.io/webcrypto/#concept-normalized-usages>
645    fn normalized_value(&self) -> Vec<KeyUsage>;
646}
647
648impl KeyUsageVecHelper for Vec<KeyUsage> {
649    fn usage_intersection(&self, other: &[KeyUsage]) -> Vec<KeyUsage> {
650        // When this specification says to calculate the usage intersection of two sequences, a and
651        // b the result shall be a sequence containing each recognized key usage value that appears
652        // in both a and b, in the order listed in the list of recognized key usage values, where a
653        // value is said to appear in a sequence if an element of the sequence exists that is a
654        // case-sensitive string match for that value.
655        let mut intersection = self
656            .iter()
657            .filter(|usage| other.contains(usage))
658            .cloned()
659            .collect::<Vec<KeyUsage>>();
660        intersection.sort();
661        intersection.dedup();
662
663        intersection
664    }
665
666    fn normalized_value(&self) -> Vec<KeyUsage> {
667        // When this specification says to calculate the normalized value of a usages list, usages
668        // the result shall be the usage intersection of usages and a sequence containing all
669        // recognized key usage values.
670        self.usage_intersection(KeyUsage::VARIANTS)
671    }
672}