1 | #! /usr/bin/env perl
|
---|
2 | # Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | #
|
---|
4 | # Licensed under the Apache License 2.0 (the "License"). You may not use
|
---|
5 | # this file except in compliance with the License. You can obtain a copy
|
---|
6 | # in the file LICENSE in the source distribution or at
|
---|
7 | # https://www.openssl.org/source/license.html
|
---|
8 |
|
---|
9 | use strict;
|
---|
10 | use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file srctop_dir bldtop_dir/;
|
---|
11 | use OpenSSL::Test::Utils;
|
---|
12 | use File::Temp qw(tempfile);
|
---|
13 | use TLSProxy::Proxy;
|
---|
14 |
|
---|
15 | my $test_name = "test_tls13psk";
|
---|
16 | setup($test_name);
|
---|
17 |
|
---|
18 | plan skip_all => "TLSProxy isn't usable on $^O"
|
---|
19 | if $^O =~ /^(VMS)$/;
|
---|
20 |
|
---|
21 | plan skip_all => "$test_name needs the dynamic engine feature enabled"
|
---|
22 | if disabled("engine") || disabled("dynamic-engine");
|
---|
23 |
|
---|
24 | plan skip_all => "$test_name needs the sock feature enabled"
|
---|
25 | if disabled("sock");
|
---|
26 |
|
---|
27 | plan skip_all => "$test_name needs TLSv1.3 enabled"
|
---|
28 | if disabled("tls1_3") || (disabled("ec") && disabled("dh"));
|
---|
29 |
|
---|
30 | $ENV{OPENSSL_ia32cap} = '~0x200000200000000';
|
---|
31 |
|
---|
32 | my $proxy = TLSProxy::Proxy->new(
|
---|
33 | undef,
|
---|
34 | cmdstr(app(["openssl"]), display => 1),
|
---|
35 | srctop_file("apps", "server.pem"),
|
---|
36 | (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
|
---|
37 | );
|
---|
38 |
|
---|
39 | use constant {
|
---|
40 | PSK_LAST_FIRST_CH => 0,
|
---|
41 | ILLEGAL_EXT_SECOND_CH => 1
|
---|
42 | };
|
---|
43 |
|
---|
44 | #Most PSK tests are done in test_ssl_new. This tests various failure scenarios
|
---|
45 | #around PSK
|
---|
46 |
|
---|
47 | #Test 1: First get a session
|
---|
48 | (undef, my $session) = tempfile();
|
---|
49 | $proxy->clientflags("-sess_out ".$session);
|
---|
50 | $proxy->serverflags("-servername localhost");
|
---|
51 | $proxy->sessionfile($session);
|
---|
52 | $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
|
---|
53 | plan tests => 5;
|
---|
54 | ok(TLSProxy::Message->success(), "Initial connection");
|
---|
55 |
|
---|
56 | #Test 2: Attempt a resume with PSK not in last place. Should fail
|
---|
57 | $proxy->clear();
|
---|
58 | $proxy->clientflags("-sess_in ".$session);
|
---|
59 | $proxy->filter(\&modify_psk_filter);
|
---|
60 | my $testtype = PSK_LAST_FIRST_CH;
|
---|
61 | $proxy->start();
|
---|
62 | ok(TLSProxy::Message->fail(), "PSK not last");
|
---|
63 |
|
---|
64 | #Test 3: Attempt a resume after an HRR where PSK hash matches selected
|
---|
65 | # ciphersuite. Should see PSK on second ClientHello
|
---|
66 | $proxy->clear();
|
---|
67 | $proxy->clientflags("-sess_in ".$session);
|
---|
68 | if (disabled("ec")) {
|
---|
69 | $proxy->serverflags("-curves ffdhe3072");
|
---|
70 | } else {
|
---|
71 | $proxy->serverflags("-curves P-256");
|
---|
72 | }
|
---|
73 | $proxy->filter(undef);
|
---|
74 | $proxy->start();
|
---|
75 | #Check if the PSK is present in the second ClientHello
|
---|
76 | my $ch2 = ${$proxy->message_list}[2];
|
---|
77 | my $ch2seen = defined $ch2 && $ch2->mt() == TLSProxy::Message::MT_CLIENT_HELLO;
|
---|
78 | my $pskseen = $ch2seen
|
---|
79 | && defined ${$ch2->{extension_data}}{TLSProxy::Message::EXT_PSK};
|
---|
80 | ok($pskseen, "PSK hash matches");
|
---|
81 |
|
---|
82 | #Test 4: Attempt a resume after an HRR where PSK hash does not match selected
|
---|
83 | # ciphersuite. Should not see PSK on second ClientHello
|
---|
84 | $proxy->clear();
|
---|
85 | $proxy->clientflags("-sess_in ".$session);
|
---|
86 | $proxy->filter(\&modify_psk_filter);
|
---|
87 | if (disabled("ec")) {
|
---|
88 | $proxy->serverflags("-curves ffdhe3072");
|
---|
89 | } else {
|
---|
90 | $proxy->serverflags("-curves P-256");
|
---|
91 | }
|
---|
92 | $proxy->ciphersuitesc("TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384");
|
---|
93 | $proxy->ciphersuitess("TLS_AES_256_GCM_SHA384");
|
---|
94 | #We force an early failure because TLS Proxy doesn't actually support
|
---|
95 | #TLS_AES_256_GCM_SHA384. That doesn't matter for this test though.
|
---|
96 | $testtype = ILLEGAL_EXT_SECOND_CH;
|
---|
97 | $proxy->start();
|
---|
98 | #Check if the PSK is present in the second ClientHello
|
---|
99 | $ch2 = ${$proxy->message_list}[2];
|
---|
100 | $ch2seen = defined $ch2 && $ch2->mt() == TLSProxy::Message::MT_CLIENT_HELLO;
|
---|
101 | $pskseen = $ch2seen
|
---|
102 | && defined ${$ch2->extension_data}{TLSProxy::Message::EXT_PSK};
|
---|
103 | ok($ch2seen && !$pskseen, "PSK hash does not match");
|
---|
104 |
|
---|
105 | #Test 5: Attempt a resume without a sig agls extension. Should succeed because
|
---|
106 | # sig algs is not needed in a resumption.
|
---|
107 | $proxy->clear();
|
---|
108 | $proxy->clientflags("-sess_in ".$session);
|
---|
109 | $proxy->filter(\&remove_sig_algs_filter);
|
---|
110 | $proxy->start();
|
---|
111 | ok(TLSProxy::Message->success(), "Remove sig algs");
|
---|
112 |
|
---|
113 | unlink $session;
|
---|
114 |
|
---|
115 | sub modify_psk_filter
|
---|
116 | {
|
---|
117 | my $proxy = shift;
|
---|
118 | my $flight;
|
---|
119 | my $message;
|
---|
120 |
|
---|
121 | if ($testtype == PSK_LAST_FIRST_CH) {
|
---|
122 | $flight = 0;
|
---|
123 | } else {
|
---|
124 | $flight = 2;
|
---|
125 | }
|
---|
126 |
|
---|
127 | # Only look at the first or second ClientHello
|
---|
128 | return if $proxy->flight != $flight;
|
---|
129 |
|
---|
130 | if ($testtype == PSK_LAST_FIRST_CH) {
|
---|
131 | $message = ${$proxy->message_list}[0];
|
---|
132 | } else {
|
---|
133 | $message = ${$proxy->message_list}[2];
|
---|
134 | }
|
---|
135 |
|
---|
136 | return if (!defined $message
|
---|
137 | || $message->mt != TLSProxy::Message::MT_CLIENT_HELLO);
|
---|
138 |
|
---|
139 | if ($testtype == PSK_LAST_FIRST_CH) {
|
---|
140 | $message->set_extension(TLSProxy::Message::EXT_FORCE_LAST, "");
|
---|
141 | } else {
|
---|
142 | #Deliberately break the connection
|
---|
143 | $message->set_extension(TLSProxy::Message::EXT_SUPPORTED_GROUPS, "");
|
---|
144 | }
|
---|
145 | $message->repack();
|
---|
146 | }
|
---|
147 |
|
---|
148 | sub remove_sig_algs_filter
|
---|
149 | {
|
---|
150 | my $proxy = shift;
|
---|
151 | my $message;
|
---|
152 |
|
---|
153 | # Only look at the first ClientHello
|
---|
154 | return if $proxy->flight != 0;
|
---|
155 |
|
---|
156 | $message = ${$proxy->message_list}[0];
|
---|
157 | $message->delete_extension(TLSProxy::Message::EXT_SIG_ALGS);
|
---|
158 | $message->repack();
|
---|
159 | }
|
---|