Skip to main content

rs_matter/
crypto.rs

1/*
2 *
3 *    Copyright (c) 2022-2026 Project CHIP Authors
4 *
5 *    Licensed under the Apache License, Version 2.0 (the "License");
6 *    you may not use this file except in compliance with the License.
7 *    You may obtain a copy of the License at
8 *
9 *        http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *    Unless required by applicable law or agreed to in writing, software
12 *    distributed under the License is distributed on an "AS IS" BASIS,
13 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *    See the License for the specific language governing permissions and
15 *    limitations under the License.
16 */
17
18//! Cryptographic abstractions and backend.
19
20use crate::error::Error;
21
22pub use rand_core::{CryptoRng, CryptoRngCore, RngCore};
23
24pub use canon::*;
25pub use rand::*;
26
27pub mod backend;
28mod canon;
29mod rand;
30
31/// Trait representing a cryptographic backend.
32///
33/// The backend should provide all the cryptographic primitives required by the Matter spec.
34///
35/// The trait is designed in a way where it allows customizing a concrete implementation by
36/// swapping out its out of the box algorithms with custom (potentially HW-accelerated) ones,
37/// by decorating the original implementation and replacing only the required types and methods.
38pub trait Crypto {
39    type Rand<'a>: CryptoRngCore + Copy
40    where
41        Self: 'a;
42
43    type WeakRand<'a>: RngCore + Copy
44    where
45        Self: 'a;
46
47    /// Hasher type returned by `Crypto::hash`.
48    ///
49    /// As per the Matter spec, the hasher should be SHA-256.
50    type Hash<'a>: Digest<HASH_LEN>
51    where
52        Self: 'a;
53
54    /// SHA-1 hasher type returned by `Crypto::hash1`.
55    type Hash1<'a>: Digest<SHA1_HASH_LEN>
56    where
57        Self: 'a;
58
59    /// HMAC hasher type returned by `Crypto::hmac`.
60    ///
61    /// As per the Matter spec, the HMAC hasher should be HMAC-SHA-256.
62    type Hmac<'a>: Digest<HASH_LEN>
63    where
64        Self: 'a;
65
66    /// KDF type returned by `Crypto::kdf`.
67    ///
68    /// As per the Matter spec, the KDF should be HKDF-SHA256.
69    type Kdf<'a>: Kdf
70    where
71        Self: 'a;
72
73    /// PBKDF type returned by `Crypto::pbkdf`.
74    ///
75    /// As per the Matter spec, the PBKDF should be PBKDF2-HMAC-SHA256.
76    type PbKdf<'a>: PbKdf
77    where
78        Self: 'a;
79
80    /// AEAD type returned by `Crypto::aead`.
81    ///
82    /// As per the Matter spec, the AEAD algorithm used is AES-CCM with 128-bit keys, 13-byte nonces
83    /// and 16-byte tags.
84    type Aead<'a>: Aead<AEAD_CANON_KEY_LEN, AEAD_NONCE_LEN>
85    where
86        Self: 'a;
87
88    /// Public key type returned by `Crypto::pub_key`.
89    ///
90    /// As per the Matter spec, the used Public Key Cryptograqphy should be
91    /// Elliptic-Curve based, and specifically secp256r1 (NIST P-256).
92    ///
93    /// In other words, the public key is a point on the secp256r1 curve.
94    ///
95    /// With that said, the implementation is free to choose a different internal
96    /// representation of the public key type as compared to the `EcPoint` type.
97    /// The only requirement is that both should be possible to convert from/to
98    /// the same canonical representation.
99    type PublicKey<'a>: PublicKey<'a, PKC_CANON_PUBLIC_KEY_LEN, PKC_SIGNATURE_LEN>
100    where
101        Self: 'a;
102
103    /// Signing secret key type returned by `Crypto::singleton_singing_secret_key`.
104    ///
105    /// As per the Matter spec, the used Public Key Cryptograqphy should be
106    /// Elliptic-Curve based, and specifically secp256r1 (NIST P-256).
107    ///
108    /// In other words, the signing secret key is a scalar on the secp256r1 curve.
109    ///
110    /// With that said, the implementation is free to choose a different internal
111    /// representation of the signing secret key type as compared to the `EcScalar` type.
112    /// The only requirement is that both should be possible to convert from/to
113    /// the same canonical representation.
114    type SigningSecretKey<'a>: SigningSecretKey<
115        'a,
116        PKC_CANON_PUBLIC_KEY_LEN,
117        PKC_SIGNATURE_LEN,
118        PublicKey<'a> = Self::PublicKey<'a>,
119    >
120    where
121        Self: 'a;
122
123    /// Secret key type returned by `Crypto::secret_key` and `Crypto::generate_secret_key`.
124    ///
125    /// As per the Matter spec, the used Public Key Cryptograqphy should be
126    /// Elliptic-Curve based, and specifically secp256r1 (NIST P-256).
127    ///
128    /// In other words, the secret key is a scalar on the secp256r1 curve.
129    ///
130    /// With that said, the implementation is free to choose a different internal
131    /// representation of the secret key type as compared to the `EcScalar` type.
132    /// The only requirement is that both should be possible to convert from/to
133    /// the same canonical representation.
134    type SecretKey<'a>: SecretKey<
135        'a,
136        PKC_CANON_SECRET_KEY_LEN,
137        PKC_CANON_PUBLIC_KEY_LEN,
138        PKC_SIGNATURE_LEN,
139        PKC_SHARED_SECRET_LEN,
140        PublicKey<'a> = Self::PublicKey<'a>,
141    >
142    where
143        Self: 'a;
144
145    /// EC scalar type returned by `Crypto::ec_scalar` and `Crypto::generate_ec_scalar`.
146    ///
147    /// As per the Matter spec, the curve used is secp256r1 (NIST P-256).
148    ///
149    /// In other words, the EC scalar is a scalar on the secp256r1 curve.
150    type EcScalar<'a>: EcScalar<'a, EC_CANON_SCALAR_LEN>
151    where
152        Self: 'a;
153
154    /// EC point type returned by `Crypto::ec_point` and `Crypto::ec_generator_point`.
155    ///
156    /// As per the Matter spec, the curve used is secp256r1 (NIST P-256).
157    ///
158    /// In other words, the EC point is a point on the secp256r1 curve.
159    type EcPoint<'a>: EcPoint<
160        'a,
161        EC_CANON_POINT_LEN,
162        EC_CANON_SCALAR_LEN,
163        Scalar<'a> = Self::EcScalar<'a>,
164    >
165    where
166        Self: 'a;
167
168    /// Create a new, cryptographically secure, random number generator instance.
169    fn rand(&self) -> Result<Self::Rand<'_>, Error>;
170
171    /// Create a new NON-cryptographically secure (but potentially faster), random number generator instance.
172    fn weak_rand(&self) -> Result<Self::WeakRand<'_>, Error>;
173
174    /// Create a new hasher instance.
175    fn hash(&self) -> Result<Self::Hash<'_>, Error>;
176
177    /// Create a new SHA-1 hasher instance.
178    fn hash1(&self) -> Result<Self::Hash1<'_>, Error>;
179
180    /// Create a new HMAC hasher instance with the given key.
181    fn hmac<const KEY_LEN: usize>(
182        &self,
183        key: CryptoSensitiveRef<'_, KEY_LEN>,
184    ) -> Result<Self::Hmac<'_>, Error>;
185
186    /// Create a new KDF instance.
187    fn kdf(&self) -> Result<Self::Kdf<'_>, Error>;
188
189    /// Create a new PBKDF instance.
190    fn pbkdf(&self) -> Result<Self::PbKdf<'_>, Error>;
191
192    /// Create a new AEAD instance.
193    fn aead(&self) -> Result<Self::Aead<'_>, Error>;
194
195    /// Create a public key instance from its canonical representation.
196    fn pub_key(&self, key: CanonPkcPublicKeyRef<'_>) -> Result<Self::PublicKey<'_>, Error>;
197
198    /// Create a secret key instance from its canonical representation.
199    fn secret_key(&self, key: CanonPkcSecretKeyRef<'_>) -> Result<Self::SecretKey<'_>, Error>;
200
201    /// Generate a new secret key instance.
202    fn generate_secret_key(&self) -> Result<Self::SecretKey<'_>, Error>;
203
204    /// Get the singleton signing secret key instance.
205    ///
206    /// This is used for device attestation.
207    fn singleton_singing_secret_key(&self) -> Result<Self::SigningSecretKey<'_>, Error>;
208
209    /// Create an EC scalar instance from its canonical representation.
210    fn ec_scalar(&self, scalar: CanonEcScalarRef<'_>) -> Result<Self::EcScalar<'_>, Error>;
211
212    /// Create an EC scalar instance from a 320-bit unsigned integer modulo the EC prime modulus.
213    fn ec_scalar_mod_p(&self, uint: CanonUint320Ref<'_>) -> Result<Self::EcScalar<'_>, Error>;
214
215    /// Generate a new random EC scalar instance.
216    fn generate_ec_scalar(&self) -> Result<Self::EcScalar<'_>, Error>;
217
218    /// Create an EC point instance from its canonical representation.
219    fn ec_point(&self, point: CanonEcPointRef<'_>) -> Result<Self::EcPoint<'_>, Error>;
220
221    /// Get the EC Generator point.
222    fn ec_generator_point(&self) -> Result<Self::EcPoint<'_>, Error>;
223}
224
225impl<T> Crypto for &T
226where
227    T: Crypto,
228{
229    type Rand<'a>
230        = T::Rand<'a>
231    where
232        Self: 'a;
233
234    type WeakRand<'a>
235        = T::WeakRand<'a>
236    where
237        Self: 'a;
238
239    type Hash<'a>
240        = T::Hash<'a>
241    where
242        Self: 'a;
243
244    type Hash1<'a>
245        = T::Hash1<'a>
246    where
247        Self: 'a;
248
249    type Hmac<'a>
250        = T::Hmac<'a>
251    where
252        Self: 'a;
253
254    type Kdf<'a>
255        = T::Kdf<'a>
256    where
257        Self: 'a;
258
259    type PbKdf<'a>
260        = T::PbKdf<'a>
261    where
262        Self: 'a;
263
264    type Aead<'a>
265        = T::Aead<'a>
266    where
267        Self: 'a;
268
269    type PublicKey<'a>
270        = T::PublicKey<'a>
271    where
272        Self: 'a;
273
274    type SecretKey<'a>
275        = T::SecretKey<'a>
276    where
277        Self: 'a;
278
279    type SigningSecretKey<'a>
280        = T::SigningSecretKey<'a>
281    where
282        Self: 'a;
283
284    type EcScalar<'a>
285        = T::EcScalar<'a>
286    where
287        Self: 'a;
288
289    type EcPoint<'a>
290        = T::EcPoint<'a>
291    where
292        Self: 'a;
293
294    fn rand(&self) -> Result<Self::Rand<'_>, Error> {
295        (*self).rand()
296    }
297
298    fn weak_rand(&self) -> Result<Self::WeakRand<'_>, Error> {
299        (*self).weak_rand()
300    }
301
302    fn hash(&self) -> Result<Self::Hash<'_>, Error> {
303        (*self).hash()
304    }
305
306    fn hash1(&self) -> Result<Self::Hash1<'_>, Error> {
307        (*self).hash1()
308    }
309
310    fn hmac<const KEY_LEN: usize>(
311        &self,
312        key: CryptoSensitiveRef<'_, KEY_LEN>,
313    ) -> Result<Self::Hmac<'_>, Error> {
314        (*self).hmac(key)
315    }
316
317    fn kdf(&self) -> Result<Self::Kdf<'_>, Error> {
318        (*self).kdf()
319    }
320
321    fn pbkdf(&self) -> Result<Self::PbKdf<'_>, Error> {
322        (*self).pbkdf()
323    }
324
325    fn aead(&self) -> Result<Self::Aead<'_>, Error> {
326        (*self).aead()
327    }
328
329    fn pub_key(&self, key: CanonPkcPublicKeyRef<'_>) -> Result<Self::PublicKey<'_>, Error> {
330        (*self).pub_key(key)
331    }
332
333    fn generate_secret_key(&self) -> Result<Self::SecretKey<'_>, Error> {
334        (*self).generate_secret_key()
335    }
336
337    fn secret_key(&self, key: CanonPkcSecretKeyRef<'_>) -> Result<Self::SecretKey<'_>, Error> {
338        (*self).secret_key(key)
339    }
340
341    fn singleton_singing_secret_key(&self) -> Result<Self::SigningSecretKey<'_>, Error> {
342        (*self).singleton_singing_secret_key()
343    }
344
345    fn ec_scalar(&self, scalar: CanonEcScalarRef<'_>) -> Result<Self::EcScalar<'_>, Error> {
346        (*self).ec_scalar(scalar)
347    }
348
349    fn ec_scalar_mod_p(&self, uint: CanonUint320Ref<'_>) -> Result<Self::EcScalar<'_>, Error> {
350        (*self).ec_scalar_mod_p(uint)
351    }
352
353    fn generate_ec_scalar(&self) -> Result<Self::EcScalar<'_>, Error> {
354        (*self).generate_ec_scalar()
355    }
356
357    fn ec_point(&self, point: CanonEcPointRef<'_>) -> Result<Self::EcPoint<'_>, Error> {
358        (*self).ec_point(point)
359    }
360
361    fn ec_generator_point(&self) -> Result<Self::EcPoint<'_>, Error> {
362        (*self).ec_generator_point()
363    }
364}
365
366/// Trait representing a generic digest (hash) algorithm.
367///
368/// The digest algorithm should support incremental updates and finalization.
369///
370/// Used for both hashing and HMAC.
371pub trait Digest<const HASH_LEN: usize> {
372    /// Update the digest with the given data.
373    fn update(&mut self, data: &[u8]) -> Result<(), Error>;
374
375    /// Finish the digest and write the result into the given buffer,
376    /// without consuming the hasher instance, allowing for further updates and finalizations.
377    fn finish_current(&mut self, hash: &mut CryptoSensitive<HASH_LEN>) -> Result<(), Error>;
378
379    /// Finish the digest and write the result into the given buffer.
380    fn finish(self, hash: &mut CryptoSensitive<HASH_LEN>) -> Result<(), Error>;
381}
382
383/// Trait representing a Key Derivation Function (KDF).
384pub trait Kdf {
385    /// Expand the given input keying material (IKM) with the given salt and info
386    /// to produce the output keying material (OKM) written into `key`.
387    fn expand<const IKM_LEN: usize, const KEY_LEN: usize>(
388        self,
389        salt: &[u8],
390        ikm: CryptoSensitiveRef<'_, IKM_LEN>,
391        info: &[u8],
392        key: &mut CryptoSensitive<KEY_LEN>,
393    ) -> Result<(), Error>;
394}
395
396/// Trait representing a Password-Based Key Derivation Function (PBKDF).
397pub trait PbKdf {
398    /// Derive a key from the given password, salt and iteration count,
399    /// writing the result into `key`.
400    fn derive<const PASS_LEN: usize, const KEY_LEN: usize>(
401        self,
402        pass: CryptoSensitiveRef<'_, PASS_LEN>,
403        iter: usize,
404        salt: &[u8],
405        key: &mut CryptoSensitive<KEY_LEN>,
406    ) -> Result<(), Error>;
407}
408
409/// Trait representing an Authenticated Encryption with Associated Data (AEAD) algorithm.
410pub trait Aead<const KEY_LEN: usize, const NONCE_LEN: usize> {
411    /// Encrypt the given data in place, using the given key, nonce and additional authenticated data (AAD).
412    ///
413    /// # Arguments
414    /// - `key`: The AEAD key.
415    /// - `nonce`: The AEAD nonce.
416    /// - `aad`: The additional authenticated data.
417    /// - `data`: The data to encrypt, which will be modified in place to contain the ciphertext and tag.
418    /// - `data_len`: The length of the plaintext data in `data`.
419    ///
420    /// # Returns
421    /// - On success, returns a slice containing the ciphertext and tag.
422    /// - On failure, returns an `Error`.
423    fn encrypt_in_place<'a>(
424        &mut self,
425        key: CryptoSensitiveRef<'_, KEY_LEN>,
426        nonce: CryptoSensitiveRef<'_, NONCE_LEN>,
427        aad: &[u8],
428        data: &'a mut [u8],
429        data_len: usize,
430    ) -> Result<&'a [u8], Error>;
431
432    /// Decrypt the given data in place, using the given key, nonce and additional authenticated data (AAD).
433    ///
434    /// # Arguments
435    /// - `key`: The AEAD key.
436    /// - `nonce`: The AEAD nonce.
437    /// - `aad`: The additional authenticated data.
438    /// - `data`: The data to decrypt, which will be modified in place to contain the plaintext.
439    ///
440    /// # Returns
441    /// - On success, returns a slice containing the plaintext.
442    /// - On failure, returns an `Error`.
443    fn decrypt_in_place<'a>(
444        &mut self,
445        key: CryptoSensitiveRef<'_, KEY_LEN>,
446        nonce: CryptoSensitiveRef<'_, NONCE_LEN>,
447        aad: &[u8],
448        data: &'a mut [u8],
449    ) -> Result<&'a [u8], Error>;
450}
451
452impl<const KEY_LEN: usize, const NONCE_LEN: usize, T> Aead<KEY_LEN, NONCE_LEN> for &mut T
453where
454    T: Aead<KEY_LEN, NONCE_LEN>,
455{
456    fn encrypt_in_place<'a>(
457        &mut self,
458        key: CryptoSensitiveRef<'_, KEY_LEN>,
459        nonce: CryptoSensitiveRef<'_, NONCE_LEN>,
460        aad: &[u8],
461        data: &'a mut [u8],
462        data_len: usize,
463    ) -> Result<&'a [u8], Error> {
464        (*self).encrypt_in_place(key, nonce, aad, data, data_len)
465    }
466
467    fn decrypt_in_place<'a>(
468        &mut self,
469        key: CryptoSensitiveRef<'_, KEY_LEN>,
470        nonce: CryptoSensitiveRef<'_, NONCE_LEN>,
471        aad: &[u8],
472        data: &'a mut [u8],
473    ) -> Result<&'a [u8], Error> {
474        (*self).decrypt_in_place(key, nonce, aad, data)
475    }
476}
477
478/// Trait representing a signing secret key.
479///
480/// A signing secret key is a weaker variant of a secret key. Namely:
481/// - It can only be used for signing operations.
482/// - It cannot be used for deriving shared secrets.
483/// - It cannot be written to its canonical representation (exported).
484///
485/// Suitable in use-cases requiring static yet strongly protected secret key (i.e. device attestation),
486/// where the secret key of the device might be offloaded to a special storage and crypto-engine
487/// and thus might not be directly accessible.
488pub trait SigningSecretKey<'a, const PUB_KEY_LEN: usize, const SIGNATURE_LEN: usize> {
489    /// Public key type associated with this secret key.
490    type PublicKey<'s>: PublicKey<'s, PUB_KEY_LEN, SIGNATURE_LEN>
491    where
492        Self: 's;
493
494    /// Get the public key corresponding to this secret key.
495    fn pub_key(&self) -> Result<Self::PublicKey<'a>, Error>;
496
497    /// Generate a Certificate Signing Request (CSR) using this secret key,
498    ///
499    /// # Arguments
500    /// - `buf`: Buffer to write the CSR into.
501    ///
502    /// # Returns
503    /// - On success, returns a slice containing the CSR, in DER format.
504    /// - On failure, returns an `Error`.
505    fn csr<'s>(&self, buf: &'s mut [u8]) -> Result<&'s [u8], Error>;
506
507    /// Sign the given data using this secret key,
508    ///
509    /// # Arguments
510    /// - `data`: Data to sign.
511    /// - `signature`: Buffer to write the signature into.
512    fn sign(
513        &self,
514        data: &[u8],
515        signature: &mut CryptoSensitive<SIGNATURE_LEN>,
516    ) -> Result<(), Error>;
517}
518
519/// Trait representing a secret key.
520///
521/// A secret key can be used for signing operations, deriving shared secrets,
522/// and can be written to its canonical representation (exported).
523pub trait SecretKey<
524    'a,
525    const KEY_LEN: usize,
526    const PUB_KEY_LEN: usize,
527    const SIGNATURE_LEN: usize,
528    const SHARED_SECRET_LEN: usize,
529>: SigningSecretKey<'a, PUB_KEY_LEN, SIGNATURE_LEN>
530{
531    /// Derive a shared secret with the given peer public key,
532    ///
533    /// # Arguments
534    /// - `peer_pub_key`: Peer public key to derive the shared secret with.
535    /// - `shared_secret`: Buffer to write the shared secret into.
536    fn derive_shared_secret(
537        &self,
538        peer_pub_key: &Self::PublicKey<'a>,
539        shared_secret: &mut CryptoSensitive<SHARED_SECRET_LEN>,
540    ) -> Result<(), Error>;
541
542    /// Write the canonical representation of this secret key into the given buffer.
543    fn write_canon(&self, key: &mut CryptoSensitive<KEY_LEN>) -> Result<(), Error>;
544}
545
546/// Trait representing a public key.
547pub trait PublicKey<'a, const KEY_LEN: usize, const SIGNATURE_LEN: usize> {
548    /// Verify the given signature over the given data using this public key.
549    ///
550    /// # Arguments
551    /// - `data`: Data to verify the signature over.
552    /// - `signature`: Signature to verify.
553    ///
554    /// # Returns
555    /// - `true` if the signature is valid.
556    fn verify(
557        &self,
558        data: &[u8],
559        signature: CryptoSensitiveRef<SIGNATURE_LEN>,
560    ) -> Result<bool, Error>;
561
562    /// Write the canonical representation of this public key into the given buffer.
563    fn write_canon(&self, key: &mut CryptoSensitive<KEY_LEN>) -> Result<(), Error>;
564}
565
566impl<'a, const KEY_LEN: usize, const SIGNATURE_LEN: usize, T> PublicKey<'a, KEY_LEN, SIGNATURE_LEN>
567    for &T
568where
569    T: PublicKey<'a, KEY_LEN, SIGNATURE_LEN>,
570{
571    fn verify(
572        &self,
573        data: &[u8],
574        signature: CryptoSensitiveRef<SIGNATURE_LEN>,
575    ) -> Result<bool, Error> {
576        (*self).verify(data, signature)
577    }
578
579    fn write_canon(&self, key: &mut CryptoSensitive<KEY_LEN>) -> Result<(), Error> {
580        (*self).write_canon(key)
581    }
582}
583
584/// Trait representing an Elliptic Curve (EC) scalar value.
585pub trait EcScalar<'a, const LEN: usize> {
586    /// Multiply this scalar by another scalar.
587    ///
588    /// # Arguments
589    /// - `other`: The other scalar to multiply with.
590    ///
591    /// # Returns
592    /// - The result of the multiplication.
593    fn mul(&self, other: &Self) -> Result<Self, Error>
594    where
595        Self: Sized;
596
597    /// Write the canonical representation of this scalar into the given buffer.
598    fn write_canon(&self, scalar: &mut CryptoSensitive<LEN>) -> Result<(), Error>;
599}
600
601/// Trait representing an Elliptic Curve (EC) point.
602pub trait EcPoint<'a, const LEN: usize, const SCALAR_LEN: usize> {
603    /// Scalar type associated with this EC point.
604    type Scalar<'s>: EcScalar<'s, SCALAR_LEN>
605    where
606        Self: 'a + 's;
607
608    /// Return `true` if this point is a valid public key on the curve, i.e. it
609    /// is on the curve, its coordinates are in range, and it is **not** the
610    /// identity (point at infinity) — equivalently, per RFC 9383 §4, that the
611    /// cofactor multiple `h*P` is not the identity element.
612    ///
613    /// SPAKE2+ requires this validation on the peer's public share (`X` on the
614    /// verifier side, `Y` on the prover side); an unchecked identity/invalid
615    /// point lets a peer force the shared secret and break the protocol's
616    /// guarantees.
617    fn is_valid_pubkey(&self) -> Result<bool, Error>;
618
619    /// Negate this EC point.
620    fn neg(&self) -> Result<Self, Error>
621    where
622        Self: Sized;
623
624    /// Multiply this EC point by the given scalar.
625    fn mul(&self, scalar: &Self::Scalar<'a>) -> Result<Self, Error>
626    where
627        Self: Sized;
628
629    /// Perform an addition-multiplication operation,
630    /// i.e. compute P1 * s1 + P2 * s2, where P1 is `self`.
631    ///
632    /// # Arguments
633    /// - `s1`: Scalar to multiply `self` with.
634    /// - `p2`: Second EC point to multiply with `s2`.
635    /// - `s2`: Scalar to multiply `p2` with.
636    ///
637    /// # Returns
638    /// - The result of the addition-multiplication.
639    fn add_mul(
640        &self,
641        s1: &Self::Scalar<'a>,
642        p2: &Self,
643        s2: &Self::Scalar<'a>,
644    ) -> Result<Self, Error>
645    where
646        Self: Sized;
647
648    /// Write the canonical representation of this EC point into the given buffer.
649    fn write_canon(&self, point: &mut CryptoSensitive<LEN>) -> Result<(), Error>;
650}
651
652#[allow(unused)]
653pub fn default_crypto<'s, R>(
654    rand: R,
655    singleton_secret_key: CanonPkcSecretKeyRef<'s>,
656) -> impl Crypto + 's
657where
658    R: CryptoRngCore + 's,
659{
660    #[cfg(feature = "openssl")]
661    let crypto = backend::openssl::OpenSslCrypto::new(singleton_secret_key);
662
663    #[cfg(all(feature = "mbedtls", not(feature = "openssl")))]
664    let crypto = backend::mbedtls::MbedtlsCrypto::new(rand, singleton_secret_key);
665
666    #[cfg(all(
667        feature = "rustcrypto",
668        not(any(feature = "openssl", feature = "mbedtls"))
669    ))]
670    let crypto = backend::rustcrypto::RustCrypto::new(rand, singleton_secret_key);
671
672    #[cfg(not(any(feature = "openssl", feature = "mbedtls", feature = "rustcrypto")))]
673    let crypto = backend::dummy::DummyCrypto;
674
675    crypto
676}
677
678pub fn test_only_crypto() -> impl Crypto {
679    default_crypto(
680        WeakTestOnlyRand::new_default(),
681        crate::dm::devices::test::DAC_PRIVKEY,
682    )
683}
684
685#[cfg(test)]
686mod tests {
687    use crate::crypto::{
688        test_only_crypto, CanonPkcPublicKeyRef, CanonPkcSignatureRef, Crypto, PublicKey,
689    };
690
691    #[test]
692    fn test_verify_msg_success() {
693        let crypto = test_only_crypto();
694
695        let key = unwrap!(crypto.pub_key(PUB_KEY1));
696        assert_eq!(unwrap!(key.verify(MSG1_SUCCESS, SIGNATURE1)), true);
697    }
698
699    #[test]
700    fn test_verify_msg_fail() {
701        let crypto = test_only_crypto();
702
703        let key = unwrap!(crypto.pub_key(PUB_KEY1));
704        assert_eq!(unwrap!(key.verify(MSG1_FAIL, SIGNATURE1)), false);
705    }
706
707    const PUB_KEY1: CanonPkcPublicKeyRef = CanonPkcPublicKeyRef::new(&[
708        0x4, 0x56, 0x19, 0x77, 0x18, 0x3f, 0xd4, 0xff, 0x2b, 0x58, 0x3d, 0xe9, 0x79, 0x34, 0x66,
709        0xdf, 0xe9, 0x0, 0xfb, 0x6d, 0xa1, 0xef, 0xe0, 0xcc, 0xdc, 0x77, 0x30, 0xc0, 0x6f, 0xb6,
710        0x2d, 0xff, 0xbe, 0x54, 0xa0, 0x95, 0x75, 0xb, 0x8b, 0x7, 0xbc, 0x55, 0xdb, 0x9c, 0xb6,
711        0x55, 0x13, 0x8, 0xb8, 0xdf, 0x2, 0xe3, 0x40, 0x6b, 0xae, 0x34, 0xf5, 0xc, 0xba, 0xc9,
712        0xf2, 0xbf, 0xf1, 0xe7, 0x50,
713    ]);
714
715    const MSG1_SUCCESS: &[u8] = &[
716        0x30, 0x82, 0x1, 0xa1, 0xa0, 0x3, 0x2, 0x1, 0x2, 0x2, 0x1, 0x1, 0x30, 0xa, 0x6, 0x8, 0x2a,
717        0x86, 0x48, 0xce, 0x3d, 0x4, 0x3, 0x2, 0x30, 0x44, 0x31, 0x20, 0x30, 0x1e, 0x6, 0xa, 0x2b,
718        0x6, 0x1, 0x4, 0x1, 0x82, 0xa2, 0x7c, 0x1, 0x3, 0xc, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30,
719        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x20, 0x30, 0x1e,
720        0x6, 0xa, 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0xa2, 0x7c, 0x1, 0x5, 0xc, 0x10, 0x30, 0x30,
721        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30,
722        0x1e, 0x17, 0xd, 0x32, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
723        0x5a, 0x17, 0xd, 0x33, 0x30, 0x31, 0x32, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
724        0x5a, 0x30, 0x44, 0x31, 0x20, 0x30, 0x1e, 0x6, 0xa, 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0xa2,
725        0x7c, 0x1, 0x1, 0xc, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
726        0x42, 0x43, 0x35, 0x43, 0x30, 0x32, 0x31, 0x20, 0x30, 0x1e, 0x6, 0xa, 0x2b, 0x6, 0x1, 0x4,
727        0x1, 0x82, 0xa2, 0x7c, 0x1, 0x5, 0xc, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
728        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x59, 0x30, 0x13, 0x6, 0x7, 0x2a,
729        0x86, 0x48, 0xce, 0x3d, 0x2, 0x1, 0x6, 0x8, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x3, 0x1, 0x7,
730        0x3, 0x42, 0x0, 0x4, 0x6, 0x47, 0xf2, 0x86, 0x4d, 0x27, 0x25, 0xdc, 0x1, 0xa, 0x87, 0xde,
731        0x8d, 0xca, 0x88, 0x37, 0xcb, 0x3b, 0xd0, 0xea, 0x93, 0xa6, 0x24, 0x65, 0x8, 0x8f, 0xa1,
732        0x75, 0xc2, 0xd4, 0x41, 0xfa, 0xca, 0x96, 0x54, 0xa3, 0xd8, 0x10, 0x85, 0x73, 0xce, 0x15,
733        0xa5, 0x38, 0xc1, 0xe3, 0xb5, 0x6b, 0x61, 0x1, 0xd3, 0xc4, 0xb7, 0x6b, 0x61, 0x16, 0xc3,
734        0x77, 0x8d, 0xe9, 0xb5, 0x44, 0xac, 0x14, 0xa3, 0x81, 0x83, 0x30, 0x81, 0x80, 0x30, 0xc,
735        0x6, 0x3, 0x55, 0x1d, 0x13, 0x1, 0x1, 0xff, 0x4, 0x2, 0x30, 0x0, 0x30, 0xe, 0x6, 0x3, 0x55,
736        0x1d, 0xf, 0x1, 0x1, 0xff, 0x4, 0x4, 0x3, 0x2, 0x7, 0x80, 0x30, 0x20, 0x6, 0x3, 0x55, 0x1d,
737        0x25, 0x1, 0x1, 0xff, 0x4, 0x16, 0x30, 0x14, 0x6, 0x8, 0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x3,
738        0x2, 0x6, 0x8, 0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x3, 0x1, 0x30, 0x1d, 0x6, 0x3, 0x55, 0x1d,
739        0xe, 0x4, 0x16, 0x4, 0x14, 0xbd, 0xfd, 0x11, 0xac, 0x89, 0xb6, 0xe0, 0x90, 0x7a, 0xf6,
740        0x12, 0x61, 0x78, 0x4d, 0x3d, 0x79, 0x56, 0xeb, 0xc2, 0xdc, 0x30, 0x1f, 0x6, 0x3, 0x55,
741        0x1d, 0x23, 0x4, 0x18, 0x30, 0x16, 0x80, 0x14, 0xce, 0x60, 0xb4, 0x28, 0x96, 0x72, 0x27,
742        0x64, 0x81, 0xbc, 0x4f, 0x0, 0x78, 0xa3, 0x30, 0x48, 0xfe, 0x6e, 0x65, 0x86,
743    ];
744
745    const MSG1_FAIL: &[u8] = &[
746        0x30, 0x82, 0x1, 0xa1, 0xa0, 0x3, 0x2, 0x1, 0x2, 0x2, 0x1, 0x1, 0x30, 0xa, 0x6, 0x8, 0x2a,
747        0x86, 0x48, 0xce, 0x3d, 0x4, 0x3, 0x2, 0x30, 0x44, 0x31, 0x20, 0x30, 0x1e, 0x6, 0xa, 0x2b,
748        0x6, 0x1, 0x4, 0x1, 0x82, 0xa2, 0x7c, 0x1, 0x3, 0xc, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30,
749        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x20, 0x30, 0x1e,
750        0x6, 0xa, 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0xa2, 0x7c, 0x1, 0x5, 0xc, 0x10, 0x30, 0x30,
751        0x30, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30,
752        0x1e, 0x17, 0xd, 0x32, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
753        0x5a, 0x17, 0xd, 0x33, 0x30, 0x31, 0x32, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
754        0x5a, 0x30, 0x44, 0x31, 0x20, 0x30, 0x1e, 0x6, 0xa, 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0xa2,
755        0x7c, 0x1, 0x1, 0xc, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
756        0x42, 0x43, 0x35, 0x43, 0x30, 0x32, 0x31, 0x20, 0x30, 0x1e, 0x6, 0xa, 0x2b, 0x6, 0x1, 0x4,
757        0x1, 0x82, 0xa2, 0x7c, 0x1, 0x5, 0xc, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
758        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x59, 0x30, 0x13, 0x6, 0x7, 0x2a,
759        0x86, 0x48, 0xce, 0x3d, 0x2, 0x1, 0x6, 0x8, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x3, 0x1, 0x7,
760        0x3, 0x42, 0x0, 0x4, 0x6, 0x47, 0xf2, 0x86, 0x4d, 0x27, 0x25, 0xdc, 0x1, 0xa, 0x87, 0xde,
761        0x8d, 0xca, 0x88, 0x37, 0xcb, 0x3b, 0xd0, 0xea, 0x93, 0xa6, 0x24, 0x65, 0x8, 0x8f, 0xa1,
762        0x75, 0xc2, 0xd4, 0x41, 0xfa, 0xca, 0x96, 0x54, 0xa3, 0xd8, 0x10, 0x85, 0x73, 0xce, 0x15,
763        0xa5, 0x38, 0xc1, 0xe3, 0xb5, 0x6b, 0x61, 0x1, 0xd3, 0xc4, 0xb7, 0x6b, 0x61, 0x16, 0xc3,
764        0x77, 0x8d, 0xe9, 0xb5, 0x44, 0xac, 0x14, 0xa3, 0x81, 0x83, 0x30, 0x81, 0x80, 0x30, 0xc,
765        0x6, 0x3, 0x55, 0x1d, 0x13, 0x1, 0x1, 0xff, 0x4, 0x2, 0x30, 0x0, 0x30, 0xe, 0x6, 0x3, 0x55,
766        0x1d, 0xf, 0x1, 0x1, 0xff, 0x4, 0x4, 0x3, 0x2, 0x7, 0x80, 0x30, 0x20, 0x6, 0x3, 0x55, 0x1d,
767        0x25, 0x1, 0x1, 0xff, 0x4, 0x16, 0x30, 0x14, 0x6, 0x8, 0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x3,
768        0x2, 0x6, 0x8, 0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x3, 0x1, 0x30, 0x1d, 0x6, 0x3, 0x55, 0x1d,
769        0xe, 0x4, 0x16, 0x4, 0x14, 0xbd, 0xfd, 0x11, 0xac, 0x89, 0xb6, 0xe0, 0x90, 0x7a, 0xf6,
770        0x12, 0x61, 0x78, 0x4d, 0x3d, 0x79, 0x56, 0xeb, 0xc2, 0xdc, 0x30, 0x1f, 0x6, 0x3, 0x55,
771        0x1d, 0x23, 0x4, 0x18, 0x30, 0x16, 0x80, 0x14, 0xce, 0x60, 0xb4, 0x28, 0x96, 0x72, 0x27,
772        0x64, 0x81, 0xbc, 0x4f, 0x0, 0x78, 0xa3, 0x30, 0x48, 0xfe, 0x6e, 0x65, 0x86,
773    ];
774
775    const SIGNATURE1: CanonPkcSignatureRef = CanonPkcSignatureRef::new(&[
776        0x20, 0x16, 0xd0, 0x13, 0x1e, 0xd0, 0xb3, 0x9d, 0x44, 0x25, 0x16, 0xea, 0x9c, 0xf2, 0x72,
777        0x44, 0xd7, 0xb0, 0xf4, 0xae, 0x4a, 0xa4, 0x37, 0x32, 0xcd, 0x6a, 0x79, 0x7a, 0x4c, 0x48,
778        0x3, 0x6d, 0xef, 0xe6, 0x26, 0x82, 0x39, 0x28, 0x9, 0x22, 0xc8, 0x9a, 0xde, 0xd5, 0x13,
779        0x9f, 0xc5, 0x40, 0x25, 0x85, 0x2c, 0x69, 0xe0, 0xdb, 0x6a, 0x79, 0x5b, 0x21, 0x82, 0x13,
780        0xb0, 0x20, 0xb9, 0x69,
781    ]);
782}