Coverage Report

Created: 2025-02-25 06:39

/rust/registry/src/index.crates.io-6f17d22bba15001f/rustls-0.23.22/src/suites.rs
Line
Count
Source (jump to first uncovered line)
1
use core::fmt;
2
3
use crate::common_state::Protocol;
4
use crate::crypto::cipher::{AeadKey, Iv};
5
use crate::crypto::{self, KeyExchangeAlgorithm};
6
use crate::enums::{CipherSuite, SignatureAlgorithm, SignatureScheme};
7
use crate::msgs::handshake::ALL_KEY_EXCHANGE_ALGORITHMS;
8
#[cfg(feature = "tls12")]
9
use crate::tls12::Tls12CipherSuite;
10
use crate::tls13::Tls13CipherSuite;
11
#[cfg(feature = "tls12")]
12
use crate::versions::TLS12;
13
use crate::versions::{SupportedProtocolVersion, TLS13};
14
15
/// Common state for cipher suites (both for TLS 1.2 and TLS 1.3)
16
pub 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
    /// each is 2<sup>14</sup> bytes. It **does not** consider confidentiality limits for
31
    /// QUIC connections - see the [`quic::KeyBuilder.confidentiality_limit`] field for
32
    /// this context.
33
    ///
34
    /// For AES-GCM implementations, this should be set to 2<sup>24</sup> to limit attack
35
    /// probability to one in 2<sup>60</sup>.  See [AEBounds] (Table 1) and [draft-irtf-aead-limits-08]:
36
    ///
37
    /// ```python
38
    /// >>> p = 2 ** -60
39
    /// >>> L = (2 ** 14 // 16) + 1
40
    /// >>> qlim = (math.sqrt(p) * (2 ** (129 // 2)) - 1) / (L + 1)
41
    /// >>> print(int(qlim).bit_length())
42
    /// 24
43
    /// ```
44
    /// [AEBounds]: https://eprint.iacr.org/2024/051.pdf
45
    /// [draft-irtf-aead-limits-08]: https://www.ietf.org/archive/id/draft-irtf-cfrg-aead-limits-08.html#section-5.1.1
46
    ///
47
    /// For chacha20-poly1305 implementations, this should be set to `u64::MAX`:
48
    /// see <https://www.ietf.org/archive/id/draft-irtf-cfrg-aead-limits-08.html#section-5.2.1>
49
    pub confidentiality_limit: u64,
50
}
51
52
impl CipherSuiteCommon {
53
    /// Return `true` if this is backed by a FIPS-approved implementation.
54
    ///
55
    /// This means all the constituent parts that do cryptography return `true` for `fips()`.
56
0
    pub fn fips(&self) -> bool {
57
0
        self.hash_provider.fips()
58
0
    }
59
}
60
61
/// A cipher suite supported by rustls.
62
///
63
/// This type carries both configuration and implementation. Compare with
64
/// [`CipherSuite`], which carries solely a cipher suite identifier.
65
#[derive(Clone, Copy, PartialEq)]
66
pub enum SupportedCipherSuite {
67
    /// A TLS 1.2 cipher suite
68
    #[cfg(feature = "tls12")]
69
    Tls12(&'static Tls12CipherSuite),
70
    /// A TLS 1.3 cipher suite
71
    Tls13(&'static Tls13CipherSuite),
72
}
73
74
impl SupportedCipherSuite {
75
    /// The cipher suite's identifier
76
0
    pub fn suite(&self) -> CipherSuite {
77
0
        self.common().suite
78
0
    }
79
80
    /// The hash function the ciphersuite uses.
81
0
    pub(crate) fn hash_provider(&self) -> &'static dyn crypto::hash::Hash {
82
0
        self.common().hash_provider
83
0
    }
84
85
0
    pub(crate) fn common(&self) -> &CipherSuiteCommon {
86
0
        match self {
87
0
            #[cfg(feature = "tls12")]
88
0
            Self::Tls12(inner) => &inner.common,
89
0
            Self::Tls13(inner) => &inner.common,
90
0
        }
91
0
    }
92
93
    /// Return the inner `Tls13CipherSuite` for this suite, if it is a TLS1.3 suite.
94
0
    pub fn tls13(&self) -> Option<&'static Tls13CipherSuite> {
95
0
        match self {
96
0
            #[cfg(feature = "tls12")]
97
0
            Self::Tls12(_) => None,
98
0
            Self::Tls13(inner) => Some(inner),
99
0
        }
100
0
    }
101
102
    /// Return supported protocol version for the cipher suite.
103
0
    pub fn version(&self) -> &'static SupportedProtocolVersion {
104
0
        match self {
105
0
            #[cfg(feature = "tls12")]
106
0
            Self::Tls12(_) => &TLS12,
107
0
            Self::Tls13(_) => &TLS13,
108
0
        }
109
0
    }
110
111
    /// Return true if this suite is usable for a key only offering `sig_alg`
112
    /// signatures.  This resolves to true for all TLS1.3 suites.
113
0
    pub fn usable_for_signature_algorithm(&self, _sig_alg: SignatureAlgorithm) -> bool {
114
0
        match self {
115
0
            Self::Tls13(_) => true, // no constraint expressed by ciphersuite (e.g., TLS1.3)
116
0
            #[cfg(feature = "tls12")]
117
0
            Self::Tls12(inner) => inner
118
0
                .sign
119
0
                .iter()
120
0
                .any(|scheme| scheme.algorithm() == _sig_alg),
121
0
        }
122
0
    }
123
124
    /// Return true if this suite is usable for the given [`Protocol`].
125
    ///
126
    /// All cipher suites are usable for TCP-TLS.  Only TLS1.3 suites
127
    /// with `Tls13CipherSuite::quic` provided are usable for QUIC.
128
0
    pub(crate) fn usable_for_protocol(&self, proto: Protocol) -> bool {
129
0
        match proto {
130
0
            Protocol::Tcp => true,
131
0
            Protocol::Quic => self
132
0
                .tls13()
133
0
                .and_then(|cs| cs.quic)
134
0
                .is_some(),
135
        }
136
0
    }
137
138
    /// Return `true` if this is backed by a FIPS-approved implementation.
139
0
    pub fn fips(&self) -> bool {
140
0
        match self {
141
0
            #[cfg(feature = "tls12")]
142
0
            Self::Tls12(cs) => cs.fips(),
143
0
            Self::Tls13(cs) => cs.fips(),
144
0
        }
145
0
    }
146
147
    /// Return the list of `KeyExchangeAlgorithm`s supported by this cipher suite.
148
    ///
149
    /// TLS 1.3 cipher suites support both ECDHE and DHE key exchange, but TLS 1.2 suites
150
    /// support one or the other.
151
0
    pub(crate) fn key_exchange_algorithms(&self) -> &[KeyExchangeAlgorithm] {
152
0
        match self {
153
0
            #[cfg(feature = "tls12")]
154
0
            Self::Tls12(tls12) => core::slice::from_ref(&tls12.kx),
155
0
            Self::Tls13(_) => ALL_KEY_EXCHANGE_ALGORITHMS,
156
0
        }
157
0
    }
158
159
    /// Say if the given `KeyExchangeAlgorithm` is supported by this cipher suite.
160
    ///
161
    /// TLS 1.3 cipher suites support all key exchange types, but TLS 1.2 suites
162
    /// support only one.
163
0
    pub(crate) fn usable_for_kx_algorithm(&self, _kxa: KeyExchangeAlgorithm) -> bool {
164
0
        match self {
165
0
            #[cfg(feature = "tls12")]
166
0
            Self::Tls12(tls12) => tls12.kx == _kxa,
167
0
            Self::Tls13(_) => true,
168
0
        }
169
0
    }
170
}
171
172
impl fmt::Debug for SupportedCipherSuite {
173
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174
0
        self.suite().fmt(f)
175
0
    }
176
}
177
178
/// Return true if `sigscheme` is usable by any of the given suites.
179
0
pub(crate) fn compatible_sigscheme_for_suites(
180
0
    sigscheme: SignatureScheme,
181
0
    common_suites: &[SupportedCipherSuite],
182
0
) -> bool {
183
0
    let sigalg = sigscheme.algorithm();
184
0
    common_suites
185
0
        .iter()
186
0
        .any(|&suite| suite.usable_for_signature_algorithm(sigalg))
187
0
}
188
189
/// Secrets for transmitting/receiving data over a TLS session.
190
///
191
/// After performing a handshake with rustls, these secrets can be extracted
192
/// to configure kTLS for a socket, and have the kernel take over encryption
193
/// and/or decryption.
194
pub struct ExtractedSecrets {
195
    /// sequence number and secrets for the "tx" (transmit) direction
196
    pub tx: (u64, ConnectionTrafficSecrets),
197
198
    /// sequence number and secrets for the "rx" (receive) direction
199
    pub rx: (u64, ConnectionTrafficSecrets),
200
}
201
202
/// [ExtractedSecrets] minus the sequence numbers
203
pub(crate) struct PartiallyExtractedSecrets {
204
    /// secrets for the "tx" (transmit) direction
205
    pub(crate) tx: ConnectionTrafficSecrets,
206
207
    /// secrets for the "rx" (receive) direction
208
    pub(crate) rx: ConnectionTrafficSecrets,
209
}
210
211
/// Secrets used to encrypt/decrypt data in a TLS session.
212
///
213
/// These can be used to configure kTLS for a socket in one direction.
214
/// The only other piece of information needed is the sequence number,
215
/// which is in [ExtractedSecrets].
216
#[non_exhaustive]
217
pub enum ConnectionTrafficSecrets {
218
    /// Secrets for the AES_128_GCM AEAD algorithm
219
    Aes128Gcm {
220
        /// AEAD Key
221
        key: AeadKey,
222
        /// Initialization vector
223
        iv: Iv,
224
    },
225
226
    /// Secrets for the AES_256_GCM AEAD algorithm
227
    Aes256Gcm {
228
        /// AEAD Key
229
        key: AeadKey,
230
        /// Initialization vector
231
        iv: Iv,
232
    },
233
234
    /// Secrets for the CHACHA20_POLY1305 AEAD algorithm
235
    Chacha20Poly1305 {
236
        /// AEAD Key
237
        key: AeadKey,
238
        /// Initialization vector
239
        iv: Iv,
240
    },
241
}
242
243
#[cfg(test)]
244
#[macro_rules_attribute::apply(test_for_each_provider)]
245
mod tests {
246
    use std::println;
247
248
    use super::provider::tls13::*;
249
250
    #[test]
251
    fn test_scs_is_debug() {
252
        println!("{:?}", super::provider::ALL_CIPHER_SUITES);
253
    }
254
255
    #[test]
256
    fn test_can_resume_to() {
257
        assert!(TLS13_AES_128_GCM_SHA256
258
            .tls13()
259
            .unwrap()
260
            .can_resume_from(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL)
261
            .is_some());
262
        assert!(TLS13_AES_256_GCM_SHA384
263
            .tls13()
264
            .unwrap()
265
            .can_resume_from(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL)
266
            .is_none());
267
    }
268
}