in rustls-0.21.2/rustls/src/client/hs.rs [490:679]
fn handle(mut self: Box<Self>, cx: &mut ClientContext<'_>, m: Message) -> NextStateOrError {
let server_hello =
require_handshake_msg!(m, HandshakeType::ServerHello, HandshakePayload::ServerHello)?;
trace!("We got ServerHello {:#?}", server_hello);
use crate::ProtocolVersion::{TLSv1_2, TLSv1_3};
let config = &self.input.config;
let tls13_supported = config.supports_version(TLSv1_3);
let server_version = if server_hello.legacy_version == TLSv1_2 {
server_hello
.get_supported_versions()
.unwrap_or(server_hello.legacy_version)
} else {
server_hello.legacy_version
};
let version = match server_version {
TLSv1_3 if tls13_supported => TLSv1_3,
TLSv1_2 if config.supports_version(TLSv1_2) => {
if cx.data.early_data.is_enabled() && cx.common.early_traffic {
// The client must fail with a dedicated error code if the server
// responds with TLS 1.2 when offering 0-RTT.
return Err(PeerMisbehaved::OfferedEarlyDataWithOldProtocolVersion.into());
}
if server_hello
.get_supported_versions()
.is_some()
{
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::SelectedTls12UsingTls13VersionExtension,
)
});
}
TLSv1_2
}
_ => {
let reason = match server_version {
TLSv1_2 | TLSv1_3 => PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig,
_ => PeerIncompatible::ServerDoesNotSupportTls12Or13,
};
return Err(cx
.common
.send_fatal_alert(AlertDescription::ProtocolVersion, reason));
}
};
if server_hello.compression_method != Compression::Null {
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::SelectedUnofferedCompression,
)
});
}
if server_hello.has_duplicate_extension() {
return Err(cx.common.send_fatal_alert(
AlertDescription::DecodeError,
PeerMisbehaved::DuplicateServerHelloExtensions,
));
}
let allowed_unsolicited = [ExtensionType::RenegotiationInfo];
if self
.input
.hello
.server_sent_unsolicited_extensions(&server_hello.extensions, &allowed_unsolicited)
{
return Err(cx.common.send_fatal_alert(
AlertDescription::UnsupportedExtension,
PeerMisbehaved::UnsolicitedServerHelloExtension,
));
}
cx.common.negotiated_version = Some(version);
// Extract ALPN protocol
if !cx.common.is_tls13() {
process_alpn_protocol(cx.common, config, server_hello.get_alpn_protocol())?;
}
// If ECPointFormats extension is supplied by the server, it must contain
// Uncompressed. But it's allowed to be omitted.
if let Some(point_fmts) = server_hello.get_ecpoints_extension() {
if !point_fmts.contains(&ECPointFormat::Uncompressed) {
return Err(cx.common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerMisbehaved::ServerHelloMustOfferUncompressedEcPoints,
));
}
}
let suite = config
.find_cipher_suite(server_hello.cipher_suite)
.ok_or_else(|| {
cx.common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerMisbehaved::SelectedUnofferedCipherSuite,
)
})?;
if version != suite.version().version {
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::SelectedUnusableCipherSuiteForVersion,
)
});
}
match self.suite {
Some(prev_suite) if prev_suite != suite => {
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::SelectedDifferentCipherSuiteAfterRetry,
)
});
}
_ => {
debug!("Using ciphersuite {:?}", suite);
self.suite = Some(suite);
cx.common.suite = Some(suite);
}
}
// Start our handshake hash, and input the server-hello.
let mut transcript = self
.transcript_buffer
.start_hash(suite.hash_algorithm());
transcript.add_message(&m);
let randoms = ConnectionRandoms::new(self.input.random, server_hello.random);
// For TLS1.3, start message encryption using
// handshake_traffic_secret.
match suite {
SupportedCipherSuite::Tls13(suite) => {
#[allow(clippy::bind_instead_of_map)]
let resuming_session = self
.input
.resuming
.and_then(|resuming| match resuming.value {
ClientSessionValue::Tls13(inner) => Some(inner),
#[cfg(feature = "tls12")]
ClientSessionValue::Tls12(_) => None,
});
tls13::handle_server_hello(
self.input.config,
cx,
server_hello,
resuming_session,
self.input.server_name,
randoms,
suite,
transcript,
self.early_key_schedule,
self.input.hello,
// We always send a key share when TLS 1.3 is enabled.
self.offered_key_share.unwrap(),
self.input.sent_tls13_fake_ccs,
)
}
#[cfg(feature = "tls12")]
SupportedCipherSuite::Tls12(suite) => {
let resuming_session = self
.input
.resuming
.and_then(|resuming| match resuming.value {
ClientSessionValue::Tls12(inner) => Some(inner),
ClientSessionValue::Tls13(_) => None,
});
tls12::CompleteServerHelloHandling {
config: self.input.config,
resuming_session,
server_name: self.input.server_name,
randoms,
using_ems: self.input.using_ems,
transcript,
}
.handle_server_hello(cx, suite, server_hello, tls13_supported)
}
}
}