/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"

extern "C" {
// This is not something that should make you happy.
#include "libssl_internals.h"
}

#include <queue>
#include "gtest_utils.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"

namespace nss_test {

class HandshakeSecretTracker {
 public:
  HandshakeSecretTracker(const std::shared_ptr<TlsAgent>& agent,
                         uint16_t first_read_epoch, uint16_t first_write_epoch)
      : agent_(agent),
        next_read_epoch_(first_read_epoch),
        next_write_epoch_(first_write_epoch) {
    EXPECT_EQ(SECSuccess,
              SSL_SecretCallback(agent_->ssl_fd(),
                                 HandshakeSecretTracker::SecretCb, this));
  }

  void CheckComplete() const {
    EXPECT_EQ(0, next_read_epoch_);
    EXPECT_EQ(0, next_write_epoch_);
  }

 private:
  static void SecretCb(PRFileDesc* fd, PRUint16 epoch, SSLSecretDirection dir,
                       PK11SymKey* secret, void* arg) {
    HandshakeSecretTracker* t = reinterpret_cast<HandshakeSecretTracker*>(arg);
    t->SecretUpdated(epoch, dir, secret);
  }

  void SecretUpdated(PRUint16 epoch, SSLSecretDirection dir,
                     PK11SymKey* secret) {
    if (g_ssl_gtest_verbose) {
      std::cerr << agent_->role_str() << ": secret callback for " << dir
                << " epoch " << epoch << std::endl;
    }

    EXPECT_TRUE(secret);
    uint16_t* p;
    if (dir == ssl_secret_read) {
      p = &next_read_epoch_;
    } else {
      ASSERT_EQ(ssl_secret_write, dir);
      p = &next_write_epoch_;
    }
    EXPECT_EQ(*p, epoch);
    switch (*p) {
      case 1:  // 1 == 0-RTT, next should be handshake.
      case 2:  // 2 == handshake, next should be application data.
        (*p)++;
        break;

      case 3:  // 3 == application data, there should be no more.
        // Use 0 as a sentinel value.
        *p = 0;
        break;

      default:
        ADD_FAILURE() << "Unexpected next epoch: " << *p;
    }
  }

  std::shared_ptr<TlsAgent> agent_;
  uint16_t next_read_epoch_;
  uint16_t next_write_epoch_;
};

TEST_F(TlsConnectTest, HandshakeSecrets) {
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  EnsureTlsSetup();

  HandshakeSecretTracker c(client_, 2, 2);
  HandshakeSecretTracker s(server_, 2, 2);

  Connect();
  SendReceive();

  c.CheckComplete();
  s.CheckComplete();
}

TEST_F(TlsConnectTest, ZeroRttSecrets) {
  SetupForZeroRtt();

  HandshakeSecretTracker c(client_, 2, 1);
  HandshakeSecretTracker s(server_, 1, 2);

  client_->Set0RttEnabled(true);
  server_->Set0RttEnabled(true);
  ExpectResumption(RESUME_TICKET);
  ZeroRttSendReceive(true, true);
  Handshake();
  ExpectEarlyDataAccepted(true);
  CheckConnected();
  SendReceive();

  c.CheckComplete();
  s.CheckComplete();
}

class KeyUpdateTracker {
 public:
  KeyUpdateTracker(const std::shared_ptr<TlsAgent>& agent,
                   bool expect_read_secret)
      : agent_(agent), expect_read_secret_(expect_read_secret), called_(false) {
    EXPECT_EQ(SECSuccess, SSL_SecretCallback(agent_->ssl_fd(),
                                             KeyUpdateTracker::SecretCb, this));
  }

  void CheckCalled() const { EXPECT_TRUE(called_); }

 private:
  static void SecretCb(PRFileDesc* fd, PRUint16 epoch, SSLSecretDirection dir,
                       PK11SymKey* secret, void* arg) {
    KeyUpdateTracker* t = reinterpret_cast<KeyUpdateTracker*>(arg);
    t->SecretUpdated(epoch, dir, secret);
  }

  void SecretUpdated(PRUint16 epoch, SSLSecretDirection dir,
                     PK11SymKey* secret) {
    EXPECT_EQ(4U, epoch);
    EXPECT_EQ(expect_read_secret_, dir == ssl_secret_read);
    EXPECT_TRUE(secret);
    called_ = true;
  }

  std::shared_ptr<TlsAgent> agent_;
  bool expect_read_secret_;
  bool called_;
};

TEST_F(TlsConnectTest, KeyUpdateSecrets) {
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  Connect();
  // The update is to the client write secret; the server read secret.
  KeyUpdateTracker c(client_, false);
  KeyUpdateTracker s(server_, true);
  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(client_->ssl_fd(), PR_FALSE));
  SendReceive(50);
  SendReceive(60);
  CheckEpochs(4, 3);
  c.CheckCalled();
  s.CheckCalled();
}

// BadPrSocket is an instance of a PR IO layer that crashes the test if it is
// ever used for reading or writing.  It does that by failing to overwrite any
// of the DummyIOLayerMethods, which all crash when invoked.
class BadPrSocket : public DummyIOLayerMethods {
 public:
  BadPrSocket(std::shared_ptr<TlsAgent>& agent) : DummyIOLayerMethods() {
    static PRDescIdentity bad_identity = PR_GetUniqueIdentity("bad NSPR id");
    fd_ = DummyIOLayerMethods::CreateFD(bad_identity, this);

    // This is terrible, but NSPR doesn't provide an easy way to replace the
    // bottom layer of an IO stack.  Take the DummyPrSocket and replace its
    // NSPR method vtable with the ones from this object.
    dummy_layer_ =
        PR_GetIdentitiesLayer(agent->ssl_fd(), DummyPrSocket::LayerId());
    EXPECT_TRUE(dummy_layer_);
    original_methods_ = dummy_layer_->methods;
    original_secret_ = dummy_layer_->secret;
    dummy_layer_->methods = fd_->methods;
    dummy_layer_->secret = reinterpret_cast<PRFilePrivate*>(this);
  }

  // This will be destroyed before the agent, so we need to restore the state
  // before we tampered with it.
  virtual ~BadPrSocket() {
    dummy_layer_->methods = original_methods_;
    dummy_layer_->secret = original_secret_;
  }

 private:
  ScopedPRFileDesc fd_;
  PRFileDesc* dummy_layer_;
  const PRIOMethods* original_methods_;
  PRFilePrivate* original_secret_;
};

class StagedRecords {
 public:
  StagedRecords(std::shared_ptr<TlsAgent>& agent) : agent_(agent), records_() {
    EXPECT_EQ(SECSuccess,
              SSL_RecordLayerWriteCallback(
                  agent_->ssl_fd(), StagedRecords::StageRecordData, this));
  }

  virtual ~StagedRecords() {
    // Uninstall so that the callback doesn't fire during cleanup.
    EXPECT_EQ(SECSuccess,
              SSL_RecordLayerWriteCallback(agent_->ssl_fd(), nullptr, nullptr));
  }

  bool empty() const { return records_.empty(); }

  void ForwardAll(std::shared_ptr<TlsAgent>& peer) {
    EXPECT_NE(agent_, peer) << "can't forward to self";
    for (auto r : records_) {
      r.Forward(peer);
    }
    records_.clear();
  }

  // This forwards all saved data and checks the resulting state.
  void ForwardAll(std::shared_ptr<TlsAgent>& peer,
                  TlsAgent::State expected_state) {
    ForwardAll(peer);
    switch (expected_state) {
      case TlsAgent::STATE_CONNECTED:
        // The handshake callback should have been called, so check that before
        // checking that SSL_ForceHandshake succeeds.
        EXPECT_EQ(expected_state, peer->state());
        EXPECT_EQ(SECSuccess, SSL_ForceHandshake(peer->ssl_fd()));
        break;

      case TlsAgent::STATE_CONNECTING:
        // Check that SSL_ForceHandshake() blocks.
        EXPECT_EQ(SECFailure, SSL_ForceHandshake(peer->ssl_fd()));
        EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
        // Update and check the state.
        peer->Handshake();
        EXPECT_EQ(TlsAgent::STATE_CONNECTING, peer->state());
        break;

      default:
        ADD_FAILURE() << "No idea how to handle this state";
    }
  }

  void ForwardPartial(std::shared_ptr<TlsAgent>& peer) {
    if (records_.empty()) {
      ADD_FAILURE() << "No records to slice";
      return;
    }
    auto& last = records_.back();
    auto tail = last.SliceTail();
    ForwardAll(peer, TlsAgent::STATE_CONNECTING);
    records_.push_back(tail);
    EXPECT_EQ(TlsAgent::STATE_CONNECTING, peer->state());
  }

 private:
  // A single record.
  class StagedRecord {
   public:
    StagedRecord(const std::string role, uint16_t epoch, SSLContentType ct,
                 const uint8_t* data, size_t len)
        : role_(role), epoch_(epoch), content_type_(ct), data_(data, len) {
      if (g_ssl_gtest_verbose) {
        std::cerr << role_ << ": staged epoch " << epoch_ << " "
                  << content_type_ << ": " << data_ << std::endl;
      }
    }

    // This forwards staged data to the identified agent.
    void Forward(std::shared_ptr<TlsAgent>& peer) {
      // Now there should be staged data.
      EXPECT_FALSE(data_.empty());
      if (g_ssl_gtest_verbose) {
        std::cerr << role_ << ": forward epoch " << epoch_ << " " << data_
                  << std::endl;
      }
      EXPECT_EQ(SECSuccess,
                SSL_RecordLayerData(peer->ssl_fd(), epoch_, content_type_,
                                    data_.data(),
                                    static_cast<unsigned int>(data_.len())));
    }

    // Slices the tail off this record and returns it.
    StagedRecord SliceTail() {
      size_t slice = 1;
      if (data_.len() <= slice) {
        ADD_FAILURE() << "record too small to slice in two";
        slice = 0;
      }
      size_t keep = data_.len() - slice;
      StagedRecord tail(role_, epoch_, content_type_, data_.data() + keep,
                        slice);
      data_.Truncate(keep);
      return tail;
    }

   private:
    std::string role_;
    uint16_t epoch_;
    SSLContentType content_type_;
    DataBuffer data_;
  };

  // This is an SSLRecordWriteCallback that stages data.
  static SECStatus StageRecordData(PRFileDesc* fd, PRUint16 epoch,
                                   SSLContentType content_type,
                                   const PRUint8* data, unsigned int len,
                                   void* arg) {
    auto stage = reinterpret_cast<StagedRecords*>(arg);
    stage->records_.push_back(StagedRecord(stage->agent_->role_str(), epoch,
                                           content_type, data,
                                           static_cast<size_t>(len)));
    return SECSuccess;
  }

  std::shared_ptr<TlsAgent>& agent_;
  std::deque<StagedRecord> records_;
};

// Attempting to feed application data in before the handshake is complete
// should be caught.
static void RefuseApplicationData(std::shared_ptr<TlsAgent>& peer,
                                  uint16_t epoch) {
  static const uint8_t d[] = {1, 2, 3};
  EXPECT_EQ(SECFailure,
            SSL_RecordLayerData(peer->ssl_fd(), epoch, ssl_ct_application_data,
                                d, static_cast<unsigned int>(sizeof(d))));
  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
}

static void SendForwardReceive(std::shared_ptr<TlsAgent>& sender,
                               StagedRecords& sender_stage,
                               std::shared_ptr<TlsAgent>& receiver) {
  const size_t count = 10;
  sender->SendData(count, count);
  sender_stage.ForwardAll(receiver);
  receiver->ReadBytes(count);
}

TEST_P(TlsConnectStream, ReplaceRecordLayer) {
  StartConnect();
  client_->SetServerKeyBits(server_->server_key_bits());

  // BadPrSocket installs an IO layer that crashes when the SSL layer attempts
  // to read or write.
  BadPrSocket bad_layer_client(client_);
  BadPrSocket bad_layer_server(server_);

  // StagedRecords installs a handler for unprotected data from the socket, and
  // captures that data.
  StagedRecords client_stage(client_);
  StagedRecords server_stage(server_);

  // Both peers should refuse application data from epoch 0.
  RefuseApplicationData(client_, 0);
  RefuseApplicationData(server_, 0);

  // This first call forwards nothing, but it causes the client to handshake,
  // which starts things off.  This stages the ClientHello as a result.
  server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
  // This processes the ClientHello and stages the first server flight.
  client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING);

  // In TLS 1.3, this is 0-RTT; in <TLS 1.3, this is application data.
  // Neither is acceptable.
  RefuseApplicationData(client_, 1);
  RefuseApplicationData(server_, 1);

  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    // Application data in handshake is never acceptable.
    RefuseApplicationData(client_, 2);
    RefuseApplicationData(server_, 2);
    // Don't accept real data until the handshake is done.
    RefuseApplicationData(client_, 3);
    RefuseApplicationData(server_, 3);
    // Process the server flight and the client is done.
    server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
    client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
  } else {
    server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
    client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
    server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
  }
  CheckKeys();

  // Reading and writing application data should work.
  SendForwardReceive(client_, client_stage, server_);
  SendForwardReceive(server_, server_stage, client_);
}

TEST_F(TlsConnectStreamTls13, ReplaceRecordLayerZeroRtt) {
  SetupForZeroRtt();

  client_->Set0RttEnabled(true);
  server_->Set0RttEnabled(true);
  StartConnect();
  client_->SetServerKeyBits(server_->server_key_bits());

  BadPrSocket bad_layer_client(client_);
  BadPrSocket bad_layer_server(server_);

  StagedRecords client_stage(client_);
  StagedRecords server_stage(server_);

  ExpectResumption(RESUME_TICKET);

  // Send ClientHello
  server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);

  // The client can never accept 0-RTT.
  RefuseApplicationData(client_, 1);

  // Send some 0-RTT data, which get staged in `client_stage`.
  const char* kMsg = "EarlyData";
  const PRInt32 kMsgLen = static_cast<PRInt32>(strlen(kMsg));
  PRInt32 rv = PR_Write(client_->ssl_fd(), kMsg, kMsgLen);
  EXPECT_EQ(kMsgLen, rv);

  client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING);

  // The server should now have 0-RTT to read.
  std::vector<uint8_t> buf(kMsgLen);
  rv = PR_Read(server_->ssl_fd(), buf.data(), kMsgLen);
  EXPECT_EQ(kMsgLen, rv);

  // The handshake should happily finish.
  server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
  client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
  ExpectEarlyDataAccepted(true);
  CheckConnected();

  // Reading and writing application data should work.
  SendForwardReceive(client_, client_stage, server_);
  SendForwardReceive(server_, server_stage, client_);
}

static SECStatus AuthCompleteBlock(TlsAgent*, PRBool, PRBool) {
  return SECWouldBlock;
}

TEST_P(TlsConnectStream, ReplaceRecordLayerAsyncLateAuth) {
  StartConnect();
  client_->SetServerKeyBits(server_->server_key_bits());

  BadPrSocket bad_layer_client(client_);
  BadPrSocket bad_layer_server(server_);
  StagedRecords client_stage(client_);
  StagedRecords server_stage(server_);

  client_->SetAuthCertificateCallback(AuthCompleteBlock);

  server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
  client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING);
  server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);

  // Prior to TLS 1.3, the client sends its second flight immediately.  But in
  // TLS 1.3, a client won't send a Finished until it is happy with the server
  // certificate.  So blocking certificate validation causes the client to send
  // nothing.
  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    ASSERT_TRUE(client_stage.empty());

    // Client should have stopped reading when it saw the Certificate message,
    // so it will be reading handshake epoch, and writing cleartext.
    client_->CheckEpochs(2, 0);
    // Server should be reading handshake, and writing application data.
    server_->CheckEpochs(2, 3);

    // Handshake again and the client will read the remainder of the server's
    // flight, but it will remain blocked.
    client_->Handshake();
    ASSERT_TRUE(client_stage.empty());
    EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());
  } else {
    // In prior versions, the client's second flight is always sent.
    ASSERT_FALSE(client_stage.empty());
  }

  // Now declare the certificate good.
  EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
  client_->Handshake();
  ASSERT_FALSE(client_stage.empty());

  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state());
    client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
  } else {
    client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
    server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
  }
  CheckKeys();

  // Reading and writing application data should work.
  SendForwardReceive(client_, client_stage, server_);
}

TEST_F(TlsConnectStreamTls13, ReplaceRecordLayerAsyncPostHandshake) {
  StartConnect();
  client_->SetServerKeyBits(server_->server_key_bits());

  BadPrSocket bad_layer_client(client_);
  BadPrSocket bad_layer_server(server_);
  StagedRecords client_stage(client_);
  StagedRecords server_stage(server_);

  client_->SetAuthCertificateCallback(AuthCompleteBlock);

  server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
  client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING);
  server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);

  ASSERT_TRUE(client_stage.empty());
  client_->Handshake();
  ASSERT_TRUE(client_stage.empty());
  EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());

  // Now declare the certificate good.
  EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
  client_->Handshake();
  ASSERT_FALSE(client_stage.empty());

  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state());
    client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
  } else {
    client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
    server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
  }
  CheckKeys();

  // Reading and writing application data should work.
  SendForwardReceive(client_, client_stage, server_);

  // Post-handshake messages should work here.
  EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), nullptr, 0));
  SendForwardReceive(server_, server_stage, client_);
}

// This test ensures that data is correctly forwarded when the handshake is
// resumed after asynchronous server certificate authentication, when
// SSL_AuthCertificateComplete() is called.  The logic for resuming the
// handshake involves a different code path than the usual one, so this test
// exercises that code fully.
TEST_F(TlsConnectStreamTls13, ReplaceRecordLayerAsyncEarlyAuth) {
  StartConnect();
  client_->SetServerKeyBits(server_->server_key_bits());

  BadPrSocket bad_layer_client(client_);
  BadPrSocket bad_layer_server(server_);
  StagedRecords client_stage(client_);
  StagedRecords server_stage(server_);

  client_->SetAuthCertificateCallback(AuthCompleteBlock);

  server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
  client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING);

  // Send a partial flight on to the client.
  // This includes enough to trigger the certificate callback.
  server_stage.ForwardPartial(client_);
  EXPECT_TRUE(client_stage.empty());

  // Declare the certificate good.
  EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
  client_->Handshake();
  EXPECT_TRUE(client_stage.empty());

  // Send the remainder of the server flight.
  PRBool pending = PR_FALSE;
  EXPECT_EQ(SECSuccess,
            SSLInt_HasPendingHandshakeData(client_->ssl_fd(), &pending));
  EXPECT_EQ(PR_TRUE, pending);
  EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());
  server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
  client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
  CheckKeys();

  SendForwardReceive(server_, server_stage, client_);
}

TEST_P(TlsConnectStream, ForwardDataFromWrongEpoch) {
  const uint8_t data[] = {1};
  Connect();
  uint16_t next_epoch;
  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    EXPECT_EQ(SECFailure,
              SSL_RecordLayerData(client_->ssl_fd(), 2, ssl_ct_application_data,
                                  data, sizeof(data)));
    EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError())
        << "Passing data from an old epoch is rejected";
    next_epoch = 4;
  } else {
    // Prior to TLS 1.3, the epoch is only updated once during the handshake.
    next_epoch = 2;
  }
  EXPECT_EQ(SECFailure,
            SSL_RecordLayerData(client_->ssl_fd(), next_epoch,
                                ssl_ct_application_data, data, sizeof(data)));
  EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError())
      << "Passing data from a future epoch blocks";
}

TEST_F(TlsConnectStreamTls13, ForwardInvalidData) {
  const uint8_t data[1] = {0};

  EnsureTlsSetup();
  // Zero-length data.
  EXPECT_EQ(SECFailure, SSL_RecordLayerData(client_->ssl_fd(), 0,
                                            ssl_ct_application_data, data, 0));
  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());

  // NULL data.
  EXPECT_EQ(SECFailure,
            SSL_RecordLayerData(client_->ssl_fd(), 0, ssl_ct_application_data,
                                nullptr, 1));
  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
}

TEST_F(TlsConnectDatagram13, ForwardDataDtls) {
  EnsureTlsSetup();
  const uint8_t data[1] = {0};
  EXPECT_EQ(SECFailure,
            SSL_RecordLayerData(client_->ssl_fd(), 0, ssl_ct_application_data,
                                data, sizeof(data)));
  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
}

TEST_F(TlsConnectStreamTls13, SuppressEndOfEarlyData) {
  SetupForZeroRtt();

  client_->Set0RttEnabled(true);
  server_->Set0RttEnabled(true);
  client_->SetOption(SSL_SUPPRESS_END_OF_EARLY_DATA, true);
  server_->SetOption(SSL_SUPPRESS_END_OF_EARLY_DATA, true);
  StartConnect();
  client_->SetServerKeyBits(server_->server_key_bits());

  BadPrSocket bad_layer_client(client_);
  BadPrSocket bad_layer_server(server_);

  StagedRecords client_stage(client_);
  StagedRecords server_stage(server_);

  ExpectResumption(RESUME_TICKET);

  // Send ClientHello
  server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);

  // Send some 0-RTT data, which get staged in `client_stage`.
  const char* kMsg = "ABCDEF";
  const PRInt32 kMsgLen = static_cast<PRInt32>(strlen(kMsg));
  PRInt32 rv = PR_Write(client_->ssl_fd(), kMsg, kMsgLen);
  EXPECT_EQ(kMsgLen, rv);

  client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING);

  // The server should now have 0-RTT to read.
  std::vector<uint8_t> buf(kMsgLen);
  rv = PR_Read(server_->ssl_fd(), buf.data(), kMsgLen);
  EXPECT_EQ(kMsgLen, rv);

  // The handshake should happily finish, without the end of the early data.
  server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
  client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
  ExpectEarlyDataAccepted(true);
  CheckConnected();

  // Reading and writing application data should work.
  SendForwardReceive(client_, client_stage, server_);
  SendForwardReceive(server_, server_stage, client_);
}

}  // namespace nss_test
