blob: 62db07670ecb24be57552712903c5c057b7ad81e [file] [log] [blame]
Adam Langleyd9e397b2015-01-22 14:27:53 -08001/* Copyright (c) 2014, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15#include <openssl/base.h>
16
17#if !defined(OPENSSL_WINDOWS)
18#include <arpa/inet.h>
19#include <netinet/in.h>
Adam Langleye9ada862015-05-11 17:20:37 -070020#include <netinet/tcp.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080021#include <signal.h>
22#include <sys/socket.h>
Adam Langley4139edb2016-01-13 15:00:54 -080023#include <sys/time.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080024#include <unistd.h>
Adam Langleye9ada862015-05-11 17:20:37 -070025#else
26#include <io.h>
David Benjamin6e899c72016-06-09 18:02:18 -040027OPENSSL_MSVC_PRAGMA(warning(push, 3))
Adam Langleye9ada862015-05-11 17:20:37 -070028#include <winsock2.h>
29#include <ws2tcpip.h>
David Benjamin6e899c72016-06-09 18:02:18 -040030OPENSSL_MSVC_PRAGMA(warning(pop))
Adam Langleye9ada862015-05-11 17:20:37 -070031
David Benjamin95add822016-10-19 01:09:12 -040032OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
Adam Langleyd9e397b2015-01-22 14:27:53 -080033#endif
34
David Benjamin6e899c72016-06-09 18:02:18 -040035#include <assert.h>
Adam Langley4139edb2016-01-13 15:00:54 -080036#include <inttypes.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080037#include <string.h>
Robert Sloana12bf462017-07-17 07:08:26 -070038#include <time.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080039
Steven Valdez909b19f2016-11-21 15:35:44 -050040#include <openssl/aead.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080041#include <openssl/bio.h>
42#include <openssl/buf.h>
43#include <openssl/bytestring.h>
Kenny Rootb8494592015-09-25 02:29:14 +000044#include <openssl/cipher.h>
Kenny Roote99801b2015-11-06 15:31:15 -080045#include <openssl/crypto.h>
David Benjaminf0c4a6c2016-08-11 13:26:41 -040046#include <openssl/digest.h>
Adam Langleye9ada862015-05-11 17:20:37 -070047#include <openssl/err.h>
David Benjaminf0c4a6c2016-08-11 13:26:41 -040048#include <openssl/evp.h>
Kenny Rootb8494592015-09-25 02:29:14 +000049#include <openssl/hmac.h>
David Benjamin4969cc92016-04-22 15:02:23 -040050#include <openssl/nid.h>
Kenny Rootb8494592015-09-25 02:29:14 +000051#include <openssl/rand.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080052#include <openssl/ssl.h>
David Benjaminf0c4a6c2016-08-11 13:26:41 -040053#include <openssl/x509.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080054
Robert Sloan36272962017-10-23 10:28:39 -070055#include <functional>
Adam Langleye9ada862015-05-11 17:20:37 -070056#include <memory>
Kenny Rootb8494592015-09-25 02:29:14 +000057#include <string>
Adam Langleye9ada862015-05-11 17:20:37 -070058#include <vector>
59
David Benjaminf0c4a6c2016-08-11 13:26:41 -040060#include "../../crypto/internal.h"
Robert Sloan8ff03552017-06-14 12:40:58 -070061#include "../internal.h"
Adam Langleyd9e397b2015-01-22 14:27:53 -080062#include "async_bio.h"
Adam Vartanianbfcf3a72018-08-10 14:55:24 +010063#include "handshake_util.h"
Adam Langleyd9e397b2015-01-22 14:27:53 -080064#include "packeted_bio.h"
Adam Vartanianbfcf3a72018-08-10 14:55:24 +010065#include "settings_writer.h"
Adam Langleyd9e397b2015-01-22 14:27:53 -080066#include "test_config.h"
Adam Vartanianbfcf3a72018-08-10 14:55:24 +010067#include "test_state.h"
Adam Langleyd9e397b2015-01-22 14:27:53 -080068
Adam Vartanianbfcf3a72018-08-10 14:55:24 +010069#if defined(OPENSSL_LINUX) && !defined(OPENSSL_ANDROID)
70#define HANDSHAKER_SUPPORTED
71#endif
Adam Langleye9ada862015-05-11 17:20:37 -070072
Steven Valdeze7531f02016-12-14 13:29:57 -050073
Adam Langleye9ada862015-05-11 17:20:37 -070074#if !defined(OPENSSL_WINDOWS)
75static int closesocket(int sock) {
76 return close(sock);
77}
78
79static void PrintSocketError(const char *func) {
80 perror(func);
81}
82#else
83static void PrintSocketError(const char *func) {
84 fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
85}
86#endif
87
88static int Usage(const char *program) {
89 fprintf(stderr, "Usage: %s [flags...]\n", program);
Adam Langleyd9e397b2015-01-22 14:27:53 -080090 return 1;
91}
92
Kenny Rootb8494592015-09-25 02:29:14 +000093template<typename T>
94struct Free {
95 void operator()(T *buf) {
96 free(buf);
97 }
98};
99
Adam Langleye9ada862015-05-11 17:20:37 -0700100// Connect returns a new socket connected to localhost on |port| or -1 on
101// error.
102static int Connect(uint16_t port) {
Robert Sloan8ff03552017-06-14 12:40:58 -0700103 for (int af : { AF_INET6, AF_INET }) {
104 int sock = socket(af, SOCK_STREAM, 0);
105 if (sock == -1) {
106 PrintSocketError("socket");
107 return -1;
108 }
109 int nodelay = 1;
110 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
111 reinterpret_cast<const char*>(&nodelay), sizeof(nodelay)) != 0) {
112 PrintSocketError("setsockopt");
113 closesocket(sock);
114 return -1;
115 }
116
117 sockaddr_storage ss;
118 OPENSSL_memset(&ss, 0, sizeof(ss));
119 ss.ss_family = af;
120 socklen_t len = 0;
121
122 if (af == AF_INET6) {
123 sockaddr_in6 *sin6 = (sockaddr_in6 *) &ss;
124 len = sizeof(*sin6);
125 sin6->sin6_port = htons(port);
126 if (!inet_pton(AF_INET6, "::1", &sin6->sin6_addr)) {
127 PrintSocketError("inet_pton");
128 closesocket(sock);
129 return -1;
130 }
131 } else if (af == AF_INET) {
132 sockaddr_in *sin = (sockaddr_in *) &ss;
133 len = sizeof(*sin);
134 sin->sin_port = htons(port);
135 if (!inet_pton(AF_INET, "127.0.0.1", &sin->sin_addr)) {
136 PrintSocketError("inet_pton");
137 closesocket(sock);
138 return -1;
139 }
140 }
141
142 if (connect(sock, reinterpret_cast<const sockaddr*>(&ss), len) == 0) {
143 return sock;
144 }
Adam Langleye9ada862015-05-11 17:20:37 -0700145 closesocket(sock);
Adam Langleye9ada862015-05-11 17:20:37 -0700146 }
Robert Sloana12bf462017-07-17 07:08:26 -0700147
148 PrintSocketError("connect");
Robert Sloan8ff03552017-06-14 12:40:58 -0700149 return -1;
Adam Langleye9ada862015-05-11 17:20:37 -0700150}
151
152class SocketCloser {
153 public:
154 explicit SocketCloser(int sock) : sock_(sock) {}
155 ~SocketCloser() {
156 // Half-close and drain the socket before releasing it. This seems to be
157 // necessary for graceful shutdown on Windows. It will also avoid write
158 // failures in the test runner.
159#if defined(OPENSSL_WINDOWS)
160 shutdown(sock_, SD_SEND);
161#else
162 shutdown(sock_, SHUT_WR);
163#endif
164 while (true) {
165 char buf[1024];
166 if (recv(sock_, buf, sizeof(buf), 0) <= 0) {
167 break;
168 }
169 }
170 closesocket(sock_);
171 }
172
173 private:
174 const int sock_;
175};
176
Adam Langleye9ada862015-05-11 17:20:37 -0700177// DoRead reads from |ssl|, resolving any asynchronous operations. It returns
178// the result value of the final |SSL_read| call.
179static int DoRead(SSL *ssl, uint8_t *out, size_t max_out) {
David Benjamind316cba2016-06-02 16:17:39 -0400180 const TestConfig *config = GetTestConfig(ssl);
Adam Langleyfad63272015-11-12 12:15:39 -0800181 TestState *test_state = GetTestState(ssl);
Adam Langleye9ada862015-05-11 17:20:37 -0700182 int ret;
183 do {
Adam Langleyfad63272015-11-12 12:15:39 -0800184 if (config->async) {
185 // The DTLS retransmit logic silently ignores write failures. So the test
186 // may progress, allow writes through synchronously. |SSL_read| may
187 // trigger a retransmit, so disconnect the write quota.
188 AsyncBioEnforceWriteQuota(test_state->async_bio, false);
189 }
Robert Sloan36272962017-10-23 10:28:39 -0700190 ret = CheckIdempotentError("SSL_peek/SSL_read", ssl, [&]() -> int {
191 return config->peek_then_read ? SSL_peek(ssl, out, max_out)
192 : SSL_read(ssl, out, max_out);
193 });
Adam Langleyfad63272015-11-12 12:15:39 -0800194 if (config->async) {
195 AsyncBioEnforceWriteQuota(test_state->async_bio, true);
196 }
Steven Valdez909b19f2016-11-21 15:35:44 -0500197
198 // Run the exporter after each read. This is to test that the exporter fails
199 // during a renegotiation.
200 if (config->use_exporter_between_reads) {
201 uint8_t buf;
202 if (!SSL_export_keying_material(ssl, &buf, 1, NULL, 0, NULL, 0, 0)) {
203 fprintf(stderr, "failed to export keying material\n");
204 return -1;
205 }
206 }
Adam Langleye9ada862015-05-11 17:20:37 -0700207 } while (config->async && RetryAsync(ssl, ret));
Steven Valdezbb1ceac2016-10-07 10:34:51 -0400208
209 if (config->peek_then_read && ret > 0) {
210 std::unique_ptr<uint8_t[]> buf(new uint8_t[static_cast<size_t>(ret)]);
211
212 // SSL_peek should synchronously return the same data.
213 int ret2 = SSL_peek(ssl, buf.get(), ret);
214 if (ret2 != ret ||
Robert Sloan69939df2017-01-09 10:53:07 -0800215 OPENSSL_memcmp(buf.get(), out, ret) != 0) {
Steven Valdezbb1ceac2016-10-07 10:34:51 -0400216 fprintf(stderr, "First and second SSL_peek did not match.\n");
217 return -1;
218 }
219
220 // SSL_read should synchronously return the same data and consume it.
221 ret2 = SSL_read(ssl, buf.get(), ret);
222 if (ret2 != ret ||
Robert Sloan69939df2017-01-09 10:53:07 -0800223 OPENSSL_memcmp(buf.get(), out, ret) != 0) {
Steven Valdezbb1ceac2016-10-07 10:34:51 -0400224 fprintf(stderr, "SSL_peek and SSL_read did not match.\n");
225 return -1;
226 }
227 }
228
Adam Langleye9ada862015-05-11 17:20:37 -0700229 return ret;
230}
231
232// WriteAll writes |in_len| bytes from |in| to |ssl|, resolving any asynchronous
233// operations. It returns the result of the final |SSL_write| call.
Robert Sloan572a4e22017-04-17 10:52:19 -0700234static int WriteAll(SSL *ssl, const void *in_, size_t in_len) {
235 const uint8_t *in = reinterpret_cast<const uint8_t *>(in_);
David Benjamind316cba2016-06-02 16:17:39 -0400236 const TestConfig *config = GetTestConfig(ssl);
Adam Langleye9ada862015-05-11 17:20:37 -0700237 int ret;
238 do {
239 ret = SSL_write(ssl, in, in_len);
240 if (ret > 0) {
241 in += ret;
242 in_len -= ret;
243 }
244 } while ((config->async && RetryAsync(ssl, ret)) || (ret > 0 && in_len > 0));
245 return ret;
246}
247
Kenny Rootb8494592015-09-25 02:29:14 +0000248// DoShutdown calls |SSL_shutdown|, resolving any asynchronous operations. It
249// returns the result of the final |SSL_shutdown| call.
250static int DoShutdown(SSL *ssl) {
David Benjamind316cba2016-06-02 16:17:39 -0400251 const TestConfig *config = GetTestConfig(ssl);
Kenny Rootb8494592015-09-25 02:29:14 +0000252 int ret;
253 do {
254 ret = SSL_shutdown(ssl);
255 } while (config->async && RetryAsync(ssl, ret));
256 return ret;
257}
258
David Benjaminc895d6b2016-08-11 13:26:41 -0400259// DoSendFatalAlert calls |SSL_send_fatal_alert|, resolving any asynchronous
260// operations. It returns the result of the final |SSL_send_fatal_alert| call.
261static int DoSendFatalAlert(SSL *ssl, uint8_t alert) {
262 const TestConfig *config = GetTestConfig(ssl);
263 int ret;
264 do {
265 ret = SSL_send_fatal_alert(ssl, alert);
266 } while (config->async && RetryAsync(ssl, ret));
267 return ret;
268}
269
270static uint16_t GetProtocolVersion(const SSL *ssl) {
271 uint16_t version = SSL_version(ssl);
272 if (!SSL_is_dtls(ssl)) {
273 return version;
274 }
275 return 0x0201 + ~version;
276}
277
Robert Sloan8f860b12017-08-28 07:37:06 -0700278// CheckAuthProperties checks, after the initial handshake is completed or
279// after a renegotiation, that authentication-related properties match |config|.
280static bool CheckAuthProperties(SSL *ssl, bool is_resume,
281 const TestConfig *config) {
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000282 if (!config->expected_ocsp_response.empty()) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700283 const uint8_t *data;
284 size_t len;
285 SSL_get0_ocsp_response(ssl, &data, &len);
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000286 if (config->expected_ocsp_response.size() != len ||
287 OPENSSL_memcmp(config->expected_ocsp_response.data(), data, len) != 0) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700288 fprintf(stderr, "OCSP response mismatch\n");
289 return false;
290 }
291 }
292
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000293 if (!config->expected_signed_cert_timestamps.empty()) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700294 const uint8_t *data;
295 size_t len;
296 SSL_get0_signed_cert_timestamp_list(ssl, &data, &len);
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000297 if (config->expected_signed_cert_timestamps.size() != len ||
298 OPENSSL_memcmp(config->expected_signed_cert_timestamps.data(), data,
Robert Sloan8f860b12017-08-28 07:37:06 -0700299 len) != 0) {
300 fprintf(stderr, "SCT list mismatch\n");
301 return false;
302 }
303 }
304
305 if (config->expect_verify_result) {
306 int expected_verify_result = config->verify_fail ?
307 X509_V_ERR_APPLICATION_VERIFICATION :
308 X509_V_OK;
309
310 if (SSL_get_verify_result(ssl) != expected_verify_result) {
311 fprintf(stderr, "Wrong certificate verification result\n");
312 return false;
313 }
314 }
315
316 if (!config->expect_peer_cert_file.empty()) {
317 bssl::UniquePtr<X509> expect_leaf;
318 bssl::UniquePtr<STACK_OF(X509)> expect_chain;
319 if (!LoadCertificate(&expect_leaf, &expect_chain,
320 config->expect_peer_cert_file)) {
321 return false;
322 }
323
324 // For historical reasons, clients report a chain with a leaf and servers
325 // without.
326 if (!config->is_server) {
327 if (!sk_X509_insert(expect_chain.get(), expect_leaf.get(), 0)) {
328 return false;
329 }
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100330 X509_up_ref(expect_leaf.get()); // sk_X509_insert takes ownership.
Robert Sloan8f860b12017-08-28 07:37:06 -0700331 }
332
333 bssl::UniquePtr<X509> leaf(SSL_get_peer_certificate(ssl));
334 STACK_OF(X509) *chain = SSL_get_peer_cert_chain(ssl);
335 if (X509_cmp(leaf.get(), expect_leaf.get()) != 0) {
336 fprintf(stderr, "Received a different leaf certificate than expected.\n");
337 return false;
338 }
339
340 if (sk_X509_num(chain) != sk_X509_num(expect_chain.get())) {
341 fprintf(stderr, "Received a chain of length %zu instead of %zu.\n",
342 sk_X509_num(chain), sk_X509_num(expect_chain.get()));
343 return false;
344 }
345
346 for (size_t i = 0; i < sk_X509_num(chain); i++) {
347 if (X509_cmp(sk_X509_value(chain, i),
348 sk_X509_value(expect_chain.get(), i)) != 0) {
349 fprintf(stderr, "Chain certificate %zu did not match.\n",
350 i + 1);
351 return false;
352 }
353 }
354 }
355
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100356 if (!!SSL_SESSION_has_peer_sha256(SSL_get_session(ssl)) !=
Robert Sloan8f860b12017-08-28 07:37:06 -0700357 config->expect_sha256_client_cert) {
358 fprintf(stderr,
359 "Unexpected SHA-256 client cert state: expected:%d is_resume:%d.\n",
360 config->expect_sha256_client_cert, is_resume);
361 return false;
362 }
363
364 if (config->expect_sha256_client_cert &&
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100365 SSL_SESSION_get0_peer_certificates(SSL_get_session(ssl)) != nullptr) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700366 fprintf(stderr, "Have both client cert and SHA-256 hash: is_resume:%d.\n",
367 is_resume);
368 return false;
369 }
370
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100371 const uint8_t *peer_sha256;
372 size_t peer_sha256_len;
373 SSL_SESSION_get0_peer_sha256(SSL_get_session(ssl), &peer_sha256,
374 &peer_sha256_len);
375 if (SSL_SESSION_has_peer_sha256(SSL_get_session(ssl))) {
376 if (peer_sha256_len != 32) {
377 fprintf(stderr, "Peer SHA-256 hash had length %zu instead of 32\n",
378 peer_sha256_len);
379 return false;
380 }
381 } else {
382 if (peer_sha256_len != 0) {
383 fprintf(stderr, "Unexpected peer SHA-256 hash of length %zu\n",
384 peer_sha256_len);
385 return false;
386 }
387 }
388
Robert Sloan8f860b12017-08-28 07:37:06 -0700389 return true;
390}
391
Kenny Rootb8494592015-09-25 02:29:14 +0000392// CheckHandshakeProperties checks, immediately after |ssl| completes its
393// initial handshake (or False Starts), whether all the properties are
394// consistent with the test configuration and invariants.
Robert Sloane56da3e2017-06-26 08:26:42 -0700395static bool CheckHandshakeProperties(SSL *ssl, bool is_resume,
396 const TestConfig *config) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700397 if (!CheckAuthProperties(ssl, is_resume, config)) {
398 return false;
399 }
400
Kenny Rootb8494592015-09-25 02:29:14 +0000401 if (SSL_get_current_cipher(ssl) == nullptr) {
402 fprintf(stderr, "null cipher after handshake\n");
403 return false;
404 }
405
Robert Sloanf6200e72017-07-10 08:09:18 -0700406 if (config->expect_version != 0 &&
407 SSL_version(ssl) != config->expect_version) {
408 fprintf(stderr, "want version %04x, got %04x\n", config->expect_version,
409 SSL_version(ssl));
410 return false;
411 }
412
Robert Sloane56da3e2017-06-26 08:26:42 -0700413 bool expect_resume =
414 is_resume && (!config->expect_session_miss || SSL_in_early_data(ssl));
415 if (!!SSL_session_reused(ssl) != expect_resume) {
416 fprintf(stderr, "session unexpectedly was%s reused\n",
Kenny Rootb8494592015-09-25 02:29:14 +0000417 SSL_session_reused(ssl) ? "" : " not");
418 return false;
419 }
420
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700421 bool expect_handshake_done =
Robert Sloane56da3e2017-06-26 08:26:42 -0700422 (is_resume || !config->false_start) && !SSL_in_early_data(ssl);
Kenny Rootb8494592015-09-25 02:29:14 +0000423 if (expect_handshake_done != GetTestState(ssl)->handshake_done) {
424 fprintf(stderr, "handshake was%s completed\n",
425 GetTestState(ssl)->handshake_done ? "" : " not");
426 return false;
427 }
428
429 if (expect_handshake_done && !config->is_server) {
430 bool expect_new_session =
431 !config->expect_no_session &&
David Benjaminc895d6b2016-08-11 13:26:41 -0400432 (!SSL_session_reused(ssl) || config->expect_ticket_renewal) &&
433 // Session tickets are sent post-handshake in TLS 1.3.
434 GetProtocolVersion(ssl) < TLS1_3_VERSION;
Kenny Rootb8494592015-09-25 02:29:14 +0000435 if (expect_new_session != GetTestState(ssl)->got_new_session) {
436 fprintf(stderr,
Kenny Roote99801b2015-11-06 15:31:15 -0800437 "new session was%s cached, but we expected the opposite\n",
Kenny Rootb8494592015-09-25 02:29:14 +0000438 GetTestState(ssl)->got_new_session ? "" : " not");
439 return false;
440 }
441 }
442
Robert Sloan4d1ac502017-02-06 08:36:14 -0800443 if (!is_resume) {
444 if (config->expect_session_id && !GetTestState(ssl)->got_new_session) {
445 fprintf(stderr, "session was not cached on the server.\n");
446 return false;
447 }
448 if (config->expect_no_session_id && GetTestState(ssl)->got_new_session) {
449 fprintf(stderr, "session was unexpectedly cached on the server.\n");
450 return false;
451 }
452 }
453
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100454 // early_callback_called is updated in the handshaker, so we don't see it
455 // here.
456 if (!config->handoff && config->is_server &&
457 !GetTestState(ssl)->early_callback_called) {
Kenny Rootb8494592015-09-25 02:29:14 +0000458 fprintf(stderr, "early callback not called\n");
459 return false;
460 }
461
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000462 if (!config->expected_server_name.empty()) {
Kenny Rootb8494592015-09-25 02:29:14 +0000463 const char *server_name =
464 SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Steven Valdez909b19f2016-11-21 15:35:44 -0500465 if (server_name == nullptr ||
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000466 server_name != config->expected_server_name) {
Kenny Rootb8494592015-09-25 02:29:14 +0000467 fprintf(stderr, "servername mismatch (got %s; want %s)\n",
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000468 server_name, config->expected_server_name.c_str());
Kenny Rootb8494592015-09-25 02:29:14 +0000469 return false;
470 }
471 }
472
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000473 if (!config->expected_next_proto.empty()) {
Kenny Rootb8494592015-09-25 02:29:14 +0000474 const uint8_t *next_proto;
475 unsigned next_proto_len;
476 SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000477 if (next_proto_len != config->expected_next_proto.size() ||
478 OPENSSL_memcmp(next_proto, config->expected_next_proto.data(),
Robert Sloan69939df2017-01-09 10:53:07 -0800479 next_proto_len) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000480 fprintf(stderr, "negotiated next proto mismatch\n");
481 return false;
482 }
483 }
484
Robert Sloan8ff03552017-06-14 12:40:58 -0700485 if (!config->is_server) {
Kenny Rootb8494592015-09-25 02:29:14 +0000486 const uint8_t *alpn_proto;
487 unsigned alpn_proto_len;
488 SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len);
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000489 if (alpn_proto_len != config->expected_alpn.size() ||
490 OPENSSL_memcmp(alpn_proto, config->expected_alpn.data(),
Robert Sloan8ff03552017-06-14 12:40:58 -0700491 alpn_proto_len) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000492 fprintf(stderr, "negotiated alpn proto mismatch\n");
493 return false;
494 }
495 }
496
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000497 if (!config->expected_quic_transport_params.empty()) {
Robert Sloan8542c082018-02-05 09:07:34 -0800498 const uint8_t *peer_params;
499 size_t peer_params_len;
500 SSL_get_peer_quic_transport_params(ssl, &peer_params, &peer_params_len);
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000501 if (peer_params_len != config->expected_quic_transport_params.size() ||
Robert Sloan8542c082018-02-05 09:07:34 -0800502 OPENSSL_memcmp(peer_params,
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000503 config->expected_quic_transport_params.data(),
Robert Sloan8542c082018-02-05 09:07:34 -0800504 peer_params_len) != 0) {
505 fprintf(stderr, "QUIC transport params mismatch\n");
506 return false;
507 }
508 }
509
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000510 if (!config->expected_channel_id.empty()) {
Kenny Rootb8494592015-09-25 02:29:14 +0000511 uint8_t channel_id[64];
512 if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) {
513 fprintf(stderr, "no channel id negotiated\n");
514 return false;
515 }
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000516 if (config->expected_channel_id.size() != 64 ||
517 OPENSSL_memcmp(config->expected_channel_id.data(), channel_id, 64) !=
Robert Sloan69939df2017-01-09 10:53:07 -0800518 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000519 fprintf(stderr, "channel id mismatch\n");
520 return false;
521 }
522 }
523
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000524 if (config->expected_token_binding_param != -1) {
Robert Sloan978112c2018-01-22 12:53:01 -0800525 if (!SSL_is_token_binding_negotiated(ssl)) {
526 fprintf(stderr, "no Token Binding negotiated\n");
527 return false;
528 }
529 if (SSL_get_negotiated_token_binding_param(ssl) !=
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000530 static_cast<uint8_t>(config->expected_token_binding_param)) {
Robert Sloan978112c2018-01-22 12:53:01 -0800531 fprintf(stderr, "Token Binding param mismatch\n");
532 return false;
533 }
534 }
535
Steven Valdezb0b45c62017-01-17 16:23:54 -0500536 if (config->expect_extended_master_secret && !SSL_get_extms_support(ssl)) {
537 fprintf(stderr, "No EMS for connection when expected\n");
538 return false;
539 }
540
541 if (config->expect_secure_renegotiation &&
542 !SSL_get_secure_renegotiation_support(ssl)) {
543 fprintf(stderr, "No secure renegotiation for connection when expected\n");
544 return false;
545 }
546
547 if (config->expect_no_secure_renegotiation &&
548 SSL_get_secure_renegotiation_support(ssl)) {
549 fprintf(stderr,
550 "Secure renegotiation unexpectedly negotiated for connection\n");
551 return false;
Kenny Rootb8494592015-09-25 02:29:14 +0000552 }
553
David Benjaminc895d6b2016-08-11 13:26:41 -0400554 if (config->expect_peer_signature_algorithm != 0 &&
555 config->expect_peer_signature_algorithm !=
556 SSL_get_peer_signature_algorithm(ssl)) {
557 fprintf(stderr, "Peer signature algorithm was %04x, wanted %04x.\n",
558 SSL_get_peer_signature_algorithm(ssl),
559 config->expect_peer_signature_algorithm);
Adam Langleyfad63272015-11-12 12:15:39 -0800560 return false;
561 }
562
Robert Sloan8ff03552017-06-14 12:40:58 -0700563 if (config->expect_curve_id != 0) {
Steven Valdeze7531f02016-12-14 13:29:57 -0500564 uint16_t curve_id = SSL_get_curve_id(ssl);
Robert Sloan8ff03552017-06-14 12:40:58 -0700565 if (static_cast<uint16_t>(config->expect_curve_id) != curve_id) {
Steven Valdeze7531f02016-12-14 13:29:57 -0500566 fprintf(stderr, "curve_id was %04x, wanted %04x\n", curve_id,
Robert Sloan8ff03552017-06-14 12:40:58 -0700567 static_cast<uint16_t>(config->expect_curve_id));
Kenny Rootb8494592015-09-25 02:29:14 +0000568 return false;
569 }
570 }
David Benjaminc895d6b2016-08-11 13:26:41 -0400571
Steven Valdez909b19f2016-11-21 15:35:44 -0500572 uint16_t cipher_id =
573 static_cast<uint16_t>(SSL_CIPHER_get_id(SSL_get_current_cipher(ssl)));
574 if (config->expect_cipher_aes != 0 &&
575 EVP_has_aes_hardware() &&
576 static_cast<uint16_t>(config->expect_cipher_aes) != cipher_id) {
577 fprintf(stderr, "Cipher ID was %04x, wanted %04x (has AES hardware)\n",
578 cipher_id, static_cast<uint16_t>(config->expect_cipher_aes));
579 return false;
580 }
581
582 if (config->expect_cipher_no_aes != 0 &&
583 !EVP_has_aes_hardware() &&
584 static_cast<uint16_t>(config->expect_cipher_no_aes) != cipher_id) {
585 fprintf(stderr, "Cipher ID was %04x, wanted %04x (no AES hardware)\n",
586 cipher_id, static_cast<uint16_t>(config->expect_cipher_no_aes));
587 return false;
588 }
589
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000590 if (is_resume && !SSL_in_early_data(ssl)) {
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700591 if ((config->expect_accept_early_data && !SSL_early_data_accepted(ssl)) ||
592 (config->expect_reject_early_data && SSL_early_data_accepted(ssl))) {
593 fprintf(stderr,
594 "Early data was%s accepted, but we expected the opposite\n",
595 SSL_early_data_accepted(ssl) ? "" : " not");
596 return false;
597 }
598 }
Steven Valdez909b19f2016-11-21 15:35:44 -0500599
David Benjaminc895d6b2016-08-11 13:26:41 -0400600 if (!config->psk.empty()) {
601 if (SSL_get_peer_cert_chain(ssl) != nullptr) {
602 fprintf(stderr, "Received peer certificate on a PSK cipher.\n");
603 return false;
604 }
605 } else if (!config->is_server || config->require_any_client_certificate) {
606 if (SSL_get_peer_cert_chain(ssl) == nullptr) {
607 fprintf(stderr, "Received no peer certificate but expected one.\n");
608 return false;
609 }
610 }
611
Robert Sloan1c9db532017-03-13 08:03:59 -0700612 if (is_resume && config->expect_ticket_age_skew != 0 &&
613 SSL_get_ticket_age_skew(ssl) != config->expect_ticket_age_skew) {
614 fprintf(stderr, "Ticket age skew was %" PRId32 ", wanted %d\n",
615 SSL_get_ticket_age_skew(ssl), config->expect_ticket_age_skew);
616 return false;
617 }
618
Robert Sloand9e572d2018-08-27 12:27:00 -0700619 if (config->expect_tls13_downgrade != !!SSL_is_tls13_downgrade(ssl)) {
620 fprintf(stderr, "Got %s downgrade signal, but wanted the opposite.\n",
621 SSL_is_tls13_downgrade(ssl) ? "" : "no ");
Robert Sloanab8b8882018-03-26 11:39:51 -0700622 return false;
Robert Sloan0da43952018-01-03 15:13:14 -0800623 }
624
Kenny Rootb8494592015-09-25 02:29:14 +0000625 return true;
626}
627
Robert Sloandc2f6092018-04-10 10:22:33 -0700628static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
629 bssl::UniquePtr<SSL> *ssl_uniqueptr,
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100630 const TestConfig *config, bool is_resume, bool is_retry,
631 SettingsWriter *writer);
Robert Sloandc2f6092018-04-10 10:22:33 -0700632
633// DoConnection tests an SSL connection against the peer. On success, it returns
634// true and sets |*out_session| to the negotiated SSL session. If the test is a
635// resumption attempt, |is_resume| is true and |session| is the session from the
636// previous exchange.
637static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
638 SSL_CTX *ssl_ctx, const TestConfig *config,
639 const TestConfig *retry_config, bool is_resume,
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100640 SSL_SESSION *session, SettingsWriter *writer) {
641 bssl::UniquePtr<SSL> ssl = config->NewSSL(
642 ssl_ctx, session, is_resume, std::unique_ptr<TestState>(new TestState));
Robert Sloandc2f6092018-04-10 10:22:33 -0700643 if (!ssl) {
644 return false;
645 }
646 if (config->is_server) {
647 SSL_set_accept_state(ssl.get());
648 } else {
649 SSL_set_connect_state(ssl.get());
650 }
651
Adam Langleye9ada862015-05-11 17:20:37 -0700652 int sock = Connect(config->port);
653 if (sock == -1) {
654 return false;
655 }
656 SocketCloser closer(sock);
657
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400658 bssl::UniquePtr<BIO> bio(BIO_new_socket(sock, BIO_NOCLOSE));
Adam Langleye9ada862015-05-11 17:20:37 -0700659 if (!bio) {
660 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800661 }
662 if (config->is_dtls) {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100663 bssl::UniquePtr<BIO> packeted = PacketedBioCreate(GetClock());
David Benjamin4969cc92016-04-22 15:02:23 -0400664 if (!packeted) {
665 return false;
666 }
David Benjamin6e899c72016-06-09 18:02:18 -0400667 GetTestState(ssl.get())->packeted_bio = packeted.get();
Adam Langleye9ada862015-05-11 17:20:37 -0700668 BIO_push(packeted.get(), bio.release());
669 bio = std::move(packeted);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800670 }
671 if (config->async) {
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400672 bssl::UniquePtr<BIO> async_scoped =
Adam Langleye9ada862015-05-11 17:20:37 -0700673 config->is_dtls ? AsyncBioCreateDatagram() : AsyncBioCreate();
David Benjamin4969cc92016-04-22 15:02:23 -0400674 if (!async_scoped) {
675 return false;
676 }
Adam Langleye9ada862015-05-11 17:20:37 -0700677 BIO_push(async_scoped.get(), bio.release());
678 GetTestState(ssl.get())->async_bio = async_scoped.get();
679 bio = std::move(async_scoped);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800680 }
Adam Langleye9ada862015-05-11 17:20:37 -0700681 SSL_set_bio(ssl.get(), bio.get(), bio.get());
682 bio.release(); // SSL_set_bio takes ownership.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800683
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100684 bool ret = DoExchange(out_session, &ssl, config, is_resume, false, writer);
Robert Sloane56da3e2017-06-26 08:26:42 -0700685 if (!config->is_server && is_resume && config->expect_reject_early_data) {
686 // We must have failed due to an early data rejection.
687 if (ret) {
688 fprintf(stderr, "0-RTT exchange unexpected succeeded.\n");
689 return false;
690 }
691 if (SSL_get_error(ssl.get(), -1) != SSL_ERROR_EARLY_DATA_REJECTED) {
692 fprintf(stderr,
693 "SSL_get_error did not signal SSL_ERROR_EARLY_DATA_REJECTED.\n");
694 return false;
695 }
696
697 // Before reseting, early state should still be available.
698 if (!SSL_in_early_data(ssl.get()) ||
699 !CheckHandshakeProperties(ssl.get(), is_resume, config)) {
700 fprintf(stderr, "SSL_in_early_data returned false before reset.\n");
701 return false;
702 }
703
704 // Reset the connection and try again at 1-RTT.
705 SSL_reset_early_data_reject(ssl.get());
Robert Sloanc9abfe42018-11-26 12:19:07 -0800706 GetTestState(ssl.get())->cert_verified = false;
Robert Sloane56da3e2017-06-26 08:26:42 -0700707
708 // After reseting, the socket should report it is no longer in an early data
709 // state.
710 if (SSL_in_early_data(ssl.get())) {
711 fprintf(stderr, "SSL_in_early_data returned true after reset.\n");
712 return false;
713 }
714
715 if (!SetTestConfig(ssl.get(), retry_config)) {
716 return false;
717 }
718
Robert Sloan8542c082018-02-05 09:07:34 -0800719 assert(!config->handoff);
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100720 ret = DoExchange(out_session, &ssl, retry_config, is_resume, true, writer);
Robert Sloane56da3e2017-06-26 08:26:42 -0700721 }
Robert Sloanfe7cd212017-08-07 09:03:39 -0700722
723 if (!ret) {
724 return false;
725 }
726
727 if (!GetTestState(ssl.get())->msg_callback_ok) {
728 return false;
729 }
730
731 if (!config->expect_msg_callback.empty() &&
732 GetTestState(ssl.get())->msg_callback_text !=
733 config->expect_msg_callback) {
734 fprintf(stderr, "Bad message callback trace. Wanted:\n%s\nGot:\n%s\n",
735 config->expect_msg_callback.c_str(),
736 GetTestState(ssl.get())->msg_callback_text.c_str());
737 return false;
738 }
739
740 return true;
Robert Sloane56da3e2017-06-26 08:26:42 -0700741}
742
Robert Sloan8542c082018-02-05 09:07:34 -0800743static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
744 bssl::UniquePtr<SSL> *ssl_uniqueptr,
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100745 const TestConfig *config, bool is_resume, bool is_retry,
746 SettingsWriter *writer) {
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700747 int ret;
Robert Sloan8542c082018-02-05 09:07:34 -0800748 SSL *ssl = ssl_uniqueptr->get();
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100749 SSL_CTX *session_ctx = SSL_get_SSL_CTX(ssl);
Robert Sloan8542c082018-02-05 09:07:34 -0800750
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700751 if (!config->implicit_handshake) {
Robert Sloan8542c082018-02-05 09:07:34 -0800752 if (config->handoff) {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100753#if defined(HANDSHAKER_SUPPORTED)
754 if (!DoSplitHandshake(ssl_uniqueptr, writer, is_resume)) {
Robert Sloan8542c082018-02-05 09:07:34 -0800755 return false;
756 }
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100757 ssl = ssl_uniqueptr->get();
758#else
759 fprintf(stderr, "The external handshaker can only be used on Linux\n");
760 return false;
761#endif
Robert Sloan8542c082018-02-05 09:07:34 -0800762 }
763
Adam Langleye9ada862015-05-11 17:20:37 -0700764 do {
Robert Sloan36272962017-10-23 10:28:39 -0700765 ret = CheckIdempotentError("SSL_do_handshake", ssl, [&]() -> int {
766 return SSL_do_handshake(ssl);
767 });
Robert Sloane56da3e2017-06-26 08:26:42 -0700768 } while (config->async && RetryAsync(ssl, ret));
Robert Sloan8542c082018-02-05 09:07:34 -0800769
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100770 if (config->forbid_renegotiation_after_handshake) {
771 SSL_set_renegotiate_mode(ssl, ssl_renegotiate_never);
Robert Sloan8542c082018-02-05 09:07:34 -0800772 }
773
Robert Sloandc2f6092018-04-10 10:22:33 -0700774 if (ret != 1 || !CheckHandshakeProperties(ssl, is_resume, config)) {
775 return false;
776 }
777
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100778 CopySessions(session_ctx, SSL_get_SSL_CTX(ssl));
Robert Sloandc2f6092018-04-10 10:22:33 -0700779
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700780 if (is_resume && !is_retry && !config->is_server &&
781 config->expect_no_offer_early_data && SSL_in_early_data(ssl)) {
782 fprintf(stderr, "Client unexpectedly offered early data.\n");
783 return false;
784 }
785
Robert Sloan6f79a502017-04-03 09:16:40 -0700786 if (config->handshake_twice) {
787 do {
Robert Sloane56da3e2017-06-26 08:26:42 -0700788 ret = SSL_do_handshake(ssl);
789 } while (config->async && RetryAsync(ssl, ret));
Robert Sloan6f79a502017-04-03 09:16:40 -0700790 if (ret != 1) {
791 return false;
792 }
793 }
794
795 // Skip the |config->async| logic as this should be a no-op.
796 if (config->no_op_extra_handshake &&
Robert Sloane56da3e2017-06-26 08:26:42 -0700797 SSL_do_handshake(ssl) != 1) {
Robert Sloan6f79a502017-04-03 09:16:40 -0700798 fprintf(stderr, "Extra SSL_do_handshake was not a no-op.\n");
799 return false;
800 }
801
Kenny Rootb8494592015-09-25 02:29:14 +0000802 // Reset the state to assert later that the callback isn't called in
803 // renegotations.
Robert Sloane56da3e2017-06-26 08:26:42 -0700804 GetTestState(ssl)->got_new_session = false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800805 }
806
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000807 if (config->export_early_keying_material > 0) {
808 std::vector<uint8_t> result(
809 static_cast<size_t>(config->export_early_keying_material));
810 if (!SSL_export_early_keying_material(
811 ssl, result.data(), result.size(), config->export_label.data(),
812 config->export_label.size(),
813 reinterpret_cast<const uint8_t *>(config->export_context.data()),
814 config->export_context.size())) {
815 fprintf(stderr, "failed to export keying material\n");
816 return false;
817 }
818 if (WriteAll(ssl, result.data(), result.size()) < 0) {
819 return false;
820 }
821 }
822
Adam Langleye9ada862015-05-11 17:20:37 -0700823 if (config->export_keying_material > 0) {
824 std::vector<uint8_t> result(
825 static_cast<size_t>(config->export_keying_material));
826 if (!SSL_export_keying_material(
Robert Sloane56da3e2017-06-26 08:26:42 -0700827 ssl, result.data(), result.size(), config->export_label.data(),
828 config->export_label.size(),
829 reinterpret_cast<const uint8_t *>(config->export_context.data()),
Adam Langleye9ada862015-05-11 17:20:37 -0700830 config->export_context.size(), config->use_export_context)) {
831 fprintf(stderr, "failed to export keying material\n");
832 return false;
833 }
Robert Sloane56da3e2017-06-26 08:26:42 -0700834 if (WriteAll(ssl, result.data(), result.size()) < 0) {
Adam Langleye9ada862015-05-11 17:20:37 -0700835 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800836 }
837 }
838
Robert Sloan11c28bd2018-12-17 12:09:20 -0800839 if (config->export_traffic_secrets) {
840 bssl::Span<const uint8_t> read_secret, write_secret;
841 if (!SSL_get_traffic_secrets(ssl, &read_secret, &write_secret)) {
842 fprintf(stderr, "failed to export traffic secrets\n");
843 return false;
844 }
845
846 assert(read_secret.size() <= 0xffff);
847 assert(write_secret.size() == read_secret.size());
848 const uint16_t secret_len = read_secret.size();
849 if (WriteAll(ssl, &secret_len, sizeof(secret_len)) < 0 ||
850 WriteAll(ssl, read_secret.data(), read_secret.size()) < 0 ||
851 WriteAll(ssl, write_secret.data(), write_secret.size()) < 0) {
852 return false;
853 }
854 }
855
Adam Langleyf4e42722015-06-04 17:45:09 -0700856 if (config->tls_unique) {
857 uint8_t tls_unique[16];
858 size_t tls_unique_len;
Robert Sloane56da3e2017-06-26 08:26:42 -0700859 if (!SSL_get_tls_unique(ssl, tls_unique, &tls_unique_len,
Adam Langleyf4e42722015-06-04 17:45:09 -0700860 sizeof(tls_unique))) {
861 fprintf(stderr, "failed to get tls-unique\n");
862 return false;
863 }
864
865 if (tls_unique_len != 12) {
866 fprintf(stderr, "expected 12 bytes of tls-unique but got %u",
867 static_cast<unsigned>(tls_unique_len));
868 return false;
869 }
870
Robert Sloane56da3e2017-06-26 08:26:42 -0700871 if (WriteAll(ssl, tls_unique, tls_unique_len) < 0) {
Adam Langleyf4e42722015-06-04 17:45:09 -0700872 return false;
873 }
874 }
875
David Benjaminc895d6b2016-08-11 13:26:41 -0400876 if (config->send_alert) {
Robert Sloane56da3e2017-06-26 08:26:42 -0700877 if (DoSendFatalAlert(ssl, SSL_AD_DECOMPRESSION_FAILURE) < 0) {
David Benjaminc895d6b2016-08-11 13:26:41 -0400878 return false;
879 }
880 return true;
881 }
882
Adam Langleyd9e397b2015-01-22 14:27:53 -0800883 if (config->write_different_record_sizes) {
884 if (config->is_dtls) {
885 fprintf(stderr, "write_different_record_sizes not supported for DTLS\n");
Adam Langleye9ada862015-05-11 17:20:37 -0700886 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800887 }
888 // This mode writes a number of different record sizes in an attempt to
889 // trip up the CBC record splitting code.
Kenny Rootb8494592015-09-25 02:29:14 +0000890 static const size_t kBufLen = 32769;
891 std::unique_ptr<uint8_t[]> buf(new uint8_t[kBufLen]);
Robert Sloan69939df2017-01-09 10:53:07 -0800892 OPENSSL_memset(buf.get(), 0x42, kBufLen);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800893 static const size_t kRecordSizes[] = {
894 0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769};
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400895 for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kRecordSizes); i++) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800896 const size_t len = kRecordSizes[i];
Kenny Rootb8494592015-09-25 02:29:14 +0000897 if (len > kBufLen) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800898 fprintf(stderr, "Bad kRecordSizes value.\n");
Adam Langleye9ada862015-05-11 17:20:37 -0700899 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800900 }
Robert Sloane56da3e2017-06-26 08:26:42 -0700901 if (WriteAll(ssl, buf.get(), len) < 0) {
Adam Langleye9ada862015-05-11 17:20:37 -0700902 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800903 }
904 }
905 } else {
Robert Sloan572a4e22017-04-17 10:52:19 -0700906 static const char kInitialWrite[] = "hello";
907 bool pending_initial_write = false;
Robert Sloan69939df2017-01-09 10:53:07 -0800908 if (config->read_with_unfinished_write) {
909 if (!config->async) {
910 fprintf(stderr, "-read-with-unfinished-write requires -async.\n");
911 return false;
912 }
913
Robert Sloane56da3e2017-06-26 08:26:42 -0700914 // Let only one byte of the record through.
915 AsyncBioAllowWrite(GetTestState(ssl)->async_bio, 1);
Robert Sloan572a4e22017-04-17 10:52:19 -0700916 int write_ret =
Robert Sloane56da3e2017-06-26 08:26:42 -0700917 SSL_write(ssl, kInitialWrite, strlen(kInitialWrite));
918 if (SSL_get_error(ssl, write_ret) != SSL_ERROR_WANT_WRITE) {
Robert Sloan69939df2017-01-09 10:53:07 -0800919 fprintf(stderr, "Failed to leave unfinished write.\n");
920 return false;
921 }
Robert Sloan572a4e22017-04-17 10:52:19 -0700922 pending_initial_write = true;
923 } else if (config->shim_writes_first) {
Robert Sloane56da3e2017-06-26 08:26:42 -0700924 if (WriteAll(ssl, kInitialWrite, strlen(kInitialWrite)) < 0) {
Adam Langleye9ada862015-05-11 17:20:37 -0700925 return false;
926 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800927 }
Kenny Rootb8494592015-09-25 02:29:14 +0000928 if (!config->shim_shuts_down) {
929 for (;;) {
Kenny Rootb8494592015-09-25 02:29:14 +0000930 // Read only 512 bytes at a time in TLS to ensure records may be
931 // returned in multiple reads.
Steven Valdezb0b45c62017-01-17 16:23:54 -0500932 size_t read_size = config->is_dtls ? 16384 : 512;
933 if (config->read_size > 0) {
934 read_size = config->read_size;
935 }
936 std::unique_ptr<uint8_t[]> buf(new uint8_t[read_size]);
937
Robert Sloane56da3e2017-06-26 08:26:42 -0700938 int n = DoRead(ssl, buf.get(), read_size);
939 int err = SSL_get_error(ssl, n);
Kenny Rootb8494592015-09-25 02:29:14 +0000940 if (err == SSL_ERROR_ZERO_RETURN ||
941 (n == 0 && err == SSL_ERROR_SYSCALL)) {
942 if (n != 0) {
943 fprintf(stderr, "Invalid SSL_get_error output\n");
944 return false;
945 }
946 // Stop on either clean or unclean shutdown.
947 break;
948 } else if (err != SSL_ERROR_NONE) {
949 if (n > 0) {
950 fprintf(stderr, "Invalid SSL_get_error output\n");
951 return false;
952 }
953 return false;
954 }
955 // Successfully read data.
956 if (n <= 0) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800957 fprintf(stderr, "Invalid SSL_get_error output\n");
Adam Langleye9ada862015-05-11 17:20:37 -0700958 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800959 }
Kenny Rootb8494592015-09-25 02:29:14 +0000960
Robert Sloane56da3e2017-06-26 08:26:42 -0700961 if (!config->is_server && is_resume && !is_retry &&
962 config->expect_reject_early_data) {
963 fprintf(stderr,
964 "Unexpectedly received data instead of 0-RTT reject.\n");
965 return false;
966 }
967
Kenny Rootb8494592015-09-25 02:29:14 +0000968 // After a successful read, with or without False Start, the handshake
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700969 // must be complete unless we are doing early data.
Robert Sloane56da3e2017-06-26 08:26:42 -0700970 if (!GetTestState(ssl)->handshake_done &&
971 !SSL_early_data_accepted(ssl)) {
Kenny Rootb8494592015-09-25 02:29:14 +0000972 fprintf(stderr, "handshake was not completed after SSL_read\n");
Adam Langleye9ada862015-05-11 17:20:37 -0700973 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800974 }
Adam Langleye9ada862015-05-11 17:20:37 -0700975
Robert Sloan572a4e22017-04-17 10:52:19 -0700976 // Clear the initial write, if unfinished.
977 if (pending_initial_write) {
Robert Sloane56da3e2017-06-26 08:26:42 -0700978 if (WriteAll(ssl, kInitialWrite, strlen(kInitialWrite)) < 0) {
Robert Sloan572a4e22017-04-17 10:52:19 -0700979 return false;
980 }
981 pending_initial_write = false;
982 }
983
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800984 if (config->key_update &&
985 !SSL_key_update(ssl, SSL_KEY_UPDATE_NOT_REQUESTED)) {
986 fprintf(stderr, "SSL_key_update failed.\n");
987 return false;
988 }
989
Kenny Rootb8494592015-09-25 02:29:14 +0000990 for (int i = 0; i < n; i++) {
991 buf[i] ^= 0xff;
992 }
Robert Sloane56da3e2017-06-26 08:26:42 -0700993 if (WriteAll(ssl, buf.get(), n) < 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000994 return false;
995 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800996 }
997 }
998 }
999
Kenny Rootb8494592015-09-25 02:29:14 +00001000 if (!config->is_server && !config->false_start &&
1001 !config->implicit_handshake &&
David Benjaminc895d6b2016-08-11 13:26:41 -04001002 // Session tickets are sent post-handshake in TLS 1.3.
Robert Sloane56da3e2017-06-26 08:26:42 -07001003 GetProtocolVersion(ssl) < TLS1_3_VERSION &&
1004 GetTestState(ssl)->got_new_session) {
Kenny Rootb8494592015-09-25 02:29:14 +00001005 fprintf(stderr, "new session was established after the handshake\n");
1006 return false;
1007 }
1008
Robert Sloane56da3e2017-06-26 08:26:42 -07001009 if (GetProtocolVersion(ssl) >= TLS1_3_VERSION && !config->is_server) {
David Benjaminc895d6b2016-08-11 13:26:41 -04001010 bool expect_new_session =
1011 !config->expect_no_session && !config->shim_shuts_down;
Robert Sloane56da3e2017-06-26 08:26:42 -07001012 if (expect_new_session != GetTestState(ssl)->got_new_session) {
David Benjaminc895d6b2016-08-11 13:26:41 -04001013 fprintf(stderr,
1014 "new session was%s cached, but we expected the opposite\n",
Robert Sloane56da3e2017-06-26 08:26:42 -07001015 GetTestState(ssl)->got_new_session ? "" : " not");
David Benjaminc895d6b2016-08-11 13:26:41 -04001016 return false;
1017 }
Robert Sloan69939df2017-01-09 10:53:07 -08001018
1019 if (expect_new_session) {
Robert Sloanb1b54b82017-11-06 13:50:02 -08001020 bool got_early_data =
Robert Sloane56da3e2017-06-26 08:26:42 -07001021 GetTestState(ssl)->new_session->ticket_max_early_data != 0;
Robert Sloanb1b54b82017-11-06 13:50:02 -08001022 if (config->expect_ticket_supports_early_data != got_early_data) {
1023 fprintf(stderr,
1024 "new session did%s support early data, but we expected the "
1025 "opposite\n",
1026 got_early_data ? "" : " not");
Robert Sloan69939df2017-01-09 10:53:07 -08001027 return false;
1028 }
1029 }
David Benjaminc895d6b2016-08-11 13:26:41 -04001030 }
1031
Adam Langleyd9e397b2015-01-22 14:27:53 -08001032 if (out_session) {
Robert Sloane56da3e2017-06-26 08:26:42 -07001033 *out_session = std::move(GetTestState(ssl)->new_session);
Adam Langleyd9e397b2015-01-22 14:27:53 -08001034 }
1035
Robert Sloane56da3e2017-06-26 08:26:42 -07001036 ret = DoShutdown(ssl);
Kenny Rootb8494592015-09-25 02:29:14 +00001037
1038 if (config->shim_shuts_down && config->check_close_notify) {
1039 // We initiate shutdown, so |SSL_shutdown| will return in two stages. First
1040 // it returns zero when our close_notify is sent, then one when the peer's
1041 // is received.
1042 if (ret != 0) {
1043 fprintf(stderr, "Unexpected SSL_shutdown result: %d != 0\n", ret);
1044 return false;
1045 }
Robert Sloane56da3e2017-06-26 08:26:42 -07001046 ret = DoShutdown(ssl);
Kenny Rootb8494592015-09-25 02:29:14 +00001047 }
1048
1049 if (ret != 1) {
1050 fprintf(stderr, "Unexpected SSL_shutdown result: %d != 1\n", ret);
1051 return false;
1052 }
1053
Robert Sloan8f860b12017-08-28 07:37:06 -07001054 if (SSL_total_renegotiations(ssl) > 0) {
1055 if (!SSL_get_session(ssl)->not_resumable) {
1056 fprintf(stderr,
1057 "Renegotiations should never produce resumable sessions.\n");
1058 return false;
1059 }
1060
Robert Sloand1d118f2017-09-11 09:00:48 -07001061 if (SSL_session_reused(ssl)) {
1062 fprintf(stderr, "Renegotiations should never resume sessions.\n");
1063 return false;
1064 }
1065
Robert Sloan8f860b12017-08-28 07:37:06 -07001066 // Re-check authentication properties after a renegotiation. The reported
1067 // values should remain unchanged even if the server sent different SCT
1068 // lists.
1069 if (!CheckAuthProperties(ssl, is_resume, config)) {
1070 return false;
1071 }
1072 }
1073
Robert Sloane56da3e2017-06-26 08:26:42 -07001074 if (SSL_total_renegotiations(ssl) != config->expect_total_renegotiations) {
Kenny Roote99801b2015-11-06 15:31:15 -08001075 fprintf(stderr, "Expected %d renegotiations, got %d\n",
Robert Sloane56da3e2017-06-26 08:26:42 -07001076 config->expect_total_renegotiations, SSL_total_renegotiations(ssl));
Kenny Roote99801b2015-11-06 15:31:15 -08001077 return false;
1078 }
1079
Adam Langleye9ada862015-05-11 17:20:37 -07001080 return true;
Adam Langleyd9e397b2015-01-22 14:27:53 -08001081}
1082
David Benjamin4969cc92016-04-22 15:02:23 -04001083class StderrDelimiter {
1084 public:
1085 ~StderrDelimiter() { fprintf(stderr, "--- DONE ---\n"); }
1086};
1087
David Benjamin1b249672016-12-06 18:25:50 -05001088int main(int argc, char **argv) {
David Benjamin4969cc92016-04-22 15:02:23 -04001089 // To distinguish ASan's output from ours, add a trailing message to stderr.
1090 // Anything following this line will be considered an error.
1091 StderrDelimiter delimiter;
1092
Adam Langleye9ada862015-05-11 17:20:37 -07001093#if defined(OPENSSL_WINDOWS)
Robert Sloana27a6a42017-09-05 08:39:28 -07001094 // Initialize Winsock.
Adam Langleye9ada862015-05-11 17:20:37 -07001095 WORD wsa_version = MAKEWORD(2, 2);
1096 WSADATA wsa_data;
1097 int wsa_err = WSAStartup(wsa_version, &wsa_data);
1098 if (wsa_err != 0) {
1099 fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
1100 return 1;
1101 }
1102 if (wsa_data.wVersion != wsa_version) {
1103 fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
1104 return 1;
1105 }
1106#else
Adam Langleyd9e397b2015-01-22 14:27:53 -08001107 signal(SIGPIPE, SIG_IGN);
1108#endif
1109
Kenny Roote99801b2015-11-06 15:31:15 -08001110 CRYPTO_library_init();
Adam Langleyd9e397b2015-01-22 14:27:53 -08001111
Robert Sloane56da3e2017-06-26 08:26:42 -07001112 TestConfig initial_config, resume_config, retry_config;
1113 if (!ParseConfig(argc - 1, argv + 1, &initial_config, &resume_config,
1114 &retry_config)) {
Adam Langleye9ada862015-05-11 17:20:37 -07001115 return Usage(argv[0]);
Adam Langleyd9e397b2015-01-22 14:27:53 -08001116 }
1117
Adam Vartanianbfcf3a72018-08-10 14:55:24 +01001118 if (initial_config.is_handshaker_supported) {
1119#if defined(HANDSHAKER_SUPPORTED)
1120 printf("Yes\n");
1121#else
1122 printf("No\n");
1123#endif
1124 return 0;
1125 }
Steven Valdez909b19f2016-11-21 15:35:44 -05001126
Robert Sloan8ff03552017-06-14 12:40:58 -07001127 bssl::UniquePtr<SSL_CTX> ssl_ctx;
Adam Langleyd9e397b2015-01-22 14:27:53 -08001128
David Benjaminf0c4a6c2016-08-11 13:26:41 -04001129 bssl::UniquePtr<SSL_SESSION> session;
Robert Sloan8ff03552017-06-14 12:40:58 -07001130 for (int i = 0; i < initial_config.resume_count + 1; i++) {
David Benjaminf0c4a6c2016-08-11 13:26:41 -04001131 bool is_resume = i > 0;
Robert Sloan8ff03552017-06-14 12:40:58 -07001132 TestConfig *config = is_resume ? &resume_config : &initial_config;
Adam Vartanianbfcf3a72018-08-10 14:55:24 +01001133 ssl_ctx = config->SetupCtx(ssl_ctx.get());
Robert Sloan8ff03552017-06-14 12:40:58 -07001134 if (!ssl_ctx) {
1135 ERR_print_errors_fp(stderr);
1136 return 1;
1137 }
1138
1139 if (is_resume && !initial_config.is_server && !session) {
David Benjaminf0c4a6c2016-08-11 13:26:41 -04001140 fprintf(stderr, "No session to offer.\n");
1141 return 1;
1142 }
Adam Langleyd9e397b2015-01-22 14:27:53 -08001143
David Benjaminf0c4a6c2016-08-11 13:26:41 -04001144 bssl::UniquePtr<SSL_SESSION> offer_session = std::move(session);
Adam Vartanianbfcf3a72018-08-10 14:55:24 +01001145 SettingsWriter writer;
1146 if (!writer.Init(i, config, offer_session.get())) {
Robert Sloanf6200e72017-07-10 08:09:18 -07001147 fprintf(stderr, "Error writing settings.\n");
1148 return 1;
1149 }
Adam Vartanianbfcf3a72018-08-10 14:55:24 +01001150 bool ok = DoConnection(&session, ssl_ctx.get(), config, &retry_config,
1151 is_resume, offer_session.get(), &writer);
1152 if (!writer.Commit()) {
1153 fprintf(stderr, "Error writing settings.\n");
1154 return 1;
1155 }
1156 if (!ok) {
David Benjaminf0c4a6c2016-08-11 13:26:41 -04001157 fprintf(stderr, "Connection %d failed.\n", i + 1);
1158 ERR_print_errors_fp(stderr);
1159 return 1;
1160 }
Steven Valdez909b19f2016-11-21 15:35:44 -05001161
Robert Sloan8ff03552017-06-14 12:40:58 -07001162 if (config->resumption_delay != 0) {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +01001163 AdvanceClock(config->resumption_delay);
Steven Valdez909b19f2016-11-21 15:35:44 -05001164 }
Adam Langleyd9e397b2015-01-22 14:27:53 -08001165 }
1166
Adam Langleye9ada862015-05-11 17:20:37 -07001167 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -08001168}