Move TLS1.3 KeySchedule into state machine

This means moving key-update processing into the state-machine too.
This commit is contained in:
Joseph Birr-Pixton 2019-12-06 13:41:15 -08:00
parent 909b9cf12d
commit 412add83da
9 changed files with 244 additions and 211 deletions

View File

@ -14,7 +14,7 @@ use crate::msgs::codec::{Codec, Reader};
use crate::msgs::persist;
use crate::client::ClientSessionImpl;
use crate::session::SessionSecrets;
use crate::key_schedule::SecretKind;
use crate::key_schedule::{KeySchedule, SecretKind};
use crate::cipher;
use crate::suites;
use crate::verify;
@ -69,12 +69,14 @@ pub trait State {
fn handle(self: Box<Self>, sess: &mut ClientSessionImpl, m: Message) -> NextStateOrError;
fn export_keying_material(&self,
_sess: &ClientSessionImpl,
_output: &mut [u8],
_label: &[u8],
_context: Option<&[u8]>) -> Result<(), TLSError> {
Err(TLSError::HandshakeNotComplete)
}
fn perhaps_write_key_update(&mut self, _sess: &mut ClientSessionImpl) {
}
}
pub fn illegal_param(sess: &mut ClientSessionImpl, why: &str) -> TLSError {
@ -164,6 +166,7 @@ pub fn start_handshake(sess: &mut ClientSessionImpl, host_name: webpki::DNSName,
struct ExpectServerHello {
handshake: HandshakeDetails,
early_key_schedule: Option<KeySchedule>,
hello: ClientHelloDetails,
server_cert: ServerCertDetails,
may_send_cert_status: bool,
@ -297,9 +300,11 @@ fn emit_client_hello_for_retry(sess: &mut ClientSessionImpl,
}),
};
if fill_in_binder {
tls13::fill_in_psk_binder(sess, &mut handshake, &mut chp);
}
let early_key_schedule = if fill_in_binder {
Some(tls13::fill_in_psk_binder(sess, &mut handshake, &mut chp))
} else {
None
};
let ch = Message {
typ: ContentType::Handshake,
@ -336,8 +341,9 @@ fn emit_client_hello_for_retry(sess: &mut ClientSessionImpl,
.and_then(|resume| sess.find_cipher_suite(resume.cipher_suite)).unwrap();
let client_hello_hash = handshake.transcript.get_hash_given(resuming_suite.get_hash(), &[]);
let client_early_traffic_secret = sess.common
.get_key_schedule()
let client_early_traffic_secret = early_key_schedule
.as_ref()
.unwrap()
.derive_logged_secret(SecretKind::ClientEarlyTrafficSecret, &client_hello_hash,
&*sess.config.key_log,
&handshake.randoms.client);
@ -357,7 +363,9 @@ fn emit_client_hello_for_retry(sess: &mut ClientSessionImpl,
}
let next = ExpectServerHello {
handshake, hello,
handshake,
hello,
early_key_schedule,
server_cert: ServerCertDetails::new(),
may_send_cert_status: false,
must_issue_new_ticket: false,
@ -388,9 +396,10 @@ pub fn sct_list_is_invalid(scts: &SCTList) -> bool {
}
impl ExpectServerHello {
fn into_expect_tls13_encrypted_extensions(self) -> NextState {
fn into_expect_tls13_encrypted_extensions(self, key_schedule: KeySchedule) -> NextState {
Box::new(tls13::ExpectEncryptedExtensions {
handshake: self.handshake,
key_schedule: key_schedule,
server_cert: self.server_cert,
hello: self.hello,
})
@ -534,9 +543,13 @@ impl State for ExpectServerHello {
// handshake_traffic_secret.
if sess.common.is_tls13() {
tls13::validate_server_hello(sess, server_hello)?;
tls13::start_handshake_traffic(sess, server_hello, &mut self.handshake, &mut self.hello)?;
let key_schedule = tls13::start_handshake_traffic(sess,
self.early_key_schedule.take(),
server_hello,
&mut self.handshake,
&mut self.hello)?;
tls13::emit_fake_ccs(&mut self.handshake, sess);
return Ok(self.into_expect_tls13_encrypted_extensions());
return Ok(self.into_expect_tls13_encrypted_extensions(key_schedule));
}
// TLS1.2 only from here-on

View File

@ -589,7 +589,16 @@ impl ClientSessionImpl {
self.state
.as_ref()
.ok_or_else(|| TLSError::HandshakeNotComplete)
.and_then(|st| st.export_keying_material(self, output, label, context))
.and_then(|st| st.export_keying_material(output, label, context))
}
fn send_some_plaintext(&mut self, buf: &[u8]) -> io::Result<usize> {
let mut st = self.state.take();
st.as_mut()
.map(|st| st.perhaps_write_key_update(self));
self.state = st;
self.common.send_some_plaintext(buf)
}
}
@ -729,7 +738,7 @@ impl io::Write for ClientSession {
/// writing much data before it can be sent will
/// cause excess memory usage.
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.imp.common.send_some_plaintext(buf)
self.imp.send_some_plaintext(buf)
}
fn flush(&mut self) -> io::Result<()> {

View File

@ -778,7 +778,6 @@ impl hs::State for ExpectTraffic {
}
fn export_keying_material(&self,
_sess: &ClientSessionImpl,
output: &mut [u8],
label: &[u8],
context: Option<&[u8]>) -> Result<(), TLSError> {

View File

@ -1,5 +1,6 @@
use crate::msgs::enums::{ContentType, HandshakeType, ExtensionType, SignatureScheme};
use crate::msgs::enums::{ProtocolVersion, AlertDescription, NamedGroup};
use crate::msgs::enums::KeyUpdateRequest;
use crate::msgs::message::{Message, MessagePayload};
use crate::msgs::base::{Payload, PayloadU8};
use crate::msgs::handshake::{HandshakePayload, HandshakeMessagePayload};
@ -122,7 +123,7 @@ pub fn choose_kx_groups(sess: &mut ClientSessionImpl,
/// data dependency on the message they are contained within.
pub fn fill_in_psk_binder(sess: &mut ClientSessionImpl,
handshake: &mut HandshakeDetails,
hmp: &mut HandshakeMessagePayload) {
hmp: &mut HandshakeMessagePayload) -> KeySchedule {
// We need to know the hash function of the suite we're trying to resume into.
let resuming = handshake.resuming_session.as_ref().unwrap();
let suite = sess.find_cipher_suite(resuming.cipher_suite).unwrap();
@ -148,17 +149,19 @@ pub fn fill_in_psk_binder(sess: &mut ClientSessionImpl,
if let HandshakePayload::ClientHello(ref mut ch) = hmp.payload {
ch.set_psk_binder(real_binder);
};
sess.common.set_key_schedule(key_schedule);
key_schedule
}
pub fn start_handshake_traffic(sess: &mut ClientSessionImpl,
early_key_schedule: Option<KeySchedule>,
server_hello: &ServerHelloPayload,
handshake: &mut HandshakeDetails,
hello: &mut ClientHelloDetails)
-> Result<(), TLSError> {
-> Result<KeySchedule, TLSError> {
let suite = sess.common.get_suite_assert();
if let Some(selected_psk) = server_hello.get_psk_index() {
let mut key_schedule = if let Some(selected_psk) = server_hello.get_psk_index() {
if let Some(ref resuming) = handshake.resuming_session {
let resume_from_suite = sess.find_cipher_suite(resuming.cipher_suite).unwrap();
if !resume_from_suite.can_resume_to(suite) {
@ -172,21 +175,21 @@ pub fn start_handshake_traffic(sess: &mut ClientSessionImpl,
}
debug!("Resuming using PSK");
// The key schedule has been initialized and set in fill_in_psk()
// The key schedule has been initialized and set in fill_in_psk_binder()
// Server must be using the resumption suite, otherwise set_suite()
// in ExpectServerHello::handle() would fail.
// key_schedule.input_secret(&resuming.master_secret.0);
} else {
return Err(TLSError::PeerMisbehavedError("server selected unoffered psk".to_string()));
}
early_key_schedule.unwrap()
} else {
debug!("Not resuming");
// Discard the early data key schedule.
sess.early_data.rejected();
sess.common.early_traffic = false;
sess.common.set_key_schedule(KeySchedule::new_with_empty_secret(suite.hkdf_algorithm));
handshake.resuming_session.take();
}
KeySchedule::new_with_empty_secret(suite.hkdf_algorithm)
};
let their_key_share = server_hello.get_key_share()
.ok_or_else(|| {
@ -201,7 +204,7 @@ pub fn start_handshake_traffic(sess: &mut ClientSessionImpl,
.to_string()))?;
save_kx_hint(sess, handshake.dns_name.as_ref(), their_key_share.group);
sess.common.get_mut_key_schedule().input_secret(&shared.shared_secret);
key_schedule.input_secret(&shared.shared_secret);
hs::check_aligned_handshake(sess)?;
@ -210,7 +213,7 @@ pub fn start_handshake_traffic(sess: &mut ClientSessionImpl,
if !sess.early_data.is_enabled() {
// Set the client encryption key for handshakes if early data is not used
let write_key = sess.common.get_key_schedule()
let write_key = key_schedule
.derive_logged_secret(SecretKind::ClientHandshakeTrafficSecret,
&handshake.hash_at_client_recvd_server_hello,
&*sess.config.key_log,
@ -218,10 +221,10 @@ pub fn start_handshake_traffic(sess: &mut ClientSessionImpl,
sess.common
.record_layer
.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
sess.common.get_mut_key_schedule().current_client_traffic_secret = Some(write_key);
key_schedule.current_client_traffic_secret = Some(write_key);
}
let read_key = sess.common.get_key_schedule()
let read_key = key_schedule
.derive_logged_secret(SecretKind::ServerHandshakeTrafficSecret,
&handshake.hash_at_client_recvd_server_hello,
&*sess.config.key_log,
@ -229,16 +232,15 @@ pub fn start_handshake_traffic(sess: &mut ClientSessionImpl,
sess.common
.record_layer
.set_message_decrypter(cipher::new_tls13_read(suite, &read_key));
sess.common.get_mut_key_schedule().current_server_traffic_secret = Some(read_key);
key_schedule.current_server_traffic_secret = Some(read_key);
#[cfg(feature = "quic")] {
let key_schedule = sess.common.key_schedule.as_ref().unwrap();
let client = if sess.early_data.is_enabled() {
// Traffic secret wasn't computed and stored above, so do it here.
sess.common.get_key_schedule().derive(
sess.common.get_key_schedule().algorithm(),
SecretKind::ClientHandshakeTrafficSecret,
&handshake.hash_at_client_recvd_server_hello)
key_schedule
.derive(key_schedule.algorithm(),
SecretKind::ClientHandshakeTrafficSecret,
&handshake.hash_at_client_recvd_server_hello)
} else {
key_schedule.current_client_traffic_secret.clone().unwrap()
};
@ -248,7 +250,7 @@ pub fn start_handshake_traffic(sess: &mut ClientSessionImpl,
});
}
Ok(())
Ok(key_schedule)
}
pub fn prepare_resumption(sess: &mut ClientSessionImpl,
@ -344,6 +346,7 @@ fn validate_encrypted_extensions(sess: &mut ClientSessionImpl,
pub struct ExpectEncryptedExtensions {
pub handshake: HandshakeDetails,
pub key_schedule: KeySchedule,
pub server_cert: ServerCertDetails,
pub hello: ClientHelloDetails,
}
@ -354,6 +357,7 @@ impl ExpectEncryptedExtensions {
sigv: verify::HandshakeSignatureValid) -> hs::NextState {
Box::new(ExpectFinished {
handshake: self.handshake,
key_schedule: self.key_schedule,
client_auth: None,
cert_verified: certv,
sig_verified: sigv,
@ -363,6 +367,7 @@ impl ExpectEncryptedExtensions {
fn into_expect_certificate_or_certreq(self) -> hs::NextState {
Box::new(ExpectCertificateOrCertReq {
handshake: self.handshake,
key_schedule: self.key_schedule,
server_cert: self.server_cert,
})
}
@ -402,7 +407,7 @@ impl hs::State for ExpectEncryptedExtensions {
if was_early_traffic && !sess.common.early_traffic {
// If no early traffic, set the encryption key for handshakes
let suite = sess.common.get_suite_assert();
let write_key = sess.common.get_key_schedule()
let write_key = self.key_schedule
.derive_logged_secret(
SecretKind::ClientHandshakeTrafficSecret,
&self.handshake.hash_at_client_recvd_server_hello,
@ -411,7 +416,7 @@ impl hs::State for ExpectEncryptedExtensions {
sess.common
.record_layer
.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
sess.common.get_mut_key_schedule()
self.key_schedule
.current_client_traffic_secret = Some(write_key);
}
let certv = verify::ServerCertVerified::assertion();
@ -429,6 +434,7 @@ impl hs::State for ExpectEncryptedExtensions {
struct ExpectCertificate {
handshake: HandshakeDetails,
key_schedule: KeySchedule,
server_cert: ServerCertDetails,
client_auth: Option<ClientAuthDetails>,
}
@ -437,6 +443,7 @@ impl ExpectCertificate {
fn into_expect_certificate_verify(self) -> hs::NextState {
Box::new(ExpectCertificateVerify {
handshake: self.handshake,
key_schedule: self.key_schedule,
server_cert: self.server_cert,
client_auth: self.client_auth,
})
@ -488,6 +495,7 @@ impl hs::State for ExpectCertificate {
struct ExpectCertificateOrCertReq {
handshake: HandshakeDetails,
key_schedule: KeySchedule,
server_cert: ServerCertDetails,
}
@ -495,6 +503,7 @@ impl ExpectCertificateOrCertReq {
fn into_expect_certificate(self) -> hs::NextState {
Box::new(ExpectCertificate {
handshake: self.handshake,
key_schedule: self.key_schedule,
server_cert: self.server_cert,
client_auth: None,
})
@ -503,6 +512,7 @@ impl ExpectCertificateOrCertReq {
fn into_expect_certificate_req(self) -> hs::NextState {
Box::new(ExpectCertificateRequest {
handshake: self.handshake,
key_schedule: self.key_schedule,
server_cert: self.server_cert,
})
}
@ -527,16 +537,18 @@ impl hs::State for ExpectCertificateOrCertReq {
// --- TLS1.3 CertificateVerify ---
struct ExpectCertificateVerify {
handshake: HandshakeDetails,
key_schedule: KeySchedule,
server_cert: ServerCertDetails,
client_auth: Option<ClientAuthDetails>,
}
impl ExpectCertificateVerify {
fn into_expect_finished(self,
certv: verify::ServerCertVerified,
sigv: verify::HandshakeSignatureValid) -> hs::NextState {
certv: verify::ServerCertVerified,
sigv: verify::HandshakeSignatureValid) -> hs::NextState {
Box::new(ExpectFinished {
handshake: self.handshake,
key_schedule: self.key_schedule,
client_auth: self.client_auth,
cert_verified: certv,
sig_verified: sigv,
@ -613,6 +625,7 @@ impl hs::State for ExpectCertificateVerify {
// in TLS1.3.
struct ExpectCertificateRequest {
handshake: HandshakeDetails,
key_schedule: KeySchedule,
server_cert: ServerCertDetails,
}
@ -620,6 +633,7 @@ impl ExpectCertificateRequest {
fn into_expect_certificate(self, client_auth: ClientAuthDetails) -> hs::NextState {
Box::new(ExpectCertificate {
handshake: self.handshake,
key_schedule: self.key_schedule,
server_cert: self.server_cert,
client_auth: Some(client_auth),
})
@ -747,10 +761,10 @@ fn emit_certverify_tls13(handshake: &mut HandshakeDetails,
}
fn emit_finished_tls13(handshake: &mut HandshakeDetails,
key_schedule: &KeySchedule,
sess: &mut ClientSessionImpl) {
let handshake_hash = handshake.transcript.get_current_hash();
let verify_data = sess.common
.get_key_schedule()
let verify_data = key_schedule
.sign_finish(SecretKind::ClientHandshakeTrafficSecret, &handshake_hash);
let verify_data_payload = Payload::new(verify_data);
@ -789,6 +803,7 @@ fn emit_end_of_early_data_tls13(handshake: &mut HandshakeDetails,
struct ExpectFinished {
handshake: HandshakeDetails,
key_schedule: KeySchedule,
client_auth: Option<ClientAuthDetails>,
cert_verified: verify::ServerCertVerified,
sig_verified: verify::HandshakeSignatureValid,
@ -796,9 +811,11 @@ struct ExpectFinished {
impl ExpectFinished {
fn into_expect_traffic(self,
fin: verify::FinishedMessageVerified) -> ExpectTraffic {
fin: verify::FinishedMessageVerified) -> ExpectTraffic {
ExpectTraffic {
handshake: self.handshake,
key_schedule: self.key_schedule,
want_write_key_update: false,
_cert_verified: self.cert_verified,
_sig_verified: self.sig_verified,
_fin_verified: fin,
@ -816,8 +833,7 @@ impl hs::State for ExpectFinished {
let finished = extract_handshake!(m, HandshakePayload::Finished).unwrap();
let handshake_hash = st.handshake.transcript.get_current_hash();
let expect_verify_data = sess.common
.get_key_schedule()
let expect_verify_data = st.key_schedule
.sign_finish(SecretKind::ServerHandshakeTrafficSecret, &handshake_hash);
let fin = constant_time::verify_slices_are_equal(&expect_verify_data, &finished.0)
@ -830,8 +846,7 @@ impl hs::State for ExpectFinished {
let suite = sess.common.get_suite_assert();
let maybe_write_key = if sess.common.early_traffic {
/* Derive the client-to-server encryption key before key schedule update */
let key = sess.common
.get_key_schedule()
let key = st.key_schedule
.derive_logged_secret(
SecretKind::ClientHandshakeTrafficSecret,
&st.handshake.hash_at_client_recvd_server_hello,
@ -845,12 +860,11 @@ impl hs::State for ExpectFinished {
st.handshake.transcript.add_message(&m);
/* Transition to application data */
sess.common.get_mut_key_schedule().input_empty();
st.key_schedule.input_empty();
/* Traffic from server is now decrypted with application data keys. */
let handshake_hash = st.handshake.transcript.get_current_hash();
let read_key = sess.common
.get_key_schedule()
let read_key = st.key_schedule
.derive_logged_secret(
SecretKind::ServerApplicationTrafficSecret,
&handshake_hash,
@ -859,18 +873,15 @@ impl hs::State for ExpectFinished {
sess.common
.record_layer
.set_message_decrypter(cipher::new_tls13_read(suite, &read_key));
sess.common
.get_mut_key_schedule()
st.key_schedule
.current_server_traffic_secret = Some(read_key);
let exporter_secret = sess.common
.get_key_schedule()
let exporter_secret = st.key_schedule
.derive_logged_secret(SecretKind::ExporterMasterSecret,
&handshake_hash,
&*sess.config.key_log,
&st.handshake.randoms.client);
sess.common
.get_mut_key_schedule()
st.key_schedule
.current_exporter_secret = Some(exporter_secret);
/* The EndOfEarlyData message to server is still encrypted with early data keys,
@ -882,7 +893,8 @@ impl hs::State for ExpectFinished {
sess.common
.record_layer
.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
sess.common.get_mut_key_schedule().current_client_traffic_secret = Some(write_key);
st.key_schedule
.current_client_traffic_secret = Some(write_key);
}
/* Send our authentication/finished messages. These are still encrypted
@ -896,12 +908,11 @@ impl hs::State for ExpectFinished {
sess)?;
}
emit_finished_tls13(&mut st.handshake, sess);
emit_finished_tls13(&mut st.handshake, &st.key_schedule, sess);
/* Now move to our application traffic keys. */
hs::check_aligned_handshake(sess)?;
let write_key = sess.common
.get_key_schedule()
let write_key = st.key_schedule
.derive_logged_secret(SecretKind::ClientApplicationTrafficSecret,
&handshake_hash,
&*sess.config.key_log,
@ -909,8 +920,7 @@ impl hs::State for ExpectFinished {
sess.common
.record_layer
.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
sess.common
.get_mut_key_schedule()
st.key_schedule
.current_client_traffic_secret = Some(write_key);
sess.common.start_traffic();
@ -918,10 +928,9 @@ impl hs::State for ExpectFinished {
let st = st.into_expect_traffic(fin);
#[cfg(feature = "quic")] {
if sess.common.protocol == Protocol::Quic {
let key_schedule = sess.common.key_schedule.as_ref().unwrap();
sess.common.quic.traffic_secrets = Some(quic::Secrets {
client: key_schedule.current_client_traffic_secret.clone().unwrap(),
server: key_schedule.current_server_traffic_secret.clone().unwrap(),
client: st.key_schedule.current_client_traffic_secret.clone().unwrap(),
server: st.key_schedule.current_server_traffic_secret.clone().unwrap(),
});
return Ok(Box::new(ExpectQUICTraffic(st)));
}
@ -936,6 +945,8 @@ impl hs::State for ExpectFinished {
// and application data.
struct ExpectTraffic {
handshake: HandshakeDetails,
key_schedule: KeySchedule,
want_write_key_update: bool,
_cert_verified: verify::ServerCertVerified,
_sig_verified: verify::HandshakeSignatureValid,
_fin_verified: verify::FinishedMessageVerified,
@ -945,11 +956,11 @@ impl ExpectTraffic {
fn handle_new_ticket_tls13(&mut self, sess: &mut ClientSessionImpl, m: Message) -> Result<(), TLSError> {
let nst = extract_handshake!(m, HandshakePayload::NewSessionTicketTLS13).unwrap();
let handshake_hash = self.handshake.transcript.get_current_hash();
let key_schedule = sess.common.get_key_schedule();
let resumption_master_secret =
key_schedule.derive(key_schedule.algorithm(), SecretKind::ResumptionMasterSecret, &handshake_hash);
let secret = sess.common
.get_key_schedule()
let resumption_master_secret = self.key_schedule
.derive(self.key_schedule.algorithm(),
SecretKind::ResumptionMasterSecret,
&handshake_hash);
let secret = self.key_schedule
.derive_ticket_psk(&resumption_master_secret, &nst.nonce.0);
let mut value = persist::ClientSessionValue::new(ProtocolVersion::TLSv1_3,
@ -995,7 +1006,38 @@ impl ExpectTraffic {
fn handle_key_update(&mut self, sess: &mut ClientSessionImpl, m: Message) -> Result<(), TLSError> {
let kur = extract_handshake!(m, HandshakePayload::KeyUpdate).unwrap();
sess.common.process_key_update(*kur, SecretKind::ServerApplicationTrafficSecret)
#[cfg(feature = "quic")]
{
if let Protocol::Quic = sess.common.protocol {
sess.common.send_fatal_alert(AlertDescription::UnexpectedMessage);
let msg = "KeyUpdate received in QUIC connection".to_string();
warn!("{}", msg);
return Err(TLSError::PeerMisbehavedError(msg));
}
}
// Mustn't be interleaved with other handshake messages.
hs::check_aligned_handshake(sess)?;
match kur {
KeyUpdateRequest::UpdateNotRequested => {}
KeyUpdateRequest::UpdateRequested => {
self.want_write_key_update = true;
}
_ => {
sess.common.send_fatal_alert(AlertDescription::IllegalParameter);
return Err(TLSError::CorruptMessagePayload(ContentType::Handshake));
}
}
// Update our read-side keys.
let new_read_key = self.key_schedule.derive_next(SecretKind::ServerApplicationTrafficSecret);
let suite = sess.common.get_suite_assert();
sess.common.record_layer.set_message_decrypter(cipher::new_tls13_read(suite, &new_read_key));
self.key_schedule.current_server_traffic_secret = Some(new_read_key);
Ok(())
}
}
@ -1019,11 +1061,22 @@ impl hs::State for ExpectTraffic {
}
fn export_keying_material(&self,
sess: &ClientSessionImpl,
output: &mut [u8],
label: &[u8],
context: Option<&[u8]>) -> Result<(), TLSError> {
sess.common.get_key_schedule().export_keying_material(output, label, context)
self.key_schedule.export_keying_material(output, label, context)
}
fn perhaps_write_key_update(&mut self, sess: &mut ClientSessionImpl) {
if self.want_write_key_update {
self.want_write_key_update = false;
sess.common.send_msg_encrypt(Message::build_key_update_notify());
let write_key = self.key_schedule.derive_next(SecretKind::ClientApplicationTrafficSecret);
let scs = sess.common.get_suite_assert();
sess.common.record_layer.set_message_encrypter(cipher::new_tls13_write(scs, &write_key));
self.key_schedule.current_client_traffic_secret = Some(write_key);
}
}
}

View File

@ -53,12 +53,14 @@ pub trait State {
fn handle(self: Box<Self>, sess: &mut ServerSessionImpl, m: Message) -> NextStateOrError;
fn export_keying_material(&self,
_sess: &ServerSessionImpl,
_output: &mut [u8],
_label: &[u8],
_context: Option<&[u8]>) -> Result<(), TLSError> {
Err(TLSError::HandshakeNotComplete)
}
fn perhaps_write_key_update(&mut self, _sess: &mut ServerSessionImpl) {
}
}
pub fn incompatible(sess: &mut ServerSessionImpl, why: &str) -> TLSError {

View File

@ -484,7 +484,15 @@ impl ServerSessionImpl {
self.state
.as_ref()
.ok_or_else(|| TLSError::HandshakeNotComplete)
.and_then(|st| st.export_keying_material(self, output, label, context))
.and_then(|st| st.export_keying_material(output, label, context))
}
fn send_some_plaintext(&mut self, buf: &[u8]) -> io::Result<usize> {
let mut st = self.state.take();
st.as_mut()
.map(|st| st.perhaps_write_key_update(self));
self.state = st;
self.common.send_some_plaintext(buf)
}
}
@ -640,7 +648,7 @@ impl io::Write for ServerSession {
/// writing much data before it can be sent will
/// cause excess memory usage.
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.imp.common.send_some_plaintext(buf)
self.imp.send_some_plaintext(buf)
}
fn flush(&mut self) -> io::Result<()> {

View File

@ -398,7 +398,6 @@ impl hs::State for ExpectTraffic {
}
fn export_keying_material(&self,
_sess: &ServerSessionImpl,
output: &mut [u8],
label: &[u8],
context: Option<&[u8]>) -> Result<(), TLSError> {

View File

@ -1,6 +1,7 @@
use crate::msgs::enums::{ContentType, HandshakeType, ProtocolVersion};
use crate::msgs::enums::{AlertDescription, SignatureScheme, NamedGroup};
use crate::msgs::enums::{Compression, PSKKeyExchangeMode};
use crate::msgs::enums::KeyUpdateRequest;
use crate::msgs::message::{Message, MessagePayload};
use crate::msgs::handshake::HandshakePayload;
use crate::msgs::handshake::HandshakeMessagePayload;
@ -88,16 +89,18 @@ impl CompleteClientHelloHandling {
})
}
fn into_expect_certificate(self) -> hs::NextState {
fn into_expect_certificate(self, key_schedule: KeySchedule) -> hs::NextState {
Box::new(ExpectCertificate {
handshake: self.handshake,
key_schedule,
send_ticket: self.send_ticket,
})
}
fn into_expect_finished(self) -> hs::NextState {
fn into_expect_finished(self, key_schedule: KeySchedule) -> hs::NextState {
Box::new(ExpectFinished {
handshake: self.handshake,
key_schedule,
send_ticket: self.send_ticket,
})
}
@ -108,7 +111,7 @@ impl CompleteClientHelloHandling {
share: &KeyShareEntry,
chosen_psk_idx: Option<usize>,
resuming_psk: Option<&[u8]>)
-> Result<(), TLSError> {
-> Result<KeySchedule, TLSError> {
let mut extensions = Vec::new();
// Do key exchange
@ -202,9 +205,8 @@ impl CompleteClientHelloHandling {
key_schedule.current_client_traffic_secret = Some(read_key);
key_schedule.current_server_traffic_secret = Some(write_key);
sess.common.set_key_schedule(key_schedule);
Ok(())
Ok(key_schedule)
}
fn emit_fake_ccs(&mut self,
@ -388,10 +390,10 @@ impl CompleteClientHelloHandling {
Ok(())
}
fn emit_finished_tls13(&mut self, sess: &mut ServerSessionImpl) {
fn emit_finished_tls13(&mut self, sess: &mut ServerSessionImpl,
key_schedule: &mut KeySchedule) {
let handshake_hash = self.handshake.transcript.get_current_hash();
let verify_data = sess.common
.get_key_schedule()
let verify_data = key_schedule
.sign_finish(SecretKind::ServerHandshakeTrafficSecret, &handshake_hash);
let verify_data_payload = Payload::new(verify_data);
@ -410,9 +412,8 @@ impl CompleteClientHelloHandling {
sess.common.send_msg(m, true);
// Now move to application data keys.
sess.common.get_mut_key_schedule().input_empty();
let write_key = sess.common
.get_key_schedule()
key_schedule.input_empty();
let write_key = key_schedule
.derive_logged_secret(SecretKind::ServerApplicationTrafficSecret,
&self.handshake.hash_at_server_fin,
&*sess.config.key_log,
@ -423,8 +424,8 @@ impl CompleteClientHelloHandling {
.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
#[cfg(feature = "quic")] {
let read_key = sess.common.get_key_schedule()
.derive(sess.common.get_key_schedule().algorithm(),
let read_key = key_schedule
.derive(key_schedule.algorithm(),
SecretKind::ClientApplicationTrafficSecret,
&self.handshake.hash_at_server_fin);
sess.common.quic.traffic_secrets = Some(quic::Secrets {
@ -433,17 +434,13 @@ impl CompleteClientHelloHandling {
});
}
sess.common.get_mut_key_schedule()
.current_server_traffic_secret = Some(write_key);
let exporter_secret = sess.common
.get_key_schedule()
key_schedule.current_server_traffic_secret = Some(write_key);
let exporter_secret = key_schedule
.derive_logged_secret(SecretKind::ExporterMasterSecret,
&self.handshake.hash_at_server_fin,
&*sess.config.key_log,
&self.handshake.randoms.client);
sess.common
.get_mut_key_schedule()
.current_exporter_secret = Some(exporter_secret);
key_schedule.current_exporter_secret = Some(exporter_secret);
}
fn attempt_tls13_ticket_decryption(&mut self,
@ -581,9 +578,9 @@ impl CompleteClientHelloHandling {
let full_handshake = resumedata.is_none();
self.handshake.transcript.add_message(chm);
self.emit_server_hello(sess, &client_hello.session_id,
chosen_share, chosen_psk_index,
resumedata.as_ref().map(|x| &x.master_secret.0[..]))?;
let mut key_schedule = self.emit_server_hello(sess, &client_hello.session_id,
chosen_share, chosen_psk_index,
resumedata.as_ref().map(|x| &x.master_secret.0[..]))?;
if !self.done_retry {
self.emit_fake_ccs(sess);
}
@ -599,24 +596,26 @@ impl CompleteClientHelloHandling {
};
hs::check_aligned_handshake(sess)?;
self.emit_finished_tls13(sess);
self.emit_finished_tls13(sess, &mut key_schedule);
if doing_client_auth {
Ok(self.into_expect_certificate())
Ok(self.into_expect_certificate(key_schedule))
} else {
Ok(self.into_expect_finished())
Ok(self.into_expect_finished(key_schedule))
}
}
}
pub struct ExpectCertificate {
pub handshake: HandshakeDetails,
pub key_schedule: KeySchedule,
pub send_ticket: bool,
}
impl ExpectCertificate {
fn into_expect_finished(self) -> hs::NextState {
Box::new(ExpectFinished {
key_schedule: self.key_schedule,
handshake: self.handshake,
send_ticket: self.send_ticket,
})
@ -626,6 +625,7 @@ impl ExpectCertificate {
cert: ClientCertDetails) -> hs::NextState {
Box::new(ExpectCertificateVerify {
handshake: self.handshake,
key_schedule: self.key_schedule,
client_cert: cert,
send_ticket: self.send_ticket,
})
@ -674,6 +674,7 @@ impl hs::State for ExpectCertificate {
pub struct ExpectCertificateVerify {
handshake: HandshakeDetails,
key_schedule: KeySchedule,
client_cert: ClientCertDetails,
send_ticket: bool,
}
@ -681,6 +682,7 @@ pub struct ExpectCertificateVerify {
impl ExpectCertificateVerify {
fn into_expect_finished(self) -> hs::NextState {
Box::new(ExpectFinished {
key_schedule: self.key_schedule,
handshake: self.handshake,
send_ticket: self.send_ticket,
})
@ -720,6 +722,7 @@ impl hs::State for ExpectCertificateVerify {
// --- Process client's Finished ---
fn get_server_session_value(handshake: &mut HandshakeDetails,
key_schedule: &KeySchedule,
sess: &ServerSessionImpl,
nonce: &[u8]) -> persist::ServerSessionValue {
let scs = sess.common.get_suite_assert();
@ -728,13 +731,11 @@ fn get_server_session_value(handshake: &mut HandshakeDetails,
let handshake_hash = handshake
.transcript
.get_current_hash();
let key_schedule = sess.common.get_key_schedule();
let resumption_master_secret =
key_schedule.derive(key_schedule.algorithm(),
SecretKind::ResumptionMasterSecret,
&handshake_hash);
let secret = sess.common
.get_key_schedule()
let secret = key_schedule
.derive_ticket_psk(&resumption_master_secret, nonce);
persist::ServerSessionValue::new(
@ -748,12 +749,15 @@ fn get_server_session_value(handshake: &mut HandshakeDetails,
pub struct ExpectFinished {
pub handshake: HandshakeDetails,
pub key_schedule: KeySchedule,
pub send_ticket: bool,
}
impl ExpectFinished {
fn into_expect_traffic(self, fin: verify::FinishedMessageVerified) -> hs::NextState {
Box::new(ExpectTraffic {
key_schedule: self.key_schedule,
want_write_key_update: false,
_fin_verified: fin,
})
}
@ -762,6 +766,7 @@ impl ExpectFinished {
debug_assert!(self.send_ticket);
let nonce = rand::random_vec(32);
let plain = get_server_session_value(&mut self.handshake,
&self.key_schedule,
sess, &nonce)
.get_encoding();
let maybe_ticket = sess.config
@ -801,6 +806,7 @@ impl ExpectFinished {
let nonce = rand::random_vec(32);
let id = rand::random_vec(32);
let plain = get_server_session_value(&mut self.handshake,
&self.key_schedule,
sess, &nonce)
.get_encoding();
@ -841,8 +847,7 @@ impl hs::State for ExpectFinished {
let finished = extract_handshake!(m, HandshakePayload::Finished).unwrap();
let handshake_hash = self.handshake.transcript.get_current_hash();
let expect_verify_data = sess.common
.get_key_schedule()
let expect_verify_data = self.key_schedule
.sign_finish(SecretKind::ClientHandshakeTrafficSecret, &handshake_hash);
let fin = constant_time::verify_slices_are_equal(&expect_verify_data, &finished.0)
@ -859,8 +864,7 @@ impl hs::State for ExpectFinished {
// Now move to using application data keys for client traffic.
// Server traffic is already done.
let read_key = sess.common
.get_key_schedule()
let read_key = self.key_schedule
.derive_logged_secret(SecretKind::ClientApplicationTrafficSecret,
&self.handshake.hash_at_server_fin,
&*sess.config.key_log,
@ -871,8 +875,7 @@ impl hs::State for ExpectFinished {
sess.common
.record_layer
.set_message_decrypter(cipher::new_tls13_read(suite, &read_key));
sess.common
.get_mut_key_schedule()
self.key_schedule
.current_client_traffic_secret = Some(read_key);
if self.send_ticket {
@ -897,6 +900,8 @@ impl hs::State for ExpectFinished {
// --- Process traffic ---
pub struct ExpectTraffic {
key_schedule: KeySchedule,
want_write_key_update: bool,
_fin_verified: verify::FinishedMessageVerified,
}
@ -906,9 +911,39 @@ impl ExpectTraffic {
Ok(())
}
fn handle_key_update(&self, sess: &mut ServerSessionImpl, m: Message) -> Result<(), TLSError> {
fn handle_key_update(&mut self, sess: &mut ServerSessionImpl, m: Message) -> Result<(), TLSError> {
let kur = extract_handshake!(m, HandshakePayload::KeyUpdate).unwrap();
sess.common.process_key_update(*kur, SecretKind::ClientApplicationTrafficSecret)
#[cfg(feature = "quic")]
{
if let Protocol::Quic = sess.common.protocol {
sess.common.send_fatal_alert(AlertDescription::UnexpectedMessage);
let msg = "KeyUpdate received in QUIC connection".to_string();
warn!("{}", msg);
return Err(TLSError::PeerMisbehavedError(msg));
}
}
hs::check_aligned_handshake(sess)?;
match kur {
KeyUpdateRequest::UpdateNotRequested => {}
KeyUpdateRequest::UpdateRequested => {
self.want_write_key_update = true;
}
_ => {
sess.common.send_fatal_alert(AlertDescription::IllegalParameter);
return Err(TLSError::CorruptMessagePayload(ContentType::Handshake));
}
}
// Update our read-side keys.
let new_read_key = self.key_schedule.derive_next(SecretKind::ClientApplicationTrafficSecret);
let suite = sess.common.get_suite_assert();
sess.common.record_layer.set_message_decrypter(cipher::new_tls13_read(suite, &new_read_key));
self.key_schedule.current_client_traffic_secret = Some(new_read_key);
Ok(())
}
}
@ -919,7 +954,7 @@ impl hs::State for ExpectTraffic {
&[HandshakeType::KeyUpdate])
}
fn handle(self: Box<Self>, sess: &mut ServerSessionImpl, m: Message) -> hs::NextStateOrError {
fn handle(mut self: Box<Self>, sess: &mut ServerSessionImpl, m: Message) -> hs::NextStateOrError {
if m.is_content_type(ContentType::ApplicationData) {
self.handle_traffic(sess, m)?;
} else if m.is_handshake_type(HandshakeType::KeyUpdate) {
@ -930,11 +965,22 @@ impl hs::State for ExpectTraffic {
}
fn export_keying_material(&self,
sess: &ServerSessionImpl,
output: &mut [u8],
label: &[u8],
context: Option<&[u8]>) -> Result<(), TLSError> {
sess.common.get_key_schedule().export_keying_material(output, label, context)
self.key_schedule.export_keying_material(output, label, context)
}
fn perhaps_write_key_update(&mut self, sess: &mut ServerSessionImpl) {
if self.want_write_key_update {
self.want_write_key_update = false;
sess.common.send_msg_encrypt(Message::build_key_update_notify());
let write_key = self.key_schedule.derive_next(SecretKind::ServerApplicationTrafficSecret);
let scs = sess.common.get_suite_assert();
sess.common.record_layer.set_message_encrypter(cipher::new_tls13_write(scs, &write_key));
self.key_schedule.current_server_traffic_secret = Some(write_key);
}
}
}

View File

@ -7,13 +7,11 @@ use crate::msgs::hsjoiner::HandshakeJoiner;
use crate::msgs::base::Payload;
use crate::msgs::codec::Codec;
use crate::msgs::enums::{ContentType, ProtocolVersion, AlertDescription, AlertLevel};
use crate::msgs::enums::KeyUpdateRequest;
use crate::error::TLSError;
use crate::suites::SupportedCipherSuite;
use crate::cipher;
use crate::vecbuf::{ChunkVecBuffer, WriteV};
use crate::key;
use crate::key_schedule::{SecretKind, KeySchedule};
use crate::prf;
use crate::rand;
use crate::quic;
@ -401,12 +399,10 @@ pub struct SessionCommon {
pub negotiated_version: Option<ProtocolVersion>,
pub is_client: bool,
pub record_layer: record_layer::RecordLayer,
pub key_schedule: Option<KeySchedule>,
suite: Option<&'static SupportedCipherSuite>,
peer_eof: bool,
pub traffic: bool,
pub early_traffic: bool,
pub want_write_key_update: bool,
pub message_deframer: MessageDeframer,
pub handshake_joiner: HandshakeJoiner,
pub message_fragmenter: MessageFragmenter,
@ -426,11 +422,9 @@ impl SessionCommon {
is_client: client,
record_layer: record_layer::RecordLayer::new(),
suite: None,
key_schedule: None,
peer_eof: false,
traffic: false,
early_traffic: false,
want_write_key_update: false,
message_deframer: MessageDeframer::new(),
handshake_joiner: HandshakeJoiner::new(),
message_fragmenter: MessageFragmenter::new(mtu.unwrap_or(MAX_FRAGMENT_LEN)),
@ -472,18 +466,6 @@ impl SessionCommon {
}
}
pub fn get_mut_key_schedule(&mut self) -> &mut KeySchedule {
self.key_schedule.as_mut().unwrap()
}
pub fn get_key_schedule(&self) -> &KeySchedule {
self.key_schedule.as_ref().unwrap()
}
pub fn set_key_schedule(&mut self, ks: KeySchedule) {
self.key_schedule = Some(ks);
}
pub fn decrypt_incoming(&mut self, encr: Message) -> Result<Message, TLSError> {
if self.record_layer.wants_close_before_decrypt() {
self.send_close_notify();
@ -539,36 +521,9 @@ impl SessionCommon {
}
}
fn do_write_key_update(&mut self) {
// TLS1.3 putting key update triggering here breaks layering
// between the handshake and record layer.
let kind = if self.is_client {
SecretKind::ClientApplicationTrafficSecret
} else {
SecretKind::ServerApplicationTrafficSecret
};
self.want_write_key_update = false;
self.send_msg_encrypt(Message::build_key_update_notify());
let write_key = self.get_key_schedule().derive_next(kind);
let scs = self.get_suite_assert();
self.record_layer.set_message_encrypter(cipher::new_tls13_write(scs, &write_key));
if self.is_client {
self.get_mut_key_schedule().current_client_traffic_secret = Some(write_key);
} else {
self.get_mut_key_schedule().current_server_traffic_secret = Some(write_key);
}
}
/// Fragment `m`, encrypt the fragments, and then queue
/// the encrypted fragments for sending.
pub fn send_msg_encrypt(&mut self, m: Message) {
if self.want_write_key_update {
self.do_write_key_update();
}
let mut plain_messages = VecDeque::new();
self.message_fragmenter.fragment(m, &mut plain_messages);
@ -581,10 +536,6 @@ impl SessionCommon {
fn send_appdata_encrypt(&mut self,
payload: &[u8],
limit: Limit) -> usize {
if self.want_write_key_update {
self.do_write_key_update();
}
// Here, the limit on sendable_tls applies to encrypted data,
// but we're respecting it for plaintext data -- so we'll
// be out by whatever the cipher+record overhead is. That's a
@ -724,7 +675,7 @@ impl SessionCommon {
"QUIC uses TLS for the cryptographic handshake only");
let mut bytes = Vec::new();
m.payload.encode(&mut bytes);
self.quic.hs_queue.push_back((self.key_schedule.is_some(), bytes));
self.quic.hs_queue.push_back((must_encrypt, bytes));
}
return;
}
@ -777,53 +728,6 @@ impl SessionCommon {
self.send_warning_alert_no_log(AlertDescription::CloseNotify);
}
pub fn process_key_update(&mut self,
kur: KeyUpdateRequest,
read_kind: SecretKind)
-> Result<(), TLSError> {
#[cfg(feature = "quic")]
{
if let Protocol::Quic = self.protocol {
self.send_fatal_alert(AlertDescription::UnexpectedMessage);
let msg = "KeyUpdate received in QUIC connection".to_string();
warn!("{}", msg);
return Err(TLSError::PeerMisbehavedError(msg));
}
}
// Mustn't be interleaved with other handshake messages.
if !self.handshake_joiner.is_empty() {
let msg = "KeyUpdate received at wrong time".to_string();
warn!("{}", msg);
return Err(TLSError::PeerMisbehavedError(msg));
}
match kur {
KeyUpdateRequest::UpdateNotRequested => {}
KeyUpdateRequest::UpdateRequested => {
self.want_write_key_update = true;
}
_ => {
self.send_fatal_alert(AlertDescription::IllegalParameter);
return Err(TLSError::CorruptMessagePayload(ContentType::Handshake));
}
}
// Update our read-side keys.
let new_read_key = self.get_key_schedule()
.derive_next(read_kind);
let suite = self.get_suite_assert();
self.record_layer.set_message_decrypter(cipher::new_tls13_read(suite, &new_read_key));
if read_kind == SecretKind::ServerApplicationTrafficSecret {
self.get_mut_key_schedule().current_server_traffic_secret = Some(new_read_key);
} else {
self.get_mut_key_schedule().current_client_traffic_secret = Some(new_read_key);
}
Ok(())
}
fn send_warning_alert_no_log(&mut self, desc: AlertDescription) {
let m = Message::build_alert(AlertLevel::Warning, desc);
self.send_msg(m, self.record_layer.is_encrypting());