Don't run dtls test on windows.
[openssl.git] / test / recipes / 70-test_dtlsrecords.t
1 #! /usr/bin/env perl
2 # Copyright 2024 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 feature 'state';
11
12 use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
13 use OpenSSL::Test::Utils;
14 use TLSProxy::Proxy;
15 use TLSProxy::Message;
16
17 my $test_name = "test_dtlsrecords";
18 setup($test_name);
19
20 plan skip_all => "TLSProxy isn't usable on $^O"
21     if $^O =~ /^(VMS|MSWin32)$/;
22
23 plan skip_all => "$test_name needs the dynamic engine feature enabled"
24     if disabled("engine") || disabled("dynamic-engine");
25
26 plan skip_all => "$test_name needs the sock feature enabled"
27     if disabled("sock");
28
29 plan skip_all => "$test_name needs DTLSv1.2 enabled"
30     if disabled("dtls1_2");
31
32 my $proxy = TLSProxy::Proxy->new_dtls(
33     undef,
34     cmdstr(app(["openssl"]), display => 1),
35     srctop_file("apps", "server.pem"),
36     (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
37 );
38
39 plan tests => 4;
40
41 my $fatal_alert = 0;        # set by filters at expected fatal alerts
42 my $inject_recs_num = 0;    # used by add_empty_recs_filter
43 my $proxy_start_success = 0;
44
45 #Test 1: Injecting out of context empty records should succeed
46 my $content_type = TLSProxy::Record::RT_APPLICATION_DATA;
47 $inject_recs_num = 1;
48 $proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
49 $proxy->clientflags("-max_protocol DTLSv1.2");
50 $proxy->filter(\&add_empty_recs_filter);
51 $proxy_start_success = $proxy->start();
52 ok($proxy_start_success && TLSProxy::Message->success(), "Out of context empty records test");
53
54 #Test 2: Injecting in context empty records should succeed
55 $proxy->clear();
56 $content_type = TLSProxy::Record::RT_HANDSHAKE;
57 $inject_recs_num = 1;
58 $proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
59 $proxy->clientflags("-max_protocol DTLSv1.2");
60 $proxy->filter(\&add_empty_recs_filter);
61 $proxy_start_success = $proxy->start();
62 ok($proxy_start_success && TLSProxy::Message->success(), "In context empty records test");
63
64 #Unrecognised record type tests
65
66 #Test 3: Sending an unrecognised record type in DTLSv1.2 should fail
67 $fatal_alert = 0;
68 $proxy->clear();
69 $proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
70 $proxy->clientflags("-max_protocol DTLSv1.2");
71 $proxy->filter(\&add_unknown_record_type);
72 ok($proxy->start() == 0, "Unrecognised record type in DTLS1.2");
73
74 SKIP: {
75     skip "DTLSv1 disabled", 1 if disabled("dtls1");
76
77     #Test 4: Sending an unrecognised record type in DTLSv1 should fail
78     $fatal_alert = 0;
79     $proxy->clear();
80     $proxy->clientflags("-min_protocol DTLSv1 -max_protocol DTLSv1 -cipher DEFAULT:\@SECLEVEL=0");
81     $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
82     $proxy->filter(\&add_unknown_record_type);
83     ok($proxy->start() == 0, "Unrecognised record type in DTLSv1");
84 }
85
86 sub add_empty_recs_filter
87 {
88     my $proxy = shift;
89     my $records = $proxy->record_list;
90
91     # We're only interested in the initial ClientHello
92     if ($proxy->flight != 0) {
93         $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
94         return;
95     }
96
97     for (my $i = 0; $i < $inject_recs_num; $i++) {
98         my $record = TLSProxy::Record->new_dtls(
99             0,
100             $content_type,
101             TLSProxy::Record::VERS_TLS_1_2,
102             0,
103             0,
104             0,
105             0,
106             0,
107             0,
108             "",
109             ""
110         );
111         push @{$records}, $record;
112     }
113 }
114
115 sub add_unknown_record_type
116 {
117     my $proxy = shift;
118     my $records = $proxy->record_list;
119     state $added_record;
120
121     # We'll change a record after the initial version neg has taken place
122     if ($proxy->flight == 0) {
123         $added_record = 0;
124         return;
125     } elsif ($proxy->flight != 1 || $added_record) {
126         $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
127         return;
128     }
129
130     my $record = TLSProxy::Record->new_dtls(
131         1,
132         TLSProxy::Record::RT_UNKNOWN,
133         @{$records}[-1]->version(),
134         @{$records}[-1]->epoch(),
135         @{$records}[-1]->seq() +1,
136         1,
137         0,
138         1,
139         1,
140         "X",
141         "X"
142     );
143
144     #Find ServerHello record and insert after that
145     my $i;
146     for ($i = 0; ${$proxy->record_list}[$i]->flight() < 1; $i++) {
147         next;
148     }
149     $i++;
150
151     splice @{$proxy->record_list}, $i, 0, $record;
152     $added_record = 1;
153 }