1 #[cfg(test)]
2 mod prf_test;
3
4 use std::convert::TryInto;
5 use std::fmt;
6
7 use hmac::{Hmac, Mac};
8 use sha1::Sha1;
9 use sha2::Digest;
10 use sha2::Sha256;
11
12 type HmacSha256 = Hmac<Sha256>;
13 type HmacSha1 = Hmac<Sha1>;
14
15 use crate::cipher_suite::CipherSuiteHash;
16 use crate::content::ContentType;
17 use crate::curve::named_curve::*;
18 use crate::error::*;
19 use crate::record_layer::record_layer_header::ProtocolVersion;
20
21 pub(crate) const PRF_MASTER_SECRET_LABEL: &str = "master secret";
22 pub(crate) const PRF_EXTENDED_MASTER_SECRET_LABEL: &str = "extended master secret";
23 pub(crate) const PRF_KEY_EXPANSION_LABEL: &str = "key expansion";
24 pub(crate) const PRF_VERIFY_DATA_CLIENT_LABEL: &str = "client finished";
25 pub(crate) const PRF_VERIFY_DATA_SERVER_LABEL: &str = "server finished";
26
27 #[derive(PartialEq, Debug, Clone)]
28 pub(crate) struct EncryptionKeys {
29 pub(crate) master_secret: Vec<u8>,
30 pub(crate) client_mac_key: Vec<u8>,
31 pub(crate) server_mac_key: Vec<u8>,
32 pub(crate) client_write_key: Vec<u8>,
33 pub(crate) server_write_key: Vec<u8>,
34 pub(crate) client_write_iv: Vec<u8>,
35 pub(crate) server_write_iv: Vec<u8>,
36 }
37
38 impl fmt::Display for EncryptionKeys {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 let mut out = "EncryptionKeys:\n".to_string();
41
42 out += format!("- master_secret: {:?}\n", self.master_secret).as_str();
43 out += format!("- client_mackey: {:?}\n", self.client_mac_key).as_str();
44 out += format!("- server_mackey: {:?}\n", self.server_mac_key).as_str();
45 out += format!("- client_write_key: {:?}\n", self.client_write_key).as_str();
46 out += format!("- server_write_key: {:?}\n", self.server_write_key).as_str();
47 out += format!("- client_write_iv: {:?}\n", self.client_write_iv).as_str();
48 out += format!("- server_write_iv: {:?}\n", self.server_write_iv).as_str();
49
50 write!(f, "{out}")
51 }
52 }
53
54 // The premaster secret is formed as follows: if the PSK is N octets
55 // long, concatenate a uint16 with the value N, N zero octets, a second
56 // uint16 with the value N, and the PSK itself.
57 //
58 // https://tools.ietf.org/html/rfc4279#section-2
prf_psk_pre_master_secret(psk: &[u8]) -> Vec<u8>59 pub(crate) fn prf_psk_pre_master_secret(psk: &[u8]) -> Vec<u8> {
60 let psk_len = psk.len();
61
62 let mut out = vec![0u8; 2 + psk_len + 2];
63
64 out.extend_from_slice(psk);
65 let be = (psk_len as u16).to_be_bytes();
66 out[..2].copy_from_slice(&be);
67 out[2 + psk_len..2 + psk_len + 2].copy_from_slice(&be);
68
69 out
70 }
71
prf_pre_master_secret( public_key: &[u8], private_key: &NamedCurvePrivateKey, curve: NamedCurve, ) -> Result<Vec<u8>>72 pub(crate) fn prf_pre_master_secret(
73 public_key: &[u8],
74 private_key: &NamedCurvePrivateKey,
75 curve: NamedCurve,
76 ) -> Result<Vec<u8>> {
77 match curve {
78 NamedCurve::P256 => elliptic_curve_pre_master_secret(public_key, private_key, curve),
79 NamedCurve::P384 => elliptic_curve_pre_master_secret(public_key, private_key, curve),
80 NamedCurve::X25519 => elliptic_curve_pre_master_secret(public_key, private_key, curve),
81 _ => Err(Error::ErrInvalidNamedCurve),
82 }
83 }
84
elliptic_curve_pre_master_secret( public_key: &[u8], private_key: &NamedCurvePrivateKey, curve: NamedCurve, ) -> Result<Vec<u8>>85 fn elliptic_curve_pre_master_secret(
86 public_key: &[u8],
87 private_key: &NamedCurvePrivateKey,
88 curve: NamedCurve,
89 ) -> Result<Vec<u8>> {
90 match curve {
91 NamedCurve::P256 => {
92 let pub_key = p256::EncodedPoint::from_bytes(public_key)?;
93 let public = p256::PublicKey::from_sec1_bytes(pub_key.as_ref())?;
94 if let NamedCurvePrivateKey::EphemeralSecretP256(secret) = private_key {
95 return Ok(secret.diffie_hellman(&public).raw_secret_bytes().to_vec());
96 }
97 }
98 NamedCurve::P384 => {
99 let pub_key = p384::EncodedPoint::from_bytes(public_key)?;
100 let public = p384::PublicKey::from_sec1_bytes(pub_key.as_ref())?;
101 if let NamedCurvePrivateKey::EphemeralSecretP384(secret) = private_key {
102 return Ok(secret.diffie_hellman(&public).raw_secret_bytes().to_vec());
103 }
104 }
105 NamedCurve::X25519 => {
106 if public_key.len() != 32 {
107 return Err(Error::Other("Public key is not 32 len".into()));
108 }
109 let pub_key: [u8; 32] = public_key.try_into().unwrap();
110 let public = x25519_dalek::PublicKey::from(pub_key);
111 if let NamedCurvePrivateKey::StaticSecretX25519(secret) = private_key {
112 return Ok(secret.diffie_hellman(&public).as_bytes().to_vec());
113 }
114 }
115 _ => return Err(Error::ErrInvalidNamedCurve),
116 }
117 Err(Error::ErrNamedCurveAndPrivateKeyMismatch)
118 }
119
120 // This PRF with the SHA-256 hash function is used for all cipher suites
121 // defined in this document and in TLS documents published prior to this
122 // document when TLS 1.2 is negotiated. New cipher suites MUST explicitly
123 // specify a PRF and, in general, SHOULD use the TLS PRF with SHA-256 or a
124 // stronger standard hash function.
125 //
126 // P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
127 // HMAC_hash(secret, A(2) + seed) +
128 // HMAC_hash(secret, A(3) + seed) + ...
129 //
130 // A() is defined as:
131 //
132 // A(0) = seed
133 // A(i) = HMAC_hash(secret, A(i-1))
134 //
135 // P_hash can be iterated as many times as necessary to produce the
136 // required quantity of data. For example, if P_SHA256 is being used to
137 // create 80 bytes of data, it will have to be iterated three times
138 // (through A(3)), creating 96 bytes of output data; the last 16 bytes
139 // of the final iteration will then be discarded, leaving 80 bytes of
140 // output data.
141 //
142 // https://tools.ietf.org/html/rfc4346w
hmac_sha(h: CipherSuiteHash, key: &[u8], data: &[u8]) -> Result<Vec<u8>>143 fn hmac_sha(h: CipherSuiteHash, key: &[u8], data: &[u8]) -> Result<Vec<u8>> {
144 let mut mac = match h {
145 CipherSuiteHash::Sha256 => {
146 HmacSha256::new_from_slice(key).map_err(|e| Error::Other(e.to_string()))?
147 }
148 };
149 mac.update(data);
150 let result = mac.finalize();
151 let code_bytes = result.into_bytes();
152 Ok(code_bytes.to_vec())
153 }
154
prf_p_hash( secret: &[u8], seed: &[u8], requested_length: usize, h: CipherSuiteHash, ) -> Result<Vec<u8>>155 pub(crate) fn prf_p_hash(
156 secret: &[u8],
157 seed: &[u8],
158 requested_length: usize,
159 h: CipherSuiteHash,
160 ) -> Result<Vec<u8>> {
161 let mut last_round = seed.to_vec();
162 let mut out = vec![];
163
164 let iterations = ((requested_length as f64) / (h.size() as f64)).ceil() as usize;
165 for _ in 0..iterations {
166 last_round = hmac_sha(h, secret, &last_round)?;
167
168 let mut last_round_seed = last_round.clone();
169 last_round_seed.extend_from_slice(seed);
170 let with_secret = hmac_sha(h, secret, &last_round_seed)?;
171
172 out.extend_from_slice(&with_secret);
173 }
174
175 Ok(out[..requested_length].to_vec())
176 }
177
prf_extended_master_secret( pre_master_secret: &[u8], session_hash: &[u8], h: CipherSuiteHash, ) -> Result<Vec<u8>>178 pub(crate) fn prf_extended_master_secret(
179 pre_master_secret: &[u8],
180 session_hash: &[u8],
181 h: CipherSuiteHash,
182 ) -> Result<Vec<u8>> {
183 let mut seed = PRF_EXTENDED_MASTER_SECRET_LABEL.as_bytes().to_vec();
184 seed.extend_from_slice(session_hash);
185 prf_p_hash(pre_master_secret, &seed, 48, h)
186 }
187
prf_master_secret( pre_master_secret: &[u8], client_random: &[u8], server_random: &[u8], h: CipherSuiteHash, ) -> Result<Vec<u8>>188 pub(crate) fn prf_master_secret(
189 pre_master_secret: &[u8],
190 client_random: &[u8],
191 server_random: &[u8],
192 h: CipherSuiteHash,
193 ) -> Result<Vec<u8>> {
194 let mut seed = PRF_MASTER_SECRET_LABEL.as_bytes().to_vec();
195 seed.extend_from_slice(client_random);
196 seed.extend_from_slice(server_random);
197 prf_p_hash(pre_master_secret, &seed, 48, h)
198 }
199
prf_encryption_keys( master_secret: &[u8], client_random: &[u8], server_random: &[u8], prf_mac_len: usize, prf_key_len: usize, prf_iv_len: usize, h: CipherSuiteHash, ) -> Result<EncryptionKeys>200 pub(crate) fn prf_encryption_keys(
201 master_secret: &[u8],
202 client_random: &[u8],
203 server_random: &[u8],
204 prf_mac_len: usize,
205 prf_key_len: usize,
206 prf_iv_len: usize,
207 h: CipherSuiteHash,
208 ) -> Result<EncryptionKeys> {
209 let mut seed = PRF_KEY_EXPANSION_LABEL.as_bytes().to_vec();
210 seed.extend_from_slice(server_random);
211 seed.extend_from_slice(client_random);
212
213 let material = prf_p_hash(
214 master_secret,
215 &seed,
216 (2 * prf_mac_len) + (2 * prf_key_len) + (2 * prf_iv_len),
217 h,
218 )?;
219 let mut key_material = &material[..];
220
221 let client_mac_key = key_material[..prf_mac_len].to_vec();
222 key_material = &key_material[prf_mac_len..];
223
224 let server_mac_key = key_material[..prf_mac_len].to_vec();
225 key_material = &key_material[prf_mac_len..];
226
227 let client_write_key = key_material[..prf_key_len].to_vec();
228 key_material = &key_material[prf_key_len..];
229
230 let server_write_key = key_material[..prf_key_len].to_vec();
231 key_material = &key_material[prf_key_len..];
232
233 let client_write_iv = key_material[..prf_iv_len].to_vec();
234 key_material = &key_material[prf_iv_len..];
235
236 let server_write_iv = key_material[..prf_iv_len].to_vec();
237
238 Ok(EncryptionKeys {
239 master_secret: master_secret.to_vec(),
240 client_mac_key,
241 server_mac_key,
242 client_write_key,
243 server_write_key,
244 client_write_iv,
245 server_write_iv,
246 })
247 }
248
prf_verify_data( master_secret: &[u8], handshake_bodies: &[u8], label: &str, h: CipherSuiteHash, ) -> Result<Vec<u8>>249 pub(crate) fn prf_verify_data(
250 master_secret: &[u8],
251 handshake_bodies: &[u8],
252 label: &str,
253 h: CipherSuiteHash,
254 ) -> Result<Vec<u8>> {
255 let mut hasher = match h {
256 CipherSuiteHash::Sha256 => Sha256::new(),
257 };
258 hasher.update(handshake_bodies);
259 let result = hasher.finalize();
260 let mut seed = label.as_bytes().to_vec();
261 seed.extend_from_slice(&result);
262
263 prf_p_hash(master_secret, &seed, 12, h)
264 }
265
prf_verify_data_client( master_secret: &[u8], handshake_bodies: &[u8], h: CipherSuiteHash, ) -> Result<Vec<u8>>266 pub(crate) fn prf_verify_data_client(
267 master_secret: &[u8],
268 handshake_bodies: &[u8],
269 h: CipherSuiteHash,
270 ) -> Result<Vec<u8>> {
271 prf_verify_data(
272 master_secret,
273 handshake_bodies,
274 PRF_VERIFY_DATA_CLIENT_LABEL,
275 h,
276 )
277 }
278
prf_verify_data_server( master_secret: &[u8], handshake_bodies: &[u8], h: CipherSuiteHash, ) -> Result<Vec<u8>>279 pub(crate) fn prf_verify_data_server(
280 master_secret: &[u8],
281 handshake_bodies: &[u8],
282 h: CipherSuiteHash,
283 ) -> Result<Vec<u8>> {
284 prf_verify_data(
285 master_secret,
286 handshake_bodies,
287 PRF_VERIFY_DATA_SERVER_LABEL,
288 h,
289 )
290 }
291
292 // compute the MAC using HMAC-SHA1
prf_mac( epoch: u16, sequence_number: u64, content_type: ContentType, protocol_version: ProtocolVersion, payload: &[u8], key: &[u8], ) -> Result<Vec<u8>>293 pub(crate) fn prf_mac(
294 epoch: u16,
295 sequence_number: u64,
296 content_type: ContentType,
297 protocol_version: ProtocolVersion,
298 payload: &[u8],
299 key: &[u8],
300 ) -> Result<Vec<u8>> {
301 let mut hmac = HmacSha1::new_from_slice(key).map_err(|e| Error::Other(e.to_string()))?;
302
303 let mut msg = vec![0u8; 13];
304 msg[..2].copy_from_slice(&epoch.to_be_bytes());
305 msg[2..8].copy_from_slice(&sequence_number.to_be_bytes()[2..]);
306 msg[8] = content_type as u8;
307 msg[9] = protocol_version.major;
308 msg[10] = protocol_version.minor;
309 msg[11..].copy_from_slice(&(payload.len() as u16).to_be_bytes());
310
311 hmac.update(&msg);
312 hmac.update(payload);
313 let result = hmac.finalize();
314
315 Ok(result.into_bytes().to_vec())
316 }
317