return WORK_FINISHED_STOP;
}
+/*
+ * TLS 1.3 reserves handshake message type 0, so a HelloRequest must reach the
+ * state machine and be rejected there whenever TLS 1.3 is still possible.
+ *
+ * By the time a client reads a server handshake message, s->version is either
+ * the configured maximum for an initial pre-ServerHello handshake, or the
+ * already negotiated version after ServerHello or during renegotiation. Skip
+ * only when that version is below TLS 1.3.
+ */
+static int should_skip_hello_request(const SSL_CONNECTION *s)
+{
+ if (SSL_CONNECTION_IS_TLS13(s))
+ return 0;
+
+ return s->version > 0 && s->version < TLS1_3_VERSION;
+}
+
int tls_get_message_header(SSL_CONNECTION *s, int *mt)
{
/* s->init_num < SSL3_HM_HEADER_LENGTH */
skip_message = 0;
if (!s->server)
if (s->statem.hand_state != TLS_ST_OK
- && p[0] == SSL3_MT_HELLO_REQUEST)
+ && p[0] == SSL3_MT_HELLO_REQUEST
+ && should_skip_hello_request(s))
/*
* The server may always send 'Hello Request' messages --
* we are doing a handshake anyway now, so ignore them if
(!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}),
have_IPv6()
);
+my $fatal_alert = 0;
+my $hello_request_added = 0;
+my $hello_request_after_server_hello = 0;
#Test 1: Check we get all the right messages for a default handshake
(undef, my $session) = tempfile();
$proxy->clientflags("-no_rx_cert_comp -sess_out ".$session);
$proxy->sessionfile($session);
$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
-plan tests => 17;
+plan tests => 19;
checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
checkhandshake::DEFAULT_EXTENSIONS,
"Default handshake test");
| checkhandshake::SUPPORTED_GROUPS_SRV_EXTENSION,
"Acceptable but non preferred key_share");
+#Test 18: HelloRequest is reserved in TLSv1.3
+$proxy->clear();
+$fatal_alert = 0;
+$hello_request_added = 0;
+$hello_request_after_server_hello = 0;
+$proxy->filter(\&inject_hello_request);
+$proxy->cipherc("DEFAULT:\@SECLEVEL=2");
+$proxy->clientflags("-no_rx_cert_comp");
+$proxy->start();
+ok($fatal_alert, "HelloRequest rejected in TLSv1.3");
+
+#Test 19: A HelloRequest received after selecting TLSv1.2 in the initial
+# handshake is still ignored, confirming the legacy skip path is
+# preserved even when TLSv1.3 was initially enabled.
+SKIP: {
+ skip "TLSv1.2 disabled", 1 if disabled("tls1_2");
+
+ $proxy->clear();
+ $fatal_alert = 0;
+ $hello_request_added = 0;
+ $hello_request_after_server_hello = 1;
+ $proxy->filter(\&inject_hello_request);
+ $proxy->cipherc("DEFAULT:\@SECLEVEL=2");
+ $proxy->clientflags("-no_rx_cert_comp");
+ $proxy->serverflags("-no_tls1_3");
+ $proxy->start();
+ ok(TLSProxy::Message->success() && !$fatal_alert,
+ "HelloRequest ignored in TLSv1.2");
+}
+
unlink $session;
+
+sub inject_hello_request
+{
+ my $proxy = shift;
+ my $records = $proxy->record_list;
+ my $hello_request;
+ my $record;
+ my $server_hello_record;
+ my $i;
+
+ if ($hello_request_added) {
+ $fatal_alert = 1
+ if @{$records}[-1]->is_fatal_alert(0)
+ == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
+ return;
+ }
+
+ return if $proxy->flight != 1;
+
+ $hello_request = pack("C4", TLSProxy::Message::MT_HELLO_REQUEST,
+ 0, 0, 0);
+ $record = TLSProxy::Record->new(
+ 1,
+ TLSProxy::Record::RT_HANDSHAKE,
+ TLSProxy::Record::VERS_TLS_1_2,
+ length($hello_request),
+ length($hello_request),
+ length($hello_request),
+ $hello_request,
+ $hello_request
+ );
+
+ if ($hello_request_after_server_hello) {
+ foreach my $message (@{$proxy->message_list}) {
+ next if $message->mt != TLSProxy::Message::MT_SERVER_HELLO
+ || ${$message->records}[0]->flight != 1;
+
+ $server_hello_record = @{$message->records}[-1];
+ last;
+ }
+
+ return if !defined $server_hello_record;
+
+ for ($i = 0; $i < @{$records}; $i++) {
+ last if ${$records}[$i] == $server_hello_record;
+ }
+ $i++;
+ } else {
+ for ($i = 0; ${$records}[$i]->flight() < 1; $i++) {
+ next;
+ }
+ }
+
+ splice @{$records}, $i, 0, $record;
+ $hello_request_added = 1;
+}