tls13: Immediate key update

This commit is contained in:
Jacob Rothstein 2023-01-10 14:49:12 -08:00 committed by Dirkjan Ochtman
parent 411a65d736
commit d28be0f31d
4 changed files with 44 additions and 48 deletions

View File

@ -889,7 +889,6 @@ impl State<ClientConnectionData> for ExpectFinished {
suite: st.suite, suite: st.suite,
transcript: st.transcript, transcript: st.transcript,
key_schedule: key_schedule_traffic, key_schedule: key_schedule_traffic,
want_write_key_update: false,
_cert_verified: st.cert_verified, _cert_verified: st.cert_verified,
_sig_verified: st.sig_verified, _sig_verified: st.sig_verified,
_fin_verified: fin, _fin_verified: fin,
@ -913,7 +912,6 @@ struct ExpectTraffic {
suite: &'static Tls13CipherSuite, suite: &'static Tls13CipherSuite,
transcript: HandshakeHash, transcript: HandshakeHash,
key_schedule: KeyScheduleTraffic, key_schedule: KeyScheduleTraffic,
want_write_key_update: bool,
_cert_verified: verify::ServerCertVerified, _cert_verified: verify::ServerCertVerified,
_sig_verified: verify::HandshakeSignatureValid, _sig_verified: verify::HandshakeSignatureValid,
_fin_verified: verify::FinishedMessageVerified, _fin_verified: verify::FinishedMessageVerified,
@ -983,7 +981,7 @@ impl ExpectTraffic {
fn handle_key_update( fn handle_key_update(
&mut self, &mut self,
common: &mut CommonState, common: &mut CommonState,
kur: &KeyUpdateRequest, key_update_request: &KeyUpdateRequest,
) -> Result<(), Error> { ) -> Result<(), Error> {
#[cfg(feature = "quic")] #[cfg(feature = "quic")]
{ {
@ -997,15 +995,9 @@ impl ExpectTraffic {
// Mustn't be interleaved with other handshake messages. // Mustn't be interleaved with other handshake messages.
common.check_aligned_handshake()?; common.check_aligned_handshake()?;
match kur { if common.should_update_key(key_update_request)? {
KeyUpdateRequest::UpdateNotRequested => {} self.key_schedule
KeyUpdateRequest::UpdateRequested => { .update_encrypter_and_notify(common);
self.want_write_key_update = true;
}
_ => {
common.send_fatal_alert(AlertDescription::IllegalParameter);
return Err(Error::CorruptMessagePayload(ContentType::Handshake));
}
} }
// Update our read-side keys. // Update our read-side keys.
@ -1059,14 +1051,6 @@ impl State<ClientConnectionData> for ExpectTraffic {
.export_keying_material(output, label, context) .export_keying_material(output, label, context)
} }
fn perhaps_write_key_update(&mut self, common: &mut CommonState) {
if self.want_write_key_update {
self.want_write_key_update = false;
self.key_schedule
.update_encrypter_and_notify(common);
}
}
#[cfg(feature = "secret_extraction")] #[cfg(feature = "secret_extraction")]
fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> { fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> {
self.key_schedule self.key_schedule

View File

@ -6,8 +6,8 @@ use crate::log::{debug, error, trace, warn};
use crate::msgs::alert::AlertMessagePayload; use crate::msgs::alert::AlertMessagePayload;
use crate::msgs::base::Payload; use crate::msgs::base::Payload;
use crate::msgs::deframer::{Deframed, MessageDeframer}; use crate::msgs::deframer::{Deframed, MessageDeframer};
use crate::msgs::enums::HandshakeType;
use crate::msgs::enums::{AlertDescription, AlertLevel, ContentType}; use crate::msgs::enums::{AlertDescription, AlertLevel, ContentType};
use crate::msgs::enums::{HandshakeType, KeyUpdateRequest};
use crate::msgs::fragmenter::MessageFragmenter; use crate::msgs::fragmenter::MessageFragmenter;
use crate::msgs::handshake::Random; use crate::msgs::handshake::Random;
use crate::msgs::message::{ use crate::msgs::message::{
@ -694,9 +694,8 @@ impl<Data> ConnectionCommon<Data> {
} }
pub(crate) fn send_some_plaintext(&mut self, buf: &[u8]) -> usize { pub(crate) fn send_some_plaintext(&mut self, buf: &[u8]) -> usize {
if let Ok(st) = &mut self.state { self.common_state
st.perhaps_write_key_update(&mut self.common_state); .perhaps_write_key_update();
}
self.common_state self.common_state
.send_some_plaintext(buf) .send_some_plaintext(buf)
} }
@ -823,6 +822,8 @@ pub struct CommonState {
received_plaintext: ChunkVecBuffer, received_plaintext: ChunkVecBuffer,
sendable_plaintext: ChunkVecBuffer, sendable_plaintext: ChunkVecBuffer,
pub(crate) sendable_tls: ChunkVecBuffer, pub(crate) sendable_tls: ChunkVecBuffer,
queued_key_update_message: Option<Vec<u8>>,
#[allow(dead_code)] // only read for QUIC #[allow(dead_code)] // only read for QUIC
/// Protocol whose key schedule should be used. Unused for TLS < 1.3. /// Protocol whose key schedule should be used. Unused for TLS < 1.3.
pub(crate) protocol: Protocol, pub(crate) protocol: Protocol,
@ -853,6 +854,7 @@ impl CommonState {
received_plaintext: ChunkVecBuffer::new(Some(DEFAULT_RECEIVED_PLAINTEXT_LIMIT)), received_plaintext: ChunkVecBuffer::new(Some(DEFAULT_RECEIVED_PLAINTEXT_LIMIT)),
sendable_plaintext: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)), sendable_plaintext: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)),
sendable_tls: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)), sendable_tls: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)),
queued_key_update_message: None,
protocol: Protocol::Tcp, protocol: Protocol::Tcp,
#[cfg(feature = "quic")] #[cfg(feature = "quic")]
@ -1317,6 +1319,35 @@ impl CommonState {
#[cfg(not(feature = "quic"))] #[cfg(not(feature = "quic"))]
false false
} }
pub(crate) fn should_update_key(
&mut self,
key_update_request: &KeyUpdateRequest,
) -> Result<bool, Error> {
match key_update_request {
KeyUpdateRequest::UpdateNotRequested => Ok(false),
KeyUpdateRequest::UpdateRequested => Ok(self.queued_key_update_message.is_none()),
_ => {
self.send_fatal_alert(AlertDescription::IllegalParameter);
Err(Error::CorruptMessagePayload(ContentType::Handshake))
}
}
}
pub(crate) fn enqueue_key_update_notification(&mut self) {
let message = PlainMessage::from(Message::build_key_update_notify());
self.queued_key_update_message = Some(
self.record_layer
.encrypt_outgoing(message.borrow())
.encode(),
);
}
fn perhaps_write_key_update(&mut self) {
if let Some(message) = self.queued_key_update_message.take() {
self.sendable_tls.append(message);
}
}
} }
pub(crate) trait State<Data>: Send + Sync { pub(crate) trait State<Data>: Send + Sync {
@ -1339,8 +1370,6 @@ pub(crate) trait State<Data>: Send + Sync {
fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> { fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> {
Err(Error::HandshakeNotComplete) Err(Error::HandshakeNotComplete)
} }
fn perhaps_write_key_update(&mut self, _cx: &mut CommonState) {}
} }
pub(crate) struct Context<'a, Data> { pub(crate) struct Context<'a, Data> {

View File

@ -1194,7 +1194,6 @@ impl State<ServerConnectionData> for ExpectFinished {
Ok(Box::new(ExpectTraffic { Ok(Box::new(ExpectTraffic {
key_schedule: key_schedule_traffic, key_schedule: key_schedule_traffic,
want_write_key_update: false,
_fin_verified: fin, _fin_verified: fin,
})) }))
} }
@ -1203,7 +1202,6 @@ impl State<ServerConnectionData> for ExpectFinished {
// --- Process traffic --- // --- Process traffic ---
struct ExpectTraffic { struct ExpectTraffic {
key_schedule: KeyScheduleTraffic, key_schedule: KeyScheduleTraffic,
want_write_key_update: bool,
_fin_verified: verify::FinishedMessageVerified, _fin_verified: verify::FinishedMessageVerified,
} }
@ -1211,7 +1209,7 @@ impl ExpectTraffic {
fn handle_key_update( fn handle_key_update(
&mut self, &mut self,
common: &mut CommonState, common: &mut CommonState,
kur: &KeyUpdateRequest, key_update_request: &KeyUpdateRequest,
) -> Result<(), Error> { ) -> Result<(), Error> {
#[cfg(feature = "quic")] #[cfg(feature = "quic")]
{ {
@ -1224,15 +1222,9 @@ impl ExpectTraffic {
common.check_aligned_handshake()?; common.check_aligned_handshake()?;
match kur { if common.should_update_key(key_update_request)? {
KeyUpdateRequest::UpdateNotRequested => {} self.key_schedule
KeyUpdateRequest::UpdateRequested => { .update_encrypter_and_notify(common);
self.want_write_key_update = true;
}
_ => {
common.send_fatal_alert(AlertDescription::IllegalParameter);
return Err(Error::CorruptMessagePayload(ContentType::Handshake));
}
} }
// Update our read-side keys. // Update our read-side keys.
@ -1278,14 +1270,6 @@ impl State<ServerConnectionData> for ExpectTraffic {
.export_keying_material(output, label, context) .export_keying_material(output, label, context)
} }
fn perhaps_write_key_update(&mut self, common: &mut CommonState) {
if self.want_write_key_update {
self.want_write_key_update = false;
self.key_schedule
.update_encrypter_and_notify(common);
}
}
#[cfg(feature = "secret_extraction")] #[cfg(feature = "secret_extraction")]
fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> { fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> {
self.key_schedule self.key_schedule

View File

@ -2,7 +2,6 @@ use crate::cipher::{Iv, IvLen, MessageDecrypter};
use crate::conn::{CommonState, Side}; use crate::conn::{CommonState, Side};
use crate::error::Error; use crate::error::Error;
use crate::msgs::base::PayloadU8; use crate::msgs::base::PayloadU8;
use crate::msgs::message::Message;
#[cfg(feature = "quic")] #[cfg(feature = "quic")]
use crate::quic; use crate::quic;
#[cfg(feature = "secret_extraction")] #[cfg(feature = "secret_extraction")]
@ -464,7 +463,7 @@ impl KeyScheduleTraffic {
pub(crate) fn update_encrypter_and_notify(&mut self, common: &mut CommonState) { pub(crate) fn update_encrypter_and_notify(&mut self, common: &mut CommonState) {
let secret = self.next_application_traffic_secret(common.side); let secret = self.next_application_traffic_secret(common.side);
common.send_msg_encrypt(Message::build_key_update_notify().into()); common.enqueue_key_update_notification();
self.ks.set_encrypter(&secret, common); self.ks.set_encrypter(&secret, common);
} }