Commit 17bd94fbd6 for openssl.org

commit 17bd94fbd6cbefb2de2cf88aacd66b3b1abdf6d8
Author: Matt Caswell <matt@openssl.foundation>
Date:   Tue Apr 21 17:36:32 2026 +0100

    Add a test for bad PSK in a PSK only server

    Check that we fail with a decrypt_alert in the same way as a binder
    validation failure

    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    MergeDate: Wed May 13 07:38:33 2026
    (Merged from https://github.com/openssl/openssl/pull/31026)

diff --git a/test/recipes/70-test_tls13psk.t b/test/recipes/70-test_tls13psk.t
index dcac269d1b..d15f838e9d 100644
--- a/test/recipes/70-test_tls13psk.t
+++ b/test/recipes/70-test_tls13psk.t
@@ -53,7 +53,7 @@ $proxy->clientflags("-sess_out ".$session);
 $proxy->serverflags("-servername localhost");
 $proxy->sessionfile($session);
 $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
-plan tests => 6;
+plan tests => 7;
 ok(TLSProxy::Message->success(), "Initial connection");

 #Test 2: Attempt a resume with PSK not in last place. Should fail
@@ -122,8 +122,36 @@ $testtype = TOO_MANY_PSKS;
 $proxy->start();
 ok(TLSProxy::Message->success(), "Too many PSKs");

+my $proxy2 = TLSProxy::Proxy->new(
+    undef,
+    cmdstr(app(["openssl"]), display => 1),
+    undef, # Deliberately set to no_cert to force a PSK-only server
+    (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}),
+    have_IPv6()
+);
+
+#Test 7: Attempt an invalid resume, with a server that can only do PSK.
+#        Should be treated the same as an invalid binder (decrypt_error)
+#        as per RFC8446 Appendix E.6
+$proxy2->clear();
+$proxy2->clientflags("-sess_in ".$session);
+$proxy2->serverflags("-psk ffeeddccbbaa99887766554433221100 -no_ticket");
+$proxy2->start() or die "Failed to start proxy2";
+ok(is_decode_error_server_alert(), "Bad PSK with no handshake fallback");
+
 unlink $session;

+sub is_decode_error_server_alert
+{
+    return 0 unless TLSProxy::Message->fail();
+
+    my $alert = TLSProxy::Message->alert();
+    return 1 if $alert->server()
+                && $alert->description()
+                   == TLSProxy::Message::AL_DESC_DECRYPT_ERROR;
+    return 0;
+}
+
 sub modify_psk_filter
 {
     my $proxy = shift;
diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm
index 57197ebba0..4c1ba50de4 100644
--- a/util/perl/TLSProxy/Message.pm
+++ b/util/perl/TLSProxy/Message.pm
@@ -48,6 +48,7 @@ use constant {
 	AL_DESC_BAD_CERTIFICATE => 42,
     AL_DESC_ILLEGAL_PARAMETER => 47,
     AL_DESC_DECODE_ERROR => 50,
+    AL_DESC_DECRYPT_ERROR => 51,
     AL_DESC_PROTOCOL_VERSION => 70,
     AL_DESC_NO_RENEGOTIATION => 100,
     AL_DESC_MISSING_EXTENSION => 109
diff --git a/util/perl/TLSProxy/Proxy.pm b/util/perl/TLSProxy/Proxy.pm
index eccdc98cf6..5ba6579ed3 100644
--- a/util/perl/TLSProxy/Proxy.pm
+++ b/util/perl/TLSProxy/Proxy.pm
@@ -340,8 +340,13 @@ sub start
         #different one that doesn't get confused.
         ." -ext_cache"
         ." -accept $self->{server_addr}:0"
-        ." -cert ".$self->cert." -cert2 ".$self->cert
         ." -naccept ".$self->serverconnects;
+    if (defined $self->cert) {
+        $execcmd .= " -cert ".$self->cert." -cert2 ".$self->cert;
+    } else {
+        $execcmd .= " -nocert";
+    }
+
     if ($self->{isdtls}) {
         $execcmd .= " -dtls -max_protocol DTLSv1.2"
                     # TLSProxy does not support message fragmentation. So