1#![allow(dead_code)]
2
3use ring::{
5 aead,
6 digest::{self, Digest},
7 hkdf::{self, KeyType as _, Prk},
8 hmac,
9};
10
11use crate::tls::rustls::cipher::{Iv, IvLen};
12use crate::tls::rustls::error::Error;
13use crate::tls::rustls::key_log::KeyLog;
14use crate::tls::rustls::msgs::base::PayloadU8;
15
16#[derive(Debug, Clone, Copy, PartialEq)]
18enum SecretKind {
19 ResumptionPskBinderKey,
20 ClientEarlyTrafficSecret,
21 ClientHandshakeTrafficSecret,
22 ServerHandshakeTrafficSecret,
23 ClientApplicationTrafficSecret,
24 ServerApplicationTrafficSecret,
25 ExporterMasterSecret,
26 ResumptionMasterSecret,
27 DerivedSecret,
28}
29
30impl SecretKind {
31 fn to_bytes(self) -> &'static [u8] {
32 use self::SecretKind::*;
33 match self {
34 ResumptionPskBinderKey => b"res binder",
35 ClientEarlyTrafficSecret => b"c e traffic",
36 ClientHandshakeTrafficSecret => b"c hs traffic",
37 ServerHandshakeTrafficSecret => b"s hs traffic",
38 ClientApplicationTrafficSecret => b"c ap traffic",
39 ServerApplicationTrafficSecret => b"s ap traffic",
40 ExporterMasterSecret => b"exp master",
41 ResumptionMasterSecret => b"res master",
42 DerivedSecret => b"derived",
43 }
44 }
45
46 fn log_label(self) -> Option<&'static str> {
47 use self::SecretKind::*;
48 Some(match self {
49 ClientEarlyTrafficSecret => "CLIENT_EARLY_TRAFFIC_SECRET",
50 ClientHandshakeTrafficSecret => "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
51 ServerHandshakeTrafficSecret => "SERVER_HANDSHAKE_TRAFFIC_SECRET",
52 ClientApplicationTrafficSecret => "CLIENT_TRAFFIC_SECRET_0",
53 ServerApplicationTrafficSecret => "SERVER_TRAFFIC_SECRET_0",
54 ExporterMasterSecret => "EXPORTER_SECRET",
55 _ => {
56 return None;
57 }
58 })
59 }
60}
61
62pub struct KeySchedule {
66 current: hkdf::Prk,
67 algorithm: ring::hkdf::Algorithm,
68}
69
70pub struct KeyScheduleEarly {
78 ks: KeySchedule,
79}
80
81impl KeyScheduleEarly {
82 pub fn new(algorithm: hkdf::Algorithm, secret: &[u8]) -> Self {
83 Self {
84 ks: KeySchedule::new(algorithm, secret),
85 }
86 }
87
88 pub fn client_early_traffic_secret(
89 &self,
90 hs_hash: &Digest,
91 key_log: &dyn KeyLog,
92 client_random: &[u8; 32],
93 ) -> hkdf::Prk {
94 self.ks.derive_logged_secret(
95 SecretKind::ClientEarlyTrafficSecret,
96 hs_hash.as_ref(),
97 key_log,
98 client_random,
99 )
100 }
101
102 pub fn resumption_psk_binder_key_and_sign_verify_data(&self, hs_hash: &Digest) -> hmac::Tag {
103 let resumption_psk_binder_key = self
104 .ks
105 .derive_for_empty_hash(SecretKind::ResumptionPskBinderKey);
106 self.ks
107 .sign_verify_data_raw(&resumption_psk_binder_key, hs_hash.as_ref())
108 }
109}
110
111pub struct KeySchedulePreHandshake {
117 ks: KeySchedule,
118}
119
120impl KeySchedulePreHandshake {
121 pub fn new(algorithm: hkdf::Algorithm) -> Self {
122 Self {
123 ks: KeySchedule::new_with_empty_secret(algorithm),
124 }
125 }
126
127 pub fn into_handshake(mut self, secret: &[u8]) -> KeyScheduleHandshakeStart {
128 self.ks.input_secret(secret);
129 KeyScheduleHandshakeStart { ks: self.ks }
130 }
131}
132
133impl From<KeyScheduleEarly> for KeySchedulePreHandshake {
134 fn from(KeyScheduleEarly { ks }: KeyScheduleEarly) -> Self {
135 Self { ks }
136 }
137}
138
139pub struct KeyScheduleHandshakeStart {
141 ks: KeySchedule,
142}
143
144impl KeyScheduleHandshakeStart {
145 pub fn new_with_secret(algorithm: hkdf::Algorithm, secret: &[u8]) -> Self {
147 let key = Prk::new_less_safe(algorithm, secret);
148 Self {
149 ks: KeySchedule {
150 current: key,
151 algorithm,
152 },
153 }
154 }
155
156 pub fn derive_handshake_secrets(
157 self,
158 hs_hash: &[u8],
159 key_log: &dyn KeyLog,
160 client_random: &[u8; 32],
161 ) -> (KeyScheduleHandshake, hkdf::Prk, hkdf::Prk) {
162 let client_secret = self.ks.derive_logged_secret(
164 SecretKind::ClientHandshakeTrafficSecret,
165 hs_hash,
166 key_log,
167 client_random,
168 );
169
170 let server_secret = self.ks.derive_logged_secret(
171 SecretKind::ServerHandshakeTrafficSecret,
172 hs_hash,
173 key_log,
174 client_random,
175 );
176
177 let new = KeyScheduleHandshake {
178 ks: self.ks,
179 client_handshake_traffic_secret: client_secret.clone(),
180 server_handshake_traffic_secret: server_secret.clone(),
181 };
182
183 (new, client_secret, server_secret)
184 }
185}
186
187pub struct KeyScheduleHandshake {
188 ks: KeySchedule,
189 client_handshake_traffic_secret: hkdf::Prk,
190 server_handshake_traffic_secret: hkdf::Prk,
191}
192
193impl KeyScheduleHandshake {
194 pub fn sign_server_finish(&self, hs_hash: &Digest) -> hmac::Tag {
195 self.sign_server_finish_raw(hs_hash.as_ref())
196 }
197
198 pub fn sign_server_finish_raw(&self, hs_hash: &[u8]) -> hmac::Tag {
199 self.ks
200 .sign_finish_raw(&self.server_handshake_traffic_secret, hs_hash)
201 }
202
203 pub fn client_key(&self) -> &hkdf::Prk {
204 &self.client_handshake_traffic_secret
205 }
206
207 pub fn into_traffic_with_client_finished_pending(
208 self,
209 hs_hash: Digest,
210 key_log: &dyn KeyLog,
211 client_random: &[u8; 32],
212 ) -> (
213 KeyScheduleTrafficWithClientFinishedPending,
214 hkdf::Prk,
215 hkdf::Prk,
216 ) {
217 self.into_traffic_with_client_finished_pending_raw(hs_hash.as_ref(), key_log, client_random)
218 }
219
220 pub fn into_traffic_with_client_finished_pending_raw(
221 self,
222 hs_hash: &[u8],
223 key_log: &dyn KeyLog,
224 client_random: &[u8; 32],
225 ) -> (
226 KeyScheduleTrafficWithClientFinishedPending,
227 hkdf::Prk,
228 hkdf::Prk,
229 ) {
230 let traffic = KeyScheduleTraffic::new(self.ks, hs_hash, key_log, client_random);
231
232 let client_secret = traffic.current_client_traffic_secret.clone();
233 let server_secret = traffic.current_server_traffic_secret.clone();
234
235 let new = KeyScheduleTrafficWithClientFinishedPending {
236 handshake_client_traffic_secret: self.client_handshake_traffic_secret,
237 traffic,
238 };
239
240 (new, client_secret, server_secret)
241 }
242}
243
244pub struct KeyScheduleTrafficWithClientFinishedPending {
249 handshake_client_traffic_secret: hkdf::Prk,
250 traffic: KeyScheduleTraffic,
251}
252
253impl KeyScheduleTrafficWithClientFinishedPending {
254 pub fn client_key(&self) -> &hkdf::Prk {
255 &self.handshake_client_traffic_secret
256 }
257
258 pub fn sign_client_finish(
259 self,
260 hs_hash: &Digest,
261 ) -> (KeyScheduleTraffic, hmac::Tag, hkdf::Prk) {
262 self.sign_client_finish_raw(hs_hash.as_ref())
263 }
264
265 pub fn sign_client_finish_raw(
266 self,
267 hs_hash: &[u8],
268 ) -> (KeyScheduleTraffic, hmac::Tag, hkdf::Prk) {
269 let tag = self
270 .traffic
271 .ks
272 .sign_finish_raw(&self.handshake_client_traffic_secret, hs_hash);
273
274 let client_secret = self.traffic.current_client_traffic_secret.clone();
275
276 (self.traffic, tag, client_secret)
277 }
278}
279
280pub struct KeyScheduleTraffic {
283 ks: KeySchedule,
284 current_client_traffic_secret: hkdf::Prk,
285 current_server_traffic_secret: hkdf::Prk,
286 current_exporter_secret: hkdf::Prk,
287}
288
289impl KeyScheduleTraffic {
290 fn new(
291 mut ks: KeySchedule,
292 hs_hash: &[u8],
293 key_log: &dyn KeyLog,
294 client_random: &[u8; 32],
295 ) -> Self {
296 ks.input_empty();
297
298 let current_client_traffic_secret = ks.derive_logged_secret(
299 SecretKind::ClientApplicationTrafficSecret,
300 hs_hash,
301 key_log,
302 client_random,
303 );
304
305 let current_server_traffic_secret = ks.derive_logged_secret(
306 SecretKind::ServerApplicationTrafficSecret,
307 hs_hash,
308 key_log,
309 client_random,
310 );
311
312 let current_exporter_secret = ks.derive_logged_secret(
313 SecretKind::ExporterMasterSecret,
314 hs_hash,
315 key_log,
316 client_random,
317 );
318
319 Self {
320 ks,
321 current_client_traffic_secret,
322 current_server_traffic_secret,
323 current_exporter_secret,
324 }
325 }
326
327 pub fn next_server_application_traffic_secret(&mut self) -> hkdf::Prk {
328 let secret = self.ks.derive_next(&self.current_server_traffic_secret);
329 self.current_server_traffic_secret = secret.clone();
330 secret
331 }
332
333 pub fn next_client_application_traffic_secret(&mut self) -> hkdf::Prk {
334 let secret = self.ks.derive_next(&self.current_client_traffic_secret);
335 self.current_client_traffic_secret = secret.clone();
336 secret
337 }
338
339 pub fn resumption_master_secret_and_derive_ticket_psk(
340 &self,
341 hs_hash: &Digest,
342 nonce: &[u8],
343 ) -> Vec<u8> {
344 self.resumption_master_secret_and_derive_ticket_psk_raw(hs_hash.as_ref(), nonce)
345 }
346
347 pub fn resumption_master_secret_and_derive_ticket_psk_raw(
348 &self,
349 hs_hash: &[u8],
350 nonce: &[u8],
351 ) -> Vec<u8> {
352 let resumption_master_secret = self.ks.derive(
353 self.ks.algorithm(),
354 SecretKind::ResumptionMasterSecret,
355 hs_hash,
356 );
357 self.ks.derive_ticket_psk(&resumption_master_secret, nonce)
358 }
359
360 pub fn export_keying_material(
361 &self,
362 out: &mut [u8],
363 label: &[u8],
364 context: Option<&[u8]>,
365 ) -> Result<(), Error> {
366 self.ks
367 .export_keying_material(&self.current_exporter_secret, out, label, context)
368 }
369}
370
371impl KeySchedule {
372 fn new(algorithm: hkdf::Algorithm, secret: &[u8]) -> Self {
373 let zeroes = [0u8; digest::MAX_OUTPUT_LEN];
374 let salt = hkdf::Salt::new(algorithm, &zeroes[..algorithm.len()]);
375 Self {
376 current: salt.extract(secret),
377 algorithm,
378 }
379 }
380
381 #[inline]
382 fn algorithm(&self) -> hkdf::Algorithm {
383 self.algorithm
384 }
385
386 fn new_with_empty_secret(algorithm: hkdf::Algorithm) -> Self {
387 let zeroes = [0u8; digest::MAX_OUTPUT_LEN];
388 Self::new(algorithm, &zeroes[..algorithm.len()])
389 }
390
391 fn input_empty(&mut self) {
393 let zeroes = [0u8; digest::MAX_OUTPUT_LEN];
394 self.input_secret(&zeroes[..self.algorithm.len()]);
395 }
396
397 fn input_secret(&mut self, secret: &[u8]) {
399 let salt: hkdf::Salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
400 self.current = salt.extract(secret);
401 }
402
403 fn derive<T, L>(&self, key_type: L, kind: SecretKind, hs_hash: &[u8]) -> T
405 where
406 T: for<'a> From<hkdf::Okm<'a, L>>,
407 L: hkdf::KeyType,
408 {
409 hkdf_expand(&self.current, key_type, kind.to_bytes(), hs_hash)
410 }
411
412 fn derive_logged_secret(
413 &self,
414 kind: SecretKind,
415 hs_hash: &[u8],
416 key_log: &dyn KeyLog,
417 client_random: &[u8; 32],
418 ) -> hkdf::Prk {
419 let log_label = kind.log_label().expect("not a loggable secret");
420 if key_log.will_log(log_label) {
421 let secret = self
422 .derive::<PayloadU8, _>(PayloadU8Len(self.algorithm.len()), kind, hs_hash)
423 .into_inner();
424 key_log.log(log_label, client_random, &secret);
425 }
426 self.derive(self.algorithm, kind, hs_hash)
427 }
428
429 fn derive_for_empty_hash<T>(&self, kind: SecretKind) -> T
434 where
435 T: for<'a> From<hkdf::Okm<'a, hkdf::Algorithm>>,
436 {
437 let digest_alg = self.algorithm.hmac_algorithm().digest_algorithm();
438 let empty_hash = digest::digest(digest_alg, &[]);
439 self.derive(self.algorithm, kind, empty_hash.as_ref())
440 }
441
442 fn sign_finish(&self, base_key: &hkdf::Prk, hs_hash: &Digest) -> hmac::Tag {
445 self.sign_finish_raw(base_key, hs_hash.as_ref())
446 }
447
448 fn sign_finish_raw(&self, base_key: &hkdf::Prk, hs_hash: &[u8]) -> hmac::Tag {
449 self.sign_verify_data_raw(base_key, hs_hash)
450 }
451
452 fn sign_verify_data(&self, base_key: &hkdf::Prk, hs_hash: &Digest) -> hmac::Tag {
455 self.sign_verify_data_raw(base_key, hs_hash.as_ref())
456 }
457
458 fn sign_verify_data_raw(&self, base_key: &hkdf::Prk, hs_hash: &[u8]) -> hmac::Tag {
459 let hmac_alg = self.algorithm.hmac_algorithm();
460 let hmac_key = hkdf_expand(base_key, hmac_alg, b"finished", &[]);
461 hmac::sign(&hmac_key, hs_hash)
462 }
463
464 fn derive_next(&self, base_key: &hkdf::Prk) -> hkdf::Prk {
466 hkdf_expand(base_key, self.algorithm, b"traffic upd", &[])
467 }
468
469 fn derive_ticket_psk(&self, rms: &hkdf::Prk, nonce: &[u8]) -> Vec<u8> {
472 let payload: PayloadU8 = hkdf_expand(
473 rms,
474 PayloadU8Len(self.algorithm.len()),
475 b"resumption",
476 nonce,
477 );
478 payload.into_inner()
479 }
480
481 fn export_keying_material(
482 &self,
483 current_exporter_secret: &hkdf::Prk,
484 out: &mut [u8],
485 label: &[u8],
486 context: Option<&[u8]>,
487 ) -> Result<(), Error> {
488 let digest_alg = self.algorithm.hmac_algorithm().digest_algorithm();
489
490 let h_empty = digest::digest(digest_alg, &[]);
491 let secret: hkdf::Prk = hkdf_expand(
492 current_exporter_secret,
493 self.algorithm,
494 label,
495 h_empty.as_ref(),
496 );
497
498 let h_context = digest::digest(digest_alg, context.unwrap_or(&[]));
499
500 hkdf_expand_info(
502 &secret,
503 PayloadU8Len(out.len()),
504 b"exporter",
505 h_context.as_ref(),
506 |okm| okm.fill(out),
507 )
508 .map_err(|_| Error::General("exporting too much".to_string()))
509 }
510}
511
512pub fn hkdf_expand<T, L>(secret: &hkdf::Prk, key_type: L, label: &[u8], context: &[u8]) -> T
513where
514 T: for<'a> From<hkdf::Okm<'a, L>>,
515 L: hkdf::KeyType,
516{
517 hkdf_expand_info(secret, key_type, label, context, |okm| okm.into())
518}
519
520fn hkdf_expand_info<F, T, L>(
521 secret: &hkdf::Prk,
522 key_type: L,
523 label: &[u8],
524 context: &[u8],
525 f: F,
526) -> T
527where
528 F: for<'b> FnOnce(hkdf::Okm<'b, L>) -> T,
529 L: hkdf::KeyType,
530{
531 const LABEL_PREFIX: &[u8] = b"tls13 ";
532
533 let output_len = u16::to_be_bytes(key_type.len() as u16);
534 let label_len = u8::to_be_bytes((LABEL_PREFIX.len() + label.len()) as u8);
535 let context_len = u8::to_be_bytes(context.len() as u8);
536
537 let info = &[
538 &output_len[..],
539 &label_len[..],
540 LABEL_PREFIX,
541 label,
542 &context_len[..],
543 context,
544 ];
545 let okm = secret.expand(info, key_type).unwrap();
546
547 f(okm)
548}
549
550pub struct PayloadU8Len(pub usize);
551impl hkdf::KeyType for PayloadU8Len {
552 fn len(&self) -> usize {
553 self.0
554 }
555}
556
557impl From<hkdf::Okm<'_, PayloadU8Len>> for PayloadU8 {
558 fn from(okm: hkdf::Okm<PayloadU8Len>) -> Self {
559 let mut r = vec![0u8; okm.len().0];
560 okm.fill(&mut r[..]).unwrap();
561 Self::new(r)
562 }
563}
564
565pub fn derive_traffic_key(
566 secret: &hkdf::Prk,
567 aead_algorithm: &'static aead::Algorithm,
568) -> aead::UnboundKey {
569 hkdf_expand(secret, aead_algorithm, b"key", &[])
570}
571
572pub fn derive_traffic_iv(secret: &hkdf::Prk) -> Iv {
573 hkdf_expand(secret, IvLen, b"iv", &[])
574}
575
576#[cfg(test)]
577mod tests {
578 use ring::{aead, hkdf};
579
580 use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind};
581 use crate::tls::rustls::key_log::KeyLog;
582
583 #[test_log::test]
584 fn test_vectors() {
585 let hs_start_hash = [
587 0xec, 0x14, 0x7a, 0x06, 0xde, 0xa3, 0xc8, 0x84, 0x6c, 0x02, 0xb2, 0x23, 0x8e, 0x41,
588 0xbd, 0xdc, 0x9d, 0x89, 0xf9, 0xae, 0xa1, 0x7b, 0x5e, 0xfd, 0x4d, 0x74, 0x82, 0xaf,
589 0x75, 0x88, 0x1c, 0x0a,
590 ];
591
592 let hs_full_hash = [
593 0x75, 0x1a, 0x3d, 0x4a, 0x14, 0xdf, 0xab, 0xeb, 0x68, 0xe9, 0x2c, 0xa5, 0x91, 0x8e,
594 0x24, 0x08, 0xb9, 0xbc, 0xb0, 0x74, 0x89, 0x82, 0xec, 0x9c, 0x32, 0x30, 0xac, 0x30,
595 0xbb, 0xeb, 0x23, 0xe2,
596 ];
597
598 let ecdhe_secret = [
599 0xe7, 0xb8, 0xfe, 0xf8, 0x90, 0x3b, 0x52, 0x0c, 0xb9, 0xa1, 0x89, 0x71, 0xb6, 0x9d,
600 0xd4, 0x5d, 0xca, 0x53, 0xce, 0x2f, 0x12, 0xbf, 0x3b, 0xef, 0x93, 0x15, 0xe3, 0x12,
601 0x71, 0xdf, 0x4b, 0x40,
602 ];
603
604 let client_hts = [
605 0x61, 0x7b, 0x35, 0x07, 0x6b, 0x9d, 0x0e, 0x08, 0xcf, 0x73, 0x1d, 0x94, 0xa8, 0x66,
606 0x14, 0x78, 0x41, 0x09, 0xef, 0x25, 0x55, 0x51, 0x92, 0x1d, 0xd4, 0x6e, 0x04, 0x01,
607 0x35, 0xcf, 0x46, 0xab,
608 ];
609
610 let client_hts_key = [
611 0x62, 0xd0, 0xdd, 0x00, 0xf6, 0x96, 0x19, 0xd3, 0xb8, 0x19, 0x3a, 0xb4, 0xa0, 0x95,
612 0x85, 0xa7,
613 ];
614
615 let client_hts_iv = [
616 0xff, 0xf7, 0x5d, 0xf5, 0xad, 0x35, 0xd5, 0xcb, 0x3c, 0x53, 0xf3, 0xa9,
617 ];
618
619 let server_hts = [
620 0xfc, 0xf7, 0xdf, 0xe6, 0x4f, 0xa2, 0xc0, 0x4f, 0x62, 0x35, 0x38, 0x7f, 0x43, 0x4e,
621 0x01, 0x42, 0x23, 0x36, 0xd9, 0xc0, 0x39, 0xde, 0x68, 0x47, 0xa0, 0xb9, 0xdd, 0xcf,
622 0x29, 0xa8, 0x87, 0x59,
623 ];
624
625 let server_hts_key = [
626 0x04, 0x67, 0xf3, 0x16, 0xa8, 0x05, 0xb8, 0xc4, 0x97, 0xee, 0x67, 0x04, 0x7b, 0xbc,
627 0xbc, 0x54,
628 ];
629
630 let server_hts_iv = [
631 0xde, 0x83, 0xa7, 0x3e, 0x9d, 0x81, 0x4b, 0x04, 0xc4, 0x8b, 0x78, 0x09,
632 ];
633
634 let client_ats = [
635 0xc1, 0x4a, 0x6d, 0x79, 0x76, 0xd8, 0x10, 0x2b, 0x5a, 0x0c, 0x99, 0x51, 0x49, 0x3f,
636 0xee, 0x87, 0xdc, 0xaf, 0xf8, 0x2c, 0x24, 0xca, 0xb2, 0x14, 0xe8, 0xbe, 0x71, 0xa8,
637 0x20, 0x6d, 0xbd, 0xa5,
638 ];
639
640 let client_ats_key = [
641 0xcc, 0x9f, 0x5f, 0x98, 0x0b, 0x5f, 0x10, 0x30, 0x6c, 0xba, 0xd7, 0xbe, 0x98, 0xd7,
642 0x57, 0x2e,
643 ];
644
645 let client_ats_iv = [
646 0xb8, 0x09, 0x29, 0xe8, 0xd0, 0x2c, 0x70, 0xf6, 0x11, 0x62, 0xed, 0x6b,
647 ];
648
649 let server_ats = [
650 0x2c, 0x90, 0x77, 0x38, 0xd3, 0xf8, 0x37, 0x02, 0xd1, 0xe4, 0x59, 0x8f, 0x48, 0x48,
651 0x53, 0x1d, 0x9f, 0x93, 0x65, 0x49, 0x1b, 0x9f, 0x7f, 0x52, 0xc8, 0x22, 0x29, 0x0d,
652 0x4c, 0x23, 0x21, 0x92,
653 ];
654
655 let server_ats_key = [
656 0x0c, 0xb2, 0x95, 0x62, 0xd8, 0xd8, 0x8f, 0x48, 0xb0, 0x2c, 0xbf, 0xbe, 0xd7, 0xe6,
657 0x2b, 0xb3,
658 ];
659
660 let server_ats_iv = [
661 0x0d, 0xb2, 0x8f, 0x98, 0x85, 0x86, 0xa1, 0xb7, 0xe4, 0xd5, 0xc6, 0x9c,
662 ];
663
664 let hkdf = hkdf::HKDF_SHA256;
665 let mut ks = KeySchedule::new_with_empty_secret(hkdf);
666 ks.input_secret(&ecdhe_secret);
667
668 assert_traffic_secret(
669 &ks,
670 SecretKind::ClientHandshakeTrafficSecret,
671 &hs_start_hash,
672 &client_hts,
673 &client_hts_key,
674 &client_hts_iv,
675 );
676
677 assert_traffic_secret(
678 &ks,
679 SecretKind::ServerHandshakeTrafficSecret,
680 &hs_start_hash,
681 &server_hts,
682 &server_hts_key,
683 &server_hts_iv,
684 );
685
686 ks.input_empty();
687
688 assert_traffic_secret(
689 &ks,
690 SecretKind::ClientApplicationTrafficSecret,
691 &hs_full_hash,
692 &client_ats,
693 &client_ats_key,
694 &client_ats_iv,
695 );
696
697 assert_traffic_secret(
698 &ks,
699 SecretKind::ServerApplicationTrafficSecret,
700 &hs_full_hash,
701 &server_ats,
702 &server_ats_key,
703 &server_ats_iv,
704 );
705 }
706
707 fn assert_traffic_secret(
708 ks: &KeySchedule,
709 kind: SecretKind,
710 hash: &[u8],
711 expected_traffic_secret: &[u8],
712 expected_key: &[u8],
713 expected_iv: &[u8],
714 ) {
715 struct Log<'a>(&'a [u8]);
716 impl KeyLog for Log<'_> {
717 fn log(&self, _label: &str, _client_random: &[u8], secret: &[u8]) {
718 assert_eq!(self.0, secret);
719 }
720 }
721 let log = Log(expected_traffic_secret);
722 let traffic_secret = ks.derive_logged_secret(kind, hash, &log, &[0; 32]);
723
724 let aead_alg = &aead::AES_128_GCM;
726 let key = derive_traffic_key(&traffic_secret, aead_alg);
727 let seal_output = seal_zeroes(key);
728 let expected_key = aead::UnboundKey::new(aead_alg, expected_key).unwrap();
729 let expected_seal_output = seal_zeroes(expected_key);
730 assert_eq!(seal_output, expected_seal_output);
731 assert!(seal_output.len() >= 48); let iv = derive_traffic_iv(&traffic_secret);
734 assert_eq!(iv.value(), expected_iv);
735 }
736
737 fn seal_zeroes(key: aead::UnboundKey) -> Vec<u8> {
738 let key = aead::LessSafeKey::new(key);
739 let mut seal_output = vec![0; 32];
740 key.seal_in_place_append_tag(
741 aead::Nonce::assume_unique_for_key([0; aead::NONCE_LEN]),
742 aead::Aad::empty(),
743 &mut seal_output,
744 )
745 .unwrap();
746 seal_output
747 }
748}