blob: f58c151063bf940b9c04eaadc4765f8762b85b2e [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) {
Pete Bentley0c61efe2019-08-13 09:32:23 +0100282 if (!config->expect_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);
Pete Bentley0c61efe2019-08-13 09:32:23 +0100286 if (config->expect_ocsp_response.size() != len ||
287 OPENSSL_memcmp(config->expect_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
Pete Bentley0c61efe2019-08-13 09:32:23 +0100293 if (!config->expect_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);
Pete Bentley0c61efe2019-08-13 09:32:23 +0100297 if (config->expect_signed_cert_timestamps.size() != len ||
298 OPENSSL_memcmp(config->expect_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
Pete Bentley0c61efe2019-08-13 09:32:23 +0100392static const char *EarlyDataReasonToString(ssl_early_data_reason_t reason) {
393 switch (reason) {
394 case ssl_early_data_unknown:
395 return "unknown";
396 case ssl_early_data_disabled:
397 return "disabled";
398 case ssl_early_data_accepted:
399 return "accepted";
400 case ssl_early_data_protocol_version:
401 return "protocol_version";
402 case ssl_early_data_peer_declined:
403 return "peer_declined";
404 case ssl_early_data_no_session_offered:
405 return "no_session_offered";
406 case ssl_early_data_session_not_resumed:
407 return "session_not_resumed";
408 case ssl_early_data_unsupported_for_session:
409 return "unsupported_for_session";
410 case ssl_early_data_hello_retry_request:
411 return "hello_retry_request";
412 case ssl_early_data_alpn_mismatch:
413 return "alpn_mismatch";
414 case ssl_early_data_channel_id:
415 return "channel_id";
416 case ssl_early_data_token_binding:
417 return "token_binding";
418 case ssl_early_data_ticket_age_skew:
419 return "ticket_age_skew";
420 }
421
422 abort();
423}
424
Kenny Rootb8494592015-09-25 02:29:14 +0000425// CheckHandshakeProperties checks, immediately after |ssl| completes its
426// initial handshake (or False Starts), whether all the properties are
427// consistent with the test configuration and invariants.
Robert Sloane56da3e2017-06-26 08:26:42 -0700428static bool CheckHandshakeProperties(SSL *ssl, bool is_resume,
429 const TestConfig *config) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700430 if (!CheckAuthProperties(ssl, is_resume, config)) {
431 return false;
432 }
433
Kenny Rootb8494592015-09-25 02:29:14 +0000434 if (SSL_get_current_cipher(ssl) == nullptr) {
435 fprintf(stderr, "null cipher after handshake\n");
436 return false;
437 }
438
Robert Sloanf6200e72017-07-10 08:09:18 -0700439 if (config->expect_version != 0 &&
440 SSL_version(ssl) != config->expect_version) {
441 fprintf(stderr, "want version %04x, got %04x\n", config->expect_version,
442 SSL_version(ssl));
443 return false;
444 }
445
Robert Sloane56da3e2017-06-26 08:26:42 -0700446 bool expect_resume =
447 is_resume && (!config->expect_session_miss || SSL_in_early_data(ssl));
448 if (!!SSL_session_reused(ssl) != expect_resume) {
449 fprintf(stderr, "session unexpectedly was%s reused\n",
Kenny Rootb8494592015-09-25 02:29:14 +0000450 SSL_session_reused(ssl) ? "" : " not");
451 return false;
452 }
453
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700454 bool expect_handshake_done =
Robert Sloane56da3e2017-06-26 08:26:42 -0700455 (is_resume || !config->false_start) && !SSL_in_early_data(ssl);
Kenny Rootb8494592015-09-25 02:29:14 +0000456 if (expect_handshake_done != GetTestState(ssl)->handshake_done) {
457 fprintf(stderr, "handshake was%s completed\n",
458 GetTestState(ssl)->handshake_done ? "" : " not");
459 return false;
460 }
461
462 if (expect_handshake_done && !config->is_server) {
463 bool expect_new_session =
464 !config->expect_no_session &&
David Benjaminc895d6b2016-08-11 13:26:41 -0400465 (!SSL_session_reused(ssl) || config->expect_ticket_renewal) &&
466 // Session tickets are sent post-handshake in TLS 1.3.
467 GetProtocolVersion(ssl) < TLS1_3_VERSION;
Kenny Rootb8494592015-09-25 02:29:14 +0000468 if (expect_new_session != GetTestState(ssl)->got_new_session) {
469 fprintf(stderr,
Kenny Roote99801b2015-11-06 15:31:15 -0800470 "new session was%s cached, but we expected the opposite\n",
Kenny Rootb8494592015-09-25 02:29:14 +0000471 GetTestState(ssl)->got_new_session ? "" : " not");
472 return false;
473 }
474 }
475
Robert Sloan4d1ac502017-02-06 08:36:14 -0800476 if (!is_resume) {
477 if (config->expect_session_id && !GetTestState(ssl)->got_new_session) {
478 fprintf(stderr, "session was not cached on the server.\n");
479 return false;
480 }
481 if (config->expect_no_session_id && GetTestState(ssl)->got_new_session) {
482 fprintf(stderr, "session was unexpectedly cached on the server.\n");
483 return false;
484 }
485 }
486
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100487 // early_callback_called is updated in the handshaker, so we don't see it
488 // here.
489 if (!config->handoff && config->is_server &&
490 !GetTestState(ssl)->early_callback_called) {
Kenny Rootb8494592015-09-25 02:29:14 +0000491 fprintf(stderr, "early callback not called\n");
492 return false;
493 }
494
Pete Bentley0c61efe2019-08-13 09:32:23 +0100495 if (!config->expect_server_name.empty()) {
Kenny Rootb8494592015-09-25 02:29:14 +0000496 const char *server_name =
497 SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Steven Valdez909b19f2016-11-21 15:35:44 -0500498 if (server_name == nullptr ||
Pete Bentley0c61efe2019-08-13 09:32:23 +0100499 server_name != config->expect_server_name) {
Kenny Rootb8494592015-09-25 02:29:14 +0000500 fprintf(stderr, "servername mismatch (got %s; want %s)\n",
Pete Bentley0c61efe2019-08-13 09:32:23 +0100501 server_name, config->expect_server_name.c_str());
Kenny Rootb8494592015-09-25 02:29:14 +0000502 return false;
503 }
504 }
505
Pete Bentley0c61efe2019-08-13 09:32:23 +0100506 if (!config->expect_next_proto.empty()) {
Kenny Rootb8494592015-09-25 02:29:14 +0000507 const uint8_t *next_proto;
508 unsigned next_proto_len;
509 SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
Pete Bentley0c61efe2019-08-13 09:32:23 +0100510 if (next_proto_len != config->expect_next_proto.size() ||
511 OPENSSL_memcmp(next_proto, config->expect_next_proto.data(),
Robert Sloan69939df2017-01-09 10:53:07 -0800512 next_proto_len) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000513 fprintf(stderr, "negotiated next proto mismatch\n");
514 return false;
515 }
516 }
517
Robert Sloan8ff03552017-06-14 12:40:58 -0700518 if (!config->is_server) {
Kenny Rootb8494592015-09-25 02:29:14 +0000519 const uint8_t *alpn_proto;
520 unsigned alpn_proto_len;
521 SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len);
Pete Bentley0c61efe2019-08-13 09:32:23 +0100522 if (alpn_proto_len != config->expect_alpn.size() ||
523 OPENSSL_memcmp(alpn_proto, config->expect_alpn.data(),
Robert Sloan8ff03552017-06-14 12:40:58 -0700524 alpn_proto_len) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000525 fprintf(stderr, "negotiated alpn proto mismatch\n");
526 return false;
527 }
528 }
529
Pete Bentley0c61efe2019-08-13 09:32:23 +0100530 if (!config->expect_quic_transport_params.empty()) {
Robert Sloan8542c082018-02-05 09:07:34 -0800531 const uint8_t *peer_params;
532 size_t peer_params_len;
533 SSL_get_peer_quic_transport_params(ssl, &peer_params, &peer_params_len);
Pete Bentley0c61efe2019-08-13 09:32:23 +0100534 if (peer_params_len != config->expect_quic_transport_params.size() ||
Robert Sloan8542c082018-02-05 09:07:34 -0800535 OPENSSL_memcmp(peer_params,
Pete Bentley0c61efe2019-08-13 09:32:23 +0100536 config->expect_quic_transport_params.data(),
Robert Sloan8542c082018-02-05 09:07:34 -0800537 peer_params_len) != 0) {
538 fprintf(stderr, "QUIC transport params mismatch\n");
539 return false;
540 }
541 }
542
Pete Bentley0c61efe2019-08-13 09:32:23 +0100543 if (!config->expect_channel_id.empty()) {
Kenny Rootb8494592015-09-25 02:29:14 +0000544 uint8_t channel_id[64];
545 if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) {
546 fprintf(stderr, "no channel id negotiated\n");
547 return false;
548 }
Pete Bentley0c61efe2019-08-13 09:32:23 +0100549 if (config->expect_channel_id.size() != 64 ||
550 OPENSSL_memcmp(config->expect_channel_id.data(), channel_id, 64) !=
Robert Sloan69939df2017-01-09 10:53:07 -0800551 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000552 fprintf(stderr, "channel id mismatch\n");
553 return false;
554 }
555 }
556
Pete Bentley0c61efe2019-08-13 09:32:23 +0100557 if (config->expect_token_binding_param != -1) {
Robert Sloan978112c2018-01-22 12:53:01 -0800558 if (!SSL_is_token_binding_negotiated(ssl)) {
559 fprintf(stderr, "no Token Binding negotiated\n");
560 return false;
561 }
562 if (SSL_get_negotiated_token_binding_param(ssl) !=
Pete Bentley0c61efe2019-08-13 09:32:23 +0100563 static_cast<uint8_t>(config->expect_token_binding_param)) {
Robert Sloan978112c2018-01-22 12:53:01 -0800564 fprintf(stderr, "Token Binding param mismatch\n");
565 return false;
566 }
567 }
568
Steven Valdezb0b45c62017-01-17 16:23:54 -0500569 if (config->expect_extended_master_secret && !SSL_get_extms_support(ssl)) {
570 fprintf(stderr, "No EMS for connection when expected\n");
571 return false;
572 }
573
574 if (config->expect_secure_renegotiation &&
575 !SSL_get_secure_renegotiation_support(ssl)) {
576 fprintf(stderr, "No secure renegotiation for connection when expected\n");
577 return false;
578 }
579
580 if (config->expect_no_secure_renegotiation &&
581 SSL_get_secure_renegotiation_support(ssl)) {
582 fprintf(stderr,
583 "Secure renegotiation unexpectedly negotiated for connection\n");
584 return false;
Kenny Rootb8494592015-09-25 02:29:14 +0000585 }
586
David Benjaminc895d6b2016-08-11 13:26:41 -0400587 if (config->expect_peer_signature_algorithm != 0 &&
588 config->expect_peer_signature_algorithm !=
589 SSL_get_peer_signature_algorithm(ssl)) {
590 fprintf(stderr, "Peer signature algorithm was %04x, wanted %04x.\n",
591 SSL_get_peer_signature_algorithm(ssl),
592 config->expect_peer_signature_algorithm);
Adam Langleyfad63272015-11-12 12:15:39 -0800593 return false;
594 }
595
Robert Sloan8ff03552017-06-14 12:40:58 -0700596 if (config->expect_curve_id != 0) {
Steven Valdeze7531f02016-12-14 13:29:57 -0500597 uint16_t curve_id = SSL_get_curve_id(ssl);
Robert Sloan8ff03552017-06-14 12:40:58 -0700598 if (static_cast<uint16_t>(config->expect_curve_id) != curve_id) {
Steven Valdeze7531f02016-12-14 13:29:57 -0500599 fprintf(stderr, "curve_id was %04x, wanted %04x\n", curve_id,
Robert Sloan8ff03552017-06-14 12:40:58 -0700600 static_cast<uint16_t>(config->expect_curve_id));
Kenny Rootb8494592015-09-25 02:29:14 +0000601 return false;
602 }
603 }
David Benjaminc895d6b2016-08-11 13:26:41 -0400604
Steven Valdez909b19f2016-11-21 15:35:44 -0500605 uint16_t cipher_id =
606 static_cast<uint16_t>(SSL_CIPHER_get_id(SSL_get_current_cipher(ssl)));
607 if (config->expect_cipher_aes != 0 &&
608 EVP_has_aes_hardware() &&
609 static_cast<uint16_t>(config->expect_cipher_aes) != cipher_id) {
610 fprintf(stderr, "Cipher ID was %04x, wanted %04x (has AES hardware)\n",
611 cipher_id, static_cast<uint16_t>(config->expect_cipher_aes));
612 return false;
613 }
614
615 if (config->expect_cipher_no_aes != 0 &&
616 !EVP_has_aes_hardware() &&
617 static_cast<uint16_t>(config->expect_cipher_no_aes) != cipher_id) {
618 fprintf(stderr, "Cipher ID was %04x, wanted %04x (no AES hardware)\n",
619 cipher_id, static_cast<uint16_t>(config->expect_cipher_no_aes));
620 return false;
621 }
622
Pete Bentley0c61efe2019-08-13 09:32:23 +0100623 // The early data status is only applicable after the handshake is confirmed.
624 if (!SSL_in_early_data(ssl)) {
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700625 if ((config->expect_accept_early_data && !SSL_early_data_accepted(ssl)) ||
626 (config->expect_reject_early_data && SSL_early_data_accepted(ssl))) {
627 fprintf(stderr,
628 "Early data was%s accepted, but we expected the opposite\n",
629 SSL_early_data_accepted(ssl) ? "" : " not");
630 return false;
631 }
Pete Bentley0c61efe2019-08-13 09:32:23 +0100632
633 const char *early_data_reason =
634 EarlyDataReasonToString(SSL_get_early_data_reason(ssl));
635 if (!config->expect_early_data_reason.empty() &&
636 config->expect_early_data_reason != early_data_reason) {
637 fprintf(stderr, "Early data reason was \"%s\", expected \"%s\"\n",
638 early_data_reason, config->expect_early_data_reason.c_str());
639 return false;
640 }
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700641 }
Steven Valdez909b19f2016-11-21 15:35:44 -0500642
David Benjaminc895d6b2016-08-11 13:26:41 -0400643 if (!config->psk.empty()) {
644 if (SSL_get_peer_cert_chain(ssl) != nullptr) {
645 fprintf(stderr, "Received peer certificate on a PSK cipher.\n");
646 return false;
647 }
648 } else if (!config->is_server || config->require_any_client_certificate) {
649 if (SSL_get_peer_cert_chain(ssl) == nullptr) {
650 fprintf(stderr, "Received no peer certificate but expected one.\n");
651 return false;
652 }
653 }
654
Robert Sloan1c9db532017-03-13 08:03:59 -0700655 if (is_resume && config->expect_ticket_age_skew != 0 &&
656 SSL_get_ticket_age_skew(ssl) != config->expect_ticket_age_skew) {
657 fprintf(stderr, "Ticket age skew was %" PRId32 ", wanted %d\n",
658 SSL_get_ticket_age_skew(ssl), config->expect_ticket_age_skew);
659 return false;
660 }
661
Robert Sloand9e572d2018-08-27 12:27:00 -0700662 if (config->expect_tls13_downgrade != !!SSL_is_tls13_downgrade(ssl)) {
663 fprintf(stderr, "Got %s downgrade signal, but wanted the opposite.\n",
664 SSL_is_tls13_downgrade(ssl) ? "" : "no ");
Robert Sloanab8b8882018-03-26 11:39:51 -0700665 return false;
Robert Sloan0da43952018-01-03 15:13:14 -0800666 }
667
Pete Bentley0c61efe2019-08-13 09:32:23 +0100668 if (config->expect_delegated_credential_used !=
669 !!SSL_delegated_credential_used(ssl)) {
670 fprintf(stderr,
671 "Got %s delegated credential usage, but wanted opposite. \n",
672 SSL_delegated_credential_used(ssl) ? "" : "no");
673 return false;
674 }
675
676 if (config->expect_pq_experiment_signal !=
677 !!SSL_pq_experiment_signal_seen(ssl)) {
678 fprintf(stderr, "Got %sPQ experiment signal, but wanted opposite. \n",
679 SSL_pq_experiment_signal_seen(ssl) ? "" : "no ");
680 return false;
681 }
682
Kenny Rootb8494592015-09-25 02:29:14 +0000683 return true;
684}
685
Robert Sloandc2f6092018-04-10 10:22:33 -0700686static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
687 bssl::UniquePtr<SSL> *ssl_uniqueptr,
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100688 const TestConfig *config, bool is_resume, bool is_retry,
689 SettingsWriter *writer);
Robert Sloandc2f6092018-04-10 10:22:33 -0700690
691// DoConnection tests an SSL connection against the peer. On success, it returns
692// true and sets |*out_session| to the negotiated SSL session. If the test is a
693// resumption attempt, |is_resume| is true and |session| is the session from the
694// previous exchange.
695static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
696 SSL_CTX *ssl_ctx, const TestConfig *config,
697 const TestConfig *retry_config, bool is_resume,
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100698 SSL_SESSION *session, SettingsWriter *writer) {
699 bssl::UniquePtr<SSL> ssl = config->NewSSL(
700 ssl_ctx, session, is_resume, std::unique_ptr<TestState>(new TestState));
Robert Sloandc2f6092018-04-10 10:22:33 -0700701 if (!ssl) {
702 return false;
703 }
704 if (config->is_server) {
705 SSL_set_accept_state(ssl.get());
706 } else {
707 SSL_set_connect_state(ssl.get());
708 }
709
Adam Langleye9ada862015-05-11 17:20:37 -0700710 int sock = Connect(config->port);
711 if (sock == -1) {
712 return false;
713 }
714 SocketCloser closer(sock);
715
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400716 bssl::UniquePtr<BIO> bio(BIO_new_socket(sock, BIO_NOCLOSE));
Adam Langleye9ada862015-05-11 17:20:37 -0700717 if (!bio) {
718 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800719 }
720 if (config->is_dtls) {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100721 bssl::UniquePtr<BIO> packeted = PacketedBioCreate(GetClock());
David Benjamin4969cc92016-04-22 15:02:23 -0400722 if (!packeted) {
723 return false;
724 }
David Benjamin6e899c72016-06-09 18:02:18 -0400725 GetTestState(ssl.get())->packeted_bio = packeted.get();
Adam Langleye9ada862015-05-11 17:20:37 -0700726 BIO_push(packeted.get(), bio.release());
727 bio = std::move(packeted);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800728 }
729 if (config->async) {
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400730 bssl::UniquePtr<BIO> async_scoped =
Adam Langleye9ada862015-05-11 17:20:37 -0700731 config->is_dtls ? AsyncBioCreateDatagram() : AsyncBioCreate();
David Benjamin4969cc92016-04-22 15:02:23 -0400732 if (!async_scoped) {
733 return false;
734 }
Adam Langleye9ada862015-05-11 17:20:37 -0700735 BIO_push(async_scoped.get(), bio.release());
736 GetTestState(ssl.get())->async_bio = async_scoped.get();
737 bio = std::move(async_scoped);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800738 }
Adam Langleye9ada862015-05-11 17:20:37 -0700739 SSL_set_bio(ssl.get(), bio.get(), bio.get());
740 bio.release(); // SSL_set_bio takes ownership.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800741
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100742 bool ret = DoExchange(out_session, &ssl, config, is_resume, false, writer);
Robert Sloane56da3e2017-06-26 08:26:42 -0700743 if (!config->is_server && is_resume && config->expect_reject_early_data) {
744 // We must have failed due to an early data rejection.
745 if (ret) {
746 fprintf(stderr, "0-RTT exchange unexpected succeeded.\n");
747 return false;
748 }
749 if (SSL_get_error(ssl.get(), -1) != SSL_ERROR_EARLY_DATA_REJECTED) {
750 fprintf(stderr,
751 "SSL_get_error did not signal SSL_ERROR_EARLY_DATA_REJECTED.\n");
752 return false;
753 }
754
755 // Before reseting, early state should still be available.
756 if (!SSL_in_early_data(ssl.get()) ||
757 !CheckHandshakeProperties(ssl.get(), is_resume, config)) {
758 fprintf(stderr, "SSL_in_early_data returned false before reset.\n");
759 return false;
760 }
761
Pete Bentley0c61efe2019-08-13 09:32:23 +0100762 // Client pre- and post-0-RTT reject states are considered logically
763 // different connections with different test expections. Check that the test
764 // did not mistakenly configure reason expectations on the wrong one.
765 if (!config->expect_early_data_reason.empty()) {
766 fprintf(stderr,
767 "Test error: client reject -expect-early-data-reason flags "
768 "should be configured with -on-retry, not -on-resume.\n");
769 return false;
770 }
771
Robert Sloane56da3e2017-06-26 08:26:42 -0700772 // Reset the connection and try again at 1-RTT.
773 SSL_reset_early_data_reject(ssl.get());
Robert Sloanc9abfe42018-11-26 12:19:07 -0800774 GetTestState(ssl.get())->cert_verified = false;
Robert Sloane56da3e2017-06-26 08:26:42 -0700775
776 // After reseting, the socket should report it is no longer in an early data
777 // state.
778 if (SSL_in_early_data(ssl.get())) {
779 fprintf(stderr, "SSL_in_early_data returned true after reset.\n");
780 return false;
781 }
782
783 if (!SetTestConfig(ssl.get(), retry_config)) {
784 return false;
785 }
786
Robert Sloan8542c082018-02-05 09:07:34 -0800787 assert(!config->handoff);
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100788 ret = DoExchange(out_session, &ssl, retry_config, is_resume, true, writer);
Robert Sloane56da3e2017-06-26 08:26:42 -0700789 }
Robert Sloanfe7cd212017-08-07 09:03:39 -0700790
791 if (!ret) {
792 return false;
793 }
794
795 if (!GetTestState(ssl.get())->msg_callback_ok) {
796 return false;
797 }
798
799 if (!config->expect_msg_callback.empty() &&
800 GetTestState(ssl.get())->msg_callback_text !=
801 config->expect_msg_callback) {
802 fprintf(stderr, "Bad message callback trace. Wanted:\n%s\nGot:\n%s\n",
803 config->expect_msg_callback.c_str(),
804 GetTestState(ssl.get())->msg_callback_text.c_str());
805 return false;
806 }
807
808 return true;
Robert Sloane56da3e2017-06-26 08:26:42 -0700809}
810
Robert Sloan8542c082018-02-05 09:07:34 -0800811static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
812 bssl::UniquePtr<SSL> *ssl_uniqueptr,
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100813 const TestConfig *config, bool is_resume, bool is_retry,
814 SettingsWriter *writer) {
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700815 int ret;
Robert Sloan8542c082018-02-05 09:07:34 -0800816 SSL *ssl = ssl_uniqueptr->get();
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100817 SSL_CTX *session_ctx = SSL_get_SSL_CTX(ssl);
Robert Sloan8542c082018-02-05 09:07:34 -0800818
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700819 if (!config->implicit_handshake) {
Robert Sloan8542c082018-02-05 09:07:34 -0800820 if (config->handoff) {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100821#if defined(HANDSHAKER_SUPPORTED)
822 if (!DoSplitHandshake(ssl_uniqueptr, writer, is_resume)) {
Robert Sloan8542c082018-02-05 09:07:34 -0800823 return false;
824 }
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100825 ssl = ssl_uniqueptr->get();
826#else
827 fprintf(stderr, "The external handshaker can only be used on Linux\n");
828 return false;
829#endif
Robert Sloan8542c082018-02-05 09:07:34 -0800830 }
831
Adam Langleye9ada862015-05-11 17:20:37 -0700832 do {
Robert Sloan36272962017-10-23 10:28:39 -0700833 ret = CheckIdempotentError("SSL_do_handshake", ssl, [&]() -> int {
834 return SSL_do_handshake(ssl);
835 });
Robert Sloane56da3e2017-06-26 08:26:42 -0700836 } while (config->async && RetryAsync(ssl, ret));
Robert Sloan8542c082018-02-05 09:07:34 -0800837
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100838 if (config->forbid_renegotiation_after_handshake) {
839 SSL_set_renegotiate_mode(ssl, ssl_renegotiate_never);
Robert Sloan8542c082018-02-05 09:07:34 -0800840 }
841
Robert Sloandc2f6092018-04-10 10:22:33 -0700842 if (ret != 1 || !CheckHandshakeProperties(ssl, is_resume, config)) {
843 return false;
844 }
845
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100846 CopySessions(session_ctx, SSL_get_SSL_CTX(ssl));
Robert Sloandc2f6092018-04-10 10:22:33 -0700847
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700848 if (is_resume && !is_retry && !config->is_server &&
849 config->expect_no_offer_early_data && SSL_in_early_data(ssl)) {
850 fprintf(stderr, "Client unexpectedly offered early data.\n");
851 return false;
852 }
853
Robert Sloan6f79a502017-04-03 09:16:40 -0700854 if (config->handshake_twice) {
855 do {
Robert Sloane56da3e2017-06-26 08:26:42 -0700856 ret = SSL_do_handshake(ssl);
857 } while (config->async && RetryAsync(ssl, ret));
Robert Sloan6f79a502017-04-03 09:16:40 -0700858 if (ret != 1) {
859 return false;
860 }
861 }
862
863 // Skip the |config->async| logic as this should be a no-op.
864 if (config->no_op_extra_handshake &&
Robert Sloane56da3e2017-06-26 08:26:42 -0700865 SSL_do_handshake(ssl) != 1) {
Robert Sloan6f79a502017-04-03 09:16:40 -0700866 fprintf(stderr, "Extra SSL_do_handshake was not a no-op.\n");
867 return false;
868 }
869
Kenny Rootb8494592015-09-25 02:29:14 +0000870 // Reset the state to assert later that the callback isn't called in
871 // renegotations.
Robert Sloane56da3e2017-06-26 08:26:42 -0700872 GetTestState(ssl)->got_new_session = false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800873 }
874
Adam Langleye9ada862015-05-11 17:20:37 -0700875 if (config->export_keying_material > 0) {
876 std::vector<uint8_t> result(
877 static_cast<size_t>(config->export_keying_material));
878 if (!SSL_export_keying_material(
Robert Sloane56da3e2017-06-26 08:26:42 -0700879 ssl, result.data(), result.size(), config->export_label.data(),
880 config->export_label.size(),
881 reinterpret_cast<const uint8_t *>(config->export_context.data()),
Adam Langleye9ada862015-05-11 17:20:37 -0700882 config->export_context.size(), config->use_export_context)) {
883 fprintf(stderr, "failed to export keying material\n");
884 return false;
885 }
Robert Sloane56da3e2017-06-26 08:26:42 -0700886 if (WriteAll(ssl, result.data(), result.size()) < 0) {
Adam Langleye9ada862015-05-11 17:20:37 -0700887 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800888 }
889 }
890
Robert Sloan11c28bd2018-12-17 12:09:20 -0800891 if (config->export_traffic_secrets) {
892 bssl::Span<const uint8_t> read_secret, write_secret;
893 if (!SSL_get_traffic_secrets(ssl, &read_secret, &write_secret)) {
894 fprintf(stderr, "failed to export traffic secrets\n");
895 return false;
896 }
897
898 assert(read_secret.size() <= 0xffff);
899 assert(write_secret.size() == read_secret.size());
900 const uint16_t secret_len = read_secret.size();
901 if (WriteAll(ssl, &secret_len, sizeof(secret_len)) < 0 ||
902 WriteAll(ssl, read_secret.data(), read_secret.size()) < 0 ||
903 WriteAll(ssl, write_secret.data(), write_secret.size()) < 0) {
904 return false;
905 }
906 }
907
Adam Langleyf4e42722015-06-04 17:45:09 -0700908 if (config->tls_unique) {
909 uint8_t tls_unique[16];
910 size_t tls_unique_len;
Robert Sloane56da3e2017-06-26 08:26:42 -0700911 if (!SSL_get_tls_unique(ssl, tls_unique, &tls_unique_len,
Adam Langleyf4e42722015-06-04 17:45:09 -0700912 sizeof(tls_unique))) {
913 fprintf(stderr, "failed to get tls-unique\n");
914 return false;
915 }
916
917 if (tls_unique_len != 12) {
918 fprintf(stderr, "expected 12 bytes of tls-unique but got %u",
919 static_cast<unsigned>(tls_unique_len));
920 return false;
921 }
922
Robert Sloane56da3e2017-06-26 08:26:42 -0700923 if (WriteAll(ssl, tls_unique, tls_unique_len) < 0) {
Adam Langleyf4e42722015-06-04 17:45:09 -0700924 return false;
925 }
926 }
927
David Benjaminc895d6b2016-08-11 13:26:41 -0400928 if (config->send_alert) {
Robert Sloane56da3e2017-06-26 08:26:42 -0700929 if (DoSendFatalAlert(ssl, SSL_AD_DECOMPRESSION_FAILURE) < 0) {
David Benjaminc895d6b2016-08-11 13:26:41 -0400930 return false;
931 }
932 return true;
933 }
934
Adam Langleyd9e397b2015-01-22 14:27:53 -0800935 if (config->write_different_record_sizes) {
936 if (config->is_dtls) {
937 fprintf(stderr, "write_different_record_sizes not supported for DTLS\n");
Adam Langleye9ada862015-05-11 17:20:37 -0700938 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800939 }
940 // This mode writes a number of different record sizes in an attempt to
941 // trip up the CBC record splitting code.
Kenny Rootb8494592015-09-25 02:29:14 +0000942 static const size_t kBufLen = 32769;
943 std::unique_ptr<uint8_t[]> buf(new uint8_t[kBufLen]);
Robert Sloan69939df2017-01-09 10:53:07 -0800944 OPENSSL_memset(buf.get(), 0x42, kBufLen);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800945 static const size_t kRecordSizes[] = {
946 0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769};
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400947 for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kRecordSizes); i++) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800948 const size_t len = kRecordSizes[i];
Kenny Rootb8494592015-09-25 02:29:14 +0000949 if (len > kBufLen) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800950 fprintf(stderr, "Bad kRecordSizes value.\n");
Adam Langleye9ada862015-05-11 17:20:37 -0700951 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800952 }
Robert Sloane56da3e2017-06-26 08:26:42 -0700953 if (WriteAll(ssl, buf.get(), len) < 0) {
Adam Langleye9ada862015-05-11 17:20:37 -0700954 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800955 }
956 }
957 } else {
Robert Sloan572a4e22017-04-17 10:52:19 -0700958 static const char kInitialWrite[] = "hello";
959 bool pending_initial_write = false;
Robert Sloan69939df2017-01-09 10:53:07 -0800960 if (config->read_with_unfinished_write) {
961 if (!config->async) {
962 fprintf(stderr, "-read-with-unfinished-write requires -async.\n");
963 return false;
964 }
965
Robert Sloane56da3e2017-06-26 08:26:42 -0700966 // Let only one byte of the record through.
967 AsyncBioAllowWrite(GetTestState(ssl)->async_bio, 1);
Robert Sloan572a4e22017-04-17 10:52:19 -0700968 int write_ret =
Robert Sloane56da3e2017-06-26 08:26:42 -0700969 SSL_write(ssl, kInitialWrite, strlen(kInitialWrite));
970 if (SSL_get_error(ssl, write_ret) != SSL_ERROR_WANT_WRITE) {
Robert Sloan69939df2017-01-09 10:53:07 -0800971 fprintf(stderr, "Failed to leave unfinished write.\n");
972 return false;
973 }
Robert Sloan572a4e22017-04-17 10:52:19 -0700974 pending_initial_write = true;
975 } else if (config->shim_writes_first) {
Robert Sloane56da3e2017-06-26 08:26:42 -0700976 if (WriteAll(ssl, kInitialWrite, strlen(kInitialWrite)) < 0) {
Adam Langleye9ada862015-05-11 17:20:37 -0700977 return false;
978 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800979 }
Kenny Rootb8494592015-09-25 02:29:14 +0000980 if (!config->shim_shuts_down) {
981 for (;;) {
Kenny Rootb8494592015-09-25 02:29:14 +0000982 // Read only 512 bytes at a time in TLS to ensure records may be
983 // returned in multiple reads.
Steven Valdezb0b45c62017-01-17 16:23:54 -0500984 size_t read_size = config->is_dtls ? 16384 : 512;
985 if (config->read_size > 0) {
986 read_size = config->read_size;
987 }
988 std::unique_ptr<uint8_t[]> buf(new uint8_t[read_size]);
989
Robert Sloane56da3e2017-06-26 08:26:42 -0700990 int n = DoRead(ssl, buf.get(), read_size);
991 int err = SSL_get_error(ssl, n);
Kenny Rootb8494592015-09-25 02:29:14 +0000992 if (err == SSL_ERROR_ZERO_RETURN ||
993 (n == 0 && err == SSL_ERROR_SYSCALL)) {
994 if (n != 0) {
995 fprintf(stderr, "Invalid SSL_get_error output\n");
996 return false;
997 }
998 // Stop on either clean or unclean shutdown.
999 break;
1000 } else if (err != SSL_ERROR_NONE) {
1001 if (n > 0) {
1002 fprintf(stderr, "Invalid SSL_get_error output\n");
1003 return false;
1004 }
1005 return false;
1006 }
1007 // Successfully read data.
1008 if (n <= 0) {
Adam Langleyd9e397b2015-01-22 14:27:53 -08001009 fprintf(stderr, "Invalid SSL_get_error output\n");
Adam Langleye9ada862015-05-11 17:20:37 -07001010 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -08001011 }
Kenny Rootb8494592015-09-25 02:29:14 +00001012
Robert Sloane56da3e2017-06-26 08:26:42 -07001013 if (!config->is_server && is_resume && !is_retry &&
1014 config->expect_reject_early_data) {
1015 fprintf(stderr,
1016 "Unexpectedly received data instead of 0-RTT reject.\n");
1017 return false;
1018 }
1019
Kenny Rootb8494592015-09-25 02:29:14 +00001020 // After a successful read, with or without False Start, the handshake
Robert Sloan6d0d00e2017-03-27 07:13:07 -07001021 // must be complete unless we are doing early data.
Robert Sloane56da3e2017-06-26 08:26:42 -07001022 if (!GetTestState(ssl)->handshake_done &&
1023 !SSL_early_data_accepted(ssl)) {
Kenny Rootb8494592015-09-25 02:29:14 +00001024 fprintf(stderr, "handshake was not completed after SSL_read\n");
Adam Langleye9ada862015-05-11 17:20:37 -07001025 return false;
Adam Langleyd9e397b2015-01-22 14:27:53 -08001026 }
Adam Langleye9ada862015-05-11 17:20:37 -07001027
Robert Sloan572a4e22017-04-17 10:52:19 -07001028 // Clear the initial write, if unfinished.
1029 if (pending_initial_write) {
Robert Sloane56da3e2017-06-26 08:26:42 -07001030 if (WriteAll(ssl, kInitialWrite, strlen(kInitialWrite)) < 0) {
Robert Sloan572a4e22017-04-17 10:52:19 -07001031 return false;
1032 }
1033 pending_initial_write = false;
1034 }
1035
Robert Sloan4c22c5f2019-03-01 15:53:37 -08001036 if (config->key_update &&
1037 !SSL_key_update(ssl, SSL_KEY_UPDATE_NOT_REQUESTED)) {
1038 fprintf(stderr, "SSL_key_update failed.\n");
1039 return false;
1040 }
1041
Kenny Rootb8494592015-09-25 02:29:14 +00001042 for (int i = 0; i < n; i++) {
1043 buf[i] ^= 0xff;
1044 }
Robert Sloane56da3e2017-06-26 08:26:42 -07001045 if (WriteAll(ssl, buf.get(), n) < 0) {
Kenny Rootb8494592015-09-25 02:29:14 +00001046 return false;
1047 }
Adam Langleyd9e397b2015-01-22 14:27:53 -08001048 }
1049 }
1050 }
1051
Kenny Rootb8494592015-09-25 02:29:14 +00001052 if (!config->is_server && !config->false_start &&
1053 !config->implicit_handshake &&
David Benjaminc895d6b2016-08-11 13:26:41 -04001054 // Session tickets are sent post-handshake in TLS 1.3.
Robert Sloane56da3e2017-06-26 08:26:42 -07001055 GetProtocolVersion(ssl) < TLS1_3_VERSION &&
1056 GetTestState(ssl)->got_new_session) {
Kenny Rootb8494592015-09-25 02:29:14 +00001057 fprintf(stderr, "new session was established after the handshake\n");
1058 return false;
1059 }
1060
Robert Sloane56da3e2017-06-26 08:26:42 -07001061 if (GetProtocolVersion(ssl) >= TLS1_3_VERSION && !config->is_server) {
David Benjaminc895d6b2016-08-11 13:26:41 -04001062 bool expect_new_session =
1063 !config->expect_no_session && !config->shim_shuts_down;
Robert Sloane56da3e2017-06-26 08:26:42 -07001064 if (expect_new_session != GetTestState(ssl)->got_new_session) {
David Benjaminc895d6b2016-08-11 13:26:41 -04001065 fprintf(stderr,
1066 "new session was%s cached, but we expected the opposite\n",
Robert Sloane56da3e2017-06-26 08:26:42 -07001067 GetTestState(ssl)->got_new_session ? "" : " not");
David Benjaminc895d6b2016-08-11 13:26:41 -04001068 return false;
1069 }
Robert Sloan69939df2017-01-09 10:53:07 -08001070
1071 if (expect_new_session) {
Robert Sloanb1b54b82017-11-06 13:50:02 -08001072 bool got_early_data =
Robert Sloane56da3e2017-06-26 08:26:42 -07001073 GetTestState(ssl)->new_session->ticket_max_early_data != 0;
Robert Sloanb1b54b82017-11-06 13:50:02 -08001074 if (config->expect_ticket_supports_early_data != got_early_data) {
1075 fprintf(stderr,
1076 "new session did%s support early data, but we expected the "
1077 "opposite\n",
1078 got_early_data ? "" : " not");
Robert Sloan69939df2017-01-09 10:53:07 -08001079 return false;
1080 }
1081 }
David Benjaminc895d6b2016-08-11 13:26:41 -04001082 }
1083
Adam Langleyd9e397b2015-01-22 14:27:53 -08001084 if (out_session) {
Robert Sloane56da3e2017-06-26 08:26:42 -07001085 *out_session = std::move(GetTestState(ssl)->new_session);
Adam Langleyd9e397b2015-01-22 14:27:53 -08001086 }
1087
Robert Sloane56da3e2017-06-26 08:26:42 -07001088 ret = DoShutdown(ssl);
Kenny Rootb8494592015-09-25 02:29:14 +00001089
1090 if (config->shim_shuts_down && config->check_close_notify) {
1091 // We initiate shutdown, so |SSL_shutdown| will return in two stages. First
1092 // it returns zero when our close_notify is sent, then one when the peer's
1093 // is received.
1094 if (ret != 0) {
1095 fprintf(stderr, "Unexpected SSL_shutdown result: %d != 0\n", ret);
1096 return false;
1097 }
Robert Sloane56da3e2017-06-26 08:26:42 -07001098 ret = DoShutdown(ssl);
Kenny Rootb8494592015-09-25 02:29:14 +00001099 }
1100
1101 if (ret != 1) {
1102 fprintf(stderr, "Unexpected SSL_shutdown result: %d != 1\n", ret);
1103 return false;
1104 }
1105
Robert Sloan8f860b12017-08-28 07:37:06 -07001106 if (SSL_total_renegotiations(ssl) > 0) {
1107 if (!SSL_get_session(ssl)->not_resumable) {
1108 fprintf(stderr,
1109 "Renegotiations should never produce resumable sessions.\n");
1110 return false;
1111 }
1112
Robert Sloand1d118f2017-09-11 09:00:48 -07001113 if (SSL_session_reused(ssl)) {
1114 fprintf(stderr, "Renegotiations should never resume sessions.\n");
1115 return false;
1116 }
1117
Robert Sloan8f860b12017-08-28 07:37:06 -07001118 // Re-check authentication properties after a renegotiation. The reported
1119 // values should remain unchanged even if the server sent different SCT
1120 // lists.
1121 if (!CheckAuthProperties(ssl, is_resume, config)) {
1122 return false;
1123 }
1124 }
1125
Robert Sloane56da3e2017-06-26 08:26:42 -07001126 if (SSL_total_renegotiations(ssl) != config->expect_total_renegotiations) {
Kenny Roote99801b2015-11-06 15:31:15 -08001127 fprintf(stderr, "Expected %d renegotiations, got %d\n",
Robert Sloane56da3e2017-06-26 08:26:42 -07001128 config->expect_total_renegotiations, SSL_total_renegotiations(ssl));
Kenny Roote99801b2015-11-06 15:31:15 -08001129 return false;
1130 }
1131
Adam Langleye9ada862015-05-11 17:20:37 -07001132 return true;
Adam Langleyd9e397b2015-01-22 14:27:53 -08001133}
1134
David Benjamin4969cc92016-04-22 15:02:23 -04001135class StderrDelimiter {
1136 public:
1137 ~StderrDelimiter() { fprintf(stderr, "--- DONE ---\n"); }
1138};
1139
David Benjamin1b249672016-12-06 18:25:50 -05001140int main(int argc, char **argv) {
David Benjamin4969cc92016-04-22 15:02:23 -04001141 // To distinguish ASan's output from ours, add a trailing message to stderr.
1142 // Anything following this line will be considered an error.
1143 StderrDelimiter delimiter;
1144
Adam Langleye9ada862015-05-11 17:20:37 -07001145#if defined(OPENSSL_WINDOWS)
Robert Sloana27a6a42017-09-05 08:39:28 -07001146 // Initialize Winsock.
Adam Langleye9ada862015-05-11 17:20:37 -07001147 WORD wsa_version = MAKEWORD(2, 2);
1148 WSADATA wsa_data;
1149 int wsa_err = WSAStartup(wsa_version, &wsa_data);
1150 if (wsa_err != 0) {
1151 fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
1152 return 1;
1153 }
1154 if (wsa_data.wVersion != wsa_version) {
1155 fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
1156 return 1;
1157 }
1158#else
Adam Langleyd9e397b2015-01-22 14:27:53 -08001159 signal(SIGPIPE, SIG_IGN);
1160#endif
1161
Kenny Roote99801b2015-11-06 15:31:15 -08001162 CRYPTO_library_init();
Adam Langleyd9e397b2015-01-22 14:27:53 -08001163
Robert Sloane56da3e2017-06-26 08:26:42 -07001164 TestConfig initial_config, resume_config, retry_config;
1165 if (!ParseConfig(argc - 1, argv + 1, &initial_config, &resume_config,
1166 &retry_config)) {
Adam Langleye9ada862015-05-11 17:20:37 -07001167 return Usage(argv[0]);
Adam Langleyd9e397b2015-01-22 14:27:53 -08001168 }
1169
Adam Vartanianbfcf3a72018-08-10 14:55:24 +01001170 if (initial_config.is_handshaker_supported) {
1171#if defined(HANDSHAKER_SUPPORTED)
1172 printf("Yes\n");
1173#else
1174 printf("No\n");
1175#endif
1176 return 0;
1177 }
Steven Valdez909b19f2016-11-21 15:35:44 -05001178
Robert Sloan8ff03552017-06-14 12:40:58 -07001179 bssl::UniquePtr<SSL_CTX> ssl_ctx;
Adam Langleyd9e397b2015-01-22 14:27:53 -08001180
David Benjaminf0c4a6c2016-08-11 13:26:41 -04001181 bssl::UniquePtr<SSL_SESSION> session;
Robert Sloan8ff03552017-06-14 12:40:58 -07001182 for (int i = 0; i < initial_config.resume_count + 1; i++) {
David Benjaminf0c4a6c2016-08-11 13:26:41 -04001183 bool is_resume = i > 0;
Robert Sloan8ff03552017-06-14 12:40:58 -07001184 TestConfig *config = is_resume ? &resume_config : &initial_config;
Adam Vartanianbfcf3a72018-08-10 14:55:24 +01001185 ssl_ctx = config->SetupCtx(ssl_ctx.get());
Robert Sloan8ff03552017-06-14 12:40:58 -07001186 if (!ssl_ctx) {
1187 ERR_print_errors_fp(stderr);
1188 return 1;
1189 }
1190
1191 if (is_resume && !initial_config.is_server && !session) {
David Benjaminf0c4a6c2016-08-11 13:26:41 -04001192 fprintf(stderr, "No session to offer.\n");
1193 return 1;
1194 }
Adam Langleyd9e397b2015-01-22 14:27:53 -08001195
David Benjaminf0c4a6c2016-08-11 13:26:41 -04001196 bssl::UniquePtr<SSL_SESSION> offer_session = std::move(session);
Adam Vartanianbfcf3a72018-08-10 14:55:24 +01001197 SettingsWriter writer;
1198 if (!writer.Init(i, config, offer_session.get())) {
Robert Sloanf6200e72017-07-10 08:09:18 -07001199 fprintf(stderr, "Error writing settings.\n");
1200 return 1;
1201 }
Adam Vartanianbfcf3a72018-08-10 14:55:24 +01001202 bool ok = DoConnection(&session, ssl_ctx.get(), config, &retry_config,
1203 is_resume, offer_session.get(), &writer);
1204 if (!writer.Commit()) {
1205 fprintf(stderr, "Error writing settings.\n");
1206 return 1;
1207 }
1208 if (!ok) {
David Benjaminf0c4a6c2016-08-11 13:26:41 -04001209 fprintf(stderr, "Connection %d failed.\n", i + 1);
1210 ERR_print_errors_fp(stderr);
1211 return 1;
1212 }
Steven Valdez909b19f2016-11-21 15:35:44 -05001213
Robert Sloan8ff03552017-06-14 12:40:58 -07001214 if (config->resumption_delay != 0) {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +01001215 AdvanceClock(config->resumption_delay);
Steven Valdez909b19f2016-11-21 15:35:44 -05001216 }
Adam Langleyd9e397b2015-01-22 14:27:53 -08001217 }
1218
Adam Langleye9ada862015-05-11 17:20:37 -07001219 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -08001220}