1use core::fmt;
2
3use crate::crypto;
4use crate::crypto::hash;
5use crate::suites::{CipherSuiteCommon, SupportedCipherSuite};
6
7pub(crate) mod key_schedule;
8
9/// A TLS 1.3 cipher suite supported by rustls.
10pub struct Tls13CipherSuite {
11 /// Common cipher suite fields.
12 pub common: CipherSuiteCommon,
13
14 /// How to complete HKDF with the suite's hash function.
15 ///
16 /// If you have a HKDF implementation, you should directly implement the `crypto::tls13::Hkdf`
17 /// trait (and associated).
18 ///
19 /// If not, you can implement the [`crypto::hmac::Hmac`] trait (and associated), and then use
20 /// [`crypto::tls13::HkdfUsingHmac`].
21 pub hkdf_provider: &'static dyn crypto::tls13::Hkdf,
22
23 /// How to produce a [MessageDecrypter] or [MessageEncrypter]
24 /// from raw key material.
25 ///
26 /// [MessageDecrypter]: crate::crypto::cipher::MessageDecrypter
27 /// [MessageEncrypter]: crate::crypto::cipher::MessageEncrypter
28 pub aead_alg: &'static dyn crypto::cipher::Tls13AeadAlgorithm,
29
30 /// How to create QUIC header and record protection algorithms
31 /// for this suite.
32 ///
33 /// Provide `None` to opt out of QUIC support for this suite. It will
34 /// not be offered in QUIC handshakes.
35 pub quic: Option<&'static dyn crate::quic::Algorithm>,
36}
37
38impl Tls13CipherSuite {
39 /// Can a session using suite self resume from suite prev?
40 pub fn can_resume_from(&self, prev: &'static Self) -> Option<&'static Self> {
41 (prev.common.hash_provider.algorithm() == self.common.hash_provider.algorithm())
42 .then_some(prev)
43 }
44
45 /// Return `true` if this is backed by a FIPS-approved implementation.
46 ///
47 /// This means all the constituent parts that do cryptography return `true` for `fips()`.
48 pub fn fips(&self) -> bool {
49 let Self {
50 common,
51 hkdf_provider,
52 aead_alg,
53 quic,
54 } = self;
55 common.fips()
56 && hkdf_provider.fips()
57 && aead_alg.fips()
58 && quic.map(|q| q.fips()).unwrap_or(true)
59 }
60
61 /// Returns a `quic::Suite` for the ciphersuite, if supported.
62 pub fn quic_suite(&'static self) -> Option<crate::quic::Suite> {
63 self.quic
64 .map(|quic| crate::quic::Suite { quic, suite: self })
65 }
66}
67
68impl From<&'static Tls13CipherSuite> for SupportedCipherSuite {
69 fn from(s: &'static Tls13CipherSuite) -> Self {
70 Self::Tls13(s)
71 }
72}
73
74impl PartialEq for Tls13CipherSuite {
75 fn eq(&self, other: &Self) -> bool {
76 self.common.suite == other.common.suite
77 }
78}
79
80impl fmt::Debug for Tls13CipherSuite {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 f&mut DebugStruct<'_, '_>.debug_struct("Tls13CipherSuite")
83 .field(name:"suite", &self.common.suite)
84 .finish()
85 }
86}
87
88/// Constructs the signature message specified in section 4.4.3 of RFC8446.
89pub(crate) fn construct_client_verify_message(handshake_hash: &hash::Output) -> VerifyMessage {
90 VerifyMessage::new(handshake_hash, CLIENT_CONSTANT)
91}
92
93/// Constructs the signature message specified in section 4.4.3 of RFC8446.
94pub(crate) fn construct_server_verify_message(handshake_hash: &hash::Output) -> VerifyMessage {
95 VerifyMessage::new(handshake_hash, SERVER_CONSTANT)
96}
97
98pub(crate) struct VerifyMessage {
99 buf: [u8; MAX_VERIFY_MSG],
100 used: usize,
101}
102
103impl VerifyMessage {
104 fn new(handshake_hash: &hash::Output, context_string_with_0: &[u8; 34]) -> Self {
105 let used: usize = 64 + context_string_with_0.len() + handshake_hash.as_ref().len();
106 let mut buf: [u8; 162] = [0x20u8; MAX_VERIFY_MSG];
107
108 let (_spaces: &mut [u8], context: &mut [u8]) = buf.split_at_mut(mid:64);
109 let (context: &mut [u8], hash: &mut [u8]) = context.split_at_mut(mid:34);
110 context.copy_from_slice(src:context_string_with_0);
111 hash[..handshake_hash.as_ref().len()].copy_from_slice(src:handshake_hash.as_ref());
112
113 Self { buf, used }
114 }
115}
116
117impl AsRef<[u8]> for VerifyMessage {
118 fn as_ref(&self) -> &[u8] {
119 &self.buf[..self.used]
120 }
121}
122
123const SERVER_CONSTANT: &[u8; 34] = b"TLS 1.3, server CertificateVerify\x00";
124const CLIENT_CONSTANT: &[u8; 34] = b"TLS 1.3, client CertificateVerify\x00";
125const MAX_VERIFY_MSG: usize = 64 + CLIENT_CONSTANT.len() + hash::Output::MAX_LEN;
126