rustls/crypto/aws_lc_rs/
mod.rs

1use alloc::borrow::Cow;
2use alloc::boxed::Box;
3
4use pki_types::PrivateKeyDer;
5use webpki::aws_lc_rs as webpki_algs;
6
7use super::signer::SigningKey;
8use crate::crypto::{
9    CryptoProvider, GetRandomFailed, KeyProvider, SecureRandom, SignatureScheme, SupportedKxGroup,
10    TicketProducer, TicketerFactory,
11};
12use crate::error::{Error, OtherError};
13use crate::sync::Arc;
14#[cfg(feature = "std")]
15use crate::ticketer::TicketRotator;
16use crate::tls12::Tls12CipherSuite;
17use crate::tls13::Tls13CipherSuite;
18use crate::webpki::WebPkiSupportedAlgorithms;
19
20/// Hybrid public key encryption (HPKE).
21pub mod hpke;
22/// Post-quantum secure algorithms.
23pub(crate) mod pq;
24/// Using software keys for authentication.
25pub mod sign;
26use sign::{EcdsaSigner, Ed25519Signer, RsaSigningKey};
27
28pub(crate) mod hash;
29pub(crate) mod hmac;
30pub(crate) mod kx;
31pub(crate) mod quic;
32#[cfg(feature = "std")]
33pub(crate) mod ticketer;
34#[cfg(feature = "std")]
35use ticketer::Rfc5077Ticketer;
36pub(crate) mod tls12;
37pub(crate) mod tls13;
38
39/// The default `CryptoProvider` backed by aws-lc-rs.
40pub const DEFAULT_PROVIDER: CryptoProvider = CryptoProvider {
41    tls12_cipher_suites: Cow::Borrowed(DEFAULT_TLS12_CIPHER_SUITES),
42    tls13_cipher_suites: Cow::Borrowed(DEFAULT_TLS13_CIPHER_SUITES),
43    kx_groups: Cow::Borrowed(DEFAULT_KX_GROUPS),
44    signature_verification_algorithms: SUPPORTED_SIG_ALGS,
45    secure_random: &AwsLcRs,
46    key_provider: &AwsLcRs,
47    ticketer_factory: &AwsLcRs,
48};
49
50/// The default `CryptoProvider` backed by aws-lc-rs that only supports TLS1.3.
51pub const DEFAULT_TLS13_PROVIDER: CryptoProvider = CryptoProvider {
52    tls12_cipher_suites: Cow::Borrowed(&[]),
53    ..DEFAULT_PROVIDER
54};
55
56/// The default `CryptoProvider` backed by aws-lc-rs that only supports TLS1.2.
57///
58/// Use of TLS1.3 is **strongly** recommended.
59pub const DEFAULT_TLS12_PROVIDER: CryptoProvider = CryptoProvider {
60    tls13_cipher_suites: Cow::Borrowed(&[]),
61    ..DEFAULT_PROVIDER
62};
63
64/// `KeyProvider` impl for aws-lc-rs
65pub static DEFAULT_KEY_PROVIDER: &dyn KeyProvider = &AwsLcRs;
66
67/// `SecureRandom` impl for aws-lc-rs
68pub static DEFAULT_SECURE_RANDOM: &dyn SecureRandom = &AwsLcRs;
69
70#[derive(Debug)]
71struct AwsLcRs;
72
73impl SecureRandom for AwsLcRs {
74    fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed> {
75        use aws_lc_rs::rand::SecureRandom;
76
77        aws_lc_rs::rand::SystemRandom::new()
78            .fill(buf)
79            .map_err(|_| GetRandomFailed)
80    }
81
82    fn fips(&self) -> bool {
83        fips()
84    }
85}
86
87impl KeyProvider for AwsLcRs {
88    fn load_private_key(
89        &self,
90        key_der: PrivateKeyDer<'static>,
91    ) -> Result<Box<dyn SigningKey>, Error> {
92        if let Ok(rsa) = RsaSigningKey::try_from(&key_der) {
93            return Ok(Box::new(rsa));
94        }
95
96        if let Ok(ecdsa) = EcdsaSigner::try_from(&key_der) {
97            return Ok(Box::new(ecdsa));
98        }
99
100        if let PrivateKeyDer::Pkcs8(pkcs8) = key_der {
101            if let Ok(eddsa) = Ed25519Signer::try_from(&pkcs8) {
102                return Ok(Box::new(eddsa));
103            }
104        }
105
106        Err(Error::General(
107            "failed to parse private key as RSA, ECDSA, or EdDSA".into(),
108        ))
109    }
110
111    fn fips(&self) -> bool {
112        fips()
113    }
114}
115
116impl TicketerFactory for AwsLcRs {
117    /// Make the recommended `Ticketer`.
118    ///
119    /// This produces tickets:
120    ///
121    /// - where each lasts for at least 6 hours,
122    /// - with randomly generated keys, and
123    /// - where keys are rotated every 6 hours.
124    ///
125    /// The `Ticketer` uses the [RFC 5077 §4] "Recommended Ticket Construction",
126    /// using AES 256 for encryption and HMAC-SHA256 for ciphertext authentication.
127    ///
128    /// [RFC 5077 §4]: https://www.rfc-editor.org/rfc/rfc5077#section-4
129    fn ticketer(&self) -> Result<Arc<dyn TicketProducer>, Error> {
130        #[cfg(feature = "std")]
131        {
132            Ok(Arc::new(TicketRotator::new(
133                TicketRotator::SIX_HOURS,
134                Rfc5077Ticketer::new,
135            )?))
136        }
137        #[cfg(not(feature = "std"))]
138        {
139            Err(Error::General(
140                "AwsLcRs::ticketer() relies on std-only RwLock via TicketRotator".into(),
141            ))
142        }
143    }
144
145    fn fips(&self) -> bool {
146        fips()
147    }
148}
149
150/// The TLS1.2 cipher suite configuration that an application should use by default.
151///
152/// This will be [`ALL_TLS12_CIPHER_SUITES`] sans any supported cipher suites that
153/// shouldn't be enabled by most applications.
154pub static DEFAULT_TLS12_CIPHER_SUITES: &[&Tls12CipherSuite] = &[
155    tls12::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
156    tls12::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
157    #[cfg(not(feature = "fips"))]
158    tls12::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
159    tls12::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
160    tls12::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
161    #[cfg(not(feature = "fips"))]
162    tls12::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
163];
164
165/// The TLS1.3 cipher suite configuration that an application should use by default.
166///
167/// This will be [`ALL_TLS13_CIPHER_SUITES`] sans any supported cipher suites that
168/// shouldn't be enabled by most applications.
169pub static DEFAULT_TLS13_CIPHER_SUITES: &[&Tls13CipherSuite] = &[
170    tls13::TLS13_AES_256_GCM_SHA384,
171    tls13::TLS13_AES_128_GCM_SHA256,
172    #[cfg(not(feature = "fips"))]
173    tls13::TLS13_CHACHA20_POLY1305_SHA256,
174];
175
176/// A list of all the TLS1.2 cipher suites supported by the rustls aws-lc-rs provider.
177pub static ALL_TLS12_CIPHER_SUITES: &[&Tls12CipherSuite] = &[
178    tls12::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
179    tls12::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
180    tls12::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
181    tls12::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
182    tls12::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
183    tls12::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
184];
185
186/// A list of all the TLS1.3 cipher suites supported by the rustls aws-lc-rs provider.
187pub static ALL_TLS13_CIPHER_SUITES: &[&Tls13CipherSuite] = &[
188    tls13::TLS13_AES_256_GCM_SHA384,
189    tls13::TLS13_AES_128_GCM_SHA256,
190    tls13::TLS13_CHACHA20_POLY1305_SHA256,
191];
192
193/// All defined cipher suites supported by aws-lc-rs appear in this module.
194pub mod cipher_suite {
195    pub use super::tls12::{
196        TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
197        TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
198        TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
199    };
200    pub use super::tls13::{
201        TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384, TLS13_CHACHA20_POLY1305_SHA256,
202    };
203}
204
205/// A `WebPkiSupportedAlgorithms` value that reflects webpki's capabilities when
206/// compiled against aws-lc-rs.
207pub static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
208    all: &[
209        webpki_algs::ECDSA_P256_SHA256,
210        webpki_algs::ECDSA_P256_SHA384,
211        webpki_algs::ECDSA_P384_SHA256,
212        webpki_algs::ECDSA_P384_SHA384,
213        webpki_algs::ECDSA_P521_SHA256,
214        webpki_algs::ECDSA_P521_SHA384,
215        webpki_algs::ECDSA_P521_SHA512,
216        webpki_algs::ED25519,
217        webpki_algs::RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
218        webpki_algs::RSA_PSS_2048_8192_SHA384_LEGACY_KEY,
219        webpki_algs::RSA_PSS_2048_8192_SHA512_LEGACY_KEY,
220        webpki_algs::RSA_PKCS1_2048_8192_SHA256,
221        webpki_algs::RSA_PKCS1_2048_8192_SHA384,
222        webpki_algs::RSA_PKCS1_2048_8192_SHA512,
223        webpki_algs::RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS,
224        webpki_algs::RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS,
225        webpki_algs::RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS,
226    ],
227    mapping: &[
228        // Note: for TLS1.2 the curve is not fixed by SignatureScheme. For TLS1.3 it is.
229        (
230            SignatureScheme::ECDSA_NISTP384_SHA384,
231            &[
232                webpki_algs::ECDSA_P384_SHA384,
233                webpki_algs::ECDSA_P256_SHA384,
234                webpki_algs::ECDSA_P521_SHA384,
235            ],
236        ),
237        (
238            SignatureScheme::ECDSA_NISTP256_SHA256,
239            &[
240                webpki_algs::ECDSA_P256_SHA256,
241                webpki_algs::ECDSA_P384_SHA256,
242                webpki_algs::ECDSA_P521_SHA256,
243            ],
244        ),
245        (
246            SignatureScheme::ECDSA_NISTP521_SHA512,
247            &[
248                webpki_algs::ECDSA_P521_SHA512,
249                webpki_algs::ECDSA_P384_SHA512,
250                webpki_algs::ECDSA_P256_SHA512,
251            ],
252        ),
253        (SignatureScheme::ED25519, &[webpki_algs::ED25519]),
254        (
255            SignatureScheme::RSA_PSS_SHA512,
256            &[webpki_algs::RSA_PSS_2048_8192_SHA512_LEGACY_KEY],
257        ),
258        (
259            SignatureScheme::RSA_PSS_SHA384,
260            &[webpki_algs::RSA_PSS_2048_8192_SHA384_LEGACY_KEY],
261        ),
262        (
263            SignatureScheme::RSA_PSS_SHA256,
264            &[webpki_algs::RSA_PSS_2048_8192_SHA256_LEGACY_KEY],
265        ),
266        (
267            SignatureScheme::RSA_PKCS1_SHA512,
268            &[webpki_algs::RSA_PKCS1_2048_8192_SHA512],
269        ),
270        (
271            SignatureScheme::RSA_PKCS1_SHA384,
272            &[webpki_algs::RSA_PKCS1_2048_8192_SHA384],
273        ),
274        (
275            SignatureScheme::RSA_PKCS1_SHA256,
276            &[webpki_algs::RSA_PKCS1_2048_8192_SHA256],
277        ),
278    ],
279};
280
281/// All defined key exchange groups supported by aws-lc-rs appear in this module.
282///
283/// [`ALL_KX_GROUPS`] is provided as an array of all of these values.
284/// [`DEFAULT_KX_GROUPS`] is provided as an array of this provider's defaults.
285pub mod kx_group {
286    pub use super::kx::{SECP256R1, SECP384R1, X25519};
287    pub use super::pq::{MLKEM768, SECP256R1MLKEM768, X25519MLKEM768};
288}
289
290/// A list of the default key exchange groups supported by this provider.
291///
292/// This does not contain MLKEM768; by default MLKEM768 is only offered
293/// in hybrid with X25519.
294pub static DEFAULT_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
295    kx_group::X25519MLKEM768,
296    #[cfg(not(feature = "fips"))]
297    kx_group::X25519,
298    kx_group::SECP256R1,
299    kx_group::SECP384R1,
300];
301
302/// A list of all the key exchange groups supported by this provider.
303pub static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
304    kx_group::X25519MLKEM768,
305    kx_group::SECP256R1MLKEM768,
306    kx_group::X25519,
307    kx_group::SECP256R1,
308    kx_group::SECP384R1,
309    kx_group::MLKEM768,
310];
311
312/// Compatibility shims between ring 0.16.x and 0.17.x API
313mod ring_shim {
314    use aws_lc_rs::agreement::{self, EphemeralPrivateKey, UnparsedPublicKey};
315
316    use crate::crypto::kx::SharedSecret;
317
318    pub(super) fn agree_ephemeral(
319        priv_key: EphemeralPrivateKey,
320        peer_key: &UnparsedPublicKey<&[u8]>,
321    ) -> Result<SharedSecret, ()> {
322        agreement::agree_ephemeral(priv_key, peer_key, (), |secret| {
323            Ok(SharedSecret::from(secret))
324        })
325    }
326}
327
328/// Are we in FIPS mode?
329pub(super) fn fips() -> bool {
330    aws_lc_rs::try_fips_mode().is_ok()
331}
332
333pub(super) fn unspecified_err(e: aws_lc_rs::error::Unspecified) -> Error {
334    Error::Other(OtherError::new(e))
335}
336
337#[cfg(test)]
338mod tests {
339    #[cfg(feature = "fips")]
340    #[test]
341    fn default_suites_are_fips() {
342        assert!(
343            super::DEFAULT_TLS12_CIPHER_SUITES
344                .iter()
345                .all(|scs| scs.fips())
346        );
347        assert!(
348            super::DEFAULT_TLS13_CIPHER_SUITES
349                .iter()
350                .all(|scs| scs.fips())
351        );
352    }
353
354    #[cfg(not(feature = "fips"))]
355    #[test]
356    fn default_suites() {
357        assert_eq!(
358            super::DEFAULT_TLS12_CIPHER_SUITES,
359            super::ALL_TLS12_CIPHER_SUITES
360        );
361        assert_eq!(
362            super::DEFAULT_TLS13_CIPHER_SUITES,
363            super::ALL_TLS13_CIPHER_SUITES
364        );
365    }
366}