380b1a8a10a358ecc07a281fd853a3344e0cfc88
[openssl.git] / test / recipes / 70-test_key_share.t
1 #! /usr/bin/env perl
2 # Copyright 2015-2016 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 use File::Temp qw(tempfile);
14
15 use constant {
16     LOOK_ONLY => 0,
17     EMPTY_EXTENSION => 1,
18     MISSING_EXTENSION => 2,
19     NO_ACCEPTABLE_KEY_SHARES => 3,
20     NON_PREFERRED_KEY_SHARE => 4,
21     ACCEPTABLE_AT_END => 5,
22     NOT_IN_SUPPORTED_GROUPS => 6,
23     GROUP_ID_TOO_SHORT => 7,
24     KEX_LEN_MISMATCH => 8,
25     ZERO_LEN_KEX_DATA => 9,
26     TRAILING_DATA => 10,
27     SELECT_X25519 => 11
28 };
29
30 use constant {
31     CLIENT_TO_SERVER => 1,
32     SERVER_TO_CLIENT => 2
33 };
34
35
36 use constant {
37     X25519 => 0x1d,
38     P_256 => 0x17
39 };
40
41 my $testtype;
42 my $direction;
43 my $selectedgroupid;
44
45 my $test_name = "test_key_share";
46 setup($test_name);
47
48 plan skip_all => "TLSProxy isn't usable on $^O"
49     if $^O =~ /^(VMS|MSWin32)$/;
50
51 plan skip_all => "$test_name needs the dynamic engine feature enabled"
52     if disabled("engine") || disabled("dynamic-engine");
53
54 plan skip_all => "$test_name needs the sock feature enabled"
55     if disabled("sock");
56
57 plan skip_all => "$test_name needs TLS1.3 enabled"
58     if disabled("tls1_3");
59
60 $ENV{OPENSSL_ia32cap} = '~0x200000200000000';
61
62 my $proxy = TLSProxy::Proxy->new(
63     undef,
64     cmdstr(app(["openssl"]), display => 1),
65     srctop_file("apps", "server.pem"),
66     (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
67 );
68
69 #We assume that test_ssl_new and friends will test the happy path for this,
70 #so we concentrate on the less common scenarios
71
72 #Test 1: An empty key_shares extension should not succeed
73 $testtype = EMPTY_EXTENSION;
74 $direction = CLIENT_TO_SERVER;
75 $proxy->filter(\&modify_key_shares_filter);
76 $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
77 plan tests => 17;
78 #TODO(TLS1.3): Actually this should succeed after a HelloRetryRequest - but
79 #we've not implemented that yet, so for now we look for a fail
80 ok(TLSProxy::Message->fail(), "Empty key_shares");
81
82 #Test 2: A missing key_shares extension should not succeed
83 $proxy->clear();
84 $testtype = MISSING_EXTENSION;
85 $proxy->start();
86 #TODO(TLS1.3): As above this should really succeed after a HelloRetryRequest,
87 #but we look for fail for now
88 ok(TLSProxy::Message->fail(), "Missing key_shares extension");
89
90 #Test 3: No acceptable key_shares should fail
91 $proxy->clear();
92 $testtype = NO_ACCEPTABLE_KEY_SHARES;
93 $proxy->start();
94 #TODO(TLS1.3): Again this should go around the loop of a HelloRetryRequest but
95 #we fail for now
96 ok(TLSProxy::Message->fail(), "No acceptable key_shares");
97
98 #Test 4: A non preferred but acceptable key_share should succeed
99 $proxy->clear();
100 $proxy->filter(undef);
101 $proxy->clientflags("-curves P-256");
102 $proxy->start();
103 ok(TLSProxy::Message->success(), "Non preferred key_share");
104 $proxy->filter(\&modify_key_shares_filter);
105
106 #Test 5: An acceptable key_share after a list of non-acceptable ones should
107 #succeed
108 $proxy->clear();
109 $testtype = ACCEPTABLE_AT_END;
110 $proxy->start();
111 ok(TLSProxy::Message->success(), "Acceptable key_share at end of list");
112
113 #Test 6: An acceptable key_share but for a group not in supported_groups should
114 #fail
115 $proxy->clear();
116 $testtype = NOT_IN_SUPPORTED_GROUPS;
117 $proxy->start();
118 ok(TLSProxy::Message->fail(), "Acceptable key_share not in supported_groups");
119
120 #Test 7: Too short group_id should fail
121 $proxy->clear();
122 $testtype = GROUP_ID_TOO_SHORT;
123 $proxy->start();
124 ok(TLSProxy::Message->fail(), "Group id too short");
125
126 #Test 8: key_exchange length mismatch should fail
127 $proxy->clear();
128 $testtype = KEX_LEN_MISMATCH;
129 $proxy->start();
130 ok(TLSProxy::Message->fail(), "key_exchange length mismatch");
131
132 #Test 9: Zero length key_exchange should fail
133 $proxy->clear();
134 $testtype = ZERO_LEN_KEX_DATA;
135 $proxy->start();
136 ok(TLSProxy::Message->fail(), "zero length key_exchange data");
137
138 #Test 10: Trailing data on key_share list should fail
139 $proxy->clear();
140 $testtype = TRAILING_DATA;
141 $proxy->start();
142 ok(TLSProxy::Message->fail(), "key_share list trailing data");
143
144 #Test 11: Multiple acceptable key_shares - we choose the first one
145 $proxy->clear();
146 $direction = SERVER_TO_CLIENT;
147 $testtype = LOOK_ONLY;
148 $proxy->clientflags("-curves P-256:X25519");
149 $proxy->start();
150 ok(TLSProxy::Message->success() && ($selectedgroupid == P_256),
151    "Multiple acceptable key_shares");
152
153 #Test 12: Multiple acceptable key_shares - we choose the first one (part 2)
154 $proxy->clear();
155 $proxy->clientflags("-curves X25519:P-256");
156 $proxy->start();
157 ok(TLSProxy::Message->success() && ($selectedgroupid == X25519),
158    "Multiple acceptable key_shares (part 2)");
159
160 #Test 13: Server sends key_share that wasn't offerred should fail
161 $proxy->clear();
162 $testtype = SELECT_X25519;
163 $proxy->clientflags("-curves P-256");
164 $proxy->start();
165 ok(TLSProxy::Message->fail(), "Non offered key_share");
166
167 #Test 14: Too short group_id in ServerHello should fail
168 $proxy->clear();
169 $testtype = GROUP_ID_TOO_SHORT;
170 $proxy->start();
171 ok(TLSProxy::Message->fail(), "Group id too short in ServerHello");
172
173 #Test 15: key_exchange length mismatch in ServerHello should fail
174 $proxy->clear();
175 $testtype = KEX_LEN_MISMATCH;
176 $proxy->start();
177 ok(TLSProxy::Message->fail(), "key_exchange length mismatch in ServerHello");
178
179 #Test 16: Zero length key_exchange in ServerHello should fail
180 $proxy->clear();
181 $testtype = ZERO_LEN_KEX_DATA;
182 $proxy->start();
183 ok(TLSProxy::Message->fail(), "zero length key_exchange data in ServerHello");
184
185 #Test 17: Trailing data on key_share in ServerHello should fail
186 $proxy->clear();
187 $testtype = TRAILING_DATA;
188 $proxy->start();
189 ok(TLSProxy::Message->fail(), "key_share trailing data in ServerHello");
190
191
192 sub modify_key_shares_filter
193 {
194     my $proxy = shift;
195
196     # We're only interested in the initial ClientHello
197     if (($direction == CLIENT_TO_SERVER && $proxy->flight != 0)
198             || ($direction == SERVER_TO_CLIENT && $proxy->flight != 1)) {
199         return;
200     }
201
202     foreach my $message (@{$proxy->message_list}) {
203         if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO
204                 && $direction == CLIENT_TO_SERVER) {
205             my $ext;
206             my $suppgroups;
207
208             #Setup supported groups to include some unrecognised groups
209             $suppgroups = pack "C8",
210                 0x00, 0x06, #List Length
211                 0xff, 0xfe, #Non existing group 1
212                 0xff, 0xff, #Non existing group 2
213                 0x00, 0x1d; #x25519
214
215             if ($testtype == EMPTY_EXTENSION) {
216                 $ext = pack "C2",
217                     0x00, 0x00;
218             } elsif ($testtype == NO_ACCEPTABLE_KEY_SHARES) {
219                 $ext = pack "C12",
220                     0x00, 0x0a, #List Length
221                     0xff, 0xfe, #Non existing group 1
222                     0x00, 0x01, 0xff, #key_exchange data
223                     0xff, 0xff, #Non existing group 2
224                     0x00, 0x01, 0xff; #key_exchange data
225             } elsif ($testtype == ACCEPTABLE_AT_END) {
226                 $ext = pack "C11H64",
227                     0x00, 0x29, #List Length
228                     0xff, 0xfe, #Non existing group 1
229                     0x00, 0x01, 0xff, #key_exchange data
230                     0x00, 0x1d, #x25519
231                     0x00, 0x20, #key_exchange data length
232                     "155155B95269ED5C87EAA99C2EF5A593".
233                     "EDF83495E80380089F831B94D14B1421";  #key_exchange data
234             } elsif ($testtype == NOT_IN_SUPPORTED_GROUPS) {
235                 $suppgroups = pack "C4",
236                     0x00, 0x02, #List Length
237                     0x00, 0xfe; #Non existing group 1
238             } elsif ($testtype == GROUP_ID_TOO_SHORT) {
239                 $ext = pack "C6H64C1",
240                     0x00, 0x25, #List Length
241                     0x00, 0x1d, #x25519
242                     0x00, 0x20, #key_exchange data length
243                     "155155B95269ED5C87EAA99C2EF5A593".
244                     "EDF83495E80380089F831B94D14B1421";  #key_exchange data
245                     0x00;       #Group id too short
246             } elsif ($testtype == KEX_LEN_MISMATCH) {
247                 $ext = pack "C8",
248                     0x00, 0x06, #List Length
249                     0x00, 0x1d, #x25519
250                     0x00, 0x20, #key_exchange data length
251                     0x15, 0x51; #Only two bytes of data, but length should be 32
252             } elsif ($testtype == ZERO_LEN_KEX_DATA) {
253                 $ext = pack "C10H64",
254                     0x00, 0x28, #List Length
255                     0xff, 0xfe, #Non existing group 1
256                     0x00, 0x00, #zero length key_exchange data is invalid
257                     0x00, 0x1d, #x25519
258                     0x00, 0x20, #key_exchange data length
259                     "155155B95269ED5C87EAA99C2EF5A593".
260                     "EDF83495E80380089F831B94D14B1421";  #key_exchange data
261             } elsif ($testtype == TRAILING_DATA) {
262                 $ext = pack "C6H64C1",
263                     0x00, 0x24, #List Length
264                     0x00, 0x1d, #x25519
265                     0x00, 0x20, #key_exchange data length
266                     "155155B95269ED5C87EAA99C2EF5A593".
267                     "EDF83495E80380089F831B94D14B1421", #key_exchange data
268                     0x00; #Trailing garbage
269             }
270
271             $message->set_extension(
272                 TLSProxy::Message::EXT_SUPPORTED_GROUPS, $suppgroups);
273
274             if ($testtype == MISSING_EXTENSION) {
275                 $message->delete_extension(
276                     TLSProxy::Message::EXT_KEY_SHARE);
277             } elsif ($testtype != NOT_IN_SUPPORTED_GROUPS) {
278                 $message->set_extension(
279                     TLSProxy::Message::EXT_KEY_SHARE, $ext);
280             }
281
282             $message->repack();
283         } elsif ($message->mt == TLSProxy::Message::MT_SERVER_HELLO
284                      && $direction == SERVER_TO_CLIENT) {
285             my $ext;
286             my $key_share =
287                 ${$message->extension_data}{TLSProxy::Message::EXT_KEY_SHARE};
288             $selectedgroupid = unpack("n", $key_share);
289
290             if ($testtype == LOOK_ONLY) {
291                 return;
292             }
293             if ($testtype == SELECT_X25519) {
294                 $ext = pack "C4H64",
295                     0x00, 0x1d, #x25519
296                     0x00, 0x20, #key_exchange data length
297                     "155155B95269ED5C87EAA99C2EF5A593".
298                     "EDF83495E80380089F831B94D14B1421";  #key_exchange data
299             } elsif ($testtype == GROUP_ID_TOO_SHORT) {
300                 $ext = pack "C1",
301                     0x00;
302             } elsif ($testtype == KEX_LEN_MISMATCH) {
303                 $ext = pack "C6",
304                     0x00, 0x1d, #x25519
305                     0x00, 0x20, #key_exchange data length
306                     0x15, 0x51; #Only two bytes of data, but length should be 32
307             } elsif ($testtype == ZERO_LEN_KEX_DATA) {
308                 $ext = pack "C4",
309                     0x00, 0x1d, #x25519
310                     0x00, 0x00, #zero length key_exchange data is invalid
311             } elsif ($testtype == TRAILING_DATA) {
312                 $ext = pack "C4H64C1",
313                     0x00, 0x1d, #x25519
314                     0x00, 0x20, #key_exchange data length
315                     "155155B95269ED5C87EAA99C2EF5A593".
316                     "EDF83495E80380089F831B94D14B1421", #key_exchange data
317                     0x00; #Trailing garbage
318             }
319             $message->set_extension( TLSProxy::Message::EXT_KEY_SHARE, $ext);
320
321             $message->repack();
322         }
323     }
324 }
325
326