clia_rustls_mod/
suites.rs

1use core::fmt;
2
3use crate::common_state::Protocol;
4use crate::crypto::cipher::{AeadKey, Iv};
5use crate::crypto::{self, KeyExchangeAlgorithm};
6use crate::enums::{CipherSuite, SignatureAlgorithm, SignatureScheme};
7use crate::msgs::handshake::ALL_KEY_EXCHANGE_ALGORITHMS;
8#[cfg(feature = "tls12")]
9use crate::tls12::Tls12CipherSuite;
10use crate::tls13::Tls13CipherSuite;
11#[cfg(feature = "tls12")]
12use crate::versions::TLS12;
13use crate::versions::{SupportedProtocolVersion, TLS13};
14
15/// Common state for cipher suites (both for TLS 1.2 and TLS 1.3)
16pub struct CipherSuiteCommon {
17    /// The TLS enumeration naming this cipher suite.
18    pub suite: CipherSuite,
19
20    /// Which hash function the suite uses.
21    pub hash_provider: &'static dyn crypto::hash::Hash,
22
23    /// Number of TCP-TLS messages that can be safely encrypted with a single key of this type
24    ///
25    /// Once a `MessageEncrypter` produced for this suite has encrypted more than
26    /// `confidentiality_limit` messages, an attacker gains an advantage in distinguishing it
27    /// from an ideal pseudorandom permutation (PRP).
28    ///
29    /// This is to be set on the assumption that messages are maximally sized --
30    /// at least 2 ** 14 bytes. It **does not** consider confidentiality limits for
31    /// QUIC connections - see the [`quic::KeyBuilder.confidentiality_limit`] field for
32    /// this context.
33    pub confidentiality_limit: u64,
34}
35
36impl CipherSuiteCommon {
37    /// Return `true` if this is backed by a FIPS-approved implementation.
38    ///
39    /// This means all the constituent parts that do cryptography return `true` for `fips()`.
40    pub fn fips(&self) -> bool {
41        self.hash_provider.fips()
42    }
43}
44
45/// A cipher suite supported by rustls.
46///
47/// This type carries both configuration and implementation. Compare with
48/// [`CipherSuite`], which carries solely a cipher suite identifier.
49#[derive(Clone, Copy, PartialEq)]
50pub enum SupportedCipherSuite {
51    /// A TLS 1.2 cipher suite
52    #[cfg(feature = "tls12")]
53    Tls12(&'static Tls12CipherSuite),
54    /// A TLS 1.3 cipher suite
55    Tls13(&'static Tls13CipherSuite),
56}
57
58impl SupportedCipherSuite {
59    /// The cipher suite's identifier
60    pub fn suite(&self) -> CipherSuite {
61        self.common().suite
62    }
63
64    /// The hash function the ciphersuite uses.
65    pub(crate) fn hash_provider(&self) -> &'static dyn crypto::hash::Hash {
66        self.common().hash_provider
67    }
68
69    pub(crate) fn common(&self) -> &CipherSuiteCommon {
70        match self {
71            #[cfg(feature = "tls12")]
72            Self::Tls12(inner) => &inner.common,
73            Self::Tls13(inner) => &inner.common,
74        }
75    }
76
77    /// Return the inner `Tls13CipherSuite` for this suite, if it is a TLS1.3 suite.
78    pub fn tls13(&self) -> Option<&'static Tls13CipherSuite> {
79        match self {
80            #[cfg(feature = "tls12")]
81            Self::Tls12(_) => None,
82            Self::Tls13(inner) => Some(inner),
83        }
84    }
85
86    /// Return supported protocol version for the cipher suite.
87    pub fn version(&self) -> &'static SupportedProtocolVersion {
88        match self {
89            #[cfg(feature = "tls12")]
90            Self::Tls12(_) => &TLS12,
91            Self::Tls13(_) => &TLS13,
92        }
93    }
94
95    /// Return true if this suite is usable for a key only offering `sig_alg`
96    /// signatures.  This resolves to true for all TLS1.3 suites.
97    pub fn usable_for_signature_algorithm(&self, _sig_alg: SignatureAlgorithm) -> bool {
98        match self {
99            Self::Tls13(_) => true, // no constraint expressed by ciphersuite (e.g., TLS1.3)
100            #[cfg(feature = "tls12")]
101            Self::Tls12(inner) => inner
102                .sign
103                .iter()
104                .any(|scheme| scheme.sign() == _sig_alg),
105        }
106    }
107
108    /// Return true if this suite is usable for the given [`Protocol`].
109    ///
110    /// All cipher suites are usable for TCP-TLS.  Only TLS1.3 suites
111    /// with `Tls13CipherSuite::quic` provided are usable for QUIC.
112    pub(crate) fn usable_for_protocol(&self, proto: Protocol) -> bool {
113        match proto {
114            Protocol::Tcp => true,
115            Protocol::Quic => self
116                .tls13()
117                .and_then(|cs| cs.quic)
118                .is_some(),
119        }
120    }
121
122    /// Return `true` if this is backed by a FIPS-approved implementation.
123    pub fn fips(&self) -> bool {
124        match self {
125            #[cfg(feature = "tls12")]
126            Self::Tls12(cs) => cs.fips(),
127            Self::Tls13(cs) => cs.fips(),
128        }
129    }
130
131    /// Return the list of `KeyExchangeAlgorithm`s supported by this cipher suite.
132    ///
133    /// TLS 1.3 cipher suites support both ECDHE and DHE key exchange, but TLS 1.2 suites
134    /// support one or the other.
135    pub(crate) fn key_exchange_algorithms(&self) -> &[KeyExchangeAlgorithm] {
136        match self {
137            #[cfg(feature = "tls12")]
138            Self::Tls12(tls12) => core::slice::from_ref(&tls12.kx),
139            Self::Tls13(_) => ALL_KEY_EXCHANGE_ALGORITHMS,
140        }
141    }
142
143    /// Say if the given `KeyExchangeAlgorithm` is supported by this cipher suite.
144    ///
145    /// TLS 1.3 cipher suites support all key exchange types, but TLS 1.2 suites
146    /// support only one.
147    pub(crate) fn usable_for_kx_algorithm(&self, _kxa: KeyExchangeAlgorithm) -> bool {
148        match self {
149            #[cfg(feature = "tls12")]
150            Self::Tls12(tls12) => tls12.kx == _kxa,
151            Self::Tls13(_) => true,
152        }
153    }
154}
155
156impl fmt::Debug for SupportedCipherSuite {
157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158        self.suite().fmt(f)
159    }
160}
161
162/// Return true if `sigscheme` is usable by any of the given suites.
163pub(crate) fn compatible_sigscheme_for_suites(
164    sigscheme: SignatureScheme,
165    common_suites: &[SupportedCipherSuite],
166) -> bool {
167    let sigalg = sigscheme.sign();
168    common_suites
169        .iter()
170        .any(|&suite| suite.usable_for_signature_algorithm(sigalg))
171}
172
173/// Secrets for transmitting/receiving data over a TLS session.
174///
175/// After performing a handshake with rustls, these secrets can be extracted
176/// to configure kTLS for a socket, and have the kernel take over encryption
177/// and/or decryption.
178pub struct ExtractedSecrets {
179    /// sequence number and secrets for the "tx" (transmit) direction
180    pub tx: (u64, ConnectionTrafficSecrets),
181
182    /// sequence number and secrets for the "rx" (receive) direction
183    pub rx: (u64, ConnectionTrafficSecrets),
184}
185
186/// [ExtractedSecrets] minus the sequence numbers
187pub(crate) struct PartiallyExtractedSecrets {
188    /// secrets for the "tx" (transmit) direction
189    pub(crate) tx: ConnectionTrafficSecrets,
190
191    /// secrets for the "rx" (receive) direction
192    pub(crate) rx: ConnectionTrafficSecrets,
193}
194
195/// Secrets used to encrypt/decrypt data in a TLS session.
196///
197/// These can be used to configure kTLS for a socket in one direction.
198/// The only other piece of information needed is the sequence number,
199/// which is in [ExtractedSecrets].
200#[non_exhaustive]
201pub enum ConnectionTrafficSecrets {
202    /// Secrets for the AES_128_GCM AEAD algorithm
203    Aes128Gcm {
204        /// AEAD Key
205        key: AeadKey,
206        /// Initialization vector
207        iv: Iv,
208    },
209
210    /// Secrets for the AES_256_GCM AEAD algorithm
211    Aes256Gcm {
212        /// AEAD Key
213        key: AeadKey,
214        /// Initialization vector
215        iv: Iv,
216    },
217
218    /// Secrets for the CHACHA20_POLY1305 AEAD algorithm
219    Chacha20Poly1305 {
220        /// AEAD Key
221        key: AeadKey,
222        /// Initialization vector
223        iv: Iv,
224    },
225}
226
227test_for_each_provider! {
228    use provider::tls13::*;
229    use std::println;
230
231    #[test]
232    fn test_scs_is_debug() {
233        println!("{:?}", provider::ALL_CIPHER_SUITES);
234    }
235
236    #[test]
237    fn test_can_resume_to() {
238        assert!(TLS13_AES_128_GCM_SHA256
239            .tls13()
240            .unwrap()
241            .can_resume_from(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL)
242            .is_some());
243        assert!(TLS13_AES_256_GCM_SHA384
244            .tls13()
245            .unwrap()
246            .can_resume_from(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL)
247            .is_none());
248    }
249}