1use crate::common_state::Protocol;
2use crate::crypto;
3use crate::crypto::cipher::{AeadKey, Iv};
4use crate::enums::{CipherSuite, ProtocolVersion, SignatureAlgorithm, SignatureScheme};
5#[cfg(feature = "tls12")]
6use crate::tls12::Tls12CipherSuite;
7use crate::tls13::Tls13CipherSuite;
8#[cfg(feature = "tls12")]
9use crate::versions::TLS12;
10use crate::versions::{SupportedProtocolVersion, TLS13};
11
12use alloc::vec::Vec;
13use core::fmt;
14
15pub struct CipherSuiteCommon {
17 pub suite: CipherSuite,
19
20 pub hash_provider: &'static dyn crypto::hash::Hash,
22
23 pub confidentiality_limit: u64,
32
33 pub integrity_limit: u64,
42}
43
44#[derive(Clone, Copy, PartialEq)]
49pub enum SupportedCipherSuite {
50 #[cfg(feature = "tls12")]
52 Tls12(&'static Tls12CipherSuite),
53 Tls13(&'static Tls13CipherSuite),
55}
56
57impl SupportedCipherSuite {
58 pub fn suite(&self) -> CipherSuite {
60 self.common().suite
61 }
62
63 pub(crate) fn hash_provider(&self) -> &'static dyn crypto::hash::Hash {
65 self.common().hash_provider
66 }
67
68 pub(crate) fn common(&self) -> &CipherSuiteCommon {
69 match self {
70 #[cfg(feature = "tls12")]
71 Self::Tls12(inner) => &inner.common,
72 Self::Tls13(inner) => &inner.common,
73 }
74 }
75
76 pub fn tls13(&self) -> Option<&'static Tls13CipherSuite> {
78 match self {
79 #[cfg(feature = "tls12")]
80 Self::Tls12(_) => None,
81 Self::Tls13(inner) => Some(inner),
82 }
83 }
84
85 pub fn version(&self) -> &'static SupportedProtocolVersion {
87 match self {
88 #[cfg(feature = "tls12")]
89 Self::Tls12(_) => &TLS12,
90 Self::Tls13(_) => &TLS13,
91 }
92 }
93
94 pub fn usable_for_signature_algorithm(&self, _sig_alg: SignatureAlgorithm) -> bool {
97 match self {
98 Self::Tls13(_) => true, #[cfg(feature = "tls12")]
100 Self::Tls12(inner) => inner
101 .sign
102 .iter()
103 .any(|scheme| scheme.sign() == _sig_alg),
104 }
105 }
106
107 pub(crate) fn usable_for_protocol(&self, proto: Protocol) -> bool {
112 match proto {
113 Protocol::Tcp => true,
114 Protocol::Quic => self
115 .tls13()
116 .and_then(|cs| cs.quic)
117 .is_some(),
118 }
119 }
120}
121
122impl fmt::Debug for SupportedCipherSuite {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 self.suite().fmt(f)
125 }
126}
127
128pub(crate) fn choose_ciphersuite_preferring_client(
130 client_suites: &[CipherSuite],
131 server_suites: &[SupportedCipherSuite],
132) -> Option<SupportedCipherSuite> {
133 for client_suite in client_suites {
134 if let Some(selected) = server_suites
135 .iter()
136 .find(|x| *client_suite == x.suite())
137 {
138 return Some(*selected);
139 }
140 }
141
142 None
143}
144
145pub(crate) fn choose_ciphersuite_preferring_server(
146 client_suites: &[CipherSuite],
147 server_suites: &[SupportedCipherSuite],
148) -> Option<SupportedCipherSuite> {
149 if let Some(selected) = server_suites
150 .iter()
151 .find(|x| client_suites.contains(&x.suite()))
152 {
153 return Some(*selected);
154 }
155
156 None
157}
158
159pub(crate) fn reduce_given_sigalg(
162 all: &[SupportedCipherSuite],
163 sigalg: SignatureAlgorithm,
164) -> Vec<SupportedCipherSuite> {
165 all.iter()
166 .filter(|&&suite| suite.usable_for_signature_algorithm(sigalg))
167 .copied()
168 .collect()
169}
170
171pub(crate) fn reduce_given_version_and_protocol(
174 all: &[SupportedCipherSuite],
175 version: ProtocolVersion,
176 proto: Protocol,
177) -> Vec<SupportedCipherSuite> {
178 all.iter()
179 .filter(|&&suite| suite.version().version == version && suite.usable_for_protocol(proto))
180 .copied()
181 .collect()
182}
183
184pub(crate) fn compatible_sigscheme_for_suites(
186 sigscheme: SignatureScheme,
187 common_suites: &[SupportedCipherSuite],
188) -> bool {
189 let sigalg = sigscheme.sign();
190 common_suites
191 .iter()
192 .any(|&suite| suite.usable_for_signature_algorithm(sigalg))
193}
194
195pub struct ExtractedSecrets {
201 pub tx: (u64, ConnectionTrafficSecrets),
203
204 pub rx: (u64, ConnectionTrafficSecrets),
206}
207
208pub(crate) struct PartiallyExtractedSecrets {
210 pub(crate) tx: ConnectionTrafficSecrets,
212
213 pub(crate) rx: ConnectionTrafficSecrets,
215}
216
217#[non_exhaustive]
223pub enum ConnectionTrafficSecrets {
224 Aes128Gcm {
226 key: AeadKey,
228 iv: Iv,
230 },
231
232 Aes256Gcm {
234 key: AeadKey,
236 iv: Iv,
238 },
239
240 Chacha20Poly1305 {
242 key: AeadKey,
244 iv: Iv,
246 },
247}
248
249#[cfg(all(test, any(feature = "ring", feature = "aws_lc_rs")))]
250mod tests {
251 use super::*;
252 use crate::test_provider::tls13::*;
253 use std::{println, vec};
254
255 #[test]
256 fn test_client_pref() {
257 let client = vec![
258 CipherSuite::TLS13_AES_128_GCM_SHA256,
259 CipherSuite::TLS13_AES_256_GCM_SHA384,
260 ];
261 let server = vec![TLS13_AES_256_GCM_SHA384, TLS13_AES_128_GCM_SHA256];
262 let chosen = choose_ciphersuite_preferring_client(&client, &server);
263 assert!(chosen.is_some());
264 assert_eq!(chosen.unwrap(), TLS13_AES_128_GCM_SHA256);
265 }
266
267 #[test]
268 fn test_server_pref() {
269 let client = vec![
270 CipherSuite::TLS13_AES_128_GCM_SHA256,
271 CipherSuite::TLS13_AES_256_GCM_SHA384,
272 ];
273 let server = vec![TLS13_AES_256_GCM_SHA384, TLS13_AES_128_GCM_SHA256];
274 let chosen = choose_ciphersuite_preferring_server(&client, &server);
275 assert!(chosen.is_some());
276 assert_eq!(chosen.unwrap(), TLS13_AES_256_GCM_SHA384);
277 }
278
279 #[test]
280 fn test_pref_fails() {
281 assert!(choose_ciphersuite_preferring_client(
282 &[CipherSuite::TLS_NULL_WITH_NULL_NULL],
283 crate::test_provider::ALL_CIPHER_SUITES
284 )
285 .is_none());
286 assert!(choose_ciphersuite_preferring_server(
287 &[CipherSuite::TLS_NULL_WITH_NULL_NULL],
288 crate::test_provider::ALL_CIPHER_SUITES
289 )
290 .is_none());
291 }
292
293 #[test]
294 fn test_scs_is_debug() {
295 println!("{:?}", crate::test_provider::ALL_CIPHER_SUITES);
296 }
297
298 #[test]
299 fn test_can_resume_to() {
300 assert!(TLS13_AES_128_GCM_SHA256
301 .tls13()
302 .unwrap()
303 .can_resume_from(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL)
304 .is_some());
305 assert!(TLS13_AES_256_GCM_SHA384
306 .tls13()
307 .unwrap()
308 .can_resume_from(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL)
309 .is_none());
310 }
311}