288c48622826eb8b76e75bd62252b559a633c96b
[openssl.git] / test / recipes / 70-test_sslextension.t
1 #! /usr/bin/env perl
2 # Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the OpenSSL license (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 bldtop_dir/;
11 use OpenSSL::Test::Utils;
12 use TLSProxy::Proxy;
13
14 my $test_name = "test_sslextension";
15 setup($test_name);
16
17 plan skip_all => "TLSProxy isn't usable on $^O"
18     if $^O =~ /^(VMS|MSWin32)$/;
19
20 plan skip_all => "$test_name needs the dynamic engine feature enabled"
21     if disabled("engine") || disabled("dynamic-engine");
22
23 plan skip_all => "$test_name needs the sock feature enabled"
24     if disabled("sock");
25
26 plan skip_all => "$test_name needs TLS enabled"
27     if alldisabled(available_protocols("tls"));
28
29 use constant {
30     UNSOLICITED_SERVER_NAME => 0,
31     UNSOLICITED_SERVER_NAME_TLS13 => 1,
32     UNSOLICITED_SCT => 2,
33     NONCOMPLIANT_SUPPORTED_GROUPS => 3
34 };
35
36 my $testtype;
37
38 $ENV{OPENSSL_ia32cap} = '~0x200000200000000';
39 my $proxy = TLSProxy::Proxy->new(
40     \&extension_filter,
41     cmdstr(app(["openssl"]), display => 1),
42     srctop_file("apps", "server.pem"),
43     (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
44 );
45
46 # Test 1: Sending a zero length extension block should pass
47 $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
48 plan tests => 7;
49 ok(TLSProxy::Message->success, "Zero extension length test");
50
51 sub extension_filter
52 {
53     my $proxy = shift;
54
55     if ($proxy->flight == 1) {
56         # Change the ServerRandom so that the downgrade sentinel doesn't cause
57         # the connection to fail
58         my $message = ${$proxy->message_list}[1];
59         $message->random("\0"x32);
60         $message->repack();
61         return;
62     }
63
64     # We're only interested in the initial ClientHello
65     if ($proxy->flight != 0) {
66         return;
67     }
68
69     foreach my $message (@{$proxy->message_list}) {
70         if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
71             # Remove all extensions and set the extension len to zero
72             $message->extension_data({});
73             $message->extensions_len(0);
74             # Extensions have been removed so make sure we don't try to use them
75             $message->process_extensions();
76
77             $message->repack();
78         }
79     }
80 }
81
82 # Test 2-3: Sending a duplicate extension should fail.
83 sub inject_duplicate_extension
84 {
85   my ($proxy, $message_type) = @_;
86
87     foreach my $message (@{$proxy->message_list}) {
88         if ($message->mt == $message_type) {
89           my %extensions = %{$message->extension_data};
90             # Add a duplicate (unknown) extension.
91             $message->set_extension(TLSProxy::Message::EXT_DUPLICATE_EXTENSION, "");
92             $message->set_extension(TLSProxy::Message::EXT_DUPLICATE_EXTENSION, "");
93             $message->repack();
94         }
95     }
96 }
97
98 sub inject_duplicate_extension_clienthello
99 {
100     my $proxy = shift;
101
102     # We're only interested in the initial ClientHello
103     if ($proxy->flight != 0) {
104         return;
105     }
106
107     inject_duplicate_extension($proxy, TLSProxy::Message::MT_CLIENT_HELLO);
108 }
109
110 sub inject_duplicate_extension_serverhello
111 {
112     my $proxy = shift;
113
114     # We're only interested in the initial ServerHello
115     if ($proxy->flight != 1) {
116         return;
117     }
118
119     inject_duplicate_extension($proxy, TLSProxy::Message::MT_SERVER_HELLO);
120 }
121
122 $proxy->clear();
123 $proxy->filter(\&inject_duplicate_extension_clienthello);
124 $proxy->start();
125 ok(TLSProxy::Message->fail(), "Duplicate ClientHello extension");
126
127 $proxy->clear();
128 $proxy->filter(\&inject_duplicate_extension_serverhello);
129 $proxy->start();
130 ok(TLSProxy::Message->fail(), "Duplicate ServerHello extension");
131
132 sub inject_unsolicited_extension
133 {
134     my $proxy = shift;
135     my $message;
136
137     # We're only interested in the initial ServerHello/EncryptedExtensions
138     if ($proxy->flight != 1) {
139         return;
140     }
141
142     if ($testtype == UNSOLICITED_SERVER_NAME_TLS13) {
143         $message = ${$proxy->message_list}[2];
144         die "Expecting EE message ".($message->mt).", ".${$proxy->message_list}[1]->mt.", ".${$proxy->message_list}[3]->mt if $message->mt != TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS;
145     } else {
146         $message = ${$proxy->message_list}[1];
147     }
148
149     my $ext = pack "C2",
150         0x00, 0x00; #Extension length
151
152     my $type;
153     if ($testtype == UNSOLICITED_SERVER_NAME
154             || $testtype == UNSOLICITED_SERVER_NAME_TLS13) {
155         $type = TLSProxy::Message::EXT_SERVER_NAME;
156     } elsif ($testtype == UNSOLICITED_SCT) {
157         $type = TLSProxy::Message::EXT_SCT;
158     } elsif ($testtype == NONCOMPLIANT_SUPPORTED_GROUPS) {
159         $type = TLSProxy::Message::EXT_SUPPORTED_GROUPS;
160     }
161     $message->set_extension($type, $ext);
162     $message->repack();
163 }
164
165 SKIP: {
166     skip "TLS <= 1.2 disabled", 2 if alldisabled(("tls1", "tls1_1", "tls1_2"));
167     #Test 4: Inject an unsolicited extension (<= TLSv1.2)
168     $proxy->clear();
169     $proxy->filter(\&inject_unsolicited_extension);
170     $testtype = UNSOLICITED_SERVER_NAME;
171     $proxy->clientflags("-no_tls1_3 -noservername");
172     $proxy->start();
173     ok(TLSProxy::Message->fail(), "Unsolicited server name extension");
174
175     #Test 5: Inject a noncompliant supported_groups extension (<= TLSv1.2)
176     $proxy->clear();
177     $proxy->filter(\&inject_unsolicited_extension);
178     $testtype = NONCOMPLIANT_SUPPORTED_GROUPS;
179     $proxy->clientflags("-no_tls1_3");
180     $proxy->start();
181     ok(TLSProxy::Message->success(), "Noncompliant supported_groups extension");
182 }
183
184 SKIP: {
185     skip "TLS <= 1.2 or CT disabled", 1
186         if alldisabled(("tls1", "tls1_1", "tls1_2")) || disabled("ct");
187     #Test 6: Same as above for the SCT extension which has special handling
188     $proxy->clear();
189     $testtype = UNSOLICITED_SCT;
190     $proxy->clientflags("-no_tls1_3");
191     $proxy->start();
192     ok(TLSProxy::Message->fail(), "Unsolicited sct extension");
193 }
194
195 SKIP: {
196     skip "TLS 1.3 disabled", 1 if disabled("tls1_3");
197     #Test 7: Inject an unsolicited extension (TLSv1.3)
198     $proxy->clear();
199     $proxy->filter(\&inject_unsolicited_extension);
200     $testtype = UNSOLICITED_SERVER_NAME_TLS13;
201     $proxy->clientflags("-noservername");
202     $proxy->start();
203     ok(TLSProxy::Message->fail(), "Unsolicited server name extension (TLSv1.3)");
204 }