1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #![no_std]
16 
17 //! Crate which provides impls for CryptoProvider backed by RustCrypto crates
18 
19 use core::{fmt::Debug, marker::PhantomData};
20 
21 pub use aes;
22 use cfg_if::cfg_if;
23 pub use hkdf;
24 pub use hmac;
25 use rand::{Rng, RngCore, SeedableRng};
26 use rand_core::CryptoRng;
27 use subtle::ConstantTimeEq;
28 
29 /// Contains the RustCrypto backed impls for AES-GCM-SIV operations
30 mod aead;
31 /// Contains the RustCrypto backed AES impl for CryptoProvider
32 pub mod aes_cp;
33 /// Contains the RustCrypto backed impl for ed25519 key generation, signing, and verification
34 mod ed25519;
35 /// Contains the RustCrypto backed hkdf impl for CryptoProvider
36 mod hkdf_cp;
37 /// Contains the RustCrypto backed hmac impl for CryptoProvider
38 mod hmac_cp;
39 /// Contains the RustCrypto backed P256 impl for CryptoProvider
40 mod p256;
41 /// Contains the RustCrypto backed SHA2 impl for CryptoProvider
42 mod sha2_cp;
43 /// Contains the RustCrypto backed X25519 impl for CryptoProvider
44 mod x25519;
45 
46 cfg_if! {
47     if #[cfg(feature = "std")] {
48         /// Providing a type alias for compatibility with existing usage of RustCrypto
49         /// by default we use StdRng for the underlying csprng
50         pub type RustCrypto = RustCryptoImpl<rand::rngs::StdRng>;
51     } else if #[cfg(feature = "rand_chacha")] {
52         /// A no_std compatible implementation of CryptoProvider backed by RustCrypto crates
53         pub type RustCrypto = RustCryptoImpl<rand_chacha::ChaCha20Rng>;
54     } else {
55         compile_error!("Must specify either --features std or --features rand_chacha");
56     }
57 }
58 
59 /// The RustCrypto backed struct which implements CryptoProvider
60 #[derive(Default, Clone, Debug, PartialEq, Eq)]
61 pub struct RustCryptoImpl<R: CryptoRng + SeedableRng + RngCore> {
62     _marker: PhantomData<R>,
63 }
64 
65 impl<R: CryptoRng + SeedableRng + RngCore> RustCryptoImpl<R> {
66     /// Create a new instance of RustCrypto
new() -> Self67     pub fn new() -> Self {
68         Self { _marker: Default::default() }
69     }
70 }
71 
72 impl<R: CryptoRng + SeedableRng + RngCore + Eq + PartialEq + Debug + Clone + Send>
73     crypto_provider::CryptoProvider for RustCryptoImpl<R>
74 {
75     type HkdfSha256 = hkdf_cp::Hkdf<sha2::Sha256>;
76     type HmacSha256 = hmac_cp::Hmac<sha2::Sha256>;
77     type HkdfSha512 = hkdf_cp::Hkdf<sha2::Sha512>;
78     type HmacSha512 = hmac_cp::Hmac<sha2::Sha512>;
79     type AesCbcPkcs7Padded = aes_cp::cbc::AesCbcPkcs7Padded;
80     type X25519 = x25519::X25519Ecdh<R>;
81     type P256 = p256::P256Ecdh<R>;
82     type Sha256 = sha2_cp::RustCryptoSha256;
83     type Sha512 = sha2_cp::RustCryptoSha512;
84     type Aes128 = aes_cp::Aes128;
85     type Aes256 = aes_cp::Aes256;
86     type AesCtr128 = aes_cp::ctr::AesCtr128;
87     type AesCtr256 = aes_cp::ctr::AesCtr256;
88     type Ed25519 = ed25519::Ed25519;
89     type Aes128GcmSiv = aead::aes_gcm_siv::AesGcmSiv<aes::Aes128>;
90     type Aes256GcmSiv = aead::aes_gcm_siv::AesGcmSiv<aes::Aes256>;
91     type Aes128Gcm = aead::aes_gcm::AesGcm<aes::Aes128>;
92     type Aes256Gcm = aead::aes_gcm::AesGcm<aes::Aes256>;
93     type CryptoRng = RcRng<R>;
94 
constant_time_eq(a: &[u8], b: &[u8]) -> bool95     fn constant_time_eq(a: &[u8], b: &[u8]) -> bool {
96         a.ct_eq(b).into()
97     }
98 }
99 
100 /// A RustCrypto wrapper for RNG
101 pub struct RcRng<R>(R);
102 
103 impl<R: rand_core::CryptoRng + RngCore + SeedableRng> crypto_provider::CryptoRng for RcRng<R> {
new() -> Self104     fn new() -> Self {
105         Self(R::from_entropy())
106     }
107 
next_u64(&mut self) -> u64108     fn next_u64(&mut self) -> u64 {
109         self.0.next_u64()
110     }
111 
fill(&mut self, dest: &mut [u8])112     fn fill(&mut self, dest: &mut [u8]) {
113         self.0.fill(dest)
114     }
115 }
116 
117 #[cfg(test)]
118 mod testing;
119 
120 #[cfg(test)]
121 mod tests {
122     use core::marker::PhantomData;
123 
124     use crypto_provider_test::prelude::*;
125     use crypto_provider_test::sha2::*;
126 
127     use crate::RustCrypto;
128 
129     #[apply(sha2_test_cases)]
sha2_tests(testcase: CryptoProviderTestCase<RustCrypto>)130     fn sha2_tests(testcase: CryptoProviderTestCase<RustCrypto>) {
131         testcase(PhantomData::<RustCrypto>);
132     }
133 }
134