]> git.ipfire.org Git - thirdparty/openssl.git/blame - test/ssl-tests/protocol_version.pm
Update copyright year
[thirdparty/openssl.git] / test / ssl-tests / protocol_version.pm
CommitLineData
74726750 1# -*- mode: perl; -*-
a28d06f3 2# Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
74726750 3#
909f1a2e 4# Licensed under the Apache License 2.0 (the "License"). You may not use
74726750
EK
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
10## Test version negotiation
11
12package ssltests;
13
14use strict;
15use warnings;
16
17use List::Util qw/max min/;
18
19use OpenSSL::Test;
1763ab10 20use OpenSSL::Test::Utils qw/anydisabled alldisabled disabled/;
74726750
EK
21setup("no_test_here");
22
582a17d6 23my @tls_protocols = ("SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3");
682bc861 24my @tls_protocols_fips = ("TLSv1.2", "TLSv1.3");
74726750 25# undef stands for "no limit".
582a17d6 26my @min_tls_protocols = (undef, "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3");
682bc861 27my @min_tls_protocols_fips = (undef, "TLSv1.2", "TLSv1.3");
582a17d6 28my @max_tls_protocols = ("SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3", undef);
682bc861 29my @max_tls_protocols_fips = ("TLSv1.2", "TLSv1.3", undef);
74726750 30
582a17d6 31my @is_tls_disabled = anydisabled("ssl3", "tls1", "tls1_1", "tls1_2", "tls1_3");
682bc861 32my @is_tls_disabled_fips = anydisabled("tls1_2", "tls1_3");
74726750
EK
33
34my $min_tls_enabled; my $max_tls_enabled;
682bc861 35my $min_tls_enabled_fips; my $max_tls_enabled_fips;
74726750
EK
36
37# Protocol configuration works in cascades, i.e.,
38# $no_tls1_1 disables TLSv1.1 and below.
39#
40# $min_enabled and $max_enabled will be correct if there is at least one
41# protocol enabled.
682bc861
MC
42
43sub min_prot_enabled {
44 my $protref = shift;
45 my $disabledref = shift;
46 my @protocols = @{$protref};
47 my @is_disabled = @{$disabledref};
48 my $min_enabled;
49
50 foreach my $i (0..$#protocols) {
51 if (!$is_disabled[$i]) {
52 $min_enabled = $i;
53 last;
54 }
74726750 55 }
682bc861 56 return $min_enabled;
74726750
EK
57}
58
682bc861
MC
59sub max_prot_enabled {
60 my $protref = shift;
61 my $disabledref = shift;
62 my @protocols = @{$protref};
63 my @is_disabled = @{$disabledref};
64 my $max_enabled;
65
66 foreach my $i (0..$#protocols) {
a763ca11
MC
67 if (!$is_disabled[$i]
68 && ($protocols[$i] ne "TLSv1.3"
69 || !disabled("ec")
70 || !disabled("dh"))) {
682bc861
MC
71 $max_enabled = $i;
72 }
74726750 73 }
682bc861 74 return $max_enabled;
74726750
EK
75}
76
682bc861
MC
77$min_tls_enabled = min_prot_enabled(\@tls_protocols, \@is_tls_disabled);
78$max_tls_enabled = max_prot_enabled(\@tls_protocols, \@is_tls_disabled);
79$min_tls_enabled_fips = min_prot_enabled(\@tls_protocols_fips, \@is_tls_disabled_fips);
80$max_tls_enabled_fips = max_prot_enabled(\@tls_protocols_fips, \@is_tls_disabled_fips);
81
82
74726750 83my @dtls_protocols = ("DTLSv1", "DTLSv1.2");
682bc861 84my @dtls_protocols_fips = ("DTLSv1.2");
74726750
EK
85# undef stands for "no limit".
86my @min_dtls_protocols = (undef, "DTLSv1", "DTLSv1.2");
682bc861 87my @min_dtls_protocols_fips = (undef, "DTLSv1.2");
74726750 88my @max_dtls_protocols = ("DTLSv1", "DTLSv1.2", undef);
682bc861 89my @max_dtls_protocols_fips = ("DTLSv1.2", undef);
74726750
EK
90
91my @is_dtls_disabled = anydisabled("dtls1", "dtls1_2");
682bc861 92my @is_dtls_disabled_fips = anydisabled("dtls1_2");
74726750
EK
93
94my $min_dtls_enabled; my $max_dtls_enabled;
682bc861 95my $min_dtls_enabled_fips; my $max_dtls_enabled_fips;
74726750
EK
96
97# $min_enabled and $max_enabled will be correct if there is at least one
98# protocol enabled.
682bc861
MC
99$min_dtls_enabled = min_prot_enabled(\@dtls_protocols, \@is_dtls_disabled);
100$max_dtls_enabled = max_prot_enabled(\@dtls_protocols, \@is_dtls_disabled);
101$min_dtls_enabled_fips = min_prot_enabled(\@dtls_protocols_fips, \@is_dtls_disabled_fips);
102$max_dtls_enabled_fips = max_prot_enabled(\@dtls_protocols_fips, \@is_dtls_disabled_fips);
74726750 103
590ed3d7
EK
104sub no_tests {
105 my ($dtls) = @_;
106 return $dtls ? alldisabled("dtls1", "dtls1_2") :
582a17d6 107 alldisabled("ssl3", "tls1", "tls1_1", "tls1_2", "tls1_3");
590ed3d7
EK
108}
109
110sub generate_version_tests {
682bc861
MC
111 my $method = shift;
112 my $fips = shift;
74726750
EK
113
114 my $dtls = $method eq "DTLS";
115 # Don't write the redundant "Method = TLS" into the configuration.
590ed3d7 116 undef $method if !$dtls;
74726750 117
682bc861
MC
118 my @protocols;
119 my @min_protocols;
120 my @max_protocols;
121 my $min_enabled;
122 my $max_enabled;
123 if ($fips) {
124 @protocols = $dtls ? @dtls_protocols_fips : @tls_protocols_fips;
125 @min_protocols = $dtls ? @min_dtls_protocols_fips : @min_tls_protocols_fips;
126 @max_protocols = $dtls ? @max_dtls_protocols_fips : @max_tls_protocols_fips;
127 $min_enabled = $dtls ? $min_dtls_enabled_fips : $min_tls_enabled_fips;
128 $max_enabled = $dtls ? $max_dtls_enabled_fips : $max_tls_enabled_fips;
129 } else {
130 @protocols = $dtls ? @dtls_protocols : @tls_protocols;
131 @min_protocols = $dtls ? @min_dtls_protocols : @min_tls_protocols;
132 @max_protocols = $dtls ? @max_dtls_protocols : @max_tls_protocols;
133 $min_enabled = $dtls ? $min_dtls_enabled : $min_tls_enabled;
134 $max_enabled = $dtls ? $max_dtls_enabled : $max_tls_enabled;
135 }
74726750 136
590ed3d7 137 if (no_tests($dtls)) {
74726750
EK
138 return;
139 }
140
141 my @tests = ();
142
00da4f4d
MC
143 for (my $sctp = 0; $sctp < ($dtls && !disabled("sctp") ? 2 : 1); $sctp++) {
144 foreach my $c_min (0..$#min_protocols) {
145 my $c_max_min = $c_min == 0 ? 0 : $c_min - 1;
146 foreach my $c_max ($c_max_min..$#max_protocols) {
147 foreach my $s_min (0..$#min_protocols) {
148 my $s_max_min = $s_min == 0 ? 0 : $s_min - 1;
149 foreach my $s_max ($s_max_min..$#max_protocols) {
150 my ($result, $protocol) =
151 expected_result($c_min, $c_max, $s_min, $s_max,
152 $min_enabled, $max_enabled,
153 \@protocols);
154 push @tests, {
155 "name" => "version-negotiation",
156 "client" => {
aba03ae5 157 "CipherString" => "DEFAULT:\@SECLEVEL=0",
00da4f4d
MC
158 "MinProtocol" => $min_protocols[$c_min],
159 "MaxProtocol" => $max_protocols[$c_max],
160 },
161 "server" => {
aba03ae5 162 "CipherString" => "DEFAULT:\@SECLEVEL=0",
00da4f4d
MC
163 "MinProtocol" => $min_protocols[$s_min],
164 "MaxProtocol" => $max_protocols[$s_max],
165 },
166 "test" => {
167 "ExpectedResult" => $result,
168 "ExpectedProtocol" => $protocol,
169 "Method" => $method,
170 }
171 };
172 $tests[-1]{"test"}{"UseSCTP"} = "Yes" if $sctp;
173 }
74726750
EK
174 }
175 }
176 }
177 }
a763ca11
MC
178 return @tests
179 if disabled("tls1_3")
180 || disabled("tls1_2")
181 || (disabled("ec") && disabled("dh"))
182 || $dtls;
975922fd
MC
183
184 #Add some version/ciphersuite sanity check tests
185 push @tests, {
186 "name" => "ciphersuite-sanity-check-client",
187 "client" => {
188 #Offering only <=TLSv1.2 ciphersuites with TLSv1.3 should fail
189 "CipherString" => "AES128-SHA",
f865b081 190 "Ciphersuites" => "",
975922fd
MC
191 },
192 "server" => {
193 "MaxProtocol" => "TLSv1.2"
194 },
195 "test" => {
196 "ExpectedResult" => "ClientFail",
197 }
198 };
199 push @tests, {
200 "name" => "ciphersuite-sanity-check-server",
201 "client" => {
202 "CipherString" => "AES128-SHA",
203 "MaxProtocol" => "TLSv1.2"
204 },
205 "server" => {
206 #Allowing only <=TLSv1.2 ciphersuites with TLSv1.3 should fail
207 "CipherString" => "AES128-SHA",
f865b081 208 "Ciphersuites" => "",
975922fd
MC
209 },
210 "test" => {
211 "ExpectedResult" => "ServerFail",
212 }
213 };
214
74726750
EK
215 return @tests;
216}
217
590ed3d7 218sub generate_resumption_tests {
682bc861
MC
219 my $method = shift;
220 my $fips = shift;
590ed3d7
EK
221
222 my $dtls = $method eq "DTLS";
223 # Don't write the redundant "Method = TLS" into the configuration.
224 undef $method if !$dtls;
225
682bc861
MC
226 my @protocols;
227 my $min_enabled;
228 my $max_enabled;
229
230 if ($fips) {
231 @protocols = $dtls ? @dtls_protocols_fips : @tls_protocols_fips;
232 $min_enabled = $dtls ? $min_dtls_enabled_fips : $min_tls_enabled_fips;
233 $max_enabled = $dtls ? $max_dtls_enabled_fips : $max_tls_enabled_fips;
234 } else {
235 @protocols = $dtls ? @dtls_protocols : @tls_protocols;
236 $min_enabled = $dtls ? $min_dtls_enabled : $min_tls_enabled;
237 $max_enabled = $dtls ? $max_dtls_enabled : $max_tls_enabled;
238 }
590ed3d7
EK
239
240 if (no_tests($dtls)) {
241 return;
242 }
243
11279b13
EK
244 my @server_tests = ();
245 my @client_tests = ();
590ed3d7 246
11279b13 247 # Obtain the first session against a fixed-version server/client.
84a68336 248 foreach my $original_protocol($min_enabled..$max_enabled) {
11279b13 249 # Upgrade or downgrade the server/client max version support and test
590ed3d7 250 # that it upgrades, downgrades or resumes the session as well.
84a68336 251 foreach my $resume_protocol($min_enabled..$max_enabled) {
590ed3d7
EK
252 my $resumption_expected;
253 # We should only resume on exact version match.
254 if ($original_protocol eq $resume_protocol) {
255 $resumption_expected = "Yes";
256 } else {
257 $resumption_expected = "No";
258 }
259
cf156009
MC
260 for (my $sctp = 0; $sctp < ($dtls && !disabled("sctp") ? 2 : 1);
261 $sctp++) {
262 foreach my $ticket ("SessionTicket", "-SessionTicket") {
263 # Client is flexible, server upgrades/downgrades.
264 push @server_tests, {
265 "name" => "resumption",
aba03ae5
KR
266 "client" => {
267 "CipherString" => "DEFAULT:\@SECLEVEL=0",
268 },
cf156009 269 "server" => {
aba03ae5 270 "CipherString" => "DEFAULT:\@SECLEVEL=0",
cf156009
MC
271 "MinProtocol" => $protocols[$original_protocol],
272 "MaxProtocol" => $protocols[$original_protocol],
273 "Options" => $ticket,
274 },
275 "resume_server" => {
aba03ae5 276 "CipherString" => "DEFAULT:\@SECLEVEL=0",
cf156009 277 "MaxProtocol" => $protocols[$resume_protocol],
6cc0b3c2 278 "Options" => $ticket,
cf156009
MC
279 },
280 "test" => {
281 "ExpectedProtocol" => $protocols[$resume_protocol],
282 "Method" => $method,
283 "HandshakeMode" => "Resume",
284 "ResumptionExpected" => $resumption_expected,
285 }
286 };
287 $server_tests[-1]{"test"}{"UseSCTP"} = "Yes" if $sctp;
288 # Server is flexible, client upgrades/downgrades.
289 push @client_tests, {
290 "name" => "resumption",
291 "client" => {
aba03ae5 292 "CipherString" => "DEFAULT:\@SECLEVEL=0",
cf156009
MC
293 "MinProtocol" => $protocols[$original_protocol],
294 "MaxProtocol" => $protocols[$original_protocol],
295 },
296 "server" => {
aba03ae5 297 "CipherString" => "DEFAULT:\@SECLEVEL=0",
cf156009
MC
298 "Options" => $ticket,
299 },
300 "resume_client" => {
aba03ae5 301 "CipherString" => "DEFAULT:\@SECLEVEL=0",
cf156009
MC
302 "MaxProtocol" => $protocols[$resume_protocol],
303 },
304 "test" => {
305 "ExpectedProtocol" => $protocols[$resume_protocol],
306 "Method" => $method,
307 "HandshakeMode" => "Resume",
308 "ResumptionExpected" => $resumption_expected,
309 }
310 };
311 $client_tests[-1]{"test"}{"UseSCTP"} = "Yes" if $sctp;
312 }
590ed3d7
EK
313 }
314 }
315 }
316
a763ca11 317 if (!disabled("tls1_3") && (!disabled("ec") || !disabled("dh")) && !$dtls) {
1763ab10
MC
318 push @client_tests, {
319 "name" => "resumption-with-hrr",
320 "client" => {
321 },
322 "server" => {
dbc6268f 323 "Curves" => disabled("ec") ? "ffdhe3072" : "P-256"
1763ab10
MC
324 },
325 "resume_client" => {
326 },
327 "test" => {
328 "ExpectedProtocol" => "TLSv1.3",
329 "Method" => "TLS",
330 "HandshakeMode" => "Resume",
331 "ResumptionExpected" => "Yes",
332 }
333 };
334 }
335
11279b13 336 return (@server_tests, @client_tests);
590ed3d7
EK
337}
338
74726750
EK
339sub expected_result {
340 my ($c_min, $c_max, $s_min, $s_max, $min_enabled, $max_enabled,
341 $protocols) = @_;
a763ca11 342 my @prots = @$protocols;
74726750 343
a763ca11 344 my $orig_c_max = $c_max;
74726750
EK
345 # Adjust for "undef" (no limit).
346 $c_min = $c_min == 0 ? 0 : $c_min - 1;
347 $c_max = $c_max == scalar @$protocols ? $c_max - 1 : $c_max;
348 $s_min = $s_min == 0 ? 0 : $s_min - 1;
349 $s_max = $s_max == scalar @$protocols ? $s_max - 1 : $s_max;
350
351 # We now have at least one protocol enabled, so $min_enabled and
352 # $max_enabled are well-defined.
353 $c_min = max $c_min, $min_enabled;
354 $s_min = max $s_min, $min_enabled;
355 $c_max = min $c_max, $max_enabled;
356 $s_max = min $s_max, $max_enabled;
357
a763ca11
MC
358 if ($c_min > $c_max
359 || ($orig_c_max != scalar @$protocols
360 && $prots[$orig_c_max] eq "TLSv1.3"
361 && $c_max != $orig_c_max
362 && !disabled("tls1_3"))) {
74726750 363 # Client should fail to even send a hello.
83964ca0 364 return ("ClientFail", undef);
74726750
EK
365 } elsif ($s_min > $s_max) {
366 # Server has no protocols, should always fail.
367 return ("ServerFail", undef);
368 } elsif ($s_min > $c_max) {
369 # Server doesn't support the client range.
370 return ("ServerFail", undef);
371 } elsif ($c_min > $s_max) {
7b21c00e
MC
372 if ($prots[$c_max] eq "TLSv1.3") {
373 # Client will have sent supported_versions, so server will know
374 # that there are no overlapping versions.
375 return ("ServerFail", undef);
582a17d6
MC
376 } else {
377 # Server will try with a version that is lower than the lowest
378 # supported client version.
379 return ("ClientFail", undef);
380 }
74726750
EK
381 } else {
382 # Server and client ranges overlap.
383 my $max_common = $s_max < $c_max ? $s_max : $c_max;
384 return ("Success", $protocols->[$max_common]);
385 }
386}
387
3881;