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