2 # Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
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
10 use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
11 use OpenSSL::Test::Utils;
12 use File::Temp qw(tempfile);
14 my $test_name = "test_tls13messages";
17 plan skip_all => "TLSProxy isn't usable on $^O"
18 if $^O =~ /^(VMS|MSWin32)$/;
20 plan skip_all => "$test_name needs the dynamic engine feature enabled"
21 if disabled("engine") || disabled("dynamic-engine");
23 plan skip_all => "$test_name needs the sock feature enabled"
26 plan skip_all => "$test_name needs TLSv1.3 enabled"
27 if disabled("tls1_3");
29 $ENV{OPENSSL_ia32cap} = '~0x200000200000000';
30 $ENV{CTLOG_FILE} = srctop_file("test", "ct", "log_list.conf");
33 DEFAULT_HANDSHAKE => 1,
35 RESUME_HANDSHAKE => 4,
36 CLIENT_AUTH_HANDSHAKE => 8,
41 DEFAULT_EXTENSIONS => 0x00000001,
42 SERVER_NAME_CLI_EXTENSION => 0x00000002,
43 SERVER_NAME_SRV_EXTENSION => 0x00000004,
44 STATUS_REQUEST_CLI_EXTENSION => 0x00000008,
45 STATUS_REQUEST_SRV_EXTENSION => 0x00000010,
46 ALPN_CLI_EXTENSION => 0x00000020,
47 ALPN_SRV_EXTENSION => 0x00000040,
48 SCT_CLI_EXTENSION => 0x00000080
52 [TLSProxy::Message::MT_CLIENT_HELLO, ALL_HANDSHAKES],
53 [TLSProxy::Message::MT_SERVER_HELLO, ALL_HANDSHAKES],
54 [TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS, ALL_HANDSHAKES],
55 [TLSProxy::Message::MT_CERTIFICATE_REQUEST, CLIENT_AUTH_HANDSHAKE],
56 [TLSProxy::Message::MT_CERTIFICATE, ALL_HANDSHAKES & ~RESUME_HANDSHAKE],
57 [TLSProxy::Message::MT_CERTIFICATE_STATUS, OCSP_HANDSHAKE],
58 [TLSProxy::Message::MT_FINISHED, ALL_HANDSHAKES],
59 [TLSProxy::Message::MT_CERTIFICATE, CLIENT_AUTH_HANDSHAKE],
60 [TLSProxy::Message::MT_CERTIFICATE_VERIFY, CLIENT_AUTH_HANDSHAKE],
61 [TLSProxy::Message::MT_FINISHED, ALL_HANDSHAKES],
66 [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SERVER_NAME, SERVER_NAME_CLI_EXTENSION],
67 [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_STATUS_REQUEST, STATUS_REQUEST_CLI_EXTENSION],
68 [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_GROUPS, DEFAULT_EXTENSIONS],
69 [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EC_POINT_FORMATS, DEFAULT_EXTENSIONS],
70 [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SIG_ALGS, DEFAULT_EXTENSIONS],
71 [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ALPN, ALPN_CLI_EXTENSION],
72 [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SCT, SCT_CLI_EXTENSION],
73 [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ENCRYPT_THEN_MAC, DEFAULT_EXTENSIONS],
74 [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET, DEFAULT_EXTENSIONS],
75 [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SESSION_TICKET, DEFAULT_EXTENSIONS],
76 [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_KEY_SHARE, DEFAULT_EXTENSIONS],
77 [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS, DEFAULT_EXTENSIONS],
79 [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_KEY_SHARE, DEFAULT_EXTENSIONS],
81 [TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS, TLSProxy::Message::EXT_SERVER_NAME, SERVER_NAME_SRV_EXTENSION],
82 [TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS, TLSProxy::Message::EXT_STATUS_REQUEST, STATUS_REQUEST_SRV_EXTENSION],
83 [TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS, TLSProxy::Message::EXT_ALPN, ALPN_SRV_EXTENSION],
87 my $proxy = TLSProxy::Proxy->new(
89 cmdstr(app(["openssl"]), display => 1),
90 srctop_file("apps", "server.pem"),
91 (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
94 sub checkmessages($$$);
96 #Test 1: Check we get all the right messages for a default handshake
97 (undef, my $session) = tempfile();
98 #$proxy->serverconnects(2);
99 $proxy->clientflags("-sess_out ".$session);
100 $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
102 checkmessages(DEFAULT_HANDSHAKE, DEFAULT_EXTENSIONS, "Default handshake test");
104 #TODO(TLS1.3): Test temporarily disabled until we implement TLS1.3 resumption
105 #Test 2: Resumption handshake
106 #$proxy->clearClient();
107 #$proxy->clientflags("-sess_in ".$session);
108 #$proxy->clientstart();
109 #checkmessages(RESUME_HANDSHAKE, "Resumption handshake test");
112 #Test 3: A status_request handshake (client request only)
114 $proxy->clientflags("-status");
116 checkmessages(DEFAULT_HANDSHAKE,
117 DEFAULT_EXTENSIONS | STATUS_REQUEST_CLI_EXTENSION,
118 "status_request handshake test (client)");
120 #Test 4: A status_request handshake (server support only)
122 $proxy->serverflags("-status_file "
123 .srctop_file("test", "recipes", "ocsp-response.der"));
125 checkmessages(DEFAULT_HANDSHAKE, DEFAULT_EXTENSIONS,
126 "status_request handshake test (server)");
128 #Test 5: A status_request handshake (client and server)
129 #TODO(TLS1.3): TLS1.3 doesn't actually have CertificateStatus messages. This is
130 #a temporary test until such time as we do proper TLS1.3 style certificate
133 $proxy->clientflags("-status");
134 $proxy->serverflags("-status_file "
135 .srctop_file("test", "recipes", "ocsp-response.der"));
137 checkmessages(OCSP_HANDSHAKE,
138 DEFAULT_EXTENSIONS | STATUS_REQUEST_CLI_EXTENSION
139 | STATUS_REQUEST_SRV_EXTENSION,
140 "status_request handshake test");
142 #Test 6: A client auth handshake
144 $proxy->clientflags("-cert ".srctop_file("apps", "server.pem"));
145 $proxy->serverflags("-Verify 5");
147 checkmessages(CLIENT_AUTH_HANDSHAKE, DEFAULT_EXTENSIONS,
148 "Client auth handshake test");
150 #Test 7: Server name handshake (client request only)
152 $proxy->clientflags("-servername testhost");
154 checkmessages(DEFAULT_HANDSHAKE, DEFAULT_EXTENSIONS | SERVER_NAME_CLI_EXTENSION,
155 "Server name handshake test (client)");
157 #Test 8: Server name handshake (server support only)
159 $proxy->serverflags("-servername testhost");
161 checkmessages(DEFAULT_HANDSHAKE, DEFAULT_EXTENSIONS,
162 "Server name handshake test (server)");
164 #Test 9: Server name handshake (client and server)
166 $proxy->clientflags("-servername testhost");
167 $proxy->serverflags("-servername testhost");
169 checkmessages(DEFAULT_HANDSHAKE,
170 DEFAULT_EXTENSIONS | SERVER_NAME_CLI_EXTENSION
171 | SERVER_NAME_SRV_EXTENSION,
172 "Server name handshake test");
174 #Test 10: ALPN handshake (client request only)
176 $proxy->clientflags("-alpn test");
178 checkmessages(DEFAULT_HANDSHAKE, DEFAULT_EXTENSIONS | ALPN_CLI_EXTENSION,
179 "ALPN handshake test (client)");
181 #Test 11: ALPN handshake (server support only)
183 $proxy->serverflags("-alpn test");
185 checkmessages(DEFAULT_HANDSHAKE, DEFAULT_EXTENSIONS,
186 "ALPN handshake test (server)");
188 #Test 12: ALPN handshake (client and server)
190 $proxy->clientflags("-alpn test");
191 $proxy->serverflags("-alpn test");
193 checkmessages(DEFAULT_HANDSHAKE,
194 DEFAULT_EXTENSIONS | ALPN_CLI_EXTENSION | ALPN_SRV_EXTENSION,
195 "ALPN handshake test");
197 #Test 13: SCT handshake (client request only)
198 #TODO(TLS1.3): This only checks that the client side extension appears. The
199 #SCT extension is unusual in that we have no built-in server side implementation
200 #The server side implementation can nomrally be added using the custom
201 #extensions framework (e.g. by using the "-serverinfo" s_server option). However
202 #currently we only support <= TLS1.2 for custom extensions because the existing
203 #framework and API has no knowledge of the TLS1.3 messages
205 #Note: -ct also sends status_request
206 $proxy->clientflags("-ct");
207 $proxy->serverflags("-status_file "
208 .srctop_file("test", "recipes", "ocsp-response.der"));
210 checkmessages(OCSP_HANDSHAKE,
211 DEFAULT_EXTENSIONS | SCT_CLI_EXTENSION
212 | STATUS_REQUEST_CLI_EXTENSION | STATUS_REQUEST_SRV_EXTENSION,
213 "SCT handshake test");
215 sub checkmessages($$$)
217 my ($handtype, $exttype, $testname) = @_;
219 subtest $testname => sub {
224 #First count the number of tests
225 for ($numtests = 1; $handmessages[$loop][1] != 0; $loop++) {
226 $numtests++ if (($handmessages[$loop][1] & $handtype) != 0);
229 #Add number of extensions we check plus 3 for the number of messages
230 #that contain extensions
231 $numtests += $#extensions + 3;
233 plan tests => $numtests;
236 foreach my $message (@{$proxy->message_list}) {
237 for (; $handmessages[$loop][1] != 0
238 && ($handmessages[$loop][1] & $handtype) == 0; $loop++) {
241 ok($handmessages[$loop][1] != 0
242 && $message->mt == $handmessages[$loop][0],
243 "Message type check. Got ".$message->mt
244 .", expected ".$handmessages[$loop][0]);
248 next if ($message->mt() != TLSProxy::Message::MT_CLIENT_HELLO
249 && $message->mt() != TLSProxy::Message::MT_SERVER_HELLO
251 TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS);
252 #Now check that we saw the extensions we expected
253 my $msgexts = $message->extension_data();
254 for (my $extloop = 0, $extcount = 0; $extensions[$extloop][2] != 0;
256 next if ($message->mt() != $extensions[$extloop][0]);
257 ok (($extensions[$extloop][2] & $exttype) == 0
258 || defined ($msgexts->{$extensions[$extloop][1]}),
259 "Extension presence check (Message: ".$message->mt()
260 ." Extension: ".($extensions[$extloop][2] & $exttype).", "
262 $extcount++ if (($extensions[$extloop][2] & $exttype) != 0);
264 ok($extcount == keys %$msgexts, "Extensions count mismatch ("
265 .$extcount.", ".(keys %$msgexts)
268 ok($handmessages[$loop][1] == 0, "All expected messages processed");