// Copyright 2014 The BoringSSL Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <openssl/base.h>

#if !defined(OPENSSL_WINDOWS)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#else
#include <io.h>
OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
#include <ws2tcpip.h>
OPENSSL_MSVC_PRAGMA(warning(pop))

OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
#endif

#include <assert.h>
#include <inttypes.h>
#include <string.h>
#include <time.h>

#include <openssl/aead.h>
#include <openssl/bio.h>
#include <openssl/bytestring.h>
#include <openssl/cipher.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/nid.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>

#include <functional>
#include <memory>
#include <string>
#include <vector>

#include "../../crypto/internal.h"
#include "async_bio.h"
#include "handshake_util.h"
#include "mock_quic_transport.h"
#include "packeted_bio.h"
#include "settings_writer.h"
#include "test_config.h"
#include "test_state.h"

#if defined(OPENSSL_LINUX)
#include <sys/prctl.h>
#endif


#if !defined(OPENSSL_WINDOWS)
using Socket = int;
#define INVALID_SOCKET (-1)

static int closesocket(int sock) { return close(sock); }
static void PrintSocketError(const char *func) { perror(func); }
#else
using Socket = SOCKET;

static void PrintSocketError(const char *func) {
  int error = WSAGetLastError();
  char *buffer;
  DWORD len = FormatMessageA(
      FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, 0, error, 0,
      reinterpret_cast<char *>(&buffer), 0, nullptr);
  std::string msg = "unknown error";
  if (len > 0) {
    msg.assign(buffer, len);
    while (!msg.empty() && (msg.back() == '\r' || msg.back() == '\n')) {
      msg.resize(msg.size() - 1);
    }
  }
  LocalFree(buffer);
  fprintf(stderr, "%s: %s (%d)\n", func, msg.c_str(), error);
}
#endif

class OwnedSocket {
 public:
  OwnedSocket() = default;
  explicit OwnedSocket(Socket sock) : sock_(sock) {}
  OwnedSocket(OwnedSocket &&other) { *this = std::move(other); }
  ~OwnedSocket() { reset(); }
  OwnedSocket &operator=(OwnedSocket &&other) {
    drain_on_close_ = other.drain_on_close_;
    reset(other.release());
    return *this;
  }

  bool is_valid() const { return sock_ != INVALID_SOCKET; }
  void set_drain_on_close(bool drain) { drain_on_close_ = drain; }

  void reset(Socket sock = INVALID_SOCKET) {
    if (is_valid()) {
      if (drain_on_close_) {
#if defined(OPENSSL_WINDOWS)
        shutdown(sock_, SD_SEND);
#else
        shutdown(sock_, SHUT_WR);
#endif
        while (true) {
          char buf[1024];
          if (recv(sock_, buf, sizeof(buf), 0) <= 0) {
            break;
          }
        }
      }
      closesocket(sock_);
    }

    drain_on_close_ = false;
    sock_ = sock;
  }

  Socket get() const { return sock_; }

  Socket release() {
    Socket sock = sock_;
    sock_ = INVALID_SOCKET;
    drain_on_close_ = false;
    return sock;
  }

 private:
  Socket sock_ = INVALID_SOCKET;
  bool drain_on_close_ = false;
};

static int Usage(const char *program) {
  fprintf(stderr, "Usage: %s [flags...]\n", program);
  return 1;
}

// Connect returns a new socket connected to the runner, or -1 on error.
static OwnedSocket Connect(const TestConfig *config) {
  sockaddr_storage addr;
  socklen_t addr_len = 0;
  if (config->ipv6) {
    sockaddr_in6 sin6;
    OPENSSL_memset(&sin6, 0, sizeof(sin6));
    sin6.sin6_family = AF_INET6;
    sin6.sin6_port = htons(config->port);
    if (!inet_pton(AF_INET6, "::1", &sin6.sin6_addr)) {
      PrintSocketError("inet_pton");
      return OwnedSocket();
    }
    addr_len = sizeof(sin6);
    memcpy(&addr, &sin6, addr_len);
  } else {
    sockaddr_in sin;
    OPENSSL_memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(config->port);
    if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
      PrintSocketError("inet_pton");
      return OwnedSocket();
    }
    addr_len = sizeof(sin);
    memcpy(&addr, &sin, addr_len);
  }

  OwnedSocket sock(socket(addr.ss_family, SOCK_STREAM, 0));
  if (!sock.is_valid()) {
    PrintSocketError("socket");
    return OwnedSocket();
  }
  int nodelay = 1;
  if (setsockopt(sock.get(), IPPROTO_TCP, TCP_NODELAY,
                 reinterpret_cast<const char *>(&nodelay),
                 sizeof(nodelay)) != 0) {
    PrintSocketError("setsockopt");
    return OwnedSocket();
  }

  if (connect(sock.get(), reinterpret_cast<const sockaddr *>(&addr),
              addr_len) != 0) {
    PrintSocketError("connect");
    return OwnedSocket();
  }

  return sock;
}

// DoRead reads from |ssl|, resolving any asynchronous operations. It returns
// the result value of the final |SSL_read| call.
static int DoRead(SSL *ssl, uint8_t *out, size_t max_out) {
  const TestConfig *config = GetTestConfig(ssl);
  TestState *test_state = GetTestState(ssl);
  if (test_state->quic_transport) {
    return test_state->quic_transport->ReadApplicationData(out, max_out);
  }
  int ret;
  do {
    ret = CheckIdempotentError("SSL_peek/SSL_read", ssl, [&]() -> int {
      return config->peek_then_read ? SSL_peek(ssl, out, max_out)
                                    : SSL_read(ssl, out, max_out);
    });

    // Run the exporter after each read. This is to test that the exporter fails
    // during a renegotiation.
    if (config->use_exporter_between_reads) {
      uint8_t buf;
      if (!SSL_export_keying_material(ssl, &buf, 1, nullptr, 0, nullptr, 0,
                                      0)) {
        fprintf(stderr, "failed to export keying material\n");
        return -1;
      }
    }
  } while (RetryAsync(ssl, ret));

  if (config->peek_then_read && ret > 0) {
    auto buf = std::make_unique<uint8_t[]>(static_cast<size_t>(ret));

    // SSL_peek should synchronously return the same data.
    int ret2 = SSL_peek(ssl, buf.get(), ret);
    if (ret2 != ret || OPENSSL_memcmp(buf.get(), out, ret) != 0) {
      fprintf(stderr, "First and second SSL_peek did not match.\n");
      return -1;
    }

    // SSL_read should synchronously return the same data and consume it.
    ret2 = SSL_read(ssl, buf.get(), ret);
    if (ret2 != ret || OPENSSL_memcmp(buf.get(), out, ret) != 0) {
      fprintf(stderr, "SSL_peek and SSL_read did not match.\n");
      return -1;
    }
  }

  return ret;
}

// WriteAll writes |in_len| bytes from |in| to |ssl|, resolving any asynchronous
// operations. It returns the result of the final |SSL_write| call.
static int WriteAll(SSL *ssl, const void *in_, size_t in_len) {
  TestState *test_state = GetTestState(ssl);
  const uint8_t *in = reinterpret_cast<const uint8_t *>(in_);
  if (test_state->quic_transport) {
    if (!test_state->quic_transport->WriteApplicationData(in, in_len)) {
      return -1;
    }
    return in_len;
  }
  int ret;
  do {
    ret = SSL_write(ssl, in, in_len);
    if (ret > 0) {
      in += ret;
      in_len -= ret;
    }
  } while (RetryAsync(ssl, ret) || (ret > 0 && in_len > 0));
  return ret;
}

// DoShutdown calls |SSL_shutdown|, resolving any asynchronous operations. It
// returns the result of the final |SSL_shutdown| call.
static int DoShutdown(SSL *ssl) {
  int ret;
  do {
    ret = SSL_shutdown(ssl);
  } while (RetryAsync(ssl, ret));
  return ret;
}

// DoSendFatalAlert calls |SSL_send_fatal_alert|, resolving any asynchronous
// operations. It returns the result of the final |SSL_send_fatal_alert| call.
static int DoSendFatalAlert(SSL *ssl, uint8_t alert) {
  int ret;
  do {
    ret = SSL_send_fatal_alert(ssl, alert);
  } while (RetryAsync(ssl, ret));
  return ret;
}

static uint16_t GetProtocolVersion(const SSL *ssl) {
  uint16_t version = SSL_version(ssl);
  if (!SSL_is_dtls(ssl)) {
    return version;
  }
  return 0x0201 + ~version;
}

static bool CheckListContains(const char *type,
                              size_t (*list_func)(const char **, size_t),
                              const char *str) {
  std::vector<const char *> list(list_func(nullptr, 0));
  list_func(list.data(), list.size());
  for (const char *expected : list) {
    if (strcmp(expected, str) == 0) {
      return true;
    }
  }
  fprintf(stderr, "Unexpected %s: %s\n", type, str);
  return false;
}

// CheckAuthProperties checks, after the initial handshake is completed or
// after a renegotiation, that authentication-related properties match |config|.
static bool CheckAuthProperties(SSL *ssl, bool is_resume,
                                const TestConfig *config) {
  if (!config->expect_ocsp_response.empty()) {
    const uint8_t *data;
    size_t len;
    SSL_get0_ocsp_response(ssl, &data, &len);
    if (bssl::Span(config->expect_ocsp_response) != bssl::Span(data, len)) {
      fprintf(stderr, "OCSP response mismatch\n");
      return false;
    }
  }

  if (!config->expect_signed_cert_timestamps.empty()) {
    const uint8_t *data;
    size_t len;
    SSL_get0_signed_cert_timestamp_list(ssl, &data, &len);
    if (bssl::Span(config->expect_signed_cert_timestamps) !=
        bssl::Span(data, len)) {
      fprintf(stderr, "SCT list mismatch\n");
      return false;
    }
  }

  if (config->expect_verify_result) {
    int expected_verify_result =
        config->verify_fail ? X509_V_ERR_APPLICATION_VERIFICATION : X509_V_OK;

    if (SSL_get_verify_result(ssl) != expected_verify_result) {
      fprintf(stderr, "Wrong certificate verification result\n");
      return false;
    }
  }

  if (!config->expect_peer_cert_file.empty()) {
    bssl::UniquePtr<X509> expect_leaf;
    bssl::UniquePtr<STACK_OF(X509)> expect_chain;
    if (!LoadCertificate(&expect_leaf, &expect_chain,
                         config->expect_peer_cert_file)) {
      return false;
    }

    // For historical reasons, clients report a chain with a leaf and servers
    // without.
    if (!config->is_server) {
      if (!sk_X509_insert(expect_chain.get(), expect_leaf.get(), 0)) {
        return false;
      }
      X509_up_ref(expect_leaf.get());  // sk_X509_insert takes ownership.
    }

    bssl::UniquePtr<X509> leaf(SSL_get_peer_certificate(ssl));
    STACK_OF(X509) *chain = SSL_get_peer_cert_chain(ssl);
    if (X509_cmp(leaf.get(), expect_leaf.get()) != 0) {
      fprintf(stderr, "Received a different leaf certificate than expected.\n");
      return false;
    }

    if (sk_X509_num(chain) != sk_X509_num(expect_chain.get())) {
      fprintf(stderr, "Received a chain of length %zu instead of %zu.\n",
              sk_X509_num(chain), sk_X509_num(expect_chain.get()));
      return false;
    }

    for (size_t i = 0; i < sk_X509_num(chain); i++) {
      if (X509_cmp(sk_X509_value(chain, i),
                   sk_X509_value(expect_chain.get(), i)) != 0) {
        fprintf(stderr, "Chain certificate %zu did not match.\n", i + 1);
        return false;
      }
    }
  }

  if (!!SSL_SESSION_has_peer_sha256(SSL_get_session(ssl)) !=
      config->expect_sha256_client_cert) {
    fprintf(stderr,
            "Unexpected SHA-256 client cert state: expected:%d is_resume:%d.\n",
            config->expect_sha256_client_cert, is_resume);
    return false;
  }

  if (config->expect_sha256_client_cert &&
      SSL_SESSION_get0_peer_certificates(SSL_get_session(ssl)) != nullptr) {
    fprintf(stderr, "Have both client cert and SHA-256 hash: is_resume:%d.\n",
            is_resume);
    return false;
  }

  const uint8_t *peer_sha256;
  size_t peer_sha256_len;
  SSL_SESSION_get0_peer_sha256(SSL_get_session(ssl), &peer_sha256,
                               &peer_sha256_len);
  if (SSL_SESSION_has_peer_sha256(SSL_get_session(ssl))) {
    if (peer_sha256_len != 32) {
      fprintf(stderr, "Peer SHA-256 hash had length %zu instead of 32\n",
              peer_sha256_len);
      return false;
    }
  } else {
    if (peer_sha256_len != 0) {
      fprintf(stderr, "Unexpected peer SHA-256 hash of length %zu\n",
              peer_sha256_len);
      return false;
    }
  }

  return true;
}

static bool IsPAKE(const SSL *ssl) {
  int idx = GetTestState(ssl)->selected_credential;
  return idx >= 0 && GetTestConfig(ssl)->credentials[idx].type ==
                         CredentialConfigType::kSPAKE2PlusV1;
}

// CheckHandshakeProperties checks, immediately after |ssl| completes its
// initial handshake (or False Starts), whether all the properties are
// consistent with the test configuration and invariants.
static bool CheckHandshakeProperties(SSL *ssl, bool is_resume,
                                     const TestConfig *config) {
  TestState *state = GetTestState(ssl);
  if (!CheckAuthProperties(ssl, is_resume, config)) {
    return false;
  }

  if (SSL_get_current_cipher(ssl) == nullptr) {
    fprintf(stderr, "null cipher after handshake\n");
    return false;
  }

  if (config->expect_version != 0 &&
      SSL_version(ssl) != int{config->expect_version}) {
    fprintf(stderr, "want version %04x, got %04x\n", config->expect_version,
            static_cast<uint16_t>(SSL_version(ssl)));
    return false;
  }

  bool expect_resume =
      is_resume && (!config->expect_session_miss || SSL_in_early_data(ssl));
  if (!!SSL_session_reused(ssl) != expect_resume) {
    fprintf(stderr, "session unexpectedly was%s reused\n",
            SSL_session_reused(ssl) ? "" : " not");
    return false;
  }

  bool expect_handshake_done =
      (is_resume || !config->false_start) && !SSL_in_early_data(ssl);
  if (expect_handshake_done != state->handshake_done) {
    fprintf(stderr, "handshake was%s completed\n",
            state->handshake_done ? "" : " not");
    return false;
  }

  if (expect_handshake_done && !config->is_server) {
    bool expect_new_session =
        !config->expect_no_session &&
        (!SSL_session_reused(ssl) || config->expect_ticket_renewal) &&
        // Session tickets are sent post-handshake in TLS 1.3.
        GetProtocolVersion(ssl) < TLS1_3_VERSION;
    if (expect_new_session != state->got_new_session) {
      fprintf(stderr,
              "new session was%s cached, but we expected the opposite\n",
              state->got_new_session ? "" : " not");
      return false;
    }
  }

  if (!is_resume) {
    if (config->expect_session_id && !state->got_new_session) {
      fprintf(stderr, "session was not cached on the server.\n");
      return false;
    }
    if (config->expect_no_session_id && state->got_new_session) {
      fprintf(stderr, "session was unexpectedly cached on the server.\n");
      return false;
    }
  }

  // early_callback_called is updated in the handshaker, so we don't see it
  // here.
  if (!config->handoff && config->is_server && !state->early_callback_called) {
    fprintf(stderr, "early callback not called\n");
    return false;
  }

  if (!config->expect_server_name.empty()) {
    const char *server_name =
        SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
    if (server_name == nullptr || server_name != config->expect_server_name) {
      fprintf(stderr, "servername mismatch (got %s; want %s)\n", server_name,
              config->expect_server_name.c_str());
      return false;
    }
  }

  if (!config->expect_next_proto.empty() || config->expect_no_next_proto) {
    const uint8_t *next_proto;
    unsigned next_proto_len;
    SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
    if (bssl::StringAsBytes(config->expect_next_proto) !=
        bssl::Span(next_proto, next_proto_len)) {
      fprintf(stderr, "negotiated next proto mismatch\n");
      return false;
    }
  }

  // On the server, the protocol selected in the ALPN callback must be echoed
  // out of |SSL_get0_alpn_selected|. On the client, it should report what the
  // test expected.
  const std::string &expect_alpn =
      config->is_server ? config->select_alpn : config->expect_alpn;
  const uint8_t *alpn_proto;
  unsigned alpn_proto_len;
  SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len);
  if (bssl::StringAsBytes(expect_alpn) !=
      bssl::Span(alpn_proto, alpn_proto_len)) {
    fprintf(stderr, "negotiated alpn proto mismatch\n");
    return false;
  }

  if (SSL_has_application_settings(ssl) !=
      (config->expect_peer_application_settings ? 1 : 0)) {
    fprintf(stderr,
            "connection %s application settings, but expected the opposite\n",
            SSL_has_application_settings(ssl) ? "has" : "does not have");
    return false;
  }
  std::string expect_settings = config->expect_peer_application_settings
                                    ? *config->expect_peer_application_settings
                                    : "";
  const uint8_t *peer_settings;
  size_t peer_settings_len;
  SSL_get0_peer_application_settings(ssl, &peer_settings, &peer_settings_len);
  if (bssl::StringAsBytes(expect_settings) !=
      bssl::Span(peer_settings, peer_settings_len)) {
    fprintf(stderr, "peer application settings mismatch\n");
    return false;
  }

  if (!config->expect_quic_transport_params.empty() && expect_handshake_done) {
    const uint8_t *peer_params;
    size_t peer_params_len;
    SSL_get_peer_quic_transport_params(ssl, &peer_params, &peer_params_len);
    if (bssl::Span(config->expect_quic_transport_params) !=
        bssl::Span(peer_params, peer_params_len)) {
      fprintf(stderr, "QUIC transport params mismatch\n");
      return false;
    }
  }

  if (!config->expect_channel_id.empty()) {
    uint8_t channel_id[64];
    if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) {
      fprintf(stderr, "no channel id negotiated\n");
      return false;
    }
    if (bssl::Span(config->expect_channel_id) != channel_id) {
      fprintf(stderr, "channel id mismatch\n");
      return false;
    }
  }

  if (config->expect_extended_master_secret && !SSL_get_extms_support(ssl)) {
    fprintf(stderr, "No EMS for connection when expected\n");
    return false;
  }

  if (config->expect_secure_renegotiation &&
      !SSL_get_secure_renegotiation_support(ssl)) {
    fprintf(stderr, "No secure renegotiation for connection when expected\n");
    return false;
  }

  if (config->expect_no_secure_renegotiation &&
      SSL_get_secure_renegotiation_support(ssl)) {
    fprintf(stderr,
            "Secure renegotiation unexpectedly negotiated for connection\n");
    return false;
  }

  if (config->expect_peer_signature_algorithm != 0 &&
      config->expect_peer_signature_algorithm !=
          SSL_get_peer_signature_algorithm(ssl)) {
    fprintf(stderr, "Peer signature algorithm was %04x, wanted %04x.\n",
            SSL_get_peer_signature_algorithm(ssl),
            config->expect_peer_signature_algorithm);
    return false;
  }

  if (config->expect_curve_id != 0) {
    uint16_t curve_id = SSL_get_curve_id(ssl);
    if (config->expect_curve_id != curve_id) {
      fprintf(stderr, "curve_id was %04x, wanted %04x\n", curve_id,
              config->expect_curve_id);
      return false;
    }
  }

  uint16_t cipher_id = SSL_CIPHER_get_protocol_id(SSL_get_current_cipher(ssl));
  if (config->expect_cipher_aes != 0 && EVP_has_aes_hardware() &&
      config->expect_cipher_aes != cipher_id) {
    fprintf(stderr, "Cipher ID was %04x, wanted %04x (has AES hardware)\n",
            cipher_id, config->expect_cipher_aes);
    return false;
  }

  if (config->expect_cipher_no_aes != 0 && !EVP_has_aes_hardware() &&
      config->expect_cipher_no_aes != cipher_id) {
    fprintf(stderr, "Cipher ID was %04x, wanted %04x (no AES hardware)\n",
            cipher_id, config->expect_cipher_no_aes);
    return false;
  }

  if (config->expect_cipher != 0 && config->expect_cipher != cipher_id) {
    fprintf(stderr, "Cipher ID was %04x, wanted %04x\n", cipher_id,
            config->expect_cipher);
    return false;
  }

  // The early data status is only applicable after the handshake is confirmed.
  if (!SSL_in_early_data(ssl) && !SSL_is_dtls(ssl)) {
    if ((config->expect_accept_early_data && !SSL_early_data_accepted(ssl)) ||
        (config->expect_reject_early_data && SSL_early_data_accepted(ssl))) {
      fprintf(stderr,
              "Early data was%s accepted, but we expected the opposite\n",
              SSL_early_data_accepted(ssl) ? "" : " not");
      return false;
    }

    const char *early_data_reason =
        SSL_early_data_reason_string(SSL_get_early_data_reason(ssl));
    if (!config->expect_early_data_reason.empty() &&
        config->expect_early_data_reason != early_data_reason) {
      fprintf(stderr, "Early data reason was \"%s\", expected \"%s\"\n",
              early_data_reason, config->expect_early_data_reason.c_str());
      return false;
    }
  }

  if (SSL_is_dtls(ssl) && SSL_in_early_data(ssl)) {
    // TODO(crbug.com/381113363): Support early data for DTLS 1.3.
    fprintf(stderr, "DTLS unexpectedly in early data\n");
    return false;
  }

  if (!config->psk.empty()) {
    if (SSL_get_peer_cert_chain(ssl) != nullptr) {
      fprintf(stderr, "Received peer certificate on a PSK cipher.\n");
      return false;
    }
  } else if (IsPAKE(ssl)) {
    if (SSL_get_peer_cert_chain(ssl) != nullptr) {
      fprintf(stderr, "Received peer certificate on a PAKE handshake.\n");
      return false;
    }
  } else if (!config->is_server || config->require_any_client_certificate) {
    if (SSL_get_peer_cert_chain(ssl) == nullptr) {
      fprintf(stderr, "Received no peer certificate but expected one.\n");
      return false;
    }
  }

  if (is_resume && config->expect_ticket_age_skew != 0 &&
      SSL_get_ticket_age_skew(ssl) != config->expect_ticket_age_skew) {
    fprintf(stderr, "Ticket age skew was %" PRId32 ", wanted %d\n",
            SSL_get_ticket_age_skew(ssl), config->expect_ticket_age_skew);
    return false;
  }

  if (config->expect_selected_credential.has_value() &&
      *config->expect_selected_credential != state->selected_credential) {
    fprintf(stderr, "Credential %d was used, wanted %d\n",
            state->selected_credential, *config->expect_selected_credential);
    return false;
  }

  if ((config->expect_hrr && !SSL_used_hello_retry_request(ssl)) ||
      (config->expect_no_hrr && SSL_used_hello_retry_request(ssl))) {
    fprintf(stderr, "Got %sHRR, but wanted opposite.\n",
            SSL_used_hello_retry_request(ssl) ? "" : "no ");
    return false;
  }

  if (config->expect_ech_accept != !!SSL_ech_accepted(ssl)) {
    fprintf(stderr, "ECH was %saccepted, but wanted opposite.\n",
            SSL_ech_accepted(ssl) ? "" : "not ");
    return false;
  }

  if (config->expect_key_usage_invalid != !!SSL_was_key_usage_invalid(ssl)) {
    fprintf(stderr, "X.509 key usage was %svalid, but wanted opposite.\n",
            SSL_was_key_usage_invalid(ssl) ? "in" : "");
    return false;
  }

  // Check all the selected parameters are covered by the string APIs.
  if (!CheckListContains("version", SSL_get_all_version_names,
                         SSL_get_version(ssl)) ||
      !CheckListContains(
          "cipher", SSL_get_all_standard_cipher_names,
          SSL_CIPHER_standard_name(SSL_get_current_cipher(ssl))) ||
      !CheckListContains("OpenSSL cipher name", SSL_get_all_cipher_names,
                         SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))) ||
      (SSL_get_group_id(ssl) != 0 &&
       !CheckListContains("group", SSL_get_all_group_names,
                          SSL_get_group_name(SSL_get_group_id(ssl)))) ||
      (SSL_get_peer_signature_algorithm(ssl) != 0 &&
       !CheckListContains(
           "sigalg", SSL_get_all_signature_algorithm_names,
           SSL_get_signature_algorithm_name(
               SSL_get_peer_signature_algorithm(ssl), /*include_curve=*/0))) ||
      (SSL_get_peer_signature_algorithm(ssl) != 0 &&
       !CheckListContains(
           "sigalg with curve", SSL_get_all_signature_algorithm_names,
           SSL_get_signature_algorithm_name(
               SSL_get_peer_signature_algorithm(ssl), /*include_curve=*/1)))) {
    return false;
  }

  // Test that handshake hints correctly skipped the expected operations.
  if (config->handshake_hints && !config->allow_hint_mismatch) {
    // If the private key operation is performed in the first roundtrip, a hint
    // match should have skipped it. This is ECDHE-based cipher suites in TLS
    // 1.2 and non-HRR handshakes in TLS 1.3.
    bool private_key_allowed;
    if (SSL_version(ssl) == TLS1_3_VERSION) {
      private_key_allowed = SSL_used_hello_retry_request(ssl);
    } else {
      private_key_allowed =
          SSL_CIPHER_get_kx_nid(SSL_get_current_cipher(ssl)) == NID_kx_rsa;
    }
    if (!private_key_allowed && state->used_private_key) {
      fprintf(
          stderr,
          "Performed private key operation, but hint should have skipped it\n");
      return false;
    }

    if (state->ticket_decrypt_done) {
      fprintf(stderr,
              "Performed ticket decryption, but hint should have skipped it\n");
      return false;
    }

    // TODO(davidben): Decide what we want to do with TLS 1.2 stateful
    // resumption.
  }
  return true;
}

static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
                       bssl::UniquePtr<SSL> *ssl_uniqueptr,
                       const TestConfig *config, bool is_resume, bool is_retry,
                       SettingsWriter *writer);

// DoConnection tests an SSL connection against the peer. On success, it returns
// true and sets |*out_session| to the negotiated SSL session. If the test is a
// resumption attempt, |is_resume| is true and |session| is the session from the
// previous exchange.
static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
                         SSL_CTX *ssl_ctx, const TestConfig *config,
                         const TestConfig *retry_config, bool is_resume,
                         SSL_SESSION *session, SettingsWriter *writer) {
  bssl::UniquePtr<SSL> ssl =
      config->NewSSL(ssl_ctx, session, std::make_unique<TestState>());
  if (!ssl) {
    return false;
  }
  if (config->is_server) {
    SSL_set_accept_state(ssl.get());
  } else {
    SSL_set_connect_state(ssl.get());
  }
  if (config->handshake_hints) {
#if defined(HANDSHAKER_SUPPORTED)
    GetTestState(ssl.get())->get_handshake_hints_cb =
        [&](const SSL_CLIENT_HELLO *client_hello) {
          return GetHandshakeHint(ssl.get(), writer, is_resume, client_hello);
        };
#else
    fprintf(stderr, "The external handshaker can only be used on Linux\n");
    return false;
#endif
  }

  OwnedSocket sock = Connect(config);
  if (!sock.is_valid()) {
    return false;
  }

  // Half-close and drain the socket before releasing it. This seems to be
  // necessary for graceful shutdown on Windows. It will also avoid write
  // failures in the test runner.
  sock.set_drain_on_close(true);

  // Windows uses |SOCKET| for socket types, but OpenSSL's API requires casting
  // them to |int|.
  bssl::UniquePtr<BIO> bio(
      BIO_new_socket(static_cast<int>(sock.get()), BIO_NOCLOSE));
  if (!bio) {
    return false;
  }

  uint8_t shim_id[8];
  CRYPTO_store_u64_le(shim_id, config->shim_id);
  if (!BIO_write_all(bio.get(), shim_id, sizeof(shim_id))) {
    return false;
  }

  if (config->is_dtls) {
    bssl::UniquePtr<BIO> packeted = PacketedBioCreate(
        GetClock(),
        [ssl_raw = ssl.get()](timeval *out) -> bool {
          return DTLSv1_get_timeout(ssl_raw, out);
        },
        [ssl_raw = ssl.get()](uint32_t mtu) -> bool {
          return SSL_set_mtu(ssl_raw, mtu);
        });
    if (!packeted) {
      return false;
    }
    GetTestState(ssl.get())->packeted_bio = packeted.get();
    BIO_push(packeted.get(), bio.release());
    bio = std::move(packeted);
  }
  if (config->async && !config->is_quic) {
    // Note async tests only affect callbacks in QUIC. The IO path does not
    // behave differently when synchronous or asynchronous our QUIC APIs.
    bssl::UniquePtr<BIO> async_scoped =
        config->is_dtls ? AsyncBioCreateDatagram() : AsyncBioCreate();
    if (!async_scoped) {
      return false;
    }
    BIO_push(async_scoped.get(), bio.release());
    GetTestState(ssl.get())->async_bio = async_scoped.get();
    bio = std::move(async_scoped);
  }
  if (config->is_quic) {
    GetTestState(ssl.get())->quic_transport =
        std::make_unique<MockQuicTransport>(std::move(bio), ssl.get());
  } else {
    SSL_set_bio(ssl.get(), bio.get(), bio.get());
    bio.release();  // SSL_set_bio takes ownership.
  }

  bool ret = DoExchange(out_session, &ssl, config, is_resume, false, writer);
  if (!config->is_server && is_resume && config->expect_reject_early_data) {
    // We must have failed due to an early data rejection.
    if (ret) {
      fprintf(stderr, "0-RTT exchange unexpected succeeded.\n");
      return false;
    }
    if (SSL_get_error(ssl.get(), -1) != SSL_ERROR_EARLY_DATA_REJECTED) {
      fprintf(stderr,
              "SSL_get_error did not signal SSL_ERROR_EARLY_DATA_REJECTED.\n");
      return false;
    }

    // Before resetting, early state should still be available.
    if (!SSL_in_early_data(ssl.get()) ||
        !CheckHandshakeProperties(ssl.get(), is_resume, config)) {
      fprintf(stderr, "SSL_in_early_data returned false before reset.\n");
      return false;
    }

    // Client pre- and post-0-RTT reject states are considered logically
    // different connections with different test expectations. Check that the
    // test did not mistakenly configure reason expectations on the wrong one.
    if (!config->expect_early_data_reason.empty()) {
      fprintf(stderr,
              "Test error: client reject -expect-early-data-reason flags "
              "should be configured with -on-retry, not -on-resume.\n");
      return false;
    }

    // Reset the connection and try again at 1-RTT.
    SSL_reset_early_data_reject(ssl.get());
    GetTestState(ssl.get())->cert_verified = false;

    // After resetting, the socket should report it is no longer in an early
    // data state.
    if (SSL_in_early_data(ssl.get())) {
      fprintf(stderr, "SSL_in_early_data returned true after reset.\n");
      return false;
    }

    if (!SetTestConfig(ssl.get(), retry_config)) {
      return false;
    }

    assert(!config->handoff);
    config = retry_config;
    ret = DoExchange(out_session, &ssl, retry_config, is_resume, true, writer);
  }

  // An ECH rejection appears as a failed connection. Note |ssl| may use a
  // different config on ECH rejection.
  if (config->expect_no_ech_retry_configs ||
      !config->expect_ech_retry_configs.empty()) {
    bssl::Span<const uint8_t> expected =
        config->expect_no_ech_retry_configs
            ? bssl::Span<const uint8_t>()
            : bssl::Span(config->expect_ech_retry_configs);
    if (ret) {
      fprintf(stderr, "Expected ECH rejection, but connection succeeded.\n");
      return false;
    }
    if (SSL_get_error(ssl.get(), -1) != SSL_ERROR_SSL ||
        !ERR_equals(ERR_peek_error(), ERR_LIB_SSL, SSL_R_ECH_REJECTED)) {
      fprintf(stderr, "Expected ECH rejection, but connection succeeded.\n");
      return false;
    }
    const uint8_t *retry_configs;
    size_t retry_configs_len;
    SSL_get0_ech_retry_configs(ssl.get(), &retry_configs, &retry_configs_len);
    if (bssl::Span(retry_configs, retry_configs_len) != expected) {
      fprintf(stderr, "ECH retry configs did not match expectations.\n");
      // Clear the error queue. Otherwise |SSL_R_ECH_REJECTED| will be printed
      // to stderr and the test framework will think the test had the expected
      // expectations.
      ERR_clear_error();
      return false;
    }
  }

  if (!ret) {
    // Print the |SSL_get_error| code. Otherwise, some failures are silent and
    // hard to debug.
    int ssl_err = SSL_get_error(ssl.get(), -1);
    if (ssl_err != SSL_ERROR_NONE) {
      fprintf(stderr, "SSL error: %s\n", SSL_error_description(ssl_err));
      if (ssl_err == SSL_ERROR_SYSCALL) {
        PrintSocketError("OS error");
      }
    }
    return false;
  }

  if (!GetTestState(ssl.get())->msg_callback_ok) {
    return false;
  }

  if (!config->expect_msg_callback.empty() &&
      GetTestState(ssl.get())->msg_callback_text !=
          config->expect_msg_callback) {
    fprintf(stderr, "Bad message callback trace. Wanted:\n%s\nGot:\n%s\n",
            config->expect_msg_callback.c_str(),
            GetTestState(ssl.get())->msg_callback_text.c_str());
    return false;
  }

  return true;
}

static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
                       bssl::UniquePtr<SSL> *ssl_uniqueptr,
                       const TestConfig *config, bool is_resume, bool is_retry,
                       SettingsWriter *writer) {
  int ret;
  SSL *ssl = ssl_uniqueptr->get();
  SSL_CTX *session_ctx = SSL_get_SSL_CTX(ssl);
  TestState *test_state = GetTestState(ssl);

  if (!config->implicit_handshake) {
    if (config->handoff) {
#if defined(HANDSHAKER_SUPPORTED)
      if (!DoSplitHandshake(ssl_uniqueptr, writer, is_resume)) {
        return false;
      }
      ssl = ssl_uniqueptr->get();
      test_state = GetTestState(ssl);
#else
      fprintf(stderr, "The external handshaker can only be used on Linux\n");
      return false;
#endif
    }

    do {
      ret = CheckIdempotentError("SSL_do_handshake", ssl, [&]() -> int {
        return SSL_do_handshake(ssl);
      });
    } while (RetryAsync(ssl, ret));

    if (config->forbid_renegotiation_after_handshake) {
      SSL_set_renegotiate_mode(ssl, ssl_renegotiate_never);
    }

    if (ret != 1 || !CheckHandshakeProperties(ssl, is_resume, config)) {
      return false;
    }

    CopySessions(session_ctx, SSL_get_SSL_CTX(ssl));

    if (is_resume && !is_retry && !config->is_server &&
        config->expect_no_offer_early_data && SSL_in_early_data(ssl)) {
      fprintf(stderr, "Client unexpectedly offered early data.\n");
      return false;
    }

    if (config->handshake_twice) {
      do {
        ret = SSL_do_handshake(ssl);
      } while (RetryAsync(ssl, ret));
      if (ret != 1) {
        return false;
      }
    }

    // Skip the |config->async| logic as this should be a no-op.
    if (config->no_op_extra_handshake && SSL_do_handshake(ssl) != 1) {
      fprintf(stderr, "Extra SSL_do_handshake was not a no-op.\n");
      return false;
    }

    if (config->early_write_after_message != 0) {
      if (!SSL_in_early_data(ssl) || config->is_server) {
        fprintf(stderr,
                "-early-write-after-message only works for 0-RTT connections "
                "on servers.\n");
        return false;
      }
      if (!config->shim_writes_first || !config->async) {
        fprintf(stderr,
                "-early-write-after-message requires -shim-writes-first and "
                "-async.\n");
        return false;
      }
      // Run the handshake until the specified message. Note that, if a
      // handshake record contains multiple messages, |SSL_do_handshake| usually
      // processes both atomically. The test must ensure there is a record
      // boundary after the desired message. Checking |last_message_received|
      // confirms this.
      do {
        ret = SSL_do_handshake(ssl);
      } while (test_state->last_message_received !=
                   config->early_write_after_message &&
               RetryAsync(ssl, ret));
      if (ret == 1) {
        fprintf(stderr, "Handshake unexpectedly succeeded.\n");
        return false;
      }
      if (test_state->last_message_received !=
          config->early_write_after_message) {
        // The handshake failed before we saw the target message. The generic
        // error-handling logic in the caller will print the error.
        return false;
      }
    }

    // Reset the state to assert later that the callback isn't called in
    // renegotiations.
    test_state->got_new_session = false;
  }

  if (config->export_keying_material > 0) {
    std::vector<uint8_t> result(
        static_cast<size_t>(config->export_keying_material));
    if (!SSL_export_keying_material(
            ssl, result.data(), result.size(), config->export_label.data(),
            config->export_label.size(),
            reinterpret_cast<const uint8_t *>(config->export_context.data()),
            config->export_context.size(), config->use_export_context)) {
      fprintf(stderr, "failed to export keying material\n");
      return false;
    }
    if (WriteAll(ssl, result.data(), result.size()) < 0) {
      return false;
    }
  }

  if (config->export_traffic_secrets) {
    bssl::Span<const uint8_t> read_secret, write_secret;
    if (!SSL_get_traffic_secrets(ssl, &read_secret, &write_secret)) {
      fprintf(stderr, "failed to export traffic secrets\n");
      return false;
    }

    assert(read_secret.size() <= 0xffff);
    assert(write_secret.size() == read_secret.size());
    const uint16_t secret_len = read_secret.size();
    if (WriteAll(ssl, &secret_len, sizeof(secret_len)) < 0 ||
        WriteAll(ssl, read_secret.data(), read_secret.size()) < 0 ||
        WriteAll(ssl, write_secret.data(), write_secret.size()) < 0) {
      return false;
    }
  }

  if (config->tls_unique) {
    uint8_t tls_unique[16];
    size_t tls_unique_len;
    if (!SSL_get_tls_unique(ssl, tls_unique, &tls_unique_len,
                            sizeof(tls_unique))) {
      fprintf(stderr, "failed to get tls-unique\n");
      return false;
    }

    if (tls_unique_len != 12) {
      fprintf(stderr, "expected 12 bytes of tls-unique but got %u",
              static_cast<unsigned>(tls_unique_len));
      return false;
    }

    if (WriteAll(ssl, tls_unique, tls_unique_len) < 0) {
      return false;
    }
  }

  if (config->send_alert) {
    if (DoSendFatalAlert(ssl, SSL_AD_DECOMPRESSION_FAILURE) < 0) {
      return false;
    }
    return true;
  }

  if (config->write_different_record_sizes) {
    if (config->is_dtls) {
      fprintf(stderr, "write_different_record_sizes not supported for DTLS\n");
      return false;
    }
    // This mode writes a number of different record sizes in an attempt to
    // trip up the CBC record splitting code.
    static const size_t kBufLen = 32769;
    auto buf = std::make_unique<uint8_t[]>(kBufLen);
    OPENSSL_memset(buf.get(), 0x42, kBufLen);
    static const size_t kRecordSizes[] = {
        0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769};
    for (size_t len : kRecordSizes) {
      if (len > kBufLen) {
        fprintf(stderr, "Bad kRecordSizes value.\n");
        return false;
      }
      if (WriteAll(ssl, buf.get(), len) < 0) {
        return false;
      }
    }
  } else {
    static const char kInitialWrite[] = "hello";
    bool pending_initial_write = false;
    if (config->read_with_unfinished_write) {
      if (!config->async) {
        fprintf(stderr, "-read-with-unfinished-write requires -async.\n");
        return false;
      }
      if (config->is_quic) {
        fprintf(stderr,
                "-read-with-unfinished-write is incompatible with QUIC.\n");
        return false;
      }

      // Let only one byte of the record through.
      AsyncBioAllowWrite(test_state->async_bio, 1);
      int write_ret = SSL_write(ssl, kInitialWrite, strlen(kInitialWrite));
      if (SSL_get_error(ssl, write_ret) != SSL_ERROR_WANT_WRITE) {
        fprintf(stderr, "Failed to leave unfinished write.\n");
        return false;
      }
      pending_initial_write = true;
    } else if (config->shim_writes_first) {
      if (WriteAll(ssl, kInitialWrite, strlen(kInitialWrite)) < 0) {
        return false;
      }
    }
    if (!config->shim_shuts_down) {
      for (;;) {
        if (config->key_update_before_read &&
            !SSL_key_update(ssl, SSL_KEY_UPDATE_NOT_REQUESTED)) {
          fprintf(stderr, "SSL_key_update failed.\n");
          return false;
        }

        // Read only 512 bytes at a time in TLS to ensure records may be
        // returned in multiple reads.
        size_t read_size = config->is_dtls ? 16384 : 512;
        if (config->read_size > 0) {
          read_size = config->read_size;
        }
        auto buf = std::make_unique<uint8_t[]>(read_size);

        int n = DoRead(ssl, buf.get(), read_size);
        int err = SSL_get_error(ssl, n);
        if (err == SSL_ERROR_ZERO_RETURN ||
            (n == 0 && err == SSL_ERROR_SYSCALL)) {
          if (n != 0) {
            fprintf(stderr, "Invalid SSL_get_error output\n");
            return false;
          }
          // Stop on either clean or unclean shutdown.
          break;
        } else if (err != SSL_ERROR_NONE) {
          if (n > 0) {
            fprintf(stderr, "Invalid SSL_get_error output\n");
            return false;
          }
          return false;
        }
        // Successfully read data.
        if (n <= 0) {
          fprintf(stderr, "Invalid SSL_get_error output\n");
          return false;
        }

        if (!config->is_server && is_resume && !is_retry &&
            config->expect_reject_early_data) {
          fprintf(stderr,
                  "Unexpectedly received data instead of 0-RTT reject.\n");
          return false;
        }

        // After a successful read, with or without False Start, the handshake
        // must be complete unless we are doing early data.
        if (!test_state->handshake_done && !SSL_early_data_accepted(ssl)) {
          fprintf(stderr, "handshake was not completed after SSL_read\n");
          return false;
        }

        // Clear the initial write, if unfinished.
        if (pending_initial_write) {
          if (WriteAll(ssl, kInitialWrite, strlen(kInitialWrite)) < 0) {
            return false;
          }
          pending_initial_write = false;
        }

        if (config->key_update &&
            !SSL_key_update(ssl, SSL_KEY_UPDATE_NOT_REQUESTED)) {
          fprintf(stderr, "SSL_key_update failed.\n");
          return false;
        }

        for (int i = 0; i < n; i++) {
          buf[i] ^= 0xff;
        }
        if (WriteAll(ssl, buf.get(), n) < 0) {
          return false;
        }
      }
    }
  }

  if (!config->is_server && !config->false_start &&
      !config->implicit_handshake &&
      // Session tickets are sent post-handshake in TLS 1.3.
      GetProtocolVersion(ssl) < TLS1_3_VERSION && test_state->got_new_session) {
    fprintf(stderr, "new session was established after the handshake\n");
    return false;
  }

  if (GetProtocolVersion(ssl) >= TLS1_3_VERSION && !config->is_server) {
    bool expect_new_session =
        !config->expect_no_session && !config->shim_shuts_down && !IsPAKE(ssl);
    if (expect_new_session != test_state->got_new_session) {
      fprintf(stderr,
              "new session was%s cached, but we expected the opposite\n",
              test_state->got_new_session ? "" : " not");
      return false;
    }

    if (expect_new_session) {
      bool got_early_data =
          !!SSL_SESSION_early_data_capable(test_state->new_session.get());
      if (config->expect_ticket_supports_early_data != got_early_data) {
        fprintf(stderr,
                "new session did%s support early data, but we expected the "
                "opposite\n",
                got_early_data ? "" : " not");
        return false;
      }

      if (config->expect_resumable_across_names.has_value()) {
        bool actual = !!SSL_SESSION_is_resumable_across_names(
            test_state->new_session.get());
        if (config->expect_resumable_across_names.value() != actual) {
          fprintf(stderr,
                  "new session did%s support cross-name resumption, but we "
                  "expected the opposite\n",
                  actual ? "" : " not");
          return false;
        }
      }
    }
  }

  if (out_session) {
    *out_session = std::move(test_state->new_session);
  }

  ret = DoShutdown(ssl);

  if (config->shim_shuts_down && config->check_close_notify) {
    // We initiate shutdown, so |SSL_shutdown| will return in two stages. First
    // it returns zero when our close_notify is sent, then one when the peer's
    // is received.
    if (ret != 0) {
      fprintf(stderr, "Unexpected SSL_shutdown result: %d != 0\n", ret);
      return false;
    }
    ret = DoShutdown(ssl);
  }

  if (ret != 1) {
    fprintf(stderr, "Unexpected SSL_shutdown result: %d != 1\n", ret);
    return false;
  }

  if (SSL_total_renegotiations(ssl) > 0) {
    if (SSL_SESSION_is_resumable(SSL_get_session(ssl))) {
      fprintf(stderr,
              "Renegotiations should never produce resumable sessions.\n");
      return false;
    }

    if (SSL_session_reused(ssl)) {
      fprintf(stderr, "Renegotiations should never resume sessions.\n");
      return false;
    }

    // Re-check authentication properties after a renegotiation. The reported
    // values should remain unchanged even if the server sent different SCT
    // lists.
    if (!CheckAuthProperties(ssl, is_resume, config)) {
      return false;
    }
  }

  if (SSL_total_renegotiations(ssl) != config->expect_total_renegotiations) {
    fprintf(stderr, "Expected %d renegotiations, got %d\n",
            config->expect_total_renegotiations, SSL_total_renegotiations(ssl));
    return false;
  }

  if (config->renegotiate_explicit &&
      SSL_total_renegotiations(ssl) != test_state->explicit_renegotiates) {
    fprintf(stderr, "Performed %d renegotiations, but triggered %d of them\n",
            SSL_total_renegotiations(ssl), test_state->explicit_renegotiates);
    return false;
  }

  return true;
}

class StderrDelimiter {
 public:
  ~StderrDelimiter() { fprintf(stderr, "--- DONE ---\n"); }
};

int main(int argc, char **argv) {
  // To distinguish ASan's output from ours, add a trailing message to stderr.
  // Anything following this line will be considered an error.
  StderrDelimiter delimiter;

#if defined(OPENSSL_WINDOWS)
  // Initialize Winsock.
  WORD wsa_version = MAKEWORD(2, 2);
  WSADATA wsa_data;
  int wsa_err = WSAStartup(wsa_version, &wsa_data);
  if (wsa_err != 0) {
    fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
    return 1;
  }
  if (wsa_data.wVersion != wsa_version) {
    fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
    return 1;
  }
#else
  signal(SIGPIPE, SIG_IGN);
#endif

  TestConfig initial_config, resume_config, retry_config;
  if (!ParseConfig(argc - 1, argv + 1, /*is_shim=*/true, &initial_config,
                   &resume_config, &retry_config)) {
    return Usage(argv[0]);
  }

  if (initial_config.is_handshaker_supported) {
#if defined(HANDSHAKER_SUPPORTED)
    printf("Yes\n");
#else
    printf("No\n");
#endif
    return 0;
  }

  if (initial_config.wait_for_debugger) {
#if defined(OPENSSL_WINDOWS)
    fprintf(stderr, "-wait-for-debugger is not supported on Windows.\n");
    return 1;
#else
#if defined(OPENSSL_LINUX)
    prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY);
#endif
    // The debugger will resume the process.
    raise(SIGSTOP);
#endif
  }

#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
  if (initial_config.fuzzer_mode) {
    CRYPTO_set_fuzzer_mode(1);
  }
#endif

  bssl::UniquePtr<SSL_CTX> ssl_ctx;
  bssl::UniquePtr<SSL_SESSION> session;
  for (int i = 0; i < initial_config.resume_count + 1; i++) {
    bool is_resume = i > 0;
    TestConfig *config = is_resume ? &resume_config : &initial_config;
    ssl_ctx = config->SetupCtx(ssl_ctx.get());
    if (!ssl_ctx) {
      ERR_print_errors_fp(stderr);
      return 1;
    }

    if (is_resume && !initial_config.is_server && !session) {
      fprintf(stderr, "No session to offer.\n");
      return 1;
    }

    bssl::UniquePtr<SSL_SESSION> offer_session = std::move(session);
    SettingsWriter writer;
    if (!writer.Init(i, config, offer_session.get())) {
      fprintf(stderr, "Error writing settings.\n");
      return 1;
    }
    bool ok = DoConnection(&session, ssl_ctx.get(), config, &retry_config,
                           is_resume, offer_session.get(), &writer);
    if (!writer.Commit()) {
      fprintf(stderr, "Error writing settings.\n");
      return 1;
    }
    if (!ok) {
      fprintf(stderr, "Connection %d failed.\n", i + 1);
      ERR_print_errors_fp(stderr);
      return 1;
    }

    if (config->resumption_delay != 0) {
      AdvanceClock(config->resumption_delay);
    }
  }

  return 0;
}
