Improve encapsulation of key material during TLS 1.3 key schedule.

This commit is contained in:
Brian Smith 2019-07-26 10:15:58 -10:00 committed by ctz
parent 952e172f87
commit 1d99471355
9 changed files with 165 additions and 153 deletions

View File

@ -13,7 +13,7 @@ categories = ["network-programming", "cryptography"]
[dependencies] [dependencies]
base64 = "0.10" base64 = "0.10"
log = { version = "0.4.4", optional = true } log = { version = "0.4.4", optional = true }
ring = "0.16.4" ring = "0.16.5"
sct = "0.6.0" sct = "0.6.0"
webpki = "0.21.0" webpki = "0.21.0"

View File

@ -122,19 +122,17 @@ pub fn new_tls12(scs: &'static SupportedCipherSuite,
} }
pub fn new_tls13_read(scs: &'static SupportedCipherSuite, pub fn new_tls13_read(scs: &'static SupportedCipherSuite,
secret: &[u8]) -> Box<dyn MessageDecrypter> { secret: &hkdf::Prk) -> Box<dyn MessageDecrypter> {
let secret = hkdf::Prk::new_less_safe(scs.hkdf_algorithm, secret); let key = derive_traffic_key(secret, scs.get_aead_alg());
let key = derive_traffic_key(&secret, scs.get_aead_alg()); let iv = derive_traffic_iv(secret);
let iv = derive_traffic_iv(&secret);
Box::new(TLS13MessageDecrypter::new(key, iv)) Box::new(TLS13MessageDecrypter::new(key, iv))
} }
pub fn new_tls13_write(scs: &'static SupportedCipherSuite, pub fn new_tls13_write(scs: &'static SupportedCipherSuite,
secret: &[u8]) -> Box<dyn MessageEncrypter> { secret: &hkdf::Prk) -> Box<dyn MessageEncrypter> {
let secret = hkdf::Prk::new_less_safe(scs.hkdf_algorithm, secret); let key = derive_traffic_key(secret, scs.get_aead_alg());
let key = derive_traffic_key(&secret, scs.get_aead_alg()); let iv = derive_traffic_iv(secret);
let iv = derive_traffic_iv(&secret);
Box::new(TLS13MessageEncrypter::new(key, iv)) Box::new(TLS13MessageEncrypter::new(key, iv))
} }

View File

@ -330,15 +330,14 @@ fn emit_client_hello_for_retry(sess: &mut ClientSessionImpl,
let client_hello_hash = handshake.transcript.get_hash_given(resuming_suite.get_hash(), &[]); let client_hello_hash = handshake.transcript.get_hash_given(resuming_suite.get_hash(), &[]);
let client_early_traffic_secret = sess.common let client_early_traffic_secret = sess.common
.get_key_schedule() .get_key_schedule()
.derive_bytes(SecretKind::ClientEarlyTrafficSecret, &client_hello_hash); .derive_logged_secret(SecretKind::ClientEarlyTrafficSecret, &client_hello_hash,
&*sess.config.key_log,
sess.common.protocol.labels().client_early_traffic_secret,
&handshake.randoms.client);
// Set early data encryption key // Set early data encryption key
sess.common sess.common
.set_message_encrypter(cipher::new_tls13_write(resuming_suite, &client_early_traffic_secret)); .set_message_encrypter(cipher::new_tls13_write(resuming_suite, &client_early_traffic_secret));
sess.config.key_log.log(sess.common.protocol.labels().client_early_traffic_secret,
&handshake.randoms.client,
&client_early_traffic_secret);
#[cfg(feature = "quic")] #[cfg(feature = "quic")]
{ {
sess.common.quic.early_secret = Some(client_early_traffic_secret); sess.common.quic.early_secret = Some(client_early_traffic_secret);

View File

@ -211,31 +211,32 @@ pub fn start_handshake_traffic(sess: &mut ClientSessionImpl,
if !sess.early_data.is_enabled() { if !sess.early_data.is_enabled() {
// Set the client encryption key for handshakes if early data is not used // Set the client encryption key for handshakes if early data is not used
let write_key = sess.common.get_key_schedule() let write_key = sess.common.get_key_schedule()
.derive_bytes(SecretKind::ClientHandshakeTrafficSecret, .derive_logged_secret(SecretKind::ClientHandshakeTrafficSecret,
&handshake.hash_at_client_recvd_server_hello); &handshake.hash_at_client_recvd_server_hello,
&*sess.config.key_log,
sess.common.protocol.labels().client_handshake_traffic_secret,
&handshake.randoms.client);
sess.common.set_message_encrypter(cipher::new_tls13_write(suite, &write_key)); sess.common.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
sess.config.key_log.log(sess.common.protocol.labels().client_handshake_traffic_secret, sess.common.get_mut_key_schedule().current_client_traffic_secret = Some(write_key);
&handshake.randoms.client,
&write_key);
sess.common.get_mut_key_schedule().current_client_traffic_secret = write_key;
} }
let read_key = sess.common.get_key_schedule() let read_key = sess.common.get_key_schedule()
.derive_bytes(SecretKind::ServerHandshakeTrafficSecret, .derive_logged_secret(SecretKind::ServerHandshakeTrafficSecret,
&handshake.hash_at_client_recvd_server_hello); &handshake.hash_at_client_recvd_server_hello,
&*sess.config.key_log,
sess.common.protocol.labels().server_handshake_traffic_secret,
&handshake.randoms.client);
sess.common.set_message_decrypter(cipher::new_tls13_read(suite, &read_key)); sess.common.set_message_decrypter(cipher::new_tls13_read(suite, &read_key));
sess.config.key_log.log(sess.common.protocol.labels().server_handshake_traffic_secret, sess.common.get_mut_key_schedule().current_server_traffic_secret = Some(read_key);
&handshake.randoms.client,
&read_key);
sess.common.get_mut_key_schedule().current_server_traffic_secret = read_key;
#[cfg(feature = "quic")] { #[cfg(feature = "quic")] {
let key_schedule = sess.common.key_schedule.as_ref().unwrap(); let key_schedule = sess.common.key_schedule.as_ref().unwrap();
let client = if sess.early_data.is_enabled() { let client = if sess.early_data.is_enabled() {
// Traffic secret wasn't computed and stored above, so do it here. // Traffic secret wasn't computed and stored above, so do it here.
sess.common.get_key_schedule() Some(sess.common.get_key_schedule().derive(
.derive_bytes(SecretKind::ClientHandshakeTrafficSecret, sess.common.get_key_schedule().algorithm(),
&handshake.hash_at_client_recvd_server_hello) SecretKind::ClientHandshakeTrafficSecret,
&handshake.hash_at_client_recvd_server_hello))
} else { } else {
key_schedule.current_client_traffic_secret.clone() key_schedule.current_client_traffic_secret.clone()
}; };
@ -400,14 +401,15 @@ impl hs::State for ExpectEncryptedExtensions {
// If no early traffic, set the encryption key for handshakes // If no early traffic, set the encryption key for handshakes
let suite = sess.common.get_suite_assert(); let suite = sess.common.get_suite_assert();
let write_key = sess.common.get_key_schedule() let write_key = sess.common.get_key_schedule()
.derive_bytes(SecretKind::ClientHandshakeTrafficSecret, .derive_logged_secret(
&self.handshake.hash_at_client_recvd_server_hello); SecretKind::ClientHandshakeTrafficSecret,
&self.handshake.hash_at_client_recvd_server_hello,
&*sess.config.key_log,
sess.common.protocol.labels().client_handshake_traffic_secret,
&self.handshake.randoms.client);
sess.common.set_message_encrypter(cipher::new_tls13_write(suite, &write_key)); sess.common.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
sess.config.key_log.log(sess.common.protocol.labels().client_handshake_traffic_secret,
&self.handshake.randoms.client,
&write_key);
sess.common.get_mut_key_schedule() sess.common.get_mut_key_schedule()
.current_client_traffic_secret = write_key; .current_client_traffic_secret = Some(write_key);
} }
let certv = verify::ServerCertVerified::assertion(); let certv = verify::ServerCertVerified::assertion();
let sigv = verify::HandshakeSignatureValid::assertion(); let sigv = verify::HandshakeSignatureValid::assertion();
@ -827,8 +829,12 @@ impl hs::State for ExpectFinished {
/* Derive the client-to-server encryption key before key schedule update */ /* Derive the client-to-server encryption key before key schedule update */
let key = sess.common let key = sess.common
.get_key_schedule() .get_key_schedule()
.derive_bytes(SecretKind::ClientHandshakeTrafficSecret, .derive_logged_secret(
&st.handshake.hash_at_client_recvd_server_hello); SecretKind::ClientHandshakeTrafficSecret,
&st.handshake.hash_at_client_recvd_server_hello,
&*sess.config.key_log,
sess.common.protocol.labels().client_handshake_traffic_secret,
&st.handshake.randoms.client);
Some(key) Some(key)
} else { } else {
None None
@ -843,24 +849,27 @@ impl hs::State for ExpectFinished {
let handshake_hash = st.handshake.transcript.get_current_hash(); let handshake_hash = st.handshake.transcript.get_current_hash();
let read_key = sess.common let read_key = sess.common
.get_key_schedule() .get_key_schedule()
.derive_bytes(SecretKind::ServerApplicationTrafficSecret, &handshake_hash); .derive_logged_secret(
sess.config.key_log.log(sess.common.protocol.labels().server_traffic_secret_0, SecretKind::ServerApplicationTrafficSecret,
&st.handshake.randoms.client, &handshake_hash,
&read_key); &*sess.config.key_log,
sess.common.protocol.labels().server_traffic_secret_0,
&st.handshake.randoms.client);
sess.common.set_message_decrypter(cipher::new_tls13_read(suite, &read_key)); sess.common.set_message_decrypter(cipher::new_tls13_read(suite, &read_key));
sess.common sess.common
.get_mut_key_schedule() .get_mut_key_schedule()
.current_server_traffic_secret = read_key; .current_server_traffic_secret = Some(read_key);
let exporter_secret = sess.common let exporter_secret = sess.common
.get_key_schedule() .get_key_schedule()
.derive_bytes(SecretKind::ExporterMasterSecret, &handshake_hash); .derive_logged_secret(SecretKind::ExporterMasterSecret,
sess.config.key_log.log(sess.common.protocol.labels().exporter_secret, &handshake_hash,
&st.handshake.randoms.client, &*sess.config.key_log,
&exporter_secret); sess.common.protocol.labels().exporter_secret,
&st.handshake.randoms.client);
sess.common sess.common
.get_mut_key_schedule() .get_mut_key_schedule()
.current_exporter_secret = exporter_secret; .current_exporter_secret = Some(exporter_secret);
/* The EndOfEarlyData message to server is still encrypted with early data keys, /* The EndOfEarlyData message to server is still encrypted with early data keys,
* but appears in the transcript after the server Finished. */ * but appears in the transcript after the server Finished. */
@ -869,10 +878,7 @@ impl hs::State for ExpectFinished {
sess.common.early_traffic = false; sess.common.early_traffic = false;
sess.early_data.finished(); sess.early_data.finished();
sess.common.set_message_encrypter(cipher::new_tls13_write(suite, &write_key)); sess.common.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
sess.config.key_log.log(sess.common.protocol.labels().client_handshake_traffic_secret, sess.common.get_mut_key_schedule().current_client_traffic_secret = Some(write_key);
&st.handshake.randoms.client,
&write_key);
sess.common.get_mut_key_schedule().current_client_traffic_secret = write_key;
} }
/* Send our authentication/finished messages. These are still encrypted /* Send our authentication/finished messages. These are still encrypted
@ -892,14 +898,15 @@ impl hs::State for ExpectFinished {
hs::check_aligned_handshake(sess)?; hs::check_aligned_handshake(sess)?;
let write_key = sess.common let write_key = sess.common
.get_key_schedule() .get_key_schedule()
.derive_bytes(SecretKind::ClientApplicationTrafficSecret, &handshake_hash); .derive_logged_secret(SecretKind::ClientApplicationTrafficSecret,
sess.config.key_log.log(sess.common.protocol.labels().client_traffic_secret_0, &handshake_hash,
&st.handshake.randoms.client, &*sess.config.key_log,
&write_key); sess.common.protocol.labels().client_traffic_secret_0,
&st.handshake.randoms.client);
sess.common.set_message_encrypter(cipher::new_tls13_write(suite, &write_key)); sess.common.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
sess.common sess.common
.get_mut_key_schedule() .get_mut_key_schedule()
.current_client_traffic_secret = write_key; .current_client_traffic_secret = Some(write_key);
sess.common.we_now_encrypting(); sess.common.we_now_encrypting();
sess.common.start_traffic(); sess.common.start_traffic();

View File

@ -4,6 +4,7 @@ use ring::{aead, hkdf::{self, KeyType as _}, hmac, digest};
use crate::error::TLSError; use crate::error::TLSError;
use crate::cipher::{Iv, IvLen}; use crate::cipher::{Iv, IvLen};
use crate::msgs::base::PayloadU8; use crate::msgs::base::PayloadU8;
use crate::KeyLog;
/// The kinds of secret we can extract from `KeySchedule`. /// The kinds of secret we can extract from `KeySchedule`.
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
@ -41,9 +42,9 @@ impl SecretKind {
pub struct KeySchedule { pub struct KeySchedule {
current: hkdf::Prk, current: hkdf::Prk,
algorithm: ring::hkdf::Algorithm, algorithm: ring::hkdf::Algorithm,
pub current_client_traffic_secret: Vec<u8>, pub current_client_traffic_secret: Option<hkdf::Prk>,
pub current_server_traffic_secret: Vec<u8>, pub current_server_traffic_secret: Option<hkdf::Prk>,
pub current_exporter_secret: Vec<u8>, pub current_exporter_secret: Option<hkdf::Prk>,
} }
impl KeySchedule { impl KeySchedule {
@ -54,9 +55,9 @@ impl KeySchedule {
KeySchedule { KeySchedule {
current: salt.extract(secret), current: salt.extract(secret),
algorithm, algorithm,
current_server_traffic_secret: Vec::new(), current_server_traffic_secret: None,
current_client_traffic_secret: Vec::new(), current_client_traffic_secret: None,
current_exporter_secret: Vec::new(), current_exporter_secret: None,
} }
} }
@ -89,10 +90,14 @@ impl KeySchedule {
hkdf_expand(&self.current, key_type, kind.to_bytes(), hs_hash) hkdf_expand(&self.current, key_type, kind.to_bytes(), hs_hash)
} }
pub fn derive_bytes(&self, kind: SecretKind, hs_hash: &[u8]) -> Vec<u8> { pub fn derive_logged_secret(&self, kind: SecretKind, hs_hash: &[u8],
let payload: PayloadU8 = key_log: &dyn KeyLog, log_label: &str, client_random: &[u8; 32])
self.derive(PayloadU8Len(self.algorithm.len()), kind, hs_hash); -> hkdf::Prk
payload.into_inner() {
let secret = self.derive::<PayloadU8, _>(PayloadU8Len(self.algorithm.len()), kind, hs_hash)
.into_inner();
key_log.log(log_label, client_random, &secret);
hkdf::Prk::new_less_safe(self.algorithm, &secret)
} }
/// Derive a secret of given `kind` using the hash of the empty string /// Derive a secret of given `kind` using the hash of the empty string
@ -109,13 +114,15 @@ impl KeySchedule {
} }
/// Return the current traffic secret, of given `kind`. /// Return the current traffic secret, of given `kind`.
fn current_traffic_secret(&self, kind: SecretKind) -> &[u8] { fn current_traffic_secret(&self, kind: SecretKind) -> &hkdf::Prk {
match kind { match kind {
SecretKind::ServerHandshakeTrafficSecret | SecretKind::ServerHandshakeTrafficSecret |
SecretKind::ServerApplicationTrafficSecret => &self.current_server_traffic_secret, SecretKind::ServerApplicationTrafficSecret =>
&self.current_server_traffic_secret.as_ref().unwrap(),
SecretKind::ClientEarlyTrafficSecret | SecretKind::ClientEarlyTrafficSecret |
SecretKind::ClientHandshakeTrafficSecret | SecretKind::ClientHandshakeTrafficSecret |
SecretKind::ClientApplicationTrafficSecret => &self.current_client_traffic_secret, SecretKind::ClientApplicationTrafficSecret =>
&self.current_client_traffic_secret.as_ref().unwrap(),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -124,8 +131,7 @@ impl KeySchedule {
/// traffic secret. /// traffic secret.
pub fn sign_finish(&self, kind: SecretKind, hs_hash: &[u8]) -> Vec<u8> { pub fn sign_finish(&self, kind: SecretKind, hs_hash: &[u8]) -> Vec<u8> {
let base_key = self.current_traffic_secret(kind); let base_key = self.current_traffic_secret(kind);
let base_key = hkdf::Prk::new_less_safe(self.algorithm, base_key); self.sign_verify_data(base_key, hs_hash)
self.sign_verify_data(&base_key, hs_hash)
} }
/// Sign the finished message consisting of `hs_hash` using the key material /// Sign the finished message consisting of `hs_hash` using the key material
@ -140,12 +146,9 @@ impl KeySchedule {
/// Derive the next application traffic secret of given `kind`, returning /// Derive the next application traffic secret of given `kind`, returning
/// it. /// it.
pub fn derive_next(&self, kind: SecretKind) -> Vec<u8> { pub fn derive_next(&self, kind: SecretKind) -> hkdf::Prk {
let base_key = self.current_traffic_secret(kind); let base_key = self.current_traffic_secret(kind);
let base_key = hkdf::Prk::new_less_safe(self.algorithm, &base_key); hkdf_expand(&base_key, self.algorithm, b"traffic upd", &[])
let payload: PayloadU8 =
hkdf_expand(&base_key, PayloadU8Len(self.algorithm.len()), b"traffic upd", &[]);
payload.into_inner()
} }
/// Derive the PSK to use given a resumption_master_secret and /// Derive the PSK to use given a resumption_master_secret and
@ -158,17 +161,13 @@ impl KeySchedule {
pub fn export_keying_material(&self, out: &mut [u8], pub fn export_keying_material(&self, out: &mut [u8],
label: &[u8], label: &[u8],
context: Option<&[u8]>) -> Result<(), TLSError> { context: Option<&[u8]>) -> Result<(), TLSError> {
if self.current_exporter_secret.is_empty() { let current_exporter_secret =
return Err(TLSError::HandshakeNotComplete); self.current_exporter_secret.as_ref().ok_or(TLSError::HandshakeNotComplete)?;
}
let digest_alg = self.algorithm.hmac_algorithm().digest_algorithm(); let digest_alg = self.algorithm.hmac_algorithm().digest_algorithm();
let h_empty = digest::digest(digest_alg, &[]); let h_empty = digest::digest(digest_alg, &[]);
let current_exporter_secret =
hkdf::Prk::new_less_safe(self.algorithm, &self.current_exporter_secret);
let secret: hkdf::Prk = let secret: hkdf::Prk =
hkdf_expand(&current_exporter_secret, self.algorithm, label, h_empty.as_ref()); hkdf_expand(current_exporter_secret, self.algorithm, label, h_empty.as_ref());
let h_context = digest::digest(digest_alg, context.unwrap_or(&[])); let h_context = digest::digest(digest_alg, context.unwrap_or(&[]));
@ -232,6 +231,7 @@ pub(crate) fn derive_traffic_iv(secret: &hkdf::Prk) -> Iv {
mod test { mod test {
use super::{KeySchedule, SecretKind, derive_traffic_key, derive_traffic_iv}; use super::{KeySchedule, SecretKind, derive_traffic_key, derive_traffic_iv};
use ring::{aead, hkdf}; use ring::{aead, hkdf};
use crate::KeyLog;
#[test] #[test]
fn test_vectors() { fn test_vectors() {
@ -361,9 +361,14 @@ mod test {
expected_key: &[u8], expected_key: &[u8],
expected_iv: &[u8], expected_iv: &[u8],
) { ) {
let traffic_secret = ks.derive_bytes(kind, &hash); struct Log<'a>(&'a [u8]);
assert_eq!(expected_traffic_secret, &traffic_secret[..]); impl KeyLog for Log<'_> {
let traffic_secret = hkdf::Prk::new_less_safe(ks.algorithm(), &traffic_secret); fn log(&self, _label: &str, _client_random: &[u8], secret: &[u8]) {
assert_eq!(self.0, secret);
}
}
let log = Log(expected_traffic_secret);
let traffic_secret = ks.derive_logged_secret(kind, &hash, &log, "", &[0; 32]);
// Since we can't test key equality, we test the output of sealing with the key instead. // Since we can't test key equality, we test the output of sealing with the key instead.
let aead_alg = &aead::AES_128_GCM; let aead_alg = &aead::AES_128_GCM;

View File

@ -9,17 +9,16 @@ use crate::key_schedule;
use crate::session::{SessionCommon, Protocol}; use crate::session::{SessionCommon, Protocol};
use std::sync::Arc; use std::sync::Arc;
use ring::hkdf::{self, KeyType as _}; use ring::hkdf;
use webpki; use webpki;
use crate::msgs::base::PayloadU8;
/// Secrets used to encrypt/decrypt traffic /// Secrets used to encrypt/decrypt traffic
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Clone, Debug)]
pub struct Secrets { pub struct Secrets {
/// Secret used to encrypt packets transmitted by the client /// Secret used to encrypt packets transmitted by the client
pub client: Vec<u8>, pub client: Option<hkdf::Prk>,
/// Secret used to encrypt packets transmitted by the server /// Secret used to encrypt packets transmitted by the server
pub server: Vec<u8>, pub server: Option<hkdf::Prk>,
} }
/// Generic methods for QUIC sessions /// Generic methods for QUIC sessions
@ -28,7 +27,7 @@ pub trait QuicExt {
fn get_quic_transport_parameters(&self) -> Option<&[u8]>; fn get_quic_transport_parameters(&self) -> Option<&[u8]>;
/// Return the early traffic secret, used to encrypt 0-RTT data. /// Return the early traffic secret, used to encrypt 0-RTT data.
fn get_early_secret(&self) -> Option<&[u8]>; fn get_early_secret(&self) -> Option<&hkdf::Prk>;
/// Consume unencrypted TLS handshake data. /// Consume unencrypted TLS handshake data.
/// ///
@ -55,8 +54,8 @@ impl QuicExt for ClientSession {
self.imp.common.quic.params.as_ref().map(|v| v.as_ref()) self.imp.common.quic.params.as_ref().map(|v| v.as_ref())
} }
fn get_early_secret(&self) -> Option<&[u8]> { fn get_early_secret(&self) -> Option<&hkdf::Prk> {
self.imp.common.quic.early_secret.as_ref().map(|x| &x[..]) self.imp.common.quic.early_secret.as_ref()
} }
fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), TLSError> { fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), TLSError> {
@ -75,8 +74,8 @@ impl QuicExt for ServerSession {
self.imp.common.quic.params.as_ref().map(|v| v.as_ref()) self.imp.common.quic.params.as_ref().map(|v| v.as_ref())
} }
fn get_early_secret(&self) -> Option<&[u8]> { fn get_early_secret(&self) -> Option<&hkdf::Prk> {
self.imp.common.quic.early_secret.as_ref().map(|x| &x[..]) self.imp.common.quic.early_secret.as_ref()
} }
fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), TLSError> { fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), TLSError> {
@ -126,20 +125,20 @@ fn write_hs(this: &mut SessionCommon, buf: &mut Vec<u8>) -> Option<Secrets> {
fn update_secrets(this: &SessionCommon, client: &[u8], server: &[u8]) -> Secrets { fn update_secrets(this: &SessionCommon, client: &[u8], server: &[u8]) -> Secrets {
let hkdf_alg= this.get_suite_assert().hkdf_algorithm; let hkdf_alg= this.get_suite_assert().hkdf_algorithm;
let client: PayloadU8 = key_schedule::hkdf_expand( let client = key_schedule::hkdf_expand(
&hkdf::Prk::new_less_safe(hkdf_alg, client), &hkdf::Prk::new_less_safe(hkdf_alg, client),
key_schedule::PayloadU8Len(hkdf_alg.len()), hkdf_alg,
b"traffic upd", b"traffic upd",
&[]); &[]);
let server: PayloadU8 = key_schedule::hkdf_expand( let server = key_schedule::hkdf_expand(
&hkdf::Prk::new_less_safe(hkdf_alg, server), &hkdf::Prk::new_less_safe(hkdf_alg, server),
key_schedule::PayloadU8Len(hkdf_alg.len()), hkdf_alg,
b"traffic upd", b"traffic upd",
&[]); &[]);
Secrets { Secrets {
client: client.into_inner(), client: Some(client),
server: server.into_inner(), server: Some(server),
} }
} }

View File

@ -160,10 +160,12 @@ impl CompleteClientHelloHandling {
#[cfg(feature = "quic")] { #[cfg(feature = "quic")] {
if sess.common.protocol == Protocol::Quic { if sess.common.protocol == Protocol::Quic {
let client_early_traffic_secret = key_schedule let client_early_traffic_secret = key_schedule
.derive_bytes(SecretKind::ClientEarlyTrafficSecret, &client_hello_hash); .derive_logged_secret(
sess.config.key_log.log(sess.common.protocol.labels().client_early_traffic_secret, SecretKind::ClientEarlyTrafficSecret,
&self.handshake.randoms.client, &client_hello_hash,
&client_early_traffic_secret); &*sess.config.key_log,
sess.common.protocol.labels().client_early_traffic_secret,
&self.handshake.randoms.client);
// If 0-RTT should be rejected, this will be clobbered by ExtensionProcessing // If 0-RTT should be rejected, this will be clobbered by ExtensionProcessing
// before the application can see. // before the application can see.
sess.common.quic.early_secret = Some(client_early_traffic_secret); sess.common.quic.early_secret = Some(client_early_traffic_secret);
@ -175,26 +177,31 @@ impl CompleteClientHelloHandling {
key_schedule.input_secret(&kxr.premaster_secret); key_schedule.input_secret(&kxr.premaster_secret);
let handshake_hash = self.handshake.transcript.get_current_hash(); let handshake_hash = self.handshake.transcript.get_current_hash();
let write_key = key_schedule.derive_bytes(SecretKind::ServerHandshakeTrafficSecret, &handshake_hash); let write_key = key_schedule.derive_logged_secret(
let read_key = key_schedule.derive_bytes(SecretKind::ClientHandshakeTrafficSecret, &handshake_hash); SecretKind::ServerHandshakeTrafficSecret,
&handshake_hash,
&*sess.config.key_log,
sess.common.protocol.labels().server_handshake_traffic_secret,
&self.handshake.randoms.client);
sess.common.set_message_encrypter(cipher::new_tls13_write(suite, &write_key)); sess.common.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
let read_key = key_schedule.derive_logged_secret(
SecretKind::ClientHandshakeTrafficSecret,
&handshake_hash,
&*sess.config.key_log,
sess.common.protocol.labels().client_handshake_traffic_secret,
&self.handshake.randoms.client);
sess.common.set_message_decrypter(cipher::new_tls13_read(suite, &read_key)); sess.common.set_message_decrypter(cipher::new_tls13_read(suite, &read_key));
sess.config.key_log.log(sess.common.protocol.labels().server_handshake_traffic_secret,
&self.handshake.randoms.client,
&write_key);
sess.config.key_log.log(sess.common.protocol.labels().client_handshake_traffic_secret,
&self.handshake.randoms.client,
&read_key);
#[cfg(feature = "quic")] { #[cfg(feature = "quic")] {
sess.common.quic.hs_secrets = Some(quic::Secrets { sess.common.quic.hs_secrets = Some(quic::Secrets {
client: read_key.clone(), client: Some(write_key.clone()),
server: write_key.clone(), server: Some(read_key.clone()),
}); });
} }
key_schedule.current_client_traffic_secret = read_key; key_schedule.current_client_traffic_secret = Some(read_key);
key_schedule.current_server_traffic_secret = write_key; key_schedule.current_server_traffic_secret = Some(write_key);
sess.common.set_key_schedule(key_schedule); sess.common.set_key_schedule(key_schedule);
Ok(()) Ok(())
@ -406,40 +413,37 @@ impl CompleteClientHelloHandling {
sess.common.get_mut_key_schedule().input_empty(); sess.common.get_mut_key_schedule().input_empty();
let write_key = sess.common let write_key = sess.common
.get_key_schedule() .get_key_schedule()
.derive_bytes(SecretKind::ServerApplicationTrafficSecret, .derive_logged_secret(SecretKind::ServerApplicationTrafficSecret,
&self.handshake.hash_at_server_fin); &self.handshake.hash_at_server_fin,
&*sess.config.key_log,
sess.common.protocol.labels().server_traffic_secret_0,
&self.handshake.randoms.client);
let suite = sess.common.get_suite_assert(); let suite = sess.common.get_suite_assert();
sess.common.set_message_encrypter(cipher::new_tls13_write(suite, &write_key)); sess.common.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
sess.config.key_log.log(sess.common.protocol.labels().server_traffic_secret_0,
&self.handshake.randoms.client,
&write_key);
#[cfg(feature = "quic")] { #[cfg(feature = "quic")] {
let read_key = sess.common let read_key = sess.common.get_key_schedule()
.get_key_schedule() .derive(sess.common.get_key_schedule().algorithm(),
.derive_bytes(SecretKind::ClientApplicationTrafficSecret, SecretKind::ClientApplicationTrafficSecret,
&self.handshake.hash_at_server_fin); &self.handshake.hash_at_server_fin);
sess.common.quic.traffic_secrets = Some(quic::Secrets { sess.common.quic.traffic_secrets = Some(quic::Secrets {
client: read_key, client: Some(read_key),
server: write_key.clone(), server: Some(write_key.clone()),
}); });
} }
sess.common sess.common.get_mut_key_schedule()
.get_mut_key_schedule() .current_server_traffic_secret = Some(write_key);
.current_server_traffic_secret = write_key;
let exporter_secret = sess.common let exporter_secret = sess.common
.get_key_schedule() .get_key_schedule()
.derive_bytes(SecretKind::ExporterMasterSecret, .derive_logged_secret(SecretKind::ExporterMasterSecret,
&self.handshake.hash_at_server_fin); &self.handshake.hash_at_server_fin,
sess.config.key_log.log(sess.common.protocol.labels().exporter_secret, &*sess.config.key_log,
&self.handshake.randoms.client, sess.common.protocol.labels().exporter_secret,
&exporter_secret); &self.handshake.randoms.client);
sess.common sess.common
.get_mut_key_schedule() .get_mut_key_schedule()
.current_exporter_secret = exporter_secret; .current_exporter_secret = Some(exporter_secret);
} }
fn attempt_tls13_ticket_decryption(&mut self, fn attempt_tls13_ticket_decryption(&mut self,
@ -842,18 +846,18 @@ impl hs::State for ExpectFinished {
// Server traffic is already done. // Server traffic is already done.
let read_key = sess.common let read_key = sess.common
.get_key_schedule() .get_key_schedule()
.derive_bytes(SecretKind::ClientApplicationTrafficSecret, .derive_logged_secret(SecretKind::ClientApplicationTrafficSecret,
&self.handshake.hash_at_server_fin); &self.handshake.hash_at_server_fin,
sess.config.key_log.log(sess.common.protocol.labels().client_traffic_secret_0, &*sess.config.key_log,
&self.handshake.randoms.client, sess.common.protocol.labels().client_traffic_secret_0,
&read_key); &self.handshake.randoms.client);
let suite = sess.common.get_suite_assert(); let suite = sess.common.get_suite_assert();
hs::check_aligned_handshake(sess)?; hs::check_aligned_handshake(sess)?;
sess.common.set_message_decrypter(cipher::new_tls13_read(suite, &read_key)); sess.common.set_message_decrypter(cipher::new_tls13_read(suite, &read_key));
sess.common sess.common
.get_mut_key_schedule() .get_mut_key_schedule()
.current_client_traffic_secret = read_key; .current_client_traffic_secret = Some(read_key);
if self.send_ticket { if self.send_ticket {
if sess.config.ticketer.enabled() { if sess.config.ticketer.enabled() {

View File

@ -628,9 +628,9 @@ impl SessionCommon {
self.set_message_encrypter(cipher::new_tls13_write(scs, &write_key)); self.set_message_encrypter(cipher::new_tls13_write(scs, &write_key));
if self.is_client { if self.is_client {
self.get_mut_key_schedule().current_client_traffic_secret = write_key; self.get_mut_key_schedule().current_client_traffic_secret = Some(write_key);
} else { } else {
self.get_mut_key_schedule().current_server_traffic_secret = write_key; self.get_mut_key_schedule().current_server_traffic_secret = Some(write_key);
} }
} }
@ -898,9 +898,9 @@ impl SessionCommon {
self.set_message_decrypter(cipher::new_tls13_read(suite, &new_read_key)); self.set_message_decrypter(cipher::new_tls13_read(suite, &new_read_key));
if read_kind == SecretKind::ServerApplicationTrafficSecret { if read_kind == SecretKind::ServerApplicationTrafficSecret {
self.get_mut_key_schedule().current_server_traffic_secret = new_read_key; self.get_mut_key_schedule().current_server_traffic_secret = Some(new_read_key);
} else { } else {
self.get_mut_key_schedule().current_client_traffic_secret = new_read_key; self.get_mut_key_schedule().current_client_traffic_secret = Some(new_read_key);
} }
Ok(()) Ok(())
@ -941,7 +941,7 @@ pub(crate) struct Quic {
pub params: Option<Vec<u8>>, pub params: Option<Vec<u8>>,
pub alert: Option<AlertDescription>, pub alert: Option<AlertDescription>,
pub hs_queue: VecDeque<(bool, Vec<u8>)>, pub hs_queue: VecDeque<(bool, Vec<u8>)>,
pub early_secret: Option<Vec<u8>>, pub early_secret: Option<ring::hkdf::Prk>,
pub hs_secrets: Option<quic::Secrets>, pub hs_secrets: Option<quic::Secrets>,
pub traffic_secrets: Option<quic::Secrets>, pub traffic_secrets: Option<quic::Secrets>,
} }

View File

@ -1952,6 +1952,6 @@ fn assert_lt(left: usize, right: usize) {
#[test] #[test]
fn session_types_are_not_huge() { fn session_types_are_not_huge() {
// Arbitrary sizes // Arbitrary sizes
assert_lt(mem::size_of::<ServerSession>(), 1536); assert_lt(mem::size_of::<ServerSession>(), 2300);
assert_lt(mem::size_of::<ClientSession>(), 1536); assert_lt(mem::size_of::<ClientSession>(), 2300);
} }