/rust/registry/src/index.crates.io-6f17d22bba15001f/rustls-0.23.22/src/tls13/mod.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use core::fmt; |
2 | | |
3 | | use crate::crypto; |
4 | | use crate::crypto::hash; |
5 | | use crate::suites::{CipherSuiteCommon, SupportedCipherSuite}; |
6 | | |
7 | | pub(crate) mod key_schedule; |
8 | | |
9 | | /// A TLS 1.3 cipher suite supported by rustls. |
10 | | pub 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 | | |
38 | | impl Tls13CipherSuite { |
39 | | /// Can a session using suite self resume from suite prev? |
40 | 0 | pub fn can_resume_from(&self, prev: &'static Self) -> Option<&'static Self> { |
41 | 0 | (prev.common.hash_provider.algorithm() == self.common.hash_provider.algorithm()) |
42 | 0 | .then_some(prev) |
43 | 0 | } |
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 | 0 | pub fn fips(&self) -> bool { |
49 | 0 | let Self { |
50 | 0 | common, |
51 | 0 | hkdf_provider, |
52 | 0 | aead_alg, |
53 | 0 | quic, |
54 | 0 | } = self; |
55 | 0 | common.fips() |
56 | 0 | && hkdf_provider.fips() |
57 | 0 | && aead_alg.fips() |
58 | 0 | && quic.map(|q| q.fips()).unwrap_or(true) |
59 | 0 | } |
60 | | |
61 | | /// Returns a `quic::Suite` for the ciphersuite, if supported. |
62 | 0 | pub fn quic_suite(&'static self) -> Option<crate::quic::Suite> { |
63 | 0 | self.quic |
64 | 0 | .map(|quic| crate::quic::Suite { quic, suite: self }) |
65 | 0 | } |
66 | | } |
67 | | |
68 | | impl From<&'static Tls13CipherSuite> for SupportedCipherSuite { |
69 | 0 | fn from(s: &'static Tls13CipherSuite) -> Self { |
70 | 0 | Self::Tls13(s) |
71 | 0 | } |
72 | | } |
73 | | |
74 | | impl PartialEq for Tls13CipherSuite { |
75 | 0 | fn eq(&self, other: &Self) -> bool { |
76 | 0 | self.common.suite == other.common.suite |
77 | 0 | } |
78 | | } |
79 | | |
80 | | impl fmt::Debug for Tls13CipherSuite { |
81 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
82 | 0 | f.debug_struct("Tls13CipherSuite") |
83 | 0 | .field("suite", &self.common.suite) |
84 | 0 | .finish() |
85 | 0 | } |
86 | | } |
87 | | |
88 | | /// Constructs the signature message specified in section 4.4.3 of RFC8446. |
89 | 0 | pub(crate) fn construct_client_verify_message(handshake_hash: &hash::Output) -> VerifyMessage { |
90 | 0 | VerifyMessage::new(handshake_hash, CLIENT_CONSTANT) |
91 | 0 | } |
92 | | |
93 | | /// Constructs the signature message specified in section 4.4.3 of RFC8446. |
94 | 0 | pub(crate) fn construct_server_verify_message(handshake_hash: &hash::Output) -> VerifyMessage { |
95 | 0 | VerifyMessage::new(handshake_hash, SERVER_CONSTANT) |
96 | 0 | } |
97 | | |
98 | | pub(crate) struct VerifyMessage { |
99 | | buf: [u8; MAX_VERIFY_MSG], |
100 | | used: usize, |
101 | | } |
102 | | |
103 | | impl VerifyMessage { |
104 | 0 | fn new(handshake_hash: &hash::Output, context_string_with_0: &[u8; 34]) -> Self { |
105 | 0 | let used = 64 + context_string_with_0.len() + handshake_hash.as_ref().len(); |
106 | 0 | let mut buf = [0x20u8; MAX_VERIFY_MSG]; |
107 | 0 |
|
108 | 0 | let (_spaces, context) = buf.split_at_mut(64); |
109 | 0 | let (context, hash) = context.split_at_mut(34); |
110 | 0 | context.copy_from_slice(context_string_with_0); |
111 | 0 | hash[..handshake_hash.as_ref().len()].copy_from_slice(handshake_hash.as_ref()); |
112 | 0 |
|
113 | 0 | Self { buf, used } |
114 | 0 | } |
115 | | } |
116 | | |
117 | | impl AsRef<[u8]> for VerifyMessage { |
118 | 0 | fn as_ref(&self) -> &[u8] { |
119 | 0 | &self.buf[..self.used] |
120 | 0 | } |
121 | | } |
122 | | |
123 | | const SERVER_CONSTANT: &[u8; 34] = b"TLS 1.3, server CertificateVerify\x00"; |
124 | | const CLIENT_CONSTANT: &[u8; 34] = b"TLS 1.3, client CertificateVerify\x00"; |
125 | | const MAX_VERIFY_MSG: usize = 64 + CLIENT_CONSTANT.len() + hash::Output::MAX_LEN; |