in quic/s2n-quic-tls/src/callback.rs [152:285]
fn on_secret(
&mut self,
conn: *mut s2n_connection,
id: s2n_secret_type_t::Type,
secret: &mut [u8],
) -> Result<(), transport::Error> {
match core::mem::replace(&mut self.state.secrets, Secrets::Waiting) {
Secrets::Waiting => {
if id == s2n_secret_type_t::CLIENT_EARLY_TRAFFIC_SECRET {
return Ok(());
}
let (prk_algo, _aead, cipher_suite) =
get_algo_type(conn).ok_or(tls::Error::INTERNAL_ERROR)?;
let secret = Prk::new_less_safe(prk_algo, secret);
self.state.secrets = Secrets::Half { secret, id };
self.state.cipher_suite = cipher_suite;
Ok(())
}
Secrets::Half {
id: other_id,
secret: other_secret,
} => {
let (prk_algo, aead_algo, cipher_suite) =
get_algo_type(conn).ok_or(tls::Error::INTERNAL_ERROR)?;
let secret = Prk::new_less_safe(prk_algo, secret);
self.state.cipher_suite = cipher_suite;
let pair = match (id, other_id) {
(
s2n_secret_type_t::CLIENT_HANDSHAKE_TRAFFIC_SECRET,
s2n_secret_type_t::SERVER_HANDSHAKE_TRAFFIC_SECRET,
)
| (
s2n_secret_type_t::CLIENT_APPLICATION_TRAFFIC_SECRET,
s2n_secret_type_t::SERVER_APPLICATION_TRAFFIC_SECRET,
) => SecretPair {
client: secret,
server: other_secret,
},
(
s2n_secret_type_t::SERVER_HANDSHAKE_TRAFFIC_SECRET,
s2n_secret_type_t::CLIENT_HANDSHAKE_TRAFFIC_SECRET,
)
| (
s2n_secret_type_t::SERVER_APPLICATION_TRAFFIC_SECRET,
s2n_secret_type_t::CLIENT_APPLICATION_TRAFFIC_SECRET,
) => SecretPair {
server: secret,
client: other_secret,
},
_ => {
debug_assert!(false, "invalid key phase");
return Err(transport::Error::INTERNAL_ERROR);
}
};
// Flush the send buffer before transitioning to the next phase
self.flush();
match self.state.tx_phase {
HandshakePhase::Initial => {
let (key, header_key) = HandshakeKey::new(self.endpoint, aead_algo, pair)
.expect("invalid cipher");
if !self.server_params.is_empty() {
debug_assert!(self.endpoint.is_server());
// Since the client transport parameters are sent in the Initial packet space
// we can access them early on in the handshake, allowing the server transport
// parameters to be configured based on the client's parameters.
unsafe {
// Safety: conn needs to outlive params
let client_params = get_application_params(conn)?;
// Allow for additional server params to be appended that depend
// on the given client params
self.context.on_client_application_params(
client_params,
self.server_params,
)?;
// Now set the server transport parameters on the connection for
// transmission to the client
s2n_connection_set_quic_transport_parameters(
conn,
self.server_params.as_ptr(),
self.server_params.len() as _,
);
}
// We've given the transport parameters to s2n-tls, so clear
// `server_params` to ensure they are not set again.
self.server_params.clear();
}
self.context.on_handshake_keys(key, header_key)?;
self.state.tx_phase.transition();
self.state.rx_phase.transition();
}
_ => {
let (key, header_key) =
OneRttKey::new(self.endpoint, aead_algo, pair).expect("invalid cipher");
// At this point the server is done writing Handshake messages
if self.endpoint.is_server() {
self.state.tx_phase.transition();
}
let params = unsafe {
// Safety: conn needs to outlive params
let application_protocol =
Bytes::copy_from_slice(get_application_protocol(conn)?);
self.context.on_application_protocol(application_protocol)?;
// Client has already emitted the server name elsewhere
if self.endpoint.is_server() {
if let Some(server_name) = get_server_name(conn) {
self.context.on_server_name(server_name)?;
}
}
if let Some(named_group) = get_key_exchange_group(conn) {
self.context.on_key_exchange_group(named_group)?;
}
get_application_params(conn)?
};
self.context.on_one_rtt_keys(key, header_key, params)?;
}
}
Ok(())
}
}
}