1 /// Key schedule maintenance for TLS1.3
2
3 use ring::{aead, hkdf::{self, KeyType as _}, hmac, digest};
4 use crate::error::TLSError;
5 use crate::cipher::{Iv, IvLen};
6 use crate::msgs::base::PayloadU8;
7 use crate::KeyLog;
8
9 /// The kinds of secret we can extract from `KeySchedule`.
10 #[derive(Debug, Clone, Copy, PartialEq)]
11 enum SecretKind {
12 ResumptionPSKBinderKey,
13 ClientEarlyTrafficSecret,
14 ClientHandshakeTrafficSecret,
15 ServerHandshakeTrafficSecret,
16 ClientApplicationTrafficSecret,
17 ServerApplicationTrafficSecret,
18 ExporterMasterSecret,
19 ResumptionMasterSecret,
20 DerivedSecret,
21 }
22
23 impl SecretKind {
to_bytes(self) -> &'static [u8]24 fn to_bytes(self) -> &'static [u8] {
25 match self {
26 SecretKind::ResumptionPSKBinderKey => b"res binder",
27 SecretKind::ClientEarlyTrafficSecret => b"c e traffic",
28 SecretKind::ClientHandshakeTrafficSecret => b"c hs traffic",
29 SecretKind::ServerHandshakeTrafficSecret => b"s hs traffic",
30 SecretKind::ClientApplicationTrafficSecret => b"c ap traffic",
31 SecretKind::ServerApplicationTrafficSecret => b"s ap traffic",
32 SecretKind::ExporterMasterSecret => b"exp master",
33 SecretKind::ResumptionMasterSecret => b"res master",
34 SecretKind::DerivedSecret => b"derived",
35 }
36 }
37
log_label(self) -> Option<&'static str>38 fn log_label(self) -> Option<&'static str> {
39 use self::SecretKind::*;
40 Some(match self {
41 ClientEarlyTrafficSecret => "CLIENT_EARLY_TRAFFIC_SECRET",
42 ClientHandshakeTrafficSecret => "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
43 ServerHandshakeTrafficSecret => "SERVER_HANDSHAKE_TRAFFIC_SECRET",
44 ClientApplicationTrafficSecret => "CLIENT_TRAFFIC_SECRET_0",
45 ServerApplicationTrafficSecret => "SERVER_TRAFFIC_SECRET_0",
46 ExporterMasterSecret => "EXPORTER_SECRET",
47 _ => { return None; }
48 })
49 }
50 }
51
52 /// This is the TLS1.3 key schedule. It stores the current secret and
53 /// the type of hash. This isn't used directly; but only through the
54 /// typestates.
55 struct KeySchedule {
56 current: hkdf::Prk,
57 algorithm: ring::hkdf::Algorithm,
58 }
59
60 // We express the state of a contained KeySchedule using these
61 // typestates. This means we can write code that cannot accidentally
62 // (eg) encrypt application data using a KeySchedule solely constructed
63 // with an empty or trivial secret, or extract the wrong kind of secrets
64 // at a given point.
65
66 /// KeySchedule for early data stage.
67 pub struct KeyScheduleEarly {
68 ks: KeySchedule,
69 }
70
71 impl KeyScheduleEarly {
new(algorithm: hkdf::Algorithm, secret: &[u8]) -> KeyScheduleEarly72 pub fn new(algorithm: hkdf::Algorithm, secret: &[u8]) -> KeyScheduleEarly {
73 KeyScheduleEarly { ks: KeySchedule::new(algorithm, secret) }
74 }
75
client_early_traffic_secret(&self, hs_hash: &[u8], key_log: &dyn KeyLog, client_random: &[u8; 32]) -> hkdf::Prk76 pub fn client_early_traffic_secret(&self,
77 hs_hash: &[u8],
78 key_log: &dyn KeyLog,
79 client_random: &[u8; 32]) -> hkdf::Prk {
80 self.ks.derive_logged_secret(SecretKind::ClientEarlyTrafficSecret,
81 hs_hash, key_log, client_random)
82 }
83
resumption_psk_binder_key_and_sign_verify_data(&self, hs_hash: &[u8]) -> Vec<u8>84 pub fn resumption_psk_binder_key_and_sign_verify_data(&self, hs_hash: &[u8]) -> Vec<u8> {
85 let resumption_psk_binder_key = self.ks.derive_for_empty_hash(SecretKind::ResumptionPSKBinderKey);
86 self.ks.sign_verify_data(&resumption_psk_binder_key, hs_hash)
87 }
88
into_handshake(mut self, secret: &[u8]) -> KeyScheduleHandshake89 pub fn into_handshake(mut self, secret: &[u8]) -> KeyScheduleHandshake {
90 self.ks.input_secret(secret);
91 KeyScheduleHandshake {
92 ks: self.ks,
93 current_client_traffic_secret: None,
94 current_server_traffic_secret: None,
95 }
96 }
97 }
98
99 /// KeySchedule for skipping early data stage. No secrets can be extracted
100 /// (since there are none), but the handshake secret can be input.
101 pub struct KeyScheduleNonSecret {
102 ks: KeySchedule,
103 }
104
105 impl KeyScheduleNonSecret {
new(algorithm: hkdf::Algorithm) -> KeyScheduleNonSecret106 pub fn new(algorithm: hkdf::Algorithm) -> KeyScheduleNonSecret {
107 KeyScheduleNonSecret { ks: KeySchedule::new_with_empty_secret(algorithm) }
108 }
109
into_handshake(mut self, secret: &[u8]) -> KeyScheduleHandshake110 pub fn into_handshake(mut self, secret: &[u8]) -> KeyScheduleHandshake {
111 self.ks.input_secret(secret);
112 KeyScheduleHandshake {
113 ks: self.ks,
114 current_client_traffic_secret: None,
115 current_server_traffic_secret: None,
116 }
117 }
118 }
119
120 /// KeySchedule during handshake.
121 pub struct KeyScheduleHandshake {
122 ks: KeySchedule,
123 current_client_traffic_secret: Option<hkdf::Prk>,
124 current_server_traffic_secret: Option<hkdf::Prk>,
125 }
126
127 impl KeyScheduleHandshake {
client_handshake_traffic_secret(&mut self, hs_hash: &[u8], key_log: &dyn KeyLog, client_random: &[u8; 32]) -> hkdf::Prk128 pub fn client_handshake_traffic_secret(&mut self, hs_hash: &[u8],
129 key_log: &dyn KeyLog,
130 client_random: &[u8; 32]) -> hkdf::Prk {
131 let secret = self.ks.derive_logged_secret(SecretKind::ClientHandshakeTrafficSecret,
132 hs_hash, key_log, client_random);
133 self.current_client_traffic_secret = Some(secret.clone());
134 secret
135 }
136
server_handshake_traffic_secret(&mut self, hs_hash: &[u8], key_log: &dyn KeyLog, client_random: &[u8; 32]) -> hkdf::Prk137 pub fn server_handshake_traffic_secret(&mut self, hs_hash: &[u8],
138 key_log: &dyn KeyLog,
139 client_random: &[u8; 32]) -> hkdf::Prk {
140 let secret = self.ks.derive_logged_secret(SecretKind::ServerHandshakeTrafficSecret,
141 hs_hash, key_log, client_random);
142 self.current_server_traffic_secret = Some(secret.clone());
143 secret
144 }
145
sign_server_finish(&self, hs_hash: &[u8]) -> Vec<u8>146 pub fn sign_server_finish(&self, hs_hash: &[u8]) -> Vec<u8> {
147 self.ks.sign_finish(self.current_server_traffic_secret.as_ref().unwrap(), hs_hash)
148 }
149
into_traffic_with_client_finished_pending(mut self) -> KeyScheduleTrafficWithClientFinishedPending150 pub fn into_traffic_with_client_finished_pending(mut self) -> KeyScheduleTrafficWithClientFinishedPending {
151 self.ks.input_empty();
152 KeyScheduleTrafficWithClientFinishedPending {
153 ks: self.ks,
154 handshake_client_traffic_secret: self.current_client_traffic_secret.unwrap(),
155 current_client_traffic_secret: None,
156 current_server_traffic_secret: None,
157 current_exporter_secret: None
158 }
159 }
160 }
161
162 /// KeySchedule during traffic stage, retaining the ability to calculate the client's
163 /// finished verify_data, and incrementally generate the first traffic keys.
164 pub struct KeyScheduleTrafficWithClientFinishedPending {
165 ks: KeySchedule,
166 handshake_client_traffic_secret: hkdf::Prk,
167 current_client_traffic_secret: Option<hkdf::Prk>,
168 current_server_traffic_secret: Option<hkdf::Prk>,
169 current_exporter_secret: Option<hkdf::Prk>,
170 }
171
172 impl KeyScheduleTrafficWithClientFinishedPending {
sign_client_finish(&self, hs_hash: &[u8]) -> Vec<u8>173 pub fn sign_client_finish(&self, hs_hash: &[u8]) -> Vec<u8> {
174 self.ks.sign_finish(&self.handshake_client_traffic_secret, hs_hash)
175 }
176
server_application_traffic_secret(&mut self, hs_hash: &[u8], key_log: &dyn KeyLog, client_random: &[u8; 32]) -> hkdf::Prk177 pub fn server_application_traffic_secret(&mut self, hs_hash: &[u8],
178 key_log: &dyn KeyLog,
179 client_random: &[u8; 32]) -> hkdf::Prk {
180 let secret = self.ks.derive_logged_secret(SecretKind::ServerApplicationTrafficSecret,
181 hs_hash, key_log, client_random);
182 self.current_server_traffic_secret = Some(secret.clone());
183 secret
184 }
185
client_application_traffic_secret(&mut self, hs_hash: &[u8], key_log: &dyn KeyLog, client_random: &[u8; 32]) -> hkdf::Prk186 pub fn client_application_traffic_secret(&mut self, hs_hash: &[u8],
187 key_log: &dyn KeyLog,
188 client_random: &[u8; 32]) -> hkdf::Prk {
189 let secret = self.ks.derive_logged_secret(SecretKind::ClientApplicationTrafficSecret,
190 hs_hash, key_log, client_random);
191 self.current_client_traffic_secret = Some(secret.clone());
192 secret
193 }
194
exporter_master_secret(&mut self, hs_hash: &[u8], key_log: &dyn KeyLog, client_random: &[u8; 32])195 pub fn exporter_master_secret(&mut self, hs_hash: &[u8],
196 key_log: &dyn KeyLog,
197 client_random: &[u8; 32]) {
198 let secret = self.ks.derive_logged_secret(SecretKind::ExporterMasterSecret,
199 hs_hash, key_log, client_random);
200 self.current_exporter_secret = Some(secret);
201 }
202
into_traffic(self) -> KeyScheduleTraffic203 pub fn into_traffic(self) -> KeyScheduleTraffic {
204 KeyScheduleTraffic {
205 ks: self.ks,
206 current_client_traffic_secret: self.current_client_traffic_secret.unwrap(),
207 current_server_traffic_secret: self.current_server_traffic_secret.unwrap(),
208 current_exporter_secret: self.current_exporter_secret.unwrap(),
209 }
210 }
211 }
212
213
214 /// KeySchedule during traffic stage. All traffic & exporter keys are guaranteed
215 /// to be available.
216 pub struct KeyScheduleTraffic {
217 ks: KeySchedule,
218 current_client_traffic_secret: hkdf::Prk,
219 current_server_traffic_secret: hkdf::Prk,
220 current_exporter_secret: hkdf::Prk,
221 }
222
223 impl KeyScheduleTraffic {
next_server_application_traffic_secret(&mut self) -> hkdf::Prk224 pub fn next_server_application_traffic_secret(&mut self) -> hkdf::Prk {
225 let secret = self.ks.derive_next(&self.current_server_traffic_secret);
226 self.current_server_traffic_secret = secret.clone();
227 secret
228 }
229
next_client_application_traffic_secret(&mut self) -> hkdf::Prk230 pub fn next_client_application_traffic_secret(&mut self) -> hkdf::Prk {
231 let secret = self.ks.derive_next(&self.current_client_traffic_secret);
232 self.current_client_traffic_secret = secret.clone();
233 secret
234 }
235
resumption_master_secret_and_derive_ticket_psk(&self, hs_hash: &[u8], nonce: &[u8]) -> Vec<u8>236 pub fn resumption_master_secret_and_derive_ticket_psk(&self, hs_hash: &[u8], nonce: &[u8]) -> Vec<u8> {
237 let resumption_master_secret = self.ks.derive(self.ks.algorithm(),
238 SecretKind::ResumptionMasterSecret,
239 hs_hash);
240 self.ks.derive_ticket_psk(&resumption_master_secret, nonce)
241 }
242
export_keying_material(&self, out: &mut [u8], label: &[u8], context: Option<&[u8]>) -> Result<(), TLSError>243 pub fn export_keying_material(&self,
244 out: &mut [u8],
245 label: &[u8],
246 context: Option<&[u8]>) -> Result<(), TLSError> {
247 self.ks.export_keying_material(&self.current_exporter_secret,
248 out, label, context)
249 }
250 }
251
252 impl KeySchedule {
new(algorithm: hkdf::Algorithm, secret: &[u8]) -> KeySchedule253 fn new(algorithm: hkdf::Algorithm, secret: &[u8]) -> KeySchedule {
254 let zeroes = [0u8; digest::MAX_OUTPUT_LEN];
255 let zeroes = &zeroes[..algorithm.len()];
256 let salt = hkdf::Salt::new(algorithm, &zeroes);
257 KeySchedule {
258 current: salt.extract(secret),
259 algorithm,
260 }
261 }
262
263 #[inline]
algorithm(&self) -> hkdf::Algorithm264 fn algorithm(&self) -> hkdf::Algorithm { self.algorithm }
265
new_with_empty_secret(algorithm: hkdf::Algorithm) -> KeySchedule266 fn new_with_empty_secret(algorithm: hkdf::Algorithm) -> KeySchedule {
267 let zeroes = [0u8; digest::MAX_OUTPUT_LEN];
268 Self::new(algorithm, &zeroes[..algorithm.len()])
269 }
270
271 /// Input the empty secret.
input_empty(&mut self)272 fn input_empty(&mut self) {
273 let zeroes = [0u8; digest::MAX_OUTPUT_LEN];
274 self.input_secret(&zeroes[..self.algorithm.len()]);
275 }
276
277 /// Input the given secret.
input_secret(&mut self, secret: &[u8])278 fn input_secret(&mut self, secret: &[u8]) {
279 let salt: hkdf::Salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
280 self.current = salt.extract(secret);
281 }
282
283 /// Derive a secret of given `kind`, using current handshake hash `hs_hash`.
derive<T, L>(&self, key_type: L, kind: SecretKind, hs_hash: &[u8]) -> T where T: for <'a> From<hkdf::Okm<'a, L>>, L: hkdf::KeyType,284 fn derive<T, L>(&self, key_type: L, kind: SecretKind, hs_hash: &[u8]) -> T
285 where
286 T: for <'a> From<hkdf::Okm<'a, L>>,
287 L: hkdf::KeyType,
288 {
289 hkdf_expand(&self.current, key_type, kind.to_bytes(), hs_hash)
290 }
291
derive_logged_secret(&self, kind: SecretKind, hs_hash: &[u8], key_log: &dyn KeyLog, client_random: &[u8; 32]) -> hkdf::Prk292 fn derive_logged_secret(&self, kind: SecretKind, hs_hash: &[u8],
293 key_log: &dyn KeyLog, client_random: &[u8; 32])
294 -> hkdf::Prk
295 {
296 let log_label = kind.log_label().expect("not a loggable secret");
297 if key_log.will_log(log_label) {
298 let secret = self.derive::<PayloadU8, _>(PayloadU8Len(self.algorithm.len()), kind, hs_hash)
299 .into_inner();
300 key_log.log(log_label, client_random, &secret);
301 }
302 self.derive(self.algorithm, kind, hs_hash)
303 }
304
305 /// Derive a secret of given `kind` using the hash of the empty string
306 /// for the handshake hash. Useful only for
307 /// `SecretKind::ResumptionPSKBinderKey` and
308 /// `SecretKind::DerivedSecret`.
derive_for_empty_hash<T>(&self, kind: SecretKind) -> T where T: for <'a> From<hkdf::Okm<'a, hkdf::Algorithm>>309 fn derive_for_empty_hash<T>(&self, kind: SecretKind) -> T
310 where
311 T: for <'a> From<hkdf::Okm<'a, hkdf::Algorithm>>
312 {
313 let digest_alg = self.algorithm.hmac_algorithm().digest_algorithm();
314 let empty_hash = digest::digest(digest_alg, &[]);
315 self.derive(self.algorithm, kind, empty_hash.as_ref())
316 }
317
318 /// Sign the finished message consisting of `hs_hash` using a current
319 /// traffic secret.
sign_finish(&self, base_key: &hkdf::Prk, hs_hash: &[u8]) -> Vec<u8>320 fn sign_finish(&self, base_key: &hkdf::Prk, hs_hash: &[u8]) -> Vec<u8> {
321 self.sign_verify_data(base_key, hs_hash)
322 }
323
324 /// Sign the finished message consisting of `hs_hash` using the key material
325 /// `base_key`.
sign_verify_data(&self, base_key: &hkdf::Prk, hs_hash: &[u8]) -> Vec<u8>326 fn sign_verify_data(&self, base_key: &hkdf::Prk, hs_hash: &[u8]) -> Vec<u8> {
327 let hmac_alg = self.algorithm.hmac_algorithm();
328 let hmac_key = hkdf_expand(base_key, hmac_alg, b"finished", &[]);
329 hmac::sign(&hmac_key, hs_hash)
330 .as_ref()
331 .to_vec()
332 }
333
334 /// Derive the next application traffic secret, returning it.
derive_next(&self, base_key: &hkdf::Prk) -> hkdf::Prk335 fn derive_next(&self, base_key: &hkdf::Prk) -> hkdf::Prk {
336 hkdf_expand(&base_key, self.algorithm, b"traffic upd", &[])
337 }
338
339 /// Derive the PSK to use given a resumption_master_secret and
340 /// ticket_nonce.
derive_ticket_psk(&self, rms: &hkdf::Prk, nonce: &[u8]) -> Vec<u8>341 fn derive_ticket_psk(&self, rms: &hkdf::Prk, nonce: &[u8]) -> Vec<u8> {
342 let payload: PayloadU8 = hkdf_expand(rms, PayloadU8Len(self.algorithm.len()), b"resumption", nonce);
343 payload.into_inner()
344 }
345
export_keying_material(&self, current_exporter_secret: &hkdf::Prk, out: &mut [u8], label: &[u8], context: Option<&[u8]>) -> Result<(), TLSError>346 fn export_keying_material(&self,
347 current_exporter_secret: &hkdf::Prk,
348 out: &mut [u8],
349 label: &[u8],
350 context: Option<&[u8]>) -> Result<(), TLSError> {
351 let digest_alg = self.algorithm.hmac_algorithm().digest_algorithm();
352
353 let h_empty = digest::digest(digest_alg, &[]);
354 let secret: hkdf::Prk =
355 hkdf_expand(current_exporter_secret, self.algorithm, label, h_empty.as_ref());
356
357 let h_context = digest::digest(digest_alg, context.unwrap_or(&[]));
358
359 // TODO: Test what happens when this fails
360 hkdf_expand_info(&secret, PayloadU8Len(out.len()), b"exporter", h_context.as_ref(),
361 |okm| okm.fill(out))
362 .map_err(|_| TLSError::General("exporting too much".to_string()))
363 }
364 }
365
hkdf_expand<T, L>(secret: &hkdf::Prk, key_type: L, label: &[u8], context: &[u8]) -> T where T: for <'a> From<hkdf::Okm<'a, L>>, L: hkdf::KeyType,366 pub(crate) fn hkdf_expand<T, L>(secret: &hkdf::Prk, key_type: L, label: &[u8], context: &[u8]) -> T
367 where
368 T: for <'a> From<hkdf::Okm<'a, L>>,
369 L: hkdf::KeyType,
370 {
371 hkdf_expand_info(secret, key_type, label, context, |okm| okm.into())
372 }
373
hkdf_expand_info<F, T, L>(secret: &hkdf::Prk, key_type: L, label: &[u8], context: &[u8], f: F) -> T where F: for<'b> FnOnce(hkdf::Okm<'b, L>) -> T, L: hkdf::KeyType374 fn hkdf_expand_info<F, T, L>(secret: &hkdf::Prk, key_type: L, label: &[u8], context: &[u8], f: F)
375 -> T
376 where
377 F: for<'b> FnOnce(hkdf::Okm<'b, L>) -> T,
378 L: hkdf::KeyType
379 {
380 const LABEL_PREFIX: &[u8] = b"tls13 ";
381
382 let output_len = u16::to_be_bytes(key_type.len() as u16);
383 let label_len = u8::to_be_bytes((LABEL_PREFIX.len() + label.len()) as u8);
384 let context_len = u8::to_be_bytes(context.len() as u8);
385
386 let info = &[&output_len[..], &label_len[..], LABEL_PREFIX, label, &context_len[..], context];
387 let okm = secret.expand(info, key_type).unwrap();
388
389 f(okm)
390 }
391
392 pub(crate) struct PayloadU8Len(pub(crate) usize);
393 impl hkdf::KeyType for PayloadU8Len {
len(&self) -> usize394 fn len(&self) -> usize { self.0 }
395 }
396
397 impl From<hkdf::Okm<'_, PayloadU8Len>> for PayloadU8 {
from(okm: hkdf::Okm<PayloadU8Len>) -> Self398 fn from(okm: hkdf::Okm<PayloadU8Len>) -> Self {
399 let mut r = vec![0u8;okm.len().0];
400 okm.fill(&mut r[..]).unwrap();
401 PayloadU8::new(r)
402 }
403 }
404
derive_traffic_key(secret: &hkdf::Prk, aead_algorithm: &'static aead::Algorithm) -> aead::UnboundKey405 pub fn derive_traffic_key(secret: &hkdf::Prk, aead_algorithm: &'static aead::Algorithm)
406 -> aead::UnboundKey
407 {
408 hkdf_expand(secret, aead_algorithm, b"key", &[])
409 }
410
derive_traffic_iv(secret: &hkdf::Prk) -> Iv411 pub(crate) fn derive_traffic_iv(secret: &hkdf::Prk) -> Iv {
412 hkdf_expand(secret, IvLen, b"iv", &[])
413 }
414
415 #[cfg(test)]
416 mod test {
417 use super::{KeySchedule, SecretKind, derive_traffic_key, derive_traffic_iv};
418 use ring::{aead, hkdf};
419 use crate::KeyLog;
420
421 #[test]
test_vectors()422 fn test_vectors() {
423 /* These test vectors generated with OpenSSL. */
424 let hs_start_hash = [
425 0xec, 0x14, 0x7a, 0x06, 0xde, 0xa3, 0xc8, 0x84, 0x6c, 0x02, 0xb2, 0x23, 0x8e,
426 0x41, 0xbd, 0xdc, 0x9d, 0x89, 0xf9, 0xae, 0xa1, 0x7b, 0x5e, 0xfd, 0x4d, 0x74,
427 0x82, 0xaf, 0x75, 0x88, 0x1c, 0x0a
428 ];
429
430 let hs_full_hash = [
431 0x75, 0x1a, 0x3d, 0x4a, 0x14, 0xdf, 0xab, 0xeb, 0x68, 0xe9, 0x2c, 0xa5, 0x91,
432 0x8e, 0x24, 0x08, 0xb9, 0xbc, 0xb0, 0x74, 0x89, 0x82, 0xec, 0x9c, 0x32, 0x30,
433 0xac, 0x30, 0xbb, 0xeb, 0x23, 0xe2
434 ];
435
436 let ecdhe_secret = [
437 0xe7, 0xb8, 0xfe, 0xf8, 0x90, 0x3b, 0x52, 0x0c, 0xb9, 0xa1, 0x89, 0x71, 0xb6,
438 0x9d, 0xd4, 0x5d, 0xca, 0x53, 0xce, 0x2f, 0x12, 0xbf, 0x3b, 0xef, 0x93, 0x15,
439 0xe3, 0x12, 0x71, 0xdf, 0x4b, 0x40
440 ];
441
442 let client_hts = [
443 0x61, 0x7b, 0x35, 0x07, 0x6b, 0x9d, 0x0e, 0x08, 0xcf, 0x73, 0x1d, 0x94, 0xa8,
444 0x66, 0x14, 0x78, 0x41, 0x09, 0xef, 0x25, 0x55, 0x51, 0x92, 0x1d, 0xd4, 0x6e,
445 0x04, 0x01, 0x35, 0xcf, 0x46, 0xab
446 ];
447
448 let client_hts_key = [
449 0x62, 0xd0, 0xdd, 0x00, 0xf6, 0x96, 0x19, 0xd3, 0xb8, 0x19, 0x3a, 0xb4, 0xa0,
450 0x95, 0x85, 0xa7
451 ];
452
453 let client_hts_iv = [
454 0xff, 0xf7, 0x5d, 0xf5, 0xad, 0x35, 0xd5, 0xcb, 0x3c, 0x53, 0xf3, 0xa9
455 ];
456
457 let server_hts = [
458 0xfc, 0xf7, 0xdf, 0xe6, 0x4f, 0xa2, 0xc0, 0x4f, 0x62, 0x35, 0x38, 0x7f, 0x43,
459 0x4e, 0x01, 0x42, 0x23, 0x36, 0xd9, 0xc0, 0x39, 0xde, 0x68, 0x47, 0xa0, 0xb9,
460 0xdd, 0xcf, 0x29, 0xa8, 0x87, 0x59
461 ];
462
463 let server_hts_key = [
464 0x04, 0x67, 0xf3, 0x16, 0xa8, 0x05, 0xb8, 0xc4, 0x97, 0xee, 0x67, 0x04, 0x7b,
465 0xbc, 0xbc, 0x54
466 ];
467
468 let server_hts_iv = [
469 0xde, 0x83, 0xa7, 0x3e, 0x9d, 0x81, 0x4b, 0x04, 0xc4, 0x8b, 0x78, 0x09
470 ];
471
472 let client_ats = [
473 0xc1, 0x4a, 0x6d, 0x79, 0x76, 0xd8, 0x10, 0x2b, 0x5a, 0x0c, 0x99, 0x51, 0x49,
474 0x3f, 0xee, 0x87, 0xdc, 0xaf, 0xf8, 0x2c, 0x24, 0xca, 0xb2, 0x14, 0xe8, 0xbe,
475 0x71, 0xa8, 0x20, 0x6d, 0xbd, 0xa5
476 ];
477
478 let client_ats_key = [
479 0xcc, 0x9f, 0x5f, 0x98, 0x0b, 0x5f, 0x10, 0x30, 0x6c, 0xba, 0xd7, 0xbe, 0x98,
480 0xd7, 0x57, 0x2e
481 ];
482
483 let client_ats_iv = [
484 0xb8, 0x09, 0x29, 0xe8, 0xd0, 0x2c, 0x70, 0xf6, 0x11, 0x62, 0xed, 0x6b
485 ];
486
487 let server_ats = [
488 0x2c, 0x90, 0x77, 0x38, 0xd3, 0xf8, 0x37, 0x02, 0xd1, 0xe4, 0x59, 0x8f, 0x48,
489 0x48, 0x53, 0x1d, 0x9f, 0x93, 0x65, 0x49, 0x1b, 0x9f, 0x7f, 0x52, 0xc8, 0x22,
490 0x29, 0x0d, 0x4c, 0x23, 0x21, 0x92
491 ];
492
493 let server_ats_key = [
494 0x0c, 0xb2, 0x95, 0x62, 0xd8, 0xd8, 0x8f, 0x48, 0xb0, 0x2c, 0xbf, 0xbe, 0xd7,
495 0xe6, 0x2b, 0xb3
496 ];
497
498 let server_ats_iv = [
499 0x0d, 0xb2, 0x8f, 0x98, 0x85, 0x86, 0xa1, 0xb7, 0xe4, 0xd5, 0xc6, 0x9c
500 ];
501
502 let hkdf = hkdf::HKDF_SHA256;
503 let mut ks = KeySchedule::new_with_empty_secret(hkdf);
504 ks.input_secret(&ecdhe_secret);
505
506 assert_traffic_secret(
507 &ks,
508 SecretKind::ClientHandshakeTrafficSecret,
509 &hs_start_hash,
510 &client_hts,
511 &client_hts_key,
512 &client_hts_iv);
513
514 assert_traffic_secret(
515 &ks,
516 SecretKind::ServerHandshakeTrafficSecret,
517 &hs_start_hash,
518 &server_hts,
519 &server_hts_key,
520 &server_hts_iv);
521
522 ks.input_empty();
523
524 assert_traffic_secret(
525 &ks,
526 SecretKind::ClientApplicationTrafficSecret,
527 &hs_full_hash,
528 &client_ats,
529 &client_ats_key,
530 &client_ats_iv);
531
532 assert_traffic_secret(
533 &ks,
534 SecretKind::ServerApplicationTrafficSecret,
535 &hs_full_hash,
536 &server_ats,
537 &server_ats_key,
538 &server_ats_iv);
539 }
540
assert_traffic_secret( ks: &KeySchedule, kind: SecretKind, hash: &[u8], expected_traffic_secret: &[u8], expected_key: &[u8], expected_iv: &[u8], )541 fn assert_traffic_secret(
542 ks: &KeySchedule,
543 kind: SecretKind,
544 hash: &[u8],
545 expected_traffic_secret: &[u8],
546 expected_key: &[u8],
547 expected_iv: &[u8],
548 ) {
549 struct Log<'a>(&'a [u8]);
550 impl KeyLog for Log<'_> {
551 fn log(&self, _label: &str, _client_random: &[u8], secret: &[u8]) {
552 assert_eq!(self.0, secret);
553 }
554 }
555 let log = Log(expected_traffic_secret);
556 let traffic_secret = ks.derive_logged_secret(kind, &hash, &log, &[0; 32]);
557
558 // Since we can't test key equality, we test the output of sealing with the key instead.
559 let aead_alg = &aead::AES_128_GCM;
560 let key = derive_traffic_key(&traffic_secret, aead_alg);
561 let seal_output = seal_zeroes(key);
562 let expected_key = aead::UnboundKey::new(aead_alg, expected_key).unwrap();
563 let expected_seal_output = seal_zeroes(expected_key);
564 assert_eq!(seal_output, expected_seal_output);
565 assert!(seal_output.len() >= 48); // Sanity check.
566
567 let iv = derive_traffic_iv(&traffic_secret);
568 assert_eq!(iv.value(), expected_iv);
569 }
570
seal_zeroes(key: aead::UnboundKey) -> Vec<u8>571 fn seal_zeroes(key: aead::UnboundKey) -> Vec<u8> {
572 let key = aead::LessSafeKey::new(key);
573 let mut seal_output = vec![0; 32];
574 key.seal_in_place_append_tag(
575 aead::Nonce::assume_unique_for_key([0; aead::NONCE_LEN]),
576 aead::Aad::empty(),
577 &mut seal_output)
578 .unwrap();
579 seal_output
580 }
581 }
582