blob: 4b770e3859c65b8a20debd944507fe4c5a69ae37 [file] [log] [blame]
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;
use crate::msgs::handshake::NewSessionTicketPayloadTLS13;
use crate::msgs::handshake::CertificateEntry;
use crate::msgs::handshake::CertificateExtension;
use crate::msgs::handshake::CertificateStatus;
use crate::msgs::handshake::CertificatePayloadTLS13;
use crate::msgs::handshake::CertificateRequestPayloadTLS13;
use crate::msgs::handshake::CertReqExtension;
use crate::msgs::handshake::ClientHelloPayload;
use crate::msgs::handshake::HelloRetryRequest;
use crate::msgs::handshake::HelloRetryExtension;
use crate::msgs::handshake::ServerHelloPayload;
use crate::msgs::handshake::KeyShareEntry;
use crate::msgs::handshake::SessionID;
use crate::msgs::handshake::ServerExtension;
use crate::msgs::handshake::Random;
use crate::msgs::handshake::DigitallySignedStruct;
use crate::msgs::ccs::ChangeCipherSpecPayload;
use crate::msgs::base::{Payload, PayloadU8};
use crate::msgs::codec::Codec;
use crate::msgs::persist;
use crate::server::ServerSessionImpl;
use crate::key_schedule::{
KeyScheduleNonSecret,
KeyScheduleEarly,
KeyScheduleHandshake,
KeyScheduleTrafficWithClientFinishedPending,
KeyScheduleTraffic
};
use crate::cipher;
use crate::verify;
use crate::rand;
use crate::sign;
use crate::suites;
#[cfg(feature = "logging")]
use crate::log::{warn, trace, debug};
use crate::error::TLSError;
use crate::handshake::{check_handshake_message, check_message};
#[cfg(feature = "quic")]
use crate::{
quic,
msgs::handshake::NewSessionTicketExtension,
session::Protocol
};
use crate::server::common::{HandshakeDetails, ClientCertDetails};
use crate::server::hs;
use ring::constant_time;
pub struct CompleteClientHelloHandling {
pub handshake: HandshakeDetails,
pub done_retry: bool,
pub send_cert_status: bool,
pub send_sct: bool,
pub send_ticket: bool,
}
impl CompleteClientHelloHandling {
fn check_binder(&self,
sess: &mut ServerSessionImpl,
client_hello: &Message,
psk: &[u8],
binder: &[u8])
-> bool {
let binder_plaintext = match client_hello.payload {
MessagePayload::Handshake(ref hmp) => hmp.get_encoding_for_binder_signing(),
_ => unreachable!(),
};
let suite = sess.common.get_suite_assert();
let suite_hash = suite.get_hash();
let handshake_hash = self.handshake.transcript.get_hash_given(suite_hash, &binder_plaintext);
let key_schedule = KeyScheduleEarly::new(suite.hkdf_algorithm, &psk);
let real_binder = key_schedule.resumption_psk_binder_key_and_sign_verify_data(&handshake_hash);
constant_time::verify_slices_are_equal(&real_binder, binder).is_ok()
}
fn into_expect_retried_client_hello(self) -> hs::NextState {
Box::new(hs::ExpectClientHello {
handshake: self.handshake,
done_retry: true,
send_cert_status: self.send_cert_status,
send_sct: self.send_sct,
send_ticket: self.send_ticket,
})
}
fn into_expect_certificate(self, key_schedule: KeyScheduleTrafficWithClientFinishedPending) -> hs::NextState {
Box::new(ExpectCertificate {
handshake: self.handshake,
key_schedule,
send_ticket: self.send_ticket,
})
}
fn into_expect_finished(self, key_schedule: KeyScheduleTrafficWithClientFinishedPending) -> hs::NextState {
Box::new(ExpectFinished {
handshake: self.handshake,
key_schedule,
send_ticket: self.send_ticket,
})
}
fn emit_server_hello(&mut self,
sess: &mut ServerSessionImpl,
session_id: &SessionID,
share: &KeyShareEntry,
chosen_psk_idx: Option<usize>,
resuming_psk: Option<&[u8]>)
-> Result<KeyScheduleHandshake, TLSError> {
let mut extensions = Vec::new();
// Do key exchange
let kxr = suites::KeyExchange::start_ecdhe(share.group)
.and_then(|kx| kx.complete(&share.payload.0))
.ok_or_else(|| TLSError::PeerMisbehavedError("key exchange failed".to_string()))?;
let kse = KeyShareEntry::new(share.group, kxr.pubkey.as_ref());
extensions.push(ServerExtension::KeyShare(kse));
extensions.push(ServerExtension::SupportedVersions(ProtocolVersion::TLSv1_3));
if let Some(psk_idx) = chosen_psk_idx {
extensions.push(ServerExtension::PresharedKey(psk_idx as u16));
}
let sh = Message {
typ: ContentType::Handshake,
version: ProtocolVersion::TLSv1_2,
payload: MessagePayload::Handshake(HandshakeMessagePayload {
typ: HandshakeType::ServerHello,
payload: HandshakePayload::ServerHello(ServerHelloPayload {
legacy_version: ProtocolVersion::TLSv1_2,
random: Random::from_slice(&self.handshake.randoms.server),
session_id: *session_id,
cipher_suite: sess.common.get_suite_assert().suite,
compression_method: Compression::Null,
extensions,
}),
}),
};
hs::check_aligned_handshake(sess)?;
#[cfg(feature = "quic")]
let client_hello_hash = self.handshake.transcript
.get_hash_given(sess.common.get_suite_assert().get_hash(), &[]);
trace!("sending server hello {:?}", sh);
self.handshake.transcript.add_message(&sh);
sess.common.send_msg(sh, false);
// Start key schedule
let suite = sess.common.get_suite_assert();
let mut key_schedule = if let Some(psk) = resuming_psk {
let early_key_schedule = KeyScheduleEarly::new(suite.hkdf_algorithm, psk);
#[cfg(feature = "quic")] {
if sess.common.protocol == Protocol::Quic {
let client_early_traffic_secret = early_key_schedule
.client_early_traffic_secret(&client_hello_hash,
&*sess.config.key_log,
&self.handshake.randoms.client);
// If 0-RTT should be rejected, this will be clobbered by ExtensionProcessing
// before the application can see.
sess.common.quic.early_secret = Some(client_early_traffic_secret);
}
}
early_key_schedule
.into_handshake(&kxr.shared_secret)
} else {
KeyScheduleNonSecret::new(suite.hkdf_algorithm)
.into_handshake(&kxr.shared_secret)
};
let handshake_hash = self.handshake.transcript.get_current_hash();
let write_key = key_schedule
.server_handshake_traffic_secret(&handshake_hash,
&*sess.config.key_log,
&self.handshake.randoms.client);
sess.common
.record_layer
.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
let read_key = key_schedule
.client_handshake_traffic_secret(&handshake_hash,
&*sess.config.key_log,
&self.handshake.randoms.client);
sess.common
.record_layer
.set_message_decrypter(cipher::new_tls13_read(suite, &read_key));
#[cfg(feature = "quic")] {
sess.common.quic.hs_secrets = Some(quic::Secrets {
client: read_key,
server: write_key,
});
}
Ok(key_schedule)
}
fn emit_fake_ccs(&mut self,
sess: &mut ServerSessionImpl) {
#[cfg(feature = "quic")] {
if let Protocol::Quic = sess.common.protocol { return; }
}
let m = Message {
typ: ContentType::ChangeCipherSpec,
version: ProtocolVersion::TLSv1_2,
payload: MessagePayload::ChangeCipherSpec(ChangeCipherSpecPayload {})
};
sess.common.send_msg(m, false);
}
fn emit_hello_retry_request(&mut self,
sess: &mut ServerSessionImpl,
group: NamedGroup) {
let mut req = HelloRetryRequest {
legacy_version: ProtocolVersion::TLSv1_2,
session_id: SessionID::empty(),
cipher_suite: sess.common.get_suite_assert().suite,
extensions: Vec::new(),
};
req.extensions.push(HelloRetryExtension::KeyShare(group));
req.extensions.push(HelloRetryExtension::SupportedVersions(ProtocolVersion::TLSv1_3));
let m = Message {
typ: ContentType::Handshake,
version: ProtocolVersion::TLSv1_2,
payload: MessagePayload::Handshake(HandshakeMessagePayload {
typ: HandshakeType::HelloRetryRequest,
payload: HandshakePayload::HelloRetryRequest(req),
}),
};
trace!("Requesting retry {:?}", m);
self.handshake.transcript.rollup_for_hrr();
self.handshake.transcript.add_message(&m);
sess.common.send_msg(m, false);
}
fn emit_encrypted_extensions(&mut self,
sess: &mut ServerSessionImpl,
server_key: &mut sign::CertifiedKey,
hello: &ClientHelloPayload,
resumedata: Option<&persist::ServerSessionValue>)
-> Result<(), TLSError> {
let mut ep = hs::ExtensionProcessing::new();
ep.process_common(sess, Some(server_key), hello, resumedata, &self.handshake)?;
self.send_cert_status = ep.send_cert_status;
self.send_sct = ep.send_sct;
let ee = Message {
typ: ContentType::Handshake,
version: ProtocolVersion::TLSv1_3,
payload: MessagePayload::Handshake(HandshakeMessagePayload {
typ: HandshakeType::EncryptedExtensions,
payload: HandshakePayload::EncryptedExtensions(ep.exts),
}),
};
trace!("sending encrypted extensions {:?}", ee);
self.handshake.transcript.add_message(&ee);
sess.common.send_msg(ee, true);
Ok(())
}
fn emit_certificate_req_tls13(&mut self, sess: &mut ServerSessionImpl) -> Result<bool, TLSError> {
if !sess.config.verifier.offer_client_auth() {
return Ok(false);
}
let mut cr = CertificateRequestPayloadTLS13 {
context: PayloadU8::empty(),
extensions: Vec::new(),
};
let schemes = verify::supported_verify_schemes();
cr.extensions.push(CertReqExtension::SignatureAlgorithms(schemes.to_vec()));
let names = sess.config.verifier.client_auth_root_subjects(sess.get_sni())
.ok_or_else(|| {
debug!("could not determine root subjects based on SNI");
sess.common.send_fatal_alert(AlertDescription::AccessDenied);
TLSError::General("client rejected by client_auth_root_subjects".into())
})?;
if !names.is_empty() {
cr.extensions.push(CertReqExtension::AuthorityNames(names));
}
let m = Message {
typ: ContentType::Handshake,
version: ProtocolVersion::TLSv1_3,
payload: MessagePayload::Handshake(HandshakeMessagePayload {
typ: HandshakeType::CertificateRequest,
payload: HandshakePayload::CertificateRequestTLS13(cr),
}),
};
trace!("Sending CertificateRequest {:?}", m);
self.handshake.transcript.add_message(&m);
sess.common.send_msg(m, true);
Ok(true)
}
fn emit_certificate_tls13(&mut self,
sess: &mut ServerSessionImpl,
server_key: &mut sign::CertifiedKey) {
let mut cert_entries = vec![];
for cert in server_key.take_cert() {
let entry = CertificateEntry {
cert,
exts: Vec::new(),
};
cert_entries.push(entry);
}
if let Some(end_entity_cert) = cert_entries.first_mut() {
// Apply OCSP response to first certificate (we don't support OCSP
// except for leaf certs).
if self.send_cert_status {
if let Some(ocsp) = server_key.take_ocsp() {
let cst = CertificateStatus::new(ocsp);
end_entity_cert.exts.push(CertificateExtension::CertificateStatus(cst));
}
}
// Likewise, SCT
if self.send_sct {
if let Some(sct_list) = server_key.take_sct_list() {
end_entity_cert.exts.push(CertificateExtension::make_sct(sct_list));
}
}
}
let cert_body = CertificatePayloadTLS13::new(cert_entries);
let c = Message {
typ: ContentType::Handshake,
version: ProtocolVersion::TLSv1_3,
payload: MessagePayload::Handshake(HandshakeMessagePayload {
typ: HandshakeType::Certificate,
payload: HandshakePayload::CertificateTLS13(cert_body),
}),
};
trace!("sending certificate {:?}", c);
self.handshake.transcript.add_message(&c);
sess.common.send_msg(c, true);
}
fn emit_certificate_verify_tls13(&mut self,
sess: &mut ServerSessionImpl,
server_key: &mut sign::CertifiedKey,
schemes: &[SignatureScheme])
-> Result<(), TLSError> {
let mut message = Vec::new();
message.resize(64, 0x20u8);
message.extend_from_slice(b"TLS 1.3, server CertificateVerify\x00");
message.extend_from_slice(&self.handshake.transcript.get_current_hash());
let signing_key = &server_key.key;
let signer = signing_key.choose_scheme(schemes)
.ok_or_else(|| hs::incompatible(sess, "no overlapping sigschemes"))?;
let scheme = signer.get_scheme();
let sig = signer.sign(&message)?;
let cv = DigitallySignedStruct::new(scheme, sig);
let m = Message {
typ: ContentType::Handshake,
version: ProtocolVersion::TLSv1_3,
payload: MessagePayload::Handshake(HandshakeMessagePayload {
typ: HandshakeType::CertificateVerify,
payload: HandshakePayload::CertificateVerify(cv),
}),
};
trace!("sending certificate-verify {:?}", m);
self.handshake.transcript.add_message(&m);
sess.common.send_msg(m, true);
Ok(())
}
fn emit_finished_tls13(&mut self, sess: &mut ServerSessionImpl,
key_schedule: KeyScheduleHandshake) -> KeyScheduleTrafficWithClientFinishedPending {
let handshake_hash = self.handshake.transcript.get_current_hash();
let verify_data = key_schedule.sign_server_finish(&handshake_hash);
let verify_data_payload = Payload::new(verify_data);
let m = Message {
typ: ContentType::Handshake,
version: ProtocolVersion::TLSv1_3,
payload: MessagePayload::Handshake(HandshakeMessagePayload {
typ: HandshakeType::Finished,
payload: HandshakePayload::Finished(verify_data_payload),
}),
};
trace!("sending finished {:?}", m);
self.handshake.transcript.add_message(&m);
self.handshake.hash_at_server_fin = self.handshake.transcript.get_current_hash();
sess.common.send_msg(m, true);
// Now move to application data keys. Read key change is deferred until
// the Finish message is received & validated.
let mut key_schedule_traffic = key_schedule.into_traffic_with_client_finished_pending();
let suite = sess.common.get_suite_assert();
let write_key = key_schedule_traffic
.server_application_traffic_secret(&self.handshake.hash_at_server_fin,
&*sess.config.key_log,
&self.handshake.randoms.client);
sess.common
.record_layer
.set_message_encrypter(cipher::new_tls13_write(suite, &write_key));
key_schedule_traffic
.exporter_master_secret(&self.handshake.hash_at_server_fin,
&*sess.config.key_log,
&self.handshake.randoms.client);
let _read_key = key_schedule_traffic
.client_application_traffic_secret(&self.handshake.hash_at_server_fin,
&*sess.config.key_log,
&self.handshake.randoms.client);
#[cfg(feature = "quic")] {
sess.common.quic.traffic_secrets = Some(quic::Secrets {
client: _read_key,
server: write_key,
});
}
key_schedule_traffic
}
fn attempt_tls13_ticket_decryption(&mut self,
sess: &mut ServerSessionImpl,
ticket: &[u8]) -> Option<persist::ServerSessionValue> {
if sess.config.ticketer.enabled() {
sess.config
.ticketer
.decrypt(ticket)
.and_then(|plain| persist::ServerSessionValue::read_bytes(&plain))
} else {
sess.config
.session_storage
.take(ticket)
.and_then(|plain| persist::ServerSessionValue::read_bytes(&plain))
}
}
pub fn handle_client_hello(mut self,
sess: &mut ServerSessionImpl,
sni: Option<webpki::DNSName>,
mut server_key: sign::CertifiedKey,
chm: &Message) -> hs::NextStateOrError {
let client_hello = extract_handshake!(chm, HandshakePayload::ClientHello).unwrap();
if client_hello.compression_methods.len() != 1 {
return Err(hs::illegal_param(sess, "client offered wrong compressions"));
}
let groups_ext = client_hello.get_namedgroups_extension()
.ok_or_else(|| hs::incompatible(sess, "client didn't describe groups"))?;
let mut sigschemes_ext = client_hello.get_sigalgs_extension()
.ok_or_else(|| hs::incompatible(sess, "client didn't describe sigschemes"))?
.clone();
let tls13_schemes = sign::supported_sign_tls13();
sigschemes_ext.retain(|scheme| tls13_schemes.contains(scheme));
let shares_ext = client_hello.get_keyshare_extension()
.ok_or_else(|| hs::incompatible(sess, "client didn't send keyshares"))?;
if client_hello.has_keyshare_extension_with_duplicates() {
return Err(hs::illegal_param(sess, "client sent duplicate keyshares"));
}
let share_groups: Vec<NamedGroup> = shares_ext.iter()
.map(|share| share.group)
.collect();
let supported_groups = suites::KeyExchange::supported_groups();
let chosen_group = supported_groups
.iter()
.filter(|group| share_groups.contains(group))
.nth(0)
.cloned();
if chosen_group.is_none() {
// We don't have a suitable key share. Choose a suitable group and
// send a HelloRetryRequest.
let retry_group_maybe = supported_groups
.iter()
.filter(|group| groups_ext.contains(group))
.nth(0)
.cloned();
self.handshake.transcript.add_message(chm);
if let Some(group) = retry_group_maybe {
if self.done_retry {
return Err(hs::illegal_param(sess, "did not follow retry request"));
}
self.emit_hello_retry_request(sess, group);
self.emit_fake_ccs(sess);
return Ok(self.into_expect_retried_client_hello());
}
return Err(hs::incompatible(sess, "no kx group overlap with client"));
}
hs::save_sni(sess, sni);
let chosen_group = chosen_group.unwrap();
let chosen_share = shares_ext.iter()
.find(|share| share.group == chosen_group)
.unwrap();
let mut chosen_psk_index = None;
let mut resumedata = None;
if let Some(psk_offer) = client_hello.get_psk() {
if !client_hello.check_psk_ext_is_last() {
return Err(hs::illegal_param(sess, "psk extension in wrong position"));
}
if psk_offer.binders.is_empty() {
return Err(hs::decode_error(sess, "psk extension missing binder"));
}
if psk_offer.binders.len() != psk_offer.identities.len() {
return Err(hs::illegal_param(sess, "psk extension mismatched ids/binders"));
}
for (i, psk_id) in psk_offer.identities.iter().enumerate() {
let maybe_resume = self.attempt_tls13_ticket_decryption(sess, &psk_id.identity.0);
if !hs::can_resume(sess, &self.handshake, &maybe_resume) {
continue;
}
let resume = maybe_resume.unwrap();
if !self.check_binder(sess, chm, &resume.master_secret.0, &psk_offer.binders[i].0) {
sess.common.send_fatal_alert(AlertDescription::DecryptError);
return Err(TLSError::PeerMisbehavedError("client sent wrong binder".to_string()));
}
chosen_psk_index = Some(i);
resumedata = Some(resume);
break;
}
}
if !client_hello.psk_mode_offered(PSKKeyExchangeMode::PSK_DHE_KE) {
warn!("Resumption ignored, DHE_KE not offered");
self.send_ticket = false;
chosen_psk_index = None;
resumedata = None;
} else {
self.send_ticket = true;
}
if let Some(ref resume) = resumedata {
sess.received_resumption_data = Some(resume.application_data.0.clone());
}
let full_handshake = resumedata.is_none();
self.handshake.transcript.add_message(chm);
let 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);
}
self.emit_encrypted_extensions(sess, &mut server_key, client_hello, resumedata.as_ref())?;
let doing_client_auth = if full_handshake {
let client_auth = self.emit_certificate_req_tls13(sess)?;
self.emit_certificate_tls13(sess, &mut server_key);
self.emit_certificate_verify_tls13(sess, &mut server_key, &sigschemes_ext)?;
client_auth
} else {
false
};
hs::check_aligned_handshake(sess)?;
let key_schedule_traffic = self.emit_finished_tls13(sess, key_schedule);
if doing_client_auth {
Ok(self.into_expect_certificate(key_schedule_traffic))
} else {
Ok(self.into_expect_finished(key_schedule_traffic))
}
}
}
pub struct ExpectCertificate {
pub handshake: HandshakeDetails,
pub key_schedule: KeyScheduleTrafficWithClientFinishedPending,
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,
})
}
fn into_expect_certificate_verify(self,
cert: ClientCertDetails) -> hs::NextState {
Box::new(ExpectCertificateVerify {
handshake: self.handshake,
key_schedule: self.key_schedule,
client_cert: cert,
send_ticket: self.send_ticket,
})
}
}
impl hs::State for ExpectCertificate {
fn check_message(&self, m: &Message) -> hs::CheckResult {
check_handshake_message(m, &[HandshakeType::Certificate])
}
fn handle(mut self: Box<Self>, sess: &mut ServerSessionImpl, m: Message) -> hs::NextStateOrError {
let certp = extract_handshake!(m, HandshakePayload::CertificateTLS13).unwrap();
self.handshake.transcript.add_message(&m);
// We don't send any CertificateRequest extensions, so any extensions
// here are illegal.
if certp.any_entry_has_extension() {
return Err(TLSError::PeerMisbehavedError("client sent unsolicited cert extension"
.to_string()));
}
let cert_chain = certp.convert();
let mandatory = sess.config.verifier.client_auth_mandatory(sess.get_sni())
.ok_or_else(|| {
debug!("could not determine if client auth is mandatory based on SNI");
sess.common.send_fatal_alert(AlertDescription::AccessDenied);
TLSError::General("client rejected by client_auth_mandatory".into())
})?;
if cert_chain.is_empty() {
if !mandatory {
debug!("client auth requested but no certificate supplied");
self.handshake.transcript.abandon_client_auth();
return Ok(self.into_expect_finished());
}
sess.common.send_fatal_alert(AlertDescription::CertificateRequired);
return Err(TLSError::NoCertificatesPresented);
}
sess.config.get_verifier().verify_client_cert(&cert_chain, sess.get_sni())
.or_else(|err| {
hs::incompatible(sess, "certificate invalid");
Err(err)
})?;
let cert = ClientCertDetails::new(cert_chain);
Ok(self.into_expect_certificate_verify(cert))
}
}
pub struct ExpectCertificateVerify {
handshake: HandshakeDetails,
key_schedule: KeyScheduleTrafficWithClientFinishedPending,
client_cert: ClientCertDetails,
send_ticket: bool,
}
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,
})
}
}
impl hs::State for ExpectCertificateVerify {
fn check_message(&self, m: &Message) -> hs::CheckResult {
check_handshake_message(m, &[HandshakeType::CertificateVerify])
}
fn handle(mut self: Box<Self>, sess: &mut ServerSessionImpl, m: Message) -> hs::NextStateOrError {
let rc = {
let sig = extract_handshake!(m, HandshakePayload::CertificateVerify).unwrap();
let handshake_hash = self.handshake.transcript.get_current_hash();
self.handshake.transcript.abandon_client_auth();
let certs = &self.client_cert.cert_chain;
verify::verify_tls13(&certs[0],
sig,
&handshake_hash,
b"TLS 1.3, client CertificateVerify\x00")
};
if let Err(e) = rc {
sess.common.send_fatal_alert(AlertDescription::AccessDenied);
return Err(e);
}
trace!("client CertificateVerify OK");
sess.client_cert_chain = Some(self.client_cert.take_chain());
self.handshake.transcript.add_message(&m);
Ok(self.into_expect_finished())
}
}
// --- Process client's Finished ---
fn get_server_session_value(handshake: &mut HandshakeDetails,
key_schedule: &KeyScheduleTraffic,
sess: &ServerSessionImpl,
nonce: &[u8]) -> persist::ServerSessionValue {
let scs = sess.common.get_suite_assert();
let version = ProtocolVersion::TLSv1_3;
let handshake_hash = handshake
.transcript
.get_current_hash();
let secret = key_schedule
.resumption_master_secret_and_derive_ticket_psk(&handshake_hash, nonce);
persist::ServerSessionValue::new(
sess.get_sni(), version,
scs.suite, secret,
&sess.client_cert_chain,
sess.alpn_protocol.clone(),
sess.resumption_data.clone(),
)
}
pub struct ExpectFinished {
pub handshake: HandshakeDetails,
pub key_schedule: KeyScheduleTrafficWithClientFinishedPending,
pub send_ticket: bool,
}
impl ExpectFinished {
fn into_expect_traffic(fin: verify::FinishedMessageVerified, ks: KeyScheduleTraffic) -> hs::NextState {
Box::new(ExpectTraffic {
key_schedule: ks,
want_write_key_update: false,
_fin_verified: fin,
})
}
fn emit_stateless_ticket(handshake: &mut HandshakeDetails,
sess: &mut ServerSessionImpl,
key_schedule: &KeyScheduleTraffic) {
let nonce = rand::random_vec(32);
let plain = get_server_session_value(handshake,
key_schedule,
sess, &nonce)
.get_encoding();
let maybe_ticket = sess.config
.ticketer
.encrypt(&plain);
let ticket_lifetime = sess.config.ticketer.get_lifetime();
if maybe_ticket.is_none() {
return;
}
let ticket = maybe_ticket.unwrap();
let age_add = rand::random_u32(); // nb, we don't do 0-RTT data, so whatever
#[allow(unused_mut)]
let mut payload = NewSessionTicketPayloadTLS13::new(ticket_lifetime, age_add, nonce, ticket);
#[cfg(feature = "quic")] {
if sess.config.max_early_data_size > 0 && sess.common.protocol == Protocol::Quic {
payload.exts.push(NewSessionTicketExtension::EarlyData(sess.config.max_early_data_size));
}
}
let m = Message {
typ: ContentType::Handshake,
version: ProtocolVersion::TLSv1_3,
payload: MessagePayload::Handshake(HandshakeMessagePayload {
typ: HandshakeType::NewSessionTicket,
payload: HandshakePayload::NewSessionTicketTLS13(payload),
}),
};
trace!("sending new ticket {:?}", m);
handshake.transcript.add_message(&m);
sess.common.send_msg(m, true);
}
fn emit_stateful_ticket(handshake: &mut HandshakeDetails,
sess: &mut ServerSessionImpl,
key_schedule: &KeyScheduleTraffic) {
let nonce = rand::random_vec(32);
let id = rand::random_vec(32);
let plain = get_server_session_value(handshake,
key_schedule,
sess, &nonce)
.get_encoding();
if sess.config.session_storage.put(id.clone(), plain) {
let stateful_lifetime = 24 * 60 * 60; // this is a bit of a punt
let age_add = rand::random_u32();
#[allow(unused_mut)]
let mut payload = NewSessionTicketPayloadTLS13::new(stateful_lifetime, age_add, nonce, id);
#[cfg(feature = "quic")] {
if sess.config.max_early_data_size > 0 && sess.common.protocol == Protocol::Quic {
payload.exts.push(NewSessionTicketExtension::EarlyData(sess.config.max_early_data_size));
}
}
let m = Message {
typ: ContentType::Handshake,
version: ProtocolVersion::TLSv1_3,
payload: MessagePayload::Handshake(HandshakeMessagePayload {
typ: HandshakeType::NewSessionTicket,
payload: HandshakePayload::NewSessionTicketTLS13(payload),
}),
};
trace!("sending new stateful ticket {:?}", m);
handshake.transcript.add_message(&m);
sess.common.send_msg(m, true);
} else {
trace!("resumption not available; not issuing ticket");
}
}
}
impl hs::State for ExpectFinished {
fn check_message(&self, m: &Message) -> hs::CheckResult {
check_handshake_message(m, &[HandshakeType::Finished])
}
fn handle(mut self: Box<Self>, sess: &mut ServerSessionImpl, m: Message) -> hs::NextStateOrError {
let finished = extract_handshake!(m, HandshakePayload::Finished).unwrap();
let handshake_hash = self.handshake.transcript.get_current_hash();
let expect_verify_data = self.key_schedule.sign_client_finish(&handshake_hash);
let fin = constant_time::verify_slices_are_equal(&expect_verify_data, &finished.0)
.map_err(|_| {
sess.common.send_fatal_alert(AlertDescription::DecryptError);
warn!("Finished wrong");
TLSError::DecryptError
})
.map(|_| verify::FinishedMessageVerified::assertion())?;
// nb. future derivations include Client Finished, but not the
// main application data keying.
self.handshake.transcript.add_message(&m);
hs::check_aligned_handshake(sess)?;
let suite = sess.common.get_suite_assert();
// Install keying to read future messages.
let read_key = self.key_schedule
.client_application_traffic_secret(&self.handshake.hash_at_server_fin,
&*sess.config.key_log,
&self.handshake.randoms.client);
sess.common
.record_layer
.set_message_decrypter(cipher::new_tls13_read(suite, &read_key));
let key_schedule_traffic = self.key_schedule.into_traffic();
if self.send_ticket {
if sess.config.ticketer.enabled() {
Self::emit_stateless_ticket(&mut self.handshake, sess, &key_schedule_traffic);
} else {
Self::emit_stateful_ticket(&mut self.handshake, sess, &key_schedule_traffic);
}
}
sess.common.start_traffic();
#[cfg(feature = "quic")] {
if sess.common.protocol == Protocol::Quic {
return Ok(Box::new(ExpectQUICTraffic { _fin_verified: fin }));
}
}
Ok(Self::into_expect_traffic(fin, key_schedule_traffic))
}
}
// --- Process traffic ---
pub struct ExpectTraffic {
key_schedule: KeyScheduleTraffic,
want_write_key_update: bool,
_fin_verified: verify::FinishedMessageVerified,
}
impl ExpectTraffic {
fn handle_traffic(&self, sess: &mut ServerSessionImpl, mut m: Message) -> Result<(), TLSError> {
sess.common.take_received_plaintext(m.take_opaque_payload().unwrap());
Ok(())
}
fn handle_key_update(&mut self, sess: &mut ServerSessionImpl, m: Message) -> Result<(), TLSError> {
let kur = extract_handshake!(m, HandshakePayload::KeyUpdate).unwrap();
#[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.next_client_application_traffic_secret();
let suite = sess.common.get_suite_assert();
sess.common.record_layer.set_message_decrypter(cipher::new_tls13_read(suite, &new_read_key));
Ok(())
}
}
impl hs::State for ExpectTraffic {
fn check_message(&self, m: &Message) -> hs::CheckResult {
check_message(m,
&[ContentType::ApplicationData, ContentType::Handshake],
&[HandshakeType::KeyUpdate])
}
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) {
self.handle_key_update(sess, m)?;
}
Ok(self)
}
fn export_keying_material(&self,
output: &mut [u8],
label: &[u8],
context: Option<&[u8]>) -> Result<(), TLSError> {
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.next_server_application_traffic_secret();
let scs = sess.common.get_suite_assert();
sess.common.record_layer.set_message_encrypter(cipher::new_tls13_write(scs, &write_key));
}
}
}
#[cfg(feature = "quic")]
pub struct ExpectQUICTraffic {
_fin_verified: verify::FinishedMessageVerified,
}
#[cfg(feature = "quic")]
impl hs::State for ExpectQUICTraffic {
fn check_message(&self, m: &Message) -> hs::CheckResult {
Err(TLSError::InappropriateMessage {
expect_types: Vec::new(),
got_type: m.typ,
})
}
fn handle(self: Box<Self>, _: &mut ServerSessionImpl, _: Message) -> hs::NextStateOrError {
unreachable!("check_message always fails");
}
}