1025b3d3459260670a883169cf0940e94cbd79b94David Benjamin/* Copyright (c) 2014, Google Inc.
2025b3d3459260670a883169cf0940e94cbd79b94David Benjamin *
3025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * Permission to use, copy, modify, and/or distribute this software for any
4025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * purpose with or without fee is hereby granted, provided that the above
5025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * copyright notice and this permission notice appear in all copies.
6025b3d3459260670a883169cf0940e94cbd79b94David Benjamin *
7025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
15ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#include <openssl/base.h>
16ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley
17ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#if !defined(OPENSSL_WINDOWS)
18025b3d3459260670a883169cf0940e94cbd79b94David Benjamin#include <arpa/inet.h>
191d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin#include <netinet/in.h>
201d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin#include <signal.h>
211d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin#include <sys/socket.h>
228f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin#include <unistd.h>
23ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#endif
24ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley
25ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#include <sys/types.h>
26025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
27025b3d3459260670a883169cf0940e94cbd79b94David Benjamin#include <openssl/bio.h>
288f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin#include <openssl/bytestring.h>
291d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin#include <openssl/ssl.h>
301d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
3143ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin#include "async_bio.h"
326fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin#include "packeted_bio.h"
335a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin#include "test_config.h"
3443ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin
351d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjaminstatic int usage(const char *program) {
365a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  fprintf(stderr, "Usage: %s [flags...]\n",
371d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin          program);
381d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  return 1;
391d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin}
40025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
415a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjaminstatic int g_ex_data_index = 0;
425a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin
435a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjaminstatic void SetConfigPtr(SSL *ssl, const TestConfig *config) {
445a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  SSL_set_ex_data(ssl, g_ex_data_index, (void *)config);
455a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin}
465a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin
475a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjaminstatic const TestConfig *GetConfigPtr(SSL *ssl) {
485a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  return (const TestConfig *)SSL_get_ex_data(ssl, g_ex_data_index);
495a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin}
505a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin
51a08e49d17ad6fcf738d73647511a63bc752fe307David Benjaminstatic EVP_PKEY *LoadPrivateKey(const std::string &file) {
52a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  BIO *bio = BIO_new(BIO_s_file());
53a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  if (bio == NULL) {
54a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    return NULL;
55a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  }
56a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  if (!BIO_read_filename(bio, file.c_str())) {
57a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    BIO_free(bio);
58a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    return NULL;
59a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  }
60a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
61a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  BIO_free(bio);
62a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  return pkey;
63a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin}
64a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin
651f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjaminstatic int early_callback_called = 0;
668f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin
671f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjaminstatic int select_certificate_callback(const struct ssl_early_callback_ctx *ctx) {
688f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin  early_callback_called = 1;
698f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin
705a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  const TestConfig *config = GetConfigPtr(ctx->ssl);
715a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin
725a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->expected_server_name.empty()) {
737b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin    return 1;
747b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin  }
758f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin
767b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin  const uint8_t *extension_data;
777b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin  size_t extension_len;
787b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin  CBS extension, server_name_list, host_name;
797b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin  uint8_t name_type;
808f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin
817b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin  if (!SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
827b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin                                            &extension_data,
837b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin                                            &extension_len)) {
847b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin    fprintf(stderr, "Could not find server_name extension.\n");
857b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin    return -1;
867b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin  }
877b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin
887b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin  CBS_init(&extension, extension_data, extension_len);
897b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin  if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) ||
907b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin      CBS_len(&extension) != 0 ||
917b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin      !CBS_get_u8(&server_name_list, &name_type) ||
927b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin      name_type != TLSEXT_NAMETYPE_host_name ||
937b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin      !CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
947b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin      CBS_len(&server_name_list) != 0) {
957b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin    fprintf(stderr, "Could not decode server_name extension.\n");
967b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin    return -1;
977b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin  }
987b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin
995a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (!CBS_mem_equal(&host_name,
1005a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin                     (const uint8_t*)config->expected_server_name.data(),
1015a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin                     config->expected_server_name.size())) {
1027b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin    fprintf(stderr, "Server name mismatch.\n");
1038f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin  }
1048f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin
1058f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin  return 1;
1068f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin}
107025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
1081f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjaminstatic int skip_verify(int preverify_ok, X509_STORE_CTX *store_ctx) {
10967666e7823297fa2e01291dbfe140d250dc458f2David Benjamin  return 1;
11067666e7823297fa2e01291dbfe140d250dc458f2David Benjamin}
11167666e7823297fa2e01291dbfe140d250dc458f2David Benjamin
1121f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjaminstatic int next_protos_advertised_callback(SSL *ssl,
1137e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin                                           const uint8_t **out,
1147e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin                                           unsigned int *out_len,
1157e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin                                           void *arg) {
1165a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  const TestConfig *config = GetConfigPtr(ssl);
1175a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->advertise_npn.empty())
1181f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin    return SSL_TLSEXT_ERR_NOACK;
1191f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin
1201f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin  // TODO(davidben): Support passing byte strings with NULs to the
1211f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin  // test shim.
1225a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  *out = (const uint8_t*)config->advertise_npn.data();
1235a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  *out_len = config->advertise_npn.size();
1241f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin  return SSL_TLSEXT_ERR_OK;
1251f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin}
1261f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin
1277e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjaminstatic int next_proto_select_callback(SSL* ssl,
1287e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin                                      uint8_t** out,
1297e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin                                      uint8_t* outlen,
1307e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin                                      const uint8_t* in,
1317e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin                                      unsigned inlen,
1327e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin                                      void* arg) {
1335a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  const TestConfig *config = GetConfigPtr(ssl);
1345a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->select_next_proto.empty())
1357e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin    return SSL_TLSEXT_ERR_NOACK;
1367e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin
1375a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  *out = (uint8_t*)config->select_next_proto.data();
1385a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  *outlen = config->select_next_proto.size();
1397e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin  return SSL_TLSEXT_ERR_OK;
1407e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin}
1417e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin
142ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjaminstatic int alpn_select_callback(SSL* ssl,
143ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin                                const uint8_t** out,
144ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin                                uint8_t* outlen,
145ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin                                const uint8_t* in,
146ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin                                unsigned inlen,
147ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin                                void* arg) {
148ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  const TestConfig *config = GetConfigPtr(ssl);
149ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  if (config->select_alpn.empty())
150ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin    return SSL_TLSEXT_ERR_NOACK;
151ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin
152ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  if (!config->expected_advertised_alpn.empty() &&
153ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin      (config->expected_advertised_alpn.size() != inlen ||
154ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin       memcmp(config->expected_advertised_alpn.data(),
155ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin              in, inlen) != 0)) {
156ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin    fprintf(stderr, "bad ALPN select callback inputs\n");
157ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin    exit(1);
158ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  }
159ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin
160ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  *out = (const uint8_t*)config->select_alpn.data();
161ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  *outlen = config->select_alpn.size();
162ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  return SSL_TLSEXT_ERR_OK;
163ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin}
164ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin
165fb4ea28bb84875a844cd65a9e4a2167ec884cd48David Benjaminstatic int cookie_generate_callback(SSL *ssl, uint8_t *cookie, size_t *cookie_len) {
1666fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  *cookie_len = 32;
1676fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  memset(cookie, 42, *cookie_len);
1686fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  return 1;
1696fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin}
1706fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin
171fb4ea28bb84875a844cd65a9e4a2167ec884cd48David Benjaminstatic int cookie_verify_callback(SSL *ssl, const uint8_t *cookie, size_t cookie_len) {
1726fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  if (cookie_len != 32) {
1736fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    fprintf(stderr, "Cookie length mismatch.\n");
1746fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    return 0;
1756fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  }
1766fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  for (size_t i = 0; i < cookie_len; i++) {
1776fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    if (cookie[i] != 42) {
1786fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin      fprintf(stderr, "Cookie mismatch.\n");
1796fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin      return 0;
1806fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    }
1816fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  }
1826fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  return 1;
1836fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin}
1846fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin
1855a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjaminstatic SSL_CTX *setup_ctx(const TestConfig *config) {
186025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  SSL_CTX *ssl_ctx = NULL;
187f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin  DH *dh = NULL;
188025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
1896fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  const SSL_METHOD *method;
1906fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  if (config->is_dtls) {
1916fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    // TODO(davidben): Get DTLS 1.2 working and test the version negotiation
1926fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    // codepath. This doesn't currently work because
1936fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    // - Session resumption is broken: https://crbug.com/403378
1946fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    // - DTLS hasn't been updated for EVP_AEAD.
1956fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    if (config->is_server) {
1966fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin      method = DTLSv1_server_method();
1976fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    } else {
1986fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin      method = DTLSv1_client_method();
1996fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    }
2006fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  } else {
2016fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    if (config->is_server) {
2026fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin      method = SSLv23_server_method();
2036fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    } else {
2046fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin      method = SSLv23_client_method();
2056fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    }
2066fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  }
2076fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  ssl_ctx = SSL_CTX_new(method);
208025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  if (ssl_ctx == NULL) {
209025b3d3459260670a883169cf0940e94cbd79b94David Benjamin    goto err;
210025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  }
211025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
2126fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  if (config->is_dtls) {
2136fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    // DTLS needs read-ahead to function on a datagram BIO.
2146fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    //
2156fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    // TODO(davidben): this should not be necessary. DTLS code should only
2166fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    // expect a datagram BIO.
2176fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    SSL_CTX_set_read_ahead(ssl_ctx, 1);
2186fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  }
2196fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin
220025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  if (!SSL_CTX_set_ecdh_auto(ssl_ctx, 1)) {
221025b3d3459260670a883169cf0940e94cbd79b94David Benjamin    goto err;
222025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  }
223025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
224025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  if (!SSL_CTX_set_cipher_list(ssl_ctx, "ALL")) {
225025b3d3459260670a883169cf0940e94cbd79b94David Benjamin    goto err;
226025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  }
227025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
228f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin  dh = DH_get_2048_256(NULL);
229f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin  if (!SSL_CTX_set_tmp_dh(ssl_ctx, dh)) {
230f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin    goto err;
231f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin  }
232f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin
2331d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_BOTH);
2341d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
2358f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin  ssl_ctx->select_certificate_cb = select_certificate_callback;
2368f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin
2371f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin  SSL_CTX_set_next_protos_advertised_cb(
2381f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin      ssl_ctx, next_protos_advertised_callback, NULL);
239ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  if (!config->select_next_proto.empty()) {
240ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin    SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_callback, NULL);
241ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  }
242ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin
243ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  if (!config->select_alpn.empty()) {
244ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin    SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_callback, NULL);
245ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  }
2461f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin
2476fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  SSL_CTX_set_cookie_generate_cb(ssl_ctx, cookie_generate_callback);
2486fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  SSL_CTX_set_cookie_verify_cb(ssl_ctx, cookie_verify_callback);
2496fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin
250a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  ssl_ctx->tlsext_channel_id_enabled_new = 1;
251a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin
252f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin  DH_free(dh);
2531d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  return ssl_ctx;
2541d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
2551d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin err:
256f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin  if (dh != NULL) {
257f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin    DH_free(dh);
258f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin  }
2591d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  if (ssl_ctx != NULL) {
2601d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin    SSL_CTX_free(ssl_ctx);
2611d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  }
2621d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  return NULL;
2631d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin}
2641d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
26543ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjaminstatic int retry_async(SSL *ssl, int ret, BIO *bio) {
26643ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  // No error; don't retry.
26743ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  if (ret >= 0) {
26843ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin    return 0;
269025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  }
27043ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  // See if we needed to read or write more. If so, allow one byte through on
27143ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  // the appropriate end to maximally stress the state machine.
27243ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  int err = SSL_get_error(ssl, ret);
27343ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  if (err == SSL_ERROR_WANT_READ) {
27443ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin    async_bio_allow_read(bio, 1);
27543ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin    return 1;
27643ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  } else if (err == SSL_ERROR_WANT_WRITE) {
27743ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin    async_bio_allow_write(bio, 1);
27843ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin    return 1;
279025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  }
28043ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  return 0;
281025b3d3459260670a883169cf0940e94cbd79b94David Benjamin}
282025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
2831d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjaminstatic int do_exchange(SSL_SESSION **out_session,
2841d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin                       SSL_CTX *ssl_ctx,
2855a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin                       const TestConfig *config,
2865a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin                       bool is_resume,
2871d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin                       int fd,
2881d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin                       SSL_SESSION *session) {
2891d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  early_callback_called = 0;
290025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
29143ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  SSL *ssl = SSL_new(ssl_ctx);
292025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  if (ssl == NULL) {
293025b3d3459260670a883169cf0940e94cbd79b94David Benjamin    BIO_print_errors_fp(stdout);
294025b3d3459260670a883169cf0940e94cbd79b94David Benjamin    return 1;
295025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  }
296025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
2975a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  SetConfigPtr(ssl, config);
2985a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin
2995a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->fallback_scsv) {
3005a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    if (!SSL_enable_fallback_scsv(ssl)) {
3015a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin      BIO_print_errors_fp(stdout);
3025a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin      return 1;
3035a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    }
3045a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  }
3055a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (!config->key_file.empty()) {
3065a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    if (!SSL_use_PrivateKey_file(ssl, config->key_file.c_str(),
3075a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin                                 SSL_FILETYPE_PEM)) {
3085a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin      BIO_print_errors_fp(stdout);
3095a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin      return 1;
3105a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    }
3115a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  }
3125a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (!config->cert_file.empty()) {
3135a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    if (!SSL_use_certificate_file(ssl, config->cert_file.c_str(),
3145a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin                                  SSL_FILETYPE_PEM)) {
3155a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin      BIO_print_errors_fp(stdout);
316025b3d3459260670a883169cf0940e94cbd79b94David Benjamin      return 1;
317025b3d3459260670a883169cf0940e94cbd79b94David Benjamin    }
318025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  }
3195a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->require_any_client_certificate) {
3205a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    SSL_set_verify(ssl, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3215a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin                   skip_verify);
3225a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  }
3235a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->false_start) {
3245a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH);
3255a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  }
3265a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->cbc_record_splitting) {
3275a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    SSL_set_mode(ssl, SSL_MODE_CBC_RECORD_SPLITTING);
3285a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  }
3295a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->partial_write) {
3305a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
3315a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  }
3325a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->no_tls12) {
3335a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    SSL_set_options(ssl, SSL_OP_NO_TLSv1_2);
3345a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  }
3355a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->no_tls11) {
3365a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    SSL_set_options(ssl, SSL_OP_NO_TLSv1_1);
3375a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  }
3385a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->no_tls1) {
3395a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    SSL_set_options(ssl, SSL_OP_NO_TLSv1);
3405a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  }
3415a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->no_ssl3) {
3425a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    SSL_set_options(ssl, SSL_OP_NO_SSLv3);
3435a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  }
3446fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  if (config->cookie_exchange) {
3456fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
3466fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  }
3475c24a1d6b67fd4a39ad7e34930763d85dd4b4b84David Benjamin  if (config->tls_d5_bug) {
3485c24a1d6b67fd4a39ad7e34930763d85dd4b4b84David Benjamin    SSL_set_options(ssl, SSL_OP_TLS_D5_BUG);
3495c24a1d6b67fd4a39ad7e34930763d85dd4b4b84David Benjamin  }
350a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  if (!config->expected_channel_id.empty()) {
351a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    SSL_enable_tls_channel_id(ssl);
352a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  }
353a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  if (!config->send_channel_id.empty()) {
354a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    EVP_PKEY *pkey = LoadPrivateKey(config->send_channel_id);
355a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    if (pkey == NULL) {
356a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin      BIO_print_errors_fp(stdout);
357a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin      return 1;
358a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    }
359a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    SSL_enable_tls_channel_id(ssl);
360a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    if (!SSL_set1_tls_channel_id(ssl, pkey)) {
361a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin      EVP_PKEY_free(pkey);
362a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin      BIO_print_errors_fp(stdout);
363a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin      return 1;
364a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    }
365a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    EVP_PKEY_free(pkey);
366a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  }
367e78bfded9f24725c47e0f5d0a64465566c3bdcf2David Benjamin  if (!config->host_name.empty()) {
368e78bfded9f24725c47e0f5d0a64465566c3bdcf2David Benjamin    SSL_set_tlsext_host_name(ssl, config->host_name.c_str());
369e78bfded9f24725c47e0f5d0a64465566c3bdcf2David Benjamin  }
370ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  if (!config->advertise_alpn.empty()) {
371ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin    SSL_set_alpn_protos(ssl, (const uint8_t *)config->advertise_alpn.data(),
372ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin                        config->advertise_alpn.size());
373ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  }
374025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
37543ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  BIO *bio = BIO_new_fd(fd, 1 /* take ownership */);
37643ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  if (bio == NULL) {
37743ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin    BIO_print_errors_fp(stdout);
37843ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin    return 1;
37943ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  }
3806fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  if (config->is_dtls) {
3816fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    BIO *packeted = packeted_bio_create();
3826fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    BIO_push(packeted, bio);
3836fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    bio = packeted;
3846fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin  }
3855a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->async) {
3866fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    BIO *async =
3876fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin        config->is_dtls ? async_bio_create_datagram() : async_bio_create();
38843ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin    BIO_push(async, bio);
38943ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin    bio = async;
39043ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  }
39143ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  SSL_set_bio(ssl, bio, bio);
39243ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin
3931d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  if (session != NULL) {
3941d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin    if (SSL_set_session(ssl, session) != 1) {
3951d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin      fprintf(stderr, "failed to set session\n");
3961d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin      return 2;
3971d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin    }
3981d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  }
3991d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
4001d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  int ret;
40143ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin  do {
4025a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    if (config->is_server) {
40343ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin      ret = SSL_accept(ssl);
40443ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin    } else {
40543ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin      ret = SSL_connect(ssl);
40643ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin    }
4075a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  } while (config->async && retry_async(ssl, ret, bio));
408025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  if (ret != 1) {
409025b3d3459260670a883169cf0940e94cbd79b94David Benjamin    SSL_free(ssl);
410025b3d3459260670a883169cf0940e94cbd79b94David Benjamin    BIO_print_errors_fp(stdout);
411025b3d3459260670a883169cf0940e94cbd79b94David Benjamin    return 2;
412025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  }
413025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
41401fe820ab957514f6b83e511492de1b3c03649d5David Benjamin  if (is_resume && (SSL_session_reused(ssl) == config->expect_session_miss)) {
41501fe820ab957514f6b83e511492de1b3c03649d5David Benjamin    fprintf(stderr, "session was%s reused\n",
41601fe820ab957514f6b83e511492de1b3c03649d5David Benjamin            SSL_session_reused(ssl) ? "" : " not");
4171d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin    return 2;
4181d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  }
4191d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
4205a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (!config->expected_server_name.empty()) {
421197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin    const char *server_name =
422197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin        SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
4235a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    if (server_name != config->expected_server_name) {
424197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin      fprintf(stderr, "servername mismatch (got %s; want %s)\n",
4255a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin              server_name, config->expected_server_name.c_str());
426197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin      return 2;
427197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin    }
4288f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin
4298f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin    if (!early_callback_called) {
4308f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin      fprintf(stderr, "early callback not called\n");
4318f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin      return 2;
4328f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin    }
433197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin  }
434197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin
4355a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (!config->expected_certificate_types.empty()) {
4367b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin    uint8_t *certificate_types;
4377b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin    int num_certificate_types =
438a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin        SSL_get0_certificate_types(ssl, &certificate_types);
4395a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    if (num_certificate_types !=
4405a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin        (int)config->expected_certificate_types.size() ||
4417b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin        memcmp(certificate_types,
4425a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin               config->expected_certificate_types.data(),
4437b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin               num_certificate_types) != 0) {
4447b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin      fprintf(stderr, "certificate types mismatch\n");
4457b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin      return 2;
4467b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin    }
4477b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin  }
4487b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin
4495a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (!config->expected_next_proto.empty()) {
4501f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin    const uint8_t *next_proto;
4511f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin    unsigned next_proto_len;
4521f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin    SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
4535a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    if (next_proto_len != config->expected_next_proto.size() ||
4545a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin        memcmp(next_proto, config->expected_next_proto.data(),
4555a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin               next_proto_len) != 0) {
4561f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin      fprintf(stderr, "negotiated next proto mismatch\n");
4571f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin      return 2;
4581f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin    }
4591f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin  }
4601f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin
461ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  if (!config->expected_alpn.empty()) {
462ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin    const uint8_t *alpn_proto;
463ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin    unsigned alpn_proto_len;
464ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin    SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len);
465ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin    if (alpn_proto_len != config->expected_alpn.size() ||
466ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin        memcmp(alpn_proto, config->expected_alpn.data(),
467ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin               alpn_proto_len) != 0) {
468ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin      fprintf(stderr, "negotiated alpn proto mismatch\n");
469ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin      return 2;
470ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin    }
471ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin  }
472ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin
473a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  if (!config->expected_channel_id.empty()) {
474a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    uint8_t channel_id[64];
475a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) {
476a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin      fprintf(stderr, "no channel id negotiated\n");
477a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin      return 2;
478a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    }
479a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    if (config->expected_channel_id.size() != 64 ||
480a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin        memcmp(config->expected_channel_id.data(),
481a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin               channel_id, 64) != 0) {
482a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin      fprintf(stderr, "channel id mismatch\n");
483a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin      return 2;
484a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin    }
485a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin  }
486a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin
4875a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config->write_different_record_sizes) {
4886fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    if (config->is_dtls) {
4896fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin      fprintf(stderr, "write_different_record_sizes not supported for DTLS\n");
4906fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin      return 6;
4916fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin    }
4927fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root    // This mode writes a number of different record sizes in an attempt to
4937fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root    // trip up the CBC record splitting code.
4947fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root    uint8_t buf[32769];
4957fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root    memset(buf, 0x42, sizeof(buf));
4967fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root    static const size_t kRecordSizes[] = {
4977fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769};
4987fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root    for (size_t i = 0; i < sizeof(kRecordSizes) / sizeof(kRecordSizes[0]);
4997fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root         i++) {
50043ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin      int w;
5017fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root      const size_t len = kRecordSizes[i];
5027fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root      size_t off = 0;
5037fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root
5047fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root      if (len > sizeof(buf)) {
5057fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        fprintf(stderr, "Bad kRecordSizes value.\n");
5067fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        return 5;
5077fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root      }
5087fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root
50943ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin      do {
5107fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        w = SSL_write(ssl, buf + off, len - off);
5117fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        if (w > 0) {
5127fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root          off += (size_t) w;
5137fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        }
5145a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin      } while ((config->async && retry_async(ssl, w, bio)) ||
5155a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin               (w > 0 && off < len));
5167fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root
5177fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root      if (w < 0 || off != len) {
518025b3d3459260670a883169cf0940e94cbd79b94David Benjamin        SSL_free(ssl);
519025b3d3459260670a883169cf0940e94cbd79b94David Benjamin        BIO_print_errors_fp(stdout);
520025b3d3459260670a883169cf0940e94cbd79b94David Benjamin        return 4;
521025b3d3459260670a883169cf0940e94cbd79b94David Benjamin      }
522025b3d3459260670a883169cf0940e94cbd79b94David Benjamin    }
5237fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root  } else {
524e58c4f53217699637e08147467a6b701b01f90d2David Benjamin    if (config->shim_writes_first) {
525e58c4f53217699637e08147467a6b701b01f90d2David Benjamin      int w;
526e58c4f53217699637e08147467a6b701b01f90d2David Benjamin      do {
527e58c4f53217699637e08147467a6b701b01f90d2David Benjamin        w = SSL_write(ssl, "hello", 5);
528e58c4f53217699637e08147467a6b701b01f90d2David Benjamin      } while (config->async && retry_async(ssl, w, bio));
529e58c4f53217699637e08147467a6b701b01f90d2David Benjamin    }
5307fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root    for (;;) {
5317fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root      uint8_t buf[512];
5327fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root      int n;
5337fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root      do {
5347fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        n = SSL_read(ssl, buf, sizeof(buf));
5355a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin      } while (config->async && retry_async(ssl, n, bio));
5367fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root      if (n < 0) {
5377fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        SSL_free(ssl);
5387fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        BIO_print_errors_fp(stdout);
5397fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        return 3;
5407fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root      } else if (n == 0) {
5417fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        break;
5427fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root      } else {
5437fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        for (int i = 0; i < n; i++) {
5447fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root          buf[i] ^= 0xff;
5457fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        }
5467fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        int w;
5477fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        do {
5487fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root          w = SSL_write(ssl, buf, n);
5495a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin        } while (config->async && retry_async(ssl, w, bio));
5507fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        if (w != n) {
5517fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root          SSL_free(ssl);
5527fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root          BIO_print_errors_fp(stdout);
5537fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root          return 4;
5547fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root        }
5557fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root      }
5567fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root    }
557025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  }
558025b3d3459260670a883169cf0940e94cbd79b94David Benjamin
5591d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  if (out_session) {
5601d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin    *out_session = SSL_get1_session(ssl);
5611d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  }
5621d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
5631d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  SSL_shutdown(ssl);
564025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  SSL_free(ssl);
565025b3d3459260670a883169cf0940e94cbd79b94David Benjamin  return 0;
566025b3d3459260670a883169cf0940e94cbd79b94David Benjamin}
5671d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
5681d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjaminint main(int argc, char **argv) {
569ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#if !defined(OPENSSL_WINDOWS)
5701d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  signal(SIGPIPE, SIG_IGN);
571ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#endif
5721d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
5735a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (!SSL_library_init()) {
5745a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin    return 1;
5751d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  }
5765a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  g_ex_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
5771d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
5785a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  TestConfig config;
5795a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (!ParseConfig(argc - 1, argv + 1, &config)) {
5801d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin    return usage(argv[0]);
5811d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  }
5821d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
5835a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  SSL_CTX *ssl_ctx = setup_ctx(&config);
5841d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  if (ssl_ctx == NULL) {
5851d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin    BIO_print_errors_fp(stdout);
5861d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin    return 1;
5871d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  }
5881d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
589e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley  SSL_SESSION *session = NULL;
5901d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  int ret = do_exchange(&session,
5915a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin                        ssl_ctx, &config,
5925a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin                        false /* is_resume */,
5931d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin                        3 /* fd */, NULL /* session */);
5941d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  if (ret != 0) {
595e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley    goto out;
5961d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  }
5971d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
5985a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin  if (config.resume) {
599e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley    ret = do_exchange(NULL,
600e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley                      ssl_ctx, &config,
601e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley                      true /* is_resume */,
602e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley                      4 /* fd */,
603e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley                      config.is_server ? NULL : session);
6041d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin    if (ret != 0) {
605e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley      goto out;
6061d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin    }
6071d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  }
6081d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin
609e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley  ret = 0;
610e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley
611e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langleyout:
6121d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  SSL_SESSION_free(session);
6131d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin  SSL_CTX_free(ssl_ctx);
614e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley  return ret;
6151d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin}
616