Inline trivial alert helper functions

This commit is contained in:
Dirkjan Ochtman 2023-04-11 17:35:39 +02:00
parent aecd933af7
commit 86719f80ae
7 changed files with 195 additions and 120 deletions

View File

@ -445,7 +445,10 @@ pub(super) fn process_alpn_protocol(
.alpn_protocols
.contains(alpn_protocol)
{
return Err(common.illegal_param(PeerMisbehaved::SelectedUnofferedApplicationProtocol));
return Err(common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::SelectedUnofferedApplicationProtocol,
));
}
}
@ -513,9 +516,12 @@ impl State<ClientConnectionData> for ExpectServerHello {
.get_supported_versions()
.is_some()
{
return Err(cx
.common
.illegal_param(PeerMisbehaved::SelectedTls12UsingTls13VersionExtension));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::SelectedTls12UsingTls13VersionExtension,
)
});
}
TLSv1_2
@ -532,9 +538,12 @@ impl State<ClientConnectionData> for ExpectServerHello {
};
if server_hello.compression_method != Compression::Null {
return Err(cx
.common
.illegal_param(PeerMisbehaved::SelectedUnofferedCompression));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::SelectedUnofferedCompression,
)
});
}
if server_hello.has_duplicate_extension() {
@ -584,16 +593,22 @@ impl State<ClientConnectionData> for ExpectServerHello {
})?;
if version != suite.version().version {
return Err(cx
.common
.illegal_param(PeerMisbehaved::SelectedUnusableCipherSuiteForVersion));
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
.illegal_param(PeerMisbehaved::SelectedDifferentCipherSuiteAfterRetry));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::SelectedDifferentCipherSuiteAfterRetry,
)
});
}
_ => {
debug!("Using ciphersuite {:?}", suite);
@ -691,17 +706,23 @@ impl ExpectServerHelloOrHelloRetryRequest {
// A retry request is illegal if it contains no cookie and asks for
// retry of a group we already sent.
if cookie.is_none() && req_group == Some(offered_key_share.group()) {
return Err(cx
.common
.illegal_param(PeerMisbehaved::IllegalHelloRetryRequestWithOfferedGroup));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::IllegalHelloRetryRequestWithOfferedGroup,
)
});
}
// Or has an empty cookie.
if let Some(cookie) = cookie {
if cookie.0.is_empty() {
return Err(cx
.common
.illegal_param(PeerMisbehaved::IllegalHelloRetryRequestWithEmptyCookie));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::IllegalHelloRetryRequestWithEmptyCookie,
)
});
}
}
@ -715,16 +736,22 @@ impl ExpectServerHelloOrHelloRetryRequest {
// Or has the same extensions more than once
if hrr.has_duplicate_extension() {
return Err(cx
.common
.illegal_param(PeerMisbehaved::DuplicateHelloRetryRequestExtensions));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::DuplicateHelloRetryRequestExtensions,
)
});
}
// Or asks us to change nothing.
if cookie.is_none() && req_group.is_none() {
return Err(cx
.common
.illegal_param(PeerMisbehaved::IllegalHelloRetryRequestWithNoChanges));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::IllegalHelloRetryRequestWithNoChanges,
)
});
}
// Or asks us to talk a protocol we didn't offer, or doesn't support HRR at all.
@ -733,9 +760,12 @@ impl ExpectServerHelloOrHelloRetryRequest {
cx.common.negotiated_version = Some(ProtocolVersion::TLSv1_3);
}
_ => {
return Err(cx.common.illegal_param(
PeerMisbehaved::IllegalHelloRetryRequestWithUnsupportedVersion,
));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::IllegalHelloRetryRequestWithUnsupportedVersion,
)
});
}
}
@ -744,9 +774,12 @@ impl ExpectServerHelloOrHelloRetryRequest {
let cs = match config.find_cipher_suite(hrr.cipher_suite) {
Some(cs) => cs,
None => {
return Err(cx.common.illegal_param(
PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedCipherSuite,
));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedCipherSuite,
)
});
}
};
@ -775,7 +808,8 @@ impl ExpectServerHelloOrHelloRetryRequest {
let key_share = match req_group {
Some(group) if group != offered_key_share.group() => {
let group = kx::KeyExchange::choose(group, &config.kx_groups).ok_or_else(|| {
cx.common.illegal_param(
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedNamedGroup,
)
})?;

View File

@ -71,9 +71,12 @@ mod server_hello {
// public values and don't require constant time comparison
let has_downgrade_marker = self.randoms.server[24..] == tls12::DOWNGRADE_SENTINEL;
if tls13_supported && has_downgrade_marker {
return Err(cx
.common
.illegal_param(PeerMisbehaved::AttemptedDowngradeToTls12WhenTls13IsSupported));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::AttemptedDowngradeToTls12WhenTls13IsSupported,
)
});
}
// Doing EMS?

View File

@ -88,9 +88,12 @@ pub(super) fn handle_server_hello(
})?;
if our_key_share.group() != their_key_share.group {
return Err(cx
.common
.illegal_param(PeerMisbehaved::WrongGroupForKeyShare));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::WrongGroupForKeyShare,
)
});
}
let key_schedule_pre_handshake = if let (Some(selected_psk), Some(early_key_schedule)) =
@ -100,24 +103,33 @@ pub(super) fn handle_server_hello(
let resuming_suite = match suite.can_resume_from(resuming.suite()) {
Some(resuming) => resuming,
None => {
return Err(cx.common.illegal_param(
PeerMisbehaved::ResumptionOfferedWithIncompatibleCipherSuite,
));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::ResumptionOfferedWithIncompatibleCipherSuite,
)
});
}
};
// If the server varies the suite here, we will have encrypted early data with
// the wrong suite.
if cx.data.early_data.is_enabled() && resuming_suite != suite {
return Err(cx
.common
.illegal_param(PeerMisbehaved::EarlyDataOfferedWithVariedCipherSuite));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::EarlyDataOfferedWithVariedCipherSuite,
)
});
}
if selected_psk != 0 {
return Err(cx
.common
.illegal_param(PeerMisbehaved::SelectedInvalidPsk));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::SelectedInvalidPsk,
)
});
}
debug!("Resuming using PSK");

View File

@ -217,10 +217,6 @@ impl CommonState {
}
}
pub(crate) fn illegal_param(&mut self, why: PeerMisbehaved) -> Error {
self.send_fatal_alert(AlertDescription::IllegalParameter, why)
}
/// Fragment `m`, encrypt the fragments, and then queue
/// the encrypted fragments for sending.
pub(crate) fn send_msg_encrypt(&mut self, m: PlainMessage) {

View File

@ -1,4 +1,4 @@
use crate::common_state::{CommonState, State};
use crate::common_state::State;
use crate::conn::ConnectionRandoms;
#[cfg(feature = "tls12")]
use crate::enums::CipherSuite;
@ -30,18 +30,6 @@ pub(super) type NextState = Box<dyn State<ServerConnectionData>>;
pub(super) type NextStateOrError = Result<NextState, Error>;
pub(super) type ServerContext<'a> = crate::common_state::Context<'a, ServerConnectionData>;
pub(super) fn incompatible(common: &mut CommonState, why: PeerIncompatible) -> Error {
common.send_fatal_alert(AlertDescription::HandshakeFailure, why)
}
fn bad_version(common: &mut CommonState, why: PeerIncompatible) -> Error {
common.send_fatal_alert(AlertDescription::ProtocolVersion, why)
}
pub(super) fn decode_error(common: &mut CommonState, why: PeerMisbehaved) -> Error {
common.send_fatal_alert(AlertDescription::DecodeError, why)
}
pub(super) fn can_resume(
suite: SupportedCipherSuite,
sni: &Option<webpki::DnsName>,
@ -286,28 +274,31 @@ impl ExpectClientHello {
if versions.contains(&ProtocolVersion::TLSv1_3) && tls13_enabled {
ProtocolVersion::TLSv1_3
} else if !versions.contains(&ProtocolVersion::TLSv1_2) || !tls12_enabled {
return Err(bad_version(
cx.common,
return Err(cx.common.send_fatal_alert(
AlertDescription::ProtocolVersion,
PeerIncompatible::Tls12NotOfferedOrEnabled,
));
} else if cx.common.is_quic() {
return Err(bad_version(
cx.common,
return Err(cx.common.send_fatal_alert(
AlertDescription::ProtocolVersion,
PeerIncompatible::Tls13RequiredForQuic,
));
} else {
ProtocolVersion::TLSv1_2
}
} else if client_hello.client_version.get_u16() < ProtocolVersion::TLSv1_2.get_u16() {
return Err(bad_version(cx.common, PeerIncompatible::Tls12NotOffered));
return Err(cx.common.send_fatal_alert(
AlertDescription::ProtocolVersion,
PeerIncompatible::Tls12NotOffered,
));
} else if !tls12_enabled && tls13_enabled {
return Err(bad_version(
cx.common,
return Err(cx.common.send_fatal_alert(
AlertDescription::ProtocolVersion,
PeerIncompatible::SupportedVersionsExtensionRequired,
));
} else if cx.common.is_quic() {
return Err(bad_version(
cx.common,
return Err(cx.common.send_fatal_alert(
AlertDescription::ProtocolVersion,
PeerIncompatible::Tls13RequiredForQuic,
));
} else {
@ -378,7 +369,12 @@ impl ExpectClientHello {
&suitable_suites,
)
}
.ok_or_else(|| incompatible(cx.common, PeerIncompatible::NoCipherSuitesInCommon))?;
.ok_or_else(|| {
cx.common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerIncompatible::NoCipherSuitesInCommon,
)
})?;
debug!("decided upon suite {:?}", suite);
cx.common.suite = Some(suite);
@ -389,9 +385,10 @@ impl ExpectClientHello {
HandshakeHashOrBuffer::Buffer(inner) => inner.start_hash(starting_hash),
HandshakeHashOrBuffer::Hash(inner) if inner.algorithm() == starting_hash => inner,
_ => {
return Err(cx
.common
.illegal_param(PeerMisbehaved::HandshakeHashVariedAfterRetry));
return Err(cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::HandshakeHashVariedAfterRetry,
));
}
};
@ -465,8 +462,8 @@ pub(super) fn process_client_hello<'a>(
}
if client_hello.has_duplicate_extension() {
return Err(decode_error(
cx.common,
return Err(cx.common.send_fatal_alert(
AlertDescription::DecodeError,
PeerMisbehaved::DuplicateClientHelloExtensions,
));
}
@ -482,8 +479,8 @@ pub(super) fn process_client_hello<'a>(
let sni: Option<webpki::DnsName> = match client_hello.get_sni_extension() {
Some(sni) => {
if sni.has_duplicate_names_for_type() {
return Err(decode_error(
cx.common,
return Err(cx.common.send_fatal_alert(
AlertDescription::DecodeError,
PeerMisbehaved::DuplicateServerNameTypes,
));
}
@ -491,9 +488,10 @@ pub(super) fn process_client_hello<'a>(
if let Some(hostname) = sni.get_single_hostname() {
Some(hostname.into())
} else {
return Err(cx
.common
.illegal_param(PeerMisbehaved::ServerNameMustContainOneHostName));
return Err(cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::ServerNameMustContainOneHostName,
));
}
}
None => None,
@ -512,8 +510,8 @@ pub(super) fn process_client_hello<'a>(
let sig_schemes = client_hello
.get_sigalgs_extension()
.ok_or_else(|| {
incompatible(
cx.common,
cx.common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerIncompatible::SignatureAlgorithmsExtensionRequired,
)
})?;

View File

@ -76,12 +76,18 @@ mod client_hello {
let groups_ext = client_hello
.get_namedgroups_extension()
.ok_or_else(|| {
hs::incompatible(cx.common, PeerIncompatible::NamedGroupsExtensionRequired)
cx.common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerIncompatible::NamedGroupsExtensionRequired,
)
})?;
let ecpoints_ext = client_hello
.get_ecpoints_extension()
.ok_or_else(|| {
hs::incompatible(cx.common, PeerIncompatible::EcPointsExtensionRequired)
cx.common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerIncompatible::EcPointsExtensionRequired,
)
})?;
trace!("namedgroups {:?}", groups_ext);
@ -155,8 +161,8 @@ mod client_hello {
.resolve_sig_schemes(&sigschemes_ext);
if sigschemes.is_empty() {
return Err(hs::incompatible(
cx.common,
return Err(cx.common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerIncompatible::NoSignatureSchemesInCommon,
));
}
@ -167,14 +173,22 @@ mod client_hello {
.iter()
.find(|skxg| groups_ext.contains(&skxg.name))
.cloned()
.ok_or_else(|| hs::incompatible(cx.common, PeerIncompatible::NoKxGroupsInCommon))?;
.ok_or_else(|| {
cx.common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerIncompatible::NoKxGroupsInCommon,
)
})?;
let ecpoint = ECPointFormat::SUPPORTED
.iter()
.find(|format| ecpoints_ext.contains(format))
.cloned()
.ok_or_else(|| {
hs::incompatible(cx.common, PeerIncompatible::NoEcPointFormatsInCommon)
cx.common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerIncompatible::NoEcPointFormatsInCommon,
)
})?;
debug_assert_eq!(ecpoint, ECPointFormat::Uncompressed);
@ -254,9 +268,10 @@ mod client_hello {
debug!("Resuming connection");
if resumedata.extended_ms && !self.using_ems {
return Err(cx
.common
.illegal_param(PeerMisbehaved::ResumptionAttemptedWithVariedEms));
return Err(cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::ResumptionAttemptedWithVariedEms,
));
}
self.session_id = *id;

View File

@ -153,15 +153,19 @@ mod client_hello {
mut sigschemes_ext: Vec<SignatureScheme>,
) -> hs::NextStateOrError {
if client_hello.compression_methods.len() != 1 {
return Err(cx
.common
.illegal_param(PeerMisbehaved::OfferedIncorrectCompressions));
return Err(cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::OfferedIncorrectCompressions,
));
}
let groups_ext = client_hello
.get_namedgroups_extension()
.ok_or_else(|| {
hs::incompatible(cx.common, PeerIncompatible::NamedGroupsExtensionRequired)
cx.common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerIncompatible::NamedGroupsExtensionRequired,
)
})?;
let tls13_schemes = sign::supported_sign_tls13();
@ -170,22 +174,29 @@ mod client_hello {
let shares_ext = client_hello
.get_keyshare_extension()
.ok_or_else(|| {
hs::incompatible(cx.common, PeerIncompatible::KeyShareExtensionRequired)
cx.common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerIncompatible::KeyShareExtensionRequired,
)
})?;
if client_hello.has_keyshare_extension_with_duplicates() {
return Err(cx
.common
.illegal_param(PeerMisbehaved::OfferedDuplicateKeyShares));
return Err(cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::OfferedDuplicateKeyShares,
));
}
let early_data_requested = client_hello.early_data_extension_offered();
// EarlyData extension is illegal in second ClientHello
if self.done_retry && early_data_requested {
return Err(cx
.common
.illegal_param(PeerMisbehaved::EarlyDataAttemptedInSecondClientHello));
return Err({
cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::EarlyDataAttemptedInSecondClientHello,
)
});
}
// choose a share that we support
@ -215,9 +226,10 @@ mod client_hello {
if let Some(group) = retry_group_maybe {
if self.done_retry {
return Err(cx
.common
.illegal_param(PeerMisbehaved::RefusedToFollowHelloRetryRequest));
return Err(cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::RefusedToFollowHelloRetryRequest,
));
}
emit_hello_retry_request(
@ -252,8 +264,8 @@ mod client_hello {
};
}
return Err(hs::incompatible(
cx.common,
return Err(cx.common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerIncompatible::NoKxGroupsInCommon,
));
}
@ -265,22 +277,24 @@ mod client_hello {
if let Some(psk_offer) = client_hello.get_psk() {
if !client_hello.check_psk_ext_is_last() {
return Err(cx
.common
.illegal_param(PeerMisbehaved::PskExtensionMustBeLast));
return Err(cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::PskExtensionMustBeLast,
));
}
if psk_offer.binders.is_empty() {
return Err(hs::decode_error(
cx.common,
return Err(cx.common.send_fatal_alert(
AlertDescription::DecodeError,
PeerMisbehaved::MissingBinderInPskExtension,
));
}
if psk_offer.binders.len() != psk_offer.identities.len() {
return Err(cx
.common
.illegal_param(PeerMisbehaved::PskExtensionWithMismatchedIdsAndBinders));
return Err(cx.common.send_fatal_alert(
AlertDescription::IllegalParameter,
PeerMisbehaved::PskExtensionWithMismatchedIdsAndBinders,
));
}
for (i, psk_id) in psk_offer.identities.iter().enumerate() {
@ -781,7 +795,10 @@ mod client_hello {
let signer = signing_key
.choose_scheme(schemes)
.ok_or_else(|| {
hs::incompatible(common, PeerIncompatible::NoSignatureSchemesInCommon)
common.send_fatal_alert(
AlertDescription::HandshakeFailure,
PeerIncompatible::NoSignatureSchemesInCommon,
)
})?;
let scheme = signer.scheme();