/* -*- 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 <functional>
#include <memory>
#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 "gtest_utils.h"
#include "tls_connect.h"

namespace nss_test {

// 1.3 is disabled in the next few tests because we don't
// presently support resumption in 1.3.
TEST_P(TlsConnectStreamPre13, RenegotiateClient) {
  Connect();
  server_->PrepareForRenegotiate();
  client_->StartRenegotiate();
  Handshake();
  CheckConnected();
}

TEST_P(TlsConnectStreamPre13, RenegotiateServer) {
  Connect();
  client_->PrepareForRenegotiate();
  server_->StartRenegotiate();
  Handshake();
  CheckConnected();
}

TEST_P(TlsConnectStreamPre13, RenegotiateRandoms) {
  SSL3Random crand1, crand2, srand1, srand2;
  Connect();
  EXPECT_EQ(SECSuccess,
            SSLInt_GetHandshakeRandoms(client_->ssl_fd(), crand1, srand1));

  // Renegotiate and check that both randoms have changed.
  client_->PrepareForRenegotiate();
  server_->StartRenegotiate();
  Handshake();
  CheckConnected();
  EXPECT_EQ(SECSuccess,
            SSLInt_GetHandshakeRandoms(client_->ssl_fd(), crand2, srand2));

  EXPECT_NE(0, memcmp(crand1, crand2, sizeof(SSL3Random)));
  EXPECT_NE(0, memcmp(srand1, srand2, sizeof(SSL3Random)));
}

// The renegotiation options shouldn't cause an error if TLS 1.3 is chosen.
TEST_F(TlsConnectTest, RenegotiationConfigTls13) {
  EnsureTlsSetup();
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  server_->SetOption(SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_UNRESTRICTED);
  server_->SetOption(SSL_REQUIRE_SAFE_NEGOTIATION, PR_TRUE);
  Connect();
  SendReceive();
  CheckKeys();
}

TEST_P(TlsConnectStream, ConnectTls10AndServerRenegotiateHigher) {
  if (version_ == SSL_LIBRARY_VERSION_TLS_1_0) {
    GTEST_SKIP();
  }
  // Set the client so it will accept any version from 1.0
  // to |version_|.
  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, version_);
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
                           SSL_LIBRARY_VERSION_TLS_1_0);
  // Reset version so that the checks succeed.
  uint16_t test_version = version_;
  version_ = SSL_LIBRARY_VERSION_TLS_1_0;
  Connect();

  // Now renegotiate, with the server being set to do
  // |version_|.
  client_->PrepareForRenegotiate();
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, test_version);
  // Reset version and cipher suite so that the preinfo callback
  // doesn't fail.
  server_->ResetPreliminaryInfo();
  server_->StartRenegotiate();

  if (test_version >= SSL_LIBRARY_VERSION_TLS_1_3) {
    ExpectAlert(server_, kTlsAlertUnexpectedMessage);
  } else {
    ExpectAlert(server_, kTlsAlertProtocolVersion);
  }

  Handshake();
  if (test_version >= SSL_LIBRARY_VERSION_TLS_1_3) {
    // In TLS 1.3, the server detects this problem.
    client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT);
    server_->CheckErrorCode(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
  } else {
    client_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT);
    server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
  }
}

TEST_P(TlsConnectStream, ConnectTls10AndClientRenegotiateHigher) {
  if (version_ == SSL_LIBRARY_VERSION_TLS_1_0) {
    GTEST_SKIP();
  }
  // Set the client so it will accept any version from 1.0
  // to |version_|.
  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, version_);
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
                           SSL_LIBRARY_VERSION_TLS_1_0);
  // Reset version so that the checks succeed.
  uint16_t test_version = version_;
  version_ = SSL_LIBRARY_VERSION_TLS_1_0;
  Connect();

  // Now renegotiate, with the server being set to do
  // |version_|.
  server_->PrepareForRenegotiate();
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, test_version);
  // Reset version and cipher suite so that the preinfo callback
  // doesn't fail.
  server_->ResetPreliminaryInfo();
  client_->StartRenegotiate();
  if (test_version >= SSL_LIBRARY_VERSION_TLS_1_3) {
    ExpectAlert(server_, kTlsAlertUnexpectedMessage);
  } else {
    ExpectAlert(server_, kTlsAlertProtocolVersion);
  }
  Handshake();
  if (test_version >= SSL_LIBRARY_VERSION_TLS_1_3) {
    // In TLS 1.3, the server detects this problem.
    client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT);
    server_->CheckErrorCode(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
  } else {
    client_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT);
    server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
  }
}

TEST_P(TlsConnectStream, ConnectAndServerRenegotiateLower) {
  if (version_ == SSL_LIBRARY_VERSION_TLS_1_0) {
    GTEST_SKIP();
  }
  Connect();

  // Now renegotiate with the server set to TLS 1.0.
  client_->PrepareForRenegotiate();
  server_->PrepareForRenegotiate();
  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, version_);
  // Reset version and cipher suite so that the preinfo callback
  // doesn't fail.
  server_->ResetPreliminaryInfo();

  SECStatus rv = SSL_ReHandshake(server_->ssl_fd(), PR_TRUE);
  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    EXPECT_EQ(SECFailure, rv);
    return;
  }
  ASSERT_EQ(SECSuccess, rv);

  // Now, before handshaking, tweak the server configuration.
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
                           SSL_LIBRARY_VERSION_TLS_1_0);

  // The server should catch the own error.
  ExpectAlert(server_, kTlsAlertProtocolVersion);

  Handshake();
  client_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT);
  server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
}

TEST_P(TlsConnectStream, ConnectAndServerWontRenegotiateLower) {
  if (version_ == SSL_LIBRARY_VERSION_TLS_1_0) {
    GTEST_SKIP();
  }
  Connect();

  // Now renegotiate with the server set to TLS 1.0.
  client_->PrepareForRenegotiate();
  server_->PrepareForRenegotiate();
  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, version_);
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
                           SSL_LIBRARY_VERSION_TLS_1_0);
  // Reset version and cipher suite so that the preinfo callback
  // doesn't fail.
  server_->ResetPreliminaryInfo();

  EXPECT_EQ(SECFailure, SSL_ReHandshake(server_->ssl_fd(), PR_TRUE));
}

TEST_P(TlsConnectStream, ConnectAndClientWontRenegotiateLower) {
  if (version_ == SSL_LIBRARY_VERSION_TLS_1_0) {
    GTEST_SKIP();
  }
  Connect();

  // Now renegotiate with the client set to TLS 1.0.
  client_->PrepareForRenegotiate();
  server_->PrepareForRenegotiate();
  server_->ResetPreliminaryInfo();
  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
                           SSL_LIBRARY_VERSION_TLS_1_0);
  // The client will refuse to renegotiate down.
  EXPECT_EQ(SECFailure, SSL_ReHandshake(client_->ssl_fd(), PR_TRUE));
}

TEST_F(TlsConnectTest, Tls13RejectsRehandshakeClient) {
  EnsureTlsSetup();
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  Connect();
  SECStatus rv = SSL_ReHandshake(client_->ssl_fd(), PR_TRUE);
  EXPECT_EQ(SECFailure, rv);
  EXPECT_EQ(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED, PORT_GetError());
}

TEST_F(TlsConnectTest, Tls13RejectsRehandshakeServer) {
  EnsureTlsSetup();
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  Connect();
  SECStatus rv = SSL_ReHandshake(server_->ssl_fd(), PR_TRUE);
  EXPECT_EQ(SECFailure, rv);
  EXPECT_EQ(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED, PORT_GetError());
}

}  // namespace nss_test
