Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions rustls/src/client/client_conn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::conn::{ConnectionCore, UnbufferedConnectionCommon};
use crate::crypto::{CryptoProvider, SupportedKxGroup};
use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme};
use crate::error::Error;
use crate::kernel::KernelConnection;
use crate::log::trace;
use crate::msgs::enums::NamedGroup;
use crate::msgs::handshake::ClientExtension;
Expand Down Expand Up @@ -896,9 +897,28 @@ impl UnbufferedClientConnection {

/// Extract secrets, so they can be used when configuring kTLS, for example.
/// Should be used with care as it exposes secret key material.
#[deprecated = "dangerous_extract_secrets() does not support session tickets or \
key updates, use dangerous_into_kernel_connection() instead"]
pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
self.inner.dangerous_extract_secrets()
}

/// Extract secrets and a [`KernelConnection`] object.
///
/// This allows you use rustls to manage keys and then manage encryption and
/// decryption yourself (e.g. for kTLS).
///
/// Should be used with care as it exposes secret key material.
///
/// See the [`crate::kernel`] documentations for details on prerequisites
/// for calling this method.
pub fn dangerous_into_kernel_connection(
self,
) -> Result<(ExtractedSecrets, KernelConnection<ClientConnectionData>), Error> {
self.inner
.core
.dangerous_into_kernel_connection()
}
}

impl Deref for UnbufferedClientConnection {
Expand Down
28 changes: 26 additions & 2 deletions rustls/src/client/tls12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@

use super::client_conn::ClientConnectionData;
use super::hs::ClientContext;
use crate::ConnectionTrafficSecrets;
use crate::check::{inappropriate_handshake_message, inappropriate_message};
use crate::client::common::{ClientAuthDetails, ServerCertDetails};
use crate::client::{ClientConfig, hs};
use crate::common_state::{CommonState, HandshakeKind, KxState, Side, State};
use crate::conn::ConnectionRandoms;
use crate::conn::kernel::{Direction, KernelContext, KernelState};
use crate::crypto::KeyExchangeAlgorithm;
use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion};
use crate::error::{Error, InvalidMessage, PeerIncompatible, PeerMisbehaved};
Expand All @@ -23,8 +25,8 @@
use crate::msgs::ccs::ChangeCipherSpecPayload;
use crate::msgs::handshake::{
CertificateChain, ClientDhParams, ClientEcdhParams, ClientKeyExchangeParams,
HandshakeMessagePayload, HandshakePayload, NewSessionTicketPayload, ServerKeyExchangeParams,
SessionId,
HandshakeMessagePayload, HandshakePayload, NewSessionTicketPayload,
NewSessionTicketPayloadTls13, ServerKeyExchangeParams, SessionId,
};
use crate::msgs::message::{Message, MessagePayload};
use crate::msgs::persist;
Expand Down Expand Up @@ -1331,7 +1333,29 @@
.extract_secrets(Side::Client)
}

fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> {
Ok(self)
}

fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
self
}
}

impl KernelState for ExpectTraffic {
fn update_secrets(&mut self, _: Direction) -> Result<ConnectionTrafficSecrets, Error> {
Err(Error::General(
"TLS 1.2 connections do not support traffic secret updates".into(),
))
}

fn handle_new_session_ticket(
&mut self,
_cx: &mut KernelContext<'_>,
_message: &NewSessionTicketPayloadTls13,
) -> Result<(), Error> {
Err(Error::General(
"TLS 1.2 session tickets may not be sent once the handshake has completed".into(),
))
}

Check warning on line 1360 in rustls/src/client/tls12.rs

View check run for this annotation

Codecov / codecov/patch

rustls/src/client/tls12.rs#L1352-L1360

Added lines #L1352 - L1360 were not covered by tests
}
83 changes: 71 additions & 12 deletions rustls/src/client/tls13.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
CommonState, HandshakeFlightTls13, HandshakeKind, KxState, Protocol, Side, State,
};
use crate::conn::ConnectionRandoms;
use crate::conn::kernel::{Direction, KernelContext, KernelState};
use crate::crypto::{ActiveKeyExchange, SharedSecret};
use crate::enums::{
AlertDescription, ContentType, HandshakeType, ProtocolVersion, SignatureScheme,
Expand Down Expand Up @@ -45,7 +46,7 @@
Tls13CipherSuite, construct_client_verify_message, construct_server_verify_message,
};
use crate::verify::{self, DigitallySignedStruct};
use crate::{KeyLog, compress, crypto};
use crate::{ConnectionTrafficSecrets, KeyLog, compress, crypto};

// Extensions we expect in plaintext in the ServerHello.
static ALLOWED_PLAINTEXT_EXTS: &[ExtensionType] = &[
Expand Down Expand Up @@ -1460,16 +1461,13 @@
}

impl ExpectTraffic {
fn handle_new_ticket_tls13(
fn handle_new_ticket_impl(
&mut self,
cx: &mut ClientContext<'_>,
cx: &mut KernelContext<'_>,
nst: &NewSessionTicketPayloadTls13,
) -> Result<(), Error> {
if nst.has_duplicate_extension() {
return Err(cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::DuplicateNewSessionTicketExtensions,
));
return Err(PeerMisbehaved::DuplicateNewSessionTicketExtensions.into());

Check warning on line 1470 in rustls/src/client/tls13.rs

View check run for this annotation

Codecov / codecov/patch

rustls/src/client/tls13.rs#L1470

Added line #L1470 was not covered by tests
}

let handshake_hash = self.transcript.current_hash();
Expand All @@ -1483,9 +1481,8 @@
self.suite,
Arc::clone(&nst.ticket),
secret.as_ref(),
cx.common
.peer_certificates
.clone()
cx.peer_certificates
.cloned()
.unwrap_or_default(),
&self.config.verifier,
&self.config.client_auth_cert_resolver,
Expand All @@ -1496,14 +1493,14 @@
.unwrap_or_default(),
);

if cx.common.is_quic() {
if cx.is_quic() {
if let Some(sz) = nst.max_early_data_size() {
if sz != 0 && sz != 0xffff_ffff {
return Err(PeerMisbehaved::InvalidMaxEarlyDataSize.into());
}
}

if let Some(quic_params) = &cx.common.quic.params {
if let Some(quic_params) = &cx.quic.params {
value.set_quic_params(quic_params);
}
}
Expand All @@ -1513,6 +1510,26 @@
Ok(())
}

fn handle_new_ticket_tls13(
&mut self,
cx: &mut ClientContext<'_>,
nst: &NewSessionTicketPayloadTls13,
) -> Result<(), Error> {
if nst.has_duplicate_extension() {
return Err(cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::DuplicateNewSessionTicketExtensions,
));
}

let mut kcx = KernelContext {
peer_certificates: cx.common.peer_certificates.as_ref(),
protocol: cx.common.protocol,
quic: &cx.common.quic,
};
self.handle_new_ticket_impl(&mut kcx, nst)
}

fn handle_key_update(
&mut self,
common: &mut CommonState,
Expand Down Expand Up @@ -1601,11 +1618,33 @@
.extract_secrets(Side::Client)
}

fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> {
Ok(self)
}

fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
self
}
}

impl KernelState for ExpectTraffic {
fn update_secrets(&mut self, dir: Direction) -> Result<ConnectionTrafficSecrets, Error> {
self.key_schedule
.refresh_traffic_secret(match dir {
Direction::Transmit => Side::Client,
Direction::Receive => Side::Server,
})
}

fn handle_new_session_ticket(
&mut self,
cx: &mut KernelContext<'_>,
message: &NewSessionTicketPayloadTls13,
) -> Result<(), Error> {
self.handle_new_ticket_impl(cx, message)
}

Check warning on line 1645 in rustls/src/client/tls13.rs

View check run for this annotation

Codecov / codecov/patch

rustls/src/client/tls13.rs#L1639-L1645

Added lines #L1639 - L1645 were not covered by tests
}

struct ExpectQuicTraffic(ExpectTraffic);

impl State<ClientConnectionData> for ExpectQuicTraffic {
Expand Down Expand Up @@ -1637,7 +1676,27 @@
.export_keying_material(output, label, context)
}

fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> {
Ok(self)
}

Check warning on line 1681 in rustls/src/client/tls13.rs

View check run for this annotation

Codecov / codecov/patch

rustls/src/client/tls13.rs#L1679-L1681

Added lines #L1679 - L1681 were not covered by tests

fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
self
}
}

impl KernelState for ExpectQuicTraffic {
fn update_secrets(&mut self, _: Direction) -> Result<ConnectionTrafficSecrets, Error> {
Err(Error::General(
"KeyUpdate is not supported for QUIC connections".into(),
))
}

Check warning on line 1693 in rustls/src/client/tls13.rs

View check run for this annotation

Codecov / codecov/patch

rustls/src/client/tls13.rs#L1689-L1693

Added lines #L1689 - L1693 were not covered by tests

fn handle_new_session_ticket(
&mut self,
cx: &mut KernelContext<'_>,
nst: &NewSessionTicketPayloadTls13,
) -> Result<(), Error> {
self.0.handle_new_ticket_impl(cx, nst)
}

Check warning on line 1701 in rustls/src/client/tls13.rs

View check run for this annotation

Codecov / codecov/patch

rustls/src/client/tls13.rs#L1695-L1701

Added lines #L1695 - L1701 were not covered by tests
}
5 changes: 5 additions & 0 deletions rustls/src/common_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use pki_types::CertificateDer;

use crate::conn::kernel::KernelState;
use crate::crypto::SupportedKxGroup;
use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion};
use crate::error::{Error, InvalidMessage, PeerMisbehaved};
Expand Down Expand Up @@ -867,6 +868,10 @@

fn handle_decrypt_error(&self) {}

fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> {
Err(Error::HandshakeNotComplete)
}

Check warning on line 873 in rustls/src/common_state.rs

View check run for this annotation

Codecov / codecov/patch

rustls/src/common_state.rs#L871-L873

Added lines #L871 - L873 were not covered by tests

fn into_owned(self: Box<Self>) -> Box<dyn State<Data> + 'static>;
}

Expand Down
47 changes: 39 additions & 8 deletions rustls/src/conn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use core::fmt::Debug;
use core::mem;
use core::ops::{Deref, DerefMut, Range};
use kernel::KernelConnection;
#[cfg(feature = "std")]
use std::io;

Expand All @@ -15,9 +16,11 @@
use crate::msgs::handshake::Random;
use crate::msgs::message::{InboundPlainMessage, Message, MessagePayload};
use crate::record_layer::Decrypted;
use crate::suites::{ExtractedSecrets, PartiallyExtractedSecrets};
use crate::suites::ExtractedSecrets;
use crate::vecbuf::ChunkVecBuffer;

// pub so that it can be re-exported from the crate root
pub mod kernel;
pub(crate) mod unbuffered;

#[cfg(feature = "std")]
Expand Down Expand Up @@ -1158,21 +1161,49 @@
}

pub(crate) fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
Ok(self
.dangerous_into_kernel_connection()?
.0)
}

pub(crate) fn dangerous_into_kernel_connection(
self,
) -> Result<(ExtractedSecrets, KernelConnection<Data>), Error> {
if !self
.common_state
.enable_secret_extraction
{
return Err(Error::General("Secret extraction is disabled".into()));
}

let st = self.state?;
if self.common_state.is_handshaking() {
return Err(Error::HandshakeNotComplete);
}

if !self
.common_state
.sendable_tls
.is_empty()
{
return Err(Error::General(
"cannot convert into an KernelConnection while there are still buffered TLS records to send"
.into()
));

Check warning on line 1191 in rustls/src/conn.rs

View check run for this annotation

Codecov / codecov/patch

rustls/src/conn.rs#L1188-L1191

Added lines #L1188 - L1191 were not covered by tests
}

let state = self.state?;

let record_layer = &self.common_state.record_layer;
let secrets = state.extract_secrets()?;
let secrets = ExtractedSecrets {
tx: (record_layer.write_seq(), secrets.tx),
rx: (record_layer.read_seq(), secrets.rx),
};

let state = state.into_external_state()?;
let external = KernelConnection::new(state, self.common_state)?;

let record_layer = self.common_state.record_layer;
let PartiallyExtractedSecrets { tx, rx } = st.extract_secrets()?;
Ok(ExtractedSecrets {
tx: (record_layer.write_seq(), tx),
rx: (record_layer.read_seq(), rx),
})
Ok((secrets, external))
}

pub(crate) fn export_keying_material<T: AsMut<[u8]>>(
Expand Down
Loading
Loading