/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.40/src/crypto/tls12.rs
Line | Count | Source |
1 | | use alloc::boxed::Box; |
2 | | |
3 | | use super::{ActiveKeyExchange, hmac}; |
4 | | use crate::error::Error; |
5 | | use crate::version::TLS12; |
6 | | |
7 | | /// Implements [`Prf`] using a [`hmac::Hmac`]. |
8 | | pub struct PrfUsingHmac<'a>(pub &'a dyn hmac::Hmac); |
9 | | |
10 | | impl Prf for PrfUsingHmac<'_> { |
11 | 0 | fn for_key_exchange( |
12 | 0 | &self, |
13 | 0 | output: &mut [u8; 48], |
14 | 0 | kx: Box<dyn ActiveKeyExchange>, |
15 | 0 | peer_pub_key: &[u8], |
16 | 0 | label: &[u8], |
17 | 0 | seed: &[u8], |
18 | 0 | ) -> Result<(), Error> { |
19 | 0 | prf( |
20 | 0 | output, |
21 | 0 | self.0 |
22 | 0 | .with_key( |
23 | 0 | kx.complete_for_tls_version(peer_pub_key, &TLS12)? |
24 | 0 | .secret_bytes(), |
25 | | ) |
26 | 0 | .as_ref(), |
27 | 0 | label, |
28 | 0 | seed, |
29 | | ); |
30 | 0 | Ok(()) |
31 | 0 | } |
32 | | |
33 | 0 | fn for_secret(&self, output: &mut [u8], secret: &[u8], label: &[u8], seed: &[u8]) { |
34 | 0 | prf(output, self.0.with_key(secret).as_ref(), label, seed); |
35 | 0 | } |
36 | | } |
37 | | |
38 | | /// An instantiation of the TLS1.2 PRF with a specific, implicit hash function. |
39 | | /// |
40 | | /// See the definition in [RFC5246 section 5](https://www.rfc-editor.org/rfc/rfc5246#section-5). |
41 | | /// |
42 | | /// See [`PrfUsingHmac`] as a route to implementing this trait with just |
43 | | /// an implementation of [`hmac::Hmac`]. |
44 | | pub trait Prf: Send + Sync { |
45 | | /// Computes `PRF(secret, label, seed)` using the secret from a completed key exchange. |
46 | | /// |
47 | | /// Completes the given key exchange, and then uses the resulting shared secret |
48 | | /// to compute the PRF, writing the result into `output`. |
49 | | /// |
50 | | /// The caller guarantees that `label`, `seed` are non-empty. The caller makes no |
51 | | /// guarantees about the contents of `peer_pub_key`. It must be validated by |
52 | | /// [`ActiveKeyExchange::complete`]. |
53 | | fn for_key_exchange( |
54 | | &self, |
55 | | output: &mut [u8; 48], |
56 | | kx: Box<dyn ActiveKeyExchange>, |
57 | | peer_pub_key: &[u8], |
58 | | label: &[u8], |
59 | | seed: &[u8], |
60 | | ) -> Result<(), Error>; |
61 | | |
62 | | /// Computes `PRF(secret, label, seed)`, writing the result into `output`. |
63 | | /// |
64 | | /// The caller guarantees that `secret`, `label`, and `seed` are non-empty. |
65 | | fn for_secret(&self, output: &mut [u8], secret: &[u8], label: &[u8], seed: &[u8]); |
66 | | |
67 | | /// Return `true` if this is backed by a FIPS-approved implementation. |
68 | 0 | fn fips(&self) -> bool { |
69 | 0 | false |
70 | 0 | } |
71 | | } |
72 | | |
73 | 0 | pub(crate) fn prf(out: &mut [u8], hmac_key: &dyn hmac::Key, label: &[u8], seed: &[u8]) { |
74 | | // A(1) |
75 | 0 | let mut current_a = hmac_key.sign(&[label, seed]); |
76 | | |
77 | 0 | let chunk_size = hmac_key.tag_len(); |
78 | 0 | for chunk in out.chunks_mut(chunk_size) { |
79 | 0 | // P_hash[i] = HMAC_hash(secret, A(i) + seed) |
80 | 0 | let p_term = hmac_key.sign(&[current_a.as_ref(), label, seed]); |
81 | 0 | chunk.copy_from_slice(&p_term.as_ref()[..chunk.len()]); |
82 | 0 |
|
83 | 0 | // A(i+1) = HMAC_hash(secret, A(i)) |
84 | 0 | current_a = hmac_key.sign(&[current_a.as_ref()]); |
85 | 0 | } |
86 | 0 | } |
87 | | |
88 | | #[cfg(all(test, feature = "ring"))] |
89 | | mod tests { |
90 | | use crate::crypto::hmac::Hmac; |
91 | | // nb: crypto::aws_lc_rs provider doesn't provide (or need) hmac, |
92 | | // so cannot be used for this test. |
93 | | use crate::crypto::ring::hmac; |
94 | | |
95 | | // Below known answer tests come from https://mailarchive.ietf.org/arch/msg/tls/fzVCzk-z3FShgGJ6DOXqM1ydxms/ |
96 | | |
97 | | #[test] |
98 | | fn check_sha256() { |
99 | | let secret = b"\x9b\xbe\x43\x6b\xa9\x40\xf0\x17\xb1\x76\x52\x84\x9a\x71\xdb\x35"; |
100 | | let seed = b"\xa0\xba\x9f\x93\x6c\xda\x31\x18\x27\xa6\xf7\x96\xff\xd5\x19\x8c"; |
101 | | let label = b"test label"; |
102 | | let expect = include_bytes!("../testdata/prf-result.1.bin"); |
103 | | let mut output = [0u8; 100]; |
104 | | |
105 | | super::prf( |
106 | | &mut output, |
107 | | &*hmac::HMAC_SHA256.with_key(secret), |
108 | | label, |
109 | | seed, |
110 | | ); |
111 | | assert_eq!(expect.len(), output.len()); |
112 | | assert_eq!(expect.to_vec(), output.to_vec()); |
113 | | } |
114 | | |
115 | | #[test] |
116 | | fn check_sha512() { |
117 | | let secret = b"\xb0\x32\x35\x23\xc1\x85\x35\x99\x58\x4d\x88\x56\x8b\xbb\x05\xeb"; |
118 | | let seed = b"\xd4\x64\x0e\x12\xe4\xbc\xdb\xfb\x43\x7f\x03\xe6\xae\x41\x8e\xe5"; |
119 | | let label = b"test label"; |
120 | | let expect = include_bytes!("../testdata/prf-result.2.bin"); |
121 | | let mut output = [0u8; 196]; |
122 | | |
123 | | super::prf( |
124 | | &mut output, |
125 | | &*hmac::HMAC_SHA512.with_key(secret), |
126 | | label, |
127 | | seed, |
128 | | ); |
129 | | assert_eq!(expect.len(), output.len()); |
130 | | assert_eq!(expect.to_vec(), output.to_vec()); |
131 | | } |
132 | | |
133 | | #[test] |
134 | | fn check_sha384() { |
135 | | let secret = b"\xb8\x0b\x73\x3d\x6c\xee\xfc\xdc\x71\x56\x6e\xa4\x8e\x55\x67\xdf"; |
136 | | let seed = b"\xcd\x66\x5c\xf6\xa8\x44\x7d\xd6\xff\x8b\x27\x55\x5e\xdb\x74\x65"; |
137 | | let label = b"test label"; |
138 | | let expect = include_bytes!("../testdata/prf-result.3.bin"); |
139 | | let mut output = [0u8; 148]; |
140 | | |
141 | | super::prf( |
142 | | &mut output, |
143 | | &*hmac::HMAC_SHA384.with_key(secret), |
144 | | label, |
145 | | seed, |
146 | | ); |
147 | | assert_eq!(expect.len(), output.len()); |
148 | | assert_eq!(expect.to_vec(), output.to_vec()); |
149 | | } |
150 | | } |
151 | | |
152 | | #[cfg(all(bench, feature = "ring"))] |
153 | | mod benchmarks { |
154 | | #[bench] |
155 | | fn bench_sha256(b: &mut test::Bencher) { |
156 | | use crate::crypto::hmac::Hmac; |
157 | | use crate::crypto::ring::hmac; |
158 | | |
159 | | let label = &b"extended master secret"[..]; |
160 | | let seed = [0u8; 32]; |
161 | | let key = &b"secret"[..]; |
162 | | |
163 | | b.iter(|| { |
164 | | let mut out = [0u8; 48]; |
165 | | super::prf(&mut out, &*hmac::HMAC_SHA256.with_key(key), &label, &seed); |
166 | | test::black_box(out); |
167 | | }); |
168 | | } |
169 | | } |