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