tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ssl_keylog_unittest.cc (5228B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <cstdlib>
      8 #include <fstream>
      9 #include <sstream>
     10 
     11 #include "gtest_utils.h"
     12 #include "tls_connect.h"
     13 
     14 namespace nss_test {
     15 
     16 static const std::string kKeylogFilePath = "keylog.txt";
     17 static const std::string kKeylogBlankEnv = "SSLKEYLOGFILE=";
     18 static const std::string kKeylogSetEnv = kKeylogBlankEnv + kKeylogFilePath;
     19 
     20 extern "C" {
     21 extern FILE* ssl_keylog_iob;
     22 }
     23 
     24 class KeyLogFileTestBase : public TlsConnectGeneric {
     25 private:
     26  std::string env_to_set_;
     27 
     28 public:
     29  virtual void CheckKeyLog() = 0;
     30 
     31  KeyLogFileTestBase(std::string env) : env_to_set_(env) {}
     32 
     33  void SetUp() override {
     34    TlsConnectGeneric::SetUp();
     35    // Remove previous results (if any).
     36    (void)remove(kKeylogFilePath.c_str());
     37    PR_SetEnv(env_to_set_.c_str());
     38  }
     39 
     40  void ConnectAndCheck() {
     41    // This is a child process, ensure that error messages immediately
     42    // propagate or else it will not be visible.
     43    ::testing::GTEST_FLAG(throw_on_failure) = true;
     44 
     45    if (version_ == SSL_LIBRARY_VERSION_TLS_1_3) {
     46      SetupForZeroRtt();
     47      client_->Set0RttEnabled(true);
     48      server_->Set0RttEnabled(true);
     49      SetupEch(client_, server_);
     50      ExpectResumption(RESUME_TICKET);
     51      ZeroRttSendReceive(true, true);
     52      Handshake();
     53      ExpectEarlyDataAccepted(true);
     54      CheckConnected();
     55      SendReceive();
     56    } else {
     57      Connect();
     58    }
     59    CheckKeyLog();
     60    _exit(0);
     61  }
     62 };
     63 
     64 class KeyLogFileTest : public KeyLogFileTestBase {
     65 public:
     66  KeyLogFileTest() : KeyLogFileTestBase(kKeylogSetEnv) {}
     67 
     68  void CheckKeyLog() override {
     69    std::ifstream f(kKeylogFilePath);
     70    std::map<std::string, size_t> labels;
     71    std::set<std::string> client_randoms;
     72    for (std::string line; std::getline(f, line);) {
     73      if (line[0] == '#') {
     74        continue;
     75      }
     76 
     77      std::istringstream iss(line);
     78      std::string label, client_random, secret;
     79      iss >> label >> client_random >> secret;
     80 
     81      ASSERT_EQ(64U, client_random.size());
     82      client_randoms.insert(client_random);
     83      labels[label]++;
     84    }
     85 
     86    if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
     87      ASSERT_EQ(1U, client_randoms.size());
     88    } else {
     89      /* two handshakes for 0-RTT and ClientRandom from Outer ClientHello */
     90      ASSERT_EQ(3U, client_randoms.size());
     91    }
     92 
     93    // Every entry occurs twice (one log from server, one from client).
     94    if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
     95      ASSERT_EQ(2U, labels["CLIENT_RANDOM"]);
     96    } else {
     97      ASSERT_EQ(2U, labels["CLIENT_EARLY_TRAFFIC_SECRET"]);
     98      ASSERT_EQ(2U, labels["EARLY_EXPORTER_SECRET"]);
     99      ASSERT_EQ(2U, labels["ECH_SECRET"]);
    100      ASSERT_EQ(2U, labels["ECH_CONFIG"]);
    101      ASSERT_EQ(4U, labels["CLIENT_HANDSHAKE_TRAFFIC_SECRET"]);
    102      ASSERT_EQ(4U, labels["SERVER_HANDSHAKE_TRAFFIC_SECRET"]);
    103      ASSERT_EQ(4U, labels["CLIENT_TRAFFIC_SECRET_0"]);
    104      ASSERT_EQ(4U, labels["SERVER_TRAFFIC_SECRET_0"]);
    105      ASSERT_EQ(4U, labels["EXPORTER_SECRET"]);
    106    }
    107  }
    108 };
    109 
    110 // Tests are run in a separate process to ensure that NSS is not initialized yet
    111 // and can process the SSLKEYLOGFILE environment variable.
    112 
    113 TEST_P(KeyLogFileTest, KeyLogFile) {
    114  testing::GTEST_FLAG(death_test_style) = "threadsafe";
    115 
    116  ASSERT_EXIT(ConnectAndCheck(), ::testing::ExitedWithCode(0), "");
    117 }
    118 
    119 INSTANTIATE_TEST_SUITE_P(
    120    KeyLogFileDTLS12, KeyLogFileTest,
    121    ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram,
    122                       TlsConnectTestBase::kTlsV11V12));
    123 INSTANTIATE_TEST_SUITE_P(
    124    KeyLogFileTLS12, KeyLogFileTest,
    125    ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
    126                       TlsConnectTestBase::kTlsV10ToV12));
    127 #ifndef NSS_DISABLE_TLS_1_3
    128 INSTANTIATE_TEST_SUITE_P(
    129    KeyLogFileTLS13, KeyLogFileTest,
    130    ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
    131                       TlsConnectTestBase::kTlsV13));
    132 #endif
    133 
    134 class KeyLogFileUnsetTest : public KeyLogFileTestBase {
    135 public:
    136  KeyLogFileUnsetTest() : KeyLogFileTestBase(kKeylogBlankEnv) {}
    137 
    138  void CheckKeyLog() override {
    139    std::ifstream f(kKeylogFilePath);
    140    EXPECT_FALSE(f.good());
    141 
    142    EXPECT_EQ(nullptr, ssl_keylog_iob);
    143  }
    144 };
    145 
    146 TEST_P(KeyLogFileUnsetTest, KeyLogFile) {
    147  testing::GTEST_FLAG(death_test_style) = "threadsafe";
    148 
    149  ASSERT_EXIT(ConnectAndCheck(), ::testing::ExitedWithCode(0), "");
    150 }
    151 
    152 INSTANTIATE_TEST_SUITE_P(
    153    KeyLogFileDTLS12, KeyLogFileUnsetTest,
    154    ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram,
    155                       TlsConnectTestBase::kTlsV11V12));
    156 INSTANTIATE_TEST_SUITE_P(
    157    KeyLogFileTLS12, KeyLogFileUnsetTest,
    158    ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
    159                       TlsConnectTestBase::kTlsV10ToV12));
    160 #ifndef NSS_DISABLE_TLS_1_3
    161 INSTANTIATE_TEST_SUITE_P(
    162    KeyLogFileTLS13, KeyLogFileUnsetTest,
    163    ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
    164                       TlsConnectTestBase::kTlsV13));
    165 #endif
    166 
    167 }  // namespace nss_test