ssl_fuzz_unittest.cc (10384B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include <limits> 6 #include <unordered_set> 7 8 #include "blapi.h" 9 #include "ssl.h" 10 #include "sslimpl.h" 11 #include "tls_connect.h" 12 13 #include "gtest/gtest.h" 14 15 namespace nss_test { 16 17 #ifdef UNSAFE_FUZZER_MODE 18 #define FUZZ_F(c, f) TEST_F(c, Fuzz_##f) 19 #define FUZZ_P(c, f) TEST_P(c, Fuzz_##f) 20 #else 21 #define FUZZ_F(c, f) TEST_F(c, DISABLED_Fuzz_##f) 22 #define FUZZ_P(c, f) TEST_P(c, DISABLED_Fuzz_##f) 23 #endif 24 25 static std::unordered_set<PRInt32> gFuzzedSslOptions = { 26 SSL_SECURITY, // irrelevant 27 SSL_SOCKS, // irrelevant 28 SSL_REQUEST_CERTIFICATE, // tls_server 29 SSL_HANDSHAKE_AS_CLIENT, // irrelevant 30 SSL_HANDSHAKE_AS_SERVER, // irrelevant 31 SSL_ENABLE_SSL2, // obsolete 32 SSL_ENABLE_SSL3, // obsolete 33 SSL_NO_CACHE, // tls_client, tls_server 34 SSL_REQUIRE_CERTIFICATE, // tls_server 35 SSL_ENABLE_FDX, 36 SSL_V2_COMPATIBLE_HELLO, // obsolete 37 SSL_ENABLE_TLS, // obsolete 38 SSL_ROLLBACK_DETECTION, 39 SSL_NO_STEP_DOWN, // unsupported 40 SSL_BYPASS_PKCS11, // unsupported 41 SSL_NO_LOCKS, // tls_client, tls_server 42 SSL_ENABLE_SESSION_TICKETS, // tls_client, tls_server 43 SSL_ENABLE_DEFLATE, // tls_client, tls_server 44 SSL_ENABLE_RENEGOTIATION, 45 SSL_REQUIRE_SAFE_NEGOTIATION, // tls_client, tls_server 46 SSL_ENABLE_FALSE_START, // tls_client 47 SSL_CBC_RANDOM_IV, // tls_client, tls_server 48 SSL_ENABLE_OCSP_STAPLING, // tls_client 49 SSL_ENABLE_NPN, // defunct 50 SSL_ENABLE_ALPN, // tls_client, tls_server 51 SSL_REUSE_SERVER_ECDHE_KEY, 52 SSL_ENABLE_FALLBACK_SCSV, // tls_client, tls_server 53 SSL_ENABLE_SERVER_DHE, 54 SSL_ENABLE_EXTENDED_MASTER_SECRET, // tls_client, tls_server 55 SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, 56 SSL_REQUIRE_DH_NAMED_GROUPS, // tls_client 57 SSL_ENABLE_0RTT_DATA, // tls_client, tls_server 58 SSL_RECORD_SIZE_LIMIT, 59 SSL_ENABLE_TLS13_COMPAT_MODE, // tls_client 60 SSL_ENABLE_DTLS_SHORT_HEADER, // tls_client, tls_server 61 SSL_ENABLE_HELLO_DOWNGRADE_CHECK, 62 SSL_ENABLE_V2_COMPATIBLE_HELLO, 63 SSL_ENABLE_POST_HANDSHAKE_AUTH, // tls_client 64 SSL_ENABLE_DELEGATED_CREDENTIALS, // tls_client, tls_server 65 SSL_SUPPRESS_END_OF_EARLY_DATA, 66 SSL_ENABLE_GREASE, // tls_client, tls_server 67 SSL_ENABLE_CH_EXTENSION_PERMUTATION, // tls_client 68 SSL_DB_LOAD_CERTIFICATE_CHAIN, 69 }; 70 71 const uint8_t kShortEmptyFinished[8] = {0}; 72 const uint8_t kLongEmptyFinished[128] = {0}; 73 74 class TlsFuzzTest : public TlsConnectGeneric {}; 75 76 // Record the application data stream. 77 class TlsApplicationDataRecorder : public TlsRecordFilter { 78 public: 79 TlsApplicationDataRecorder(const std::shared_ptr<TlsAgent>& a) 80 : TlsRecordFilter(a), buffer_() {} 81 82 virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, 83 const DataBuffer& input, 84 DataBuffer* output) { 85 if (header.content_type() == ssl_ct_application_data) { 86 buffer_.Append(input); 87 } 88 89 return KEEP; 90 } 91 92 const DataBuffer& buffer() const { return buffer_; } 93 94 private: 95 DataBuffer buffer_; 96 }; 97 98 // Check that due to the deterministic PRNG we derive 99 // the same master secret in two consecutive TLS sessions. 100 FUZZ_P(TlsFuzzTest, DeterministicExporter) { 101 const char kLabel[] = "label"; 102 std::vector<unsigned char> out1(32), out2(32); 103 104 // Make sure we have RSA blinding params. 105 Connect(); 106 107 Reset(); 108 ConfigureSessionCache(RESUME_NONE, RESUME_NONE); 109 110 // Reset the RNG state. 111 EXPECT_EQ(SECSuccess, RNG_RandomUpdate(NULL, 0)); 112 Connect(); 113 114 // Export a key derived from the MS and nonces. 115 SECStatus rv = 116 SSL_ExportKeyingMaterial(client_->ssl_fd(), kLabel, strlen(kLabel), false, 117 NULL, 0, out1.data(), out1.size()); 118 EXPECT_EQ(SECSuccess, rv); 119 120 Reset(); 121 ConfigureSessionCache(RESUME_NONE, RESUME_NONE); 122 123 // Reset the RNG state. 124 EXPECT_EQ(SECSuccess, RNG_RandomUpdate(NULL, 0)); 125 Connect(); 126 127 // Export another key derived from the MS and nonces. 128 rv = SSL_ExportKeyingMaterial(client_->ssl_fd(), kLabel, strlen(kLabel), 129 false, NULL, 0, out2.data(), out2.size()); 130 EXPECT_EQ(SECSuccess, rv); 131 132 // The two exported keys should be the same. 133 EXPECT_EQ(out1, out2); 134 } 135 136 // Check that due to the deterministic RNG two consecutive 137 // TLS sessions will have the exact same transcript. 138 FUZZ_P(TlsFuzzTest, DeterministicTranscript) { 139 // Make sure we have RSA blinding params. 140 Connect(); 141 142 // Connect a few times and compare the transcripts byte-by-byte. 143 DataBuffer last; 144 for (size_t i = 0; i < 5; i++) { 145 Reset(); 146 ConfigureSessionCache(RESUME_NONE, RESUME_NONE); 147 148 DataBuffer buffer; 149 MakeTlsFilter<TlsConversationRecorder>(client_, buffer); 150 MakeTlsFilter<TlsConversationRecorder>(server_, buffer); 151 152 // Reset the RNG state. 153 EXPECT_EQ(SECSuccess, RNG_RandomUpdate(NULL, 0)); 154 Connect(); 155 156 // Ensure the filters go away before |buffer| does. 157 client_->ClearFilter(); 158 server_->ClearFilter(); 159 160 if (last.len() > 0) { 161 EXPECT_EQ(last, buffer); 162 } 163 164 last = buffer; 165 } 166 } 167 168 // Check that we can establish and use a connection 169 // with all supported TLS versions, STREAM and DGRAM. 170 // Check that records are NOT encrypted. 171 // Check that records don't have a MAC. 172 FUZZ_P(TlsFuzzTest, ConnectSendReceive_NullCipher) { 173 // Set up app data filters. 174 auto client_recorder = MakeTlsFilter<TlsApplicationDataRecorder>(client_); 175 auto server_recorder = MakeTlsFilter<TlsApplicationDataRecorder>(server_); 176 177 Connect(); 178 179 // Construct the plaintext. 180 DataBuffer buf; 181 buf.Allocate(50); 182 for (size_t i = 0; i < buf.len(); ++i) { 183 buf.data()[i] = i & 0xff; 184 } 185 186 // Send/Receive data. 187 client_->SendBuffer(buf); 188 server_->SendBuffer(buf); 189 Receive(buf.len()); 190 191 // Check for plaintext on the wire. 192 EXPECT_EQ(buf, client_recorder->buffer()); 193 EXPECT_EQ(buf, server_recorder->buffer()); 194 } 195 196 // Check that an invalid Finished message doesn't abort the connection. 197 FUZZ_P(TlsFuzzTest, BogusClientFinished) { 198 EnsureTlsSetup(); 199 200 MakeTlsFilter<TlsInspectorReplaceHandshakeMessage>( 201 client_, kTlsHandshakeFinished, 202 DataBuffer(kShortEmptyFinished, sizeof(kShortEmptyFinished))); 203 Connect(); 204 SendReceive(); 205 } 206 207 // Check that an invalid Finished message doesn't abort the connection. 208 FUZZ_P(TlsFuzzTest, BogusServerFinished) { 209 EnsureTlsSetup(); 210 211 MakeTlsFilter<TlsInspectorReplaceHandshakeMessage>( 212 server_, kTlsHandshakeFinished, 213 DataBuffer(kLongEmptyFinished, sizeof(kLongEmptyFinished))); 214 Connect(); 215 SendReceive(); 216 } 217 218 // Check that an invalid server auth signature doesn't abort the connection. 219 FUZZ_P(TlsFuzzTest, BogusServerAuthSignature) { 220 EnsureTlsSetup(); 221 uint8_t msg_type = version_ == SSL_LIBRARY_VERSION_TLS_1_3 222 ? kTlsHandshakeCertificateVerify 223 : kTlsHandshakeServerKeyExchange; 224 MakeTlsFilter<TlsLastByteDamager>(server_, msg_type); 225 Connect(); 226 SendReceive(); 227 } 228 229 // Check that an invalid client auth signature doesn't abort the connection. 230 FUZZ_P(TlsFuzzTest, BogusClientAuthSignature) { 231 EnsureTlsSetup(); 232 client_->SetupClientAuth(); 233 server_->RequestClientAuth(true); 234 MakeTlsFilter<TlsLastByteDamager>(client_, kTlsHandshakeCertificateVerify); 235 Connect(); 236 } 237 238 // Check that session ticket resumption works. 239 FUZZ_P(TlsFuzzTest, SessionTicketResumption) { 240 ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); 241 Connect(); 242 SendReceive(); 243 244 Reset(); 245 ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); 246 ExpectResumption(RESUME_TICKET); 247 Connect(); 248 SendReceive(); 249 } 250 251 // Check that session tickets are not encrypted. 252 FUZZ_P(TlsFuzzTest, UnencryptedSessionTickets) { 253 ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET); 254 255 auto filter = MakeTlsFilter<TlsHandshakeRecorder>( 256 server_, kTlsHandshakeNewSessionTicket); 257 Connect(); 258 259 std::cerr << "ticket" << filter->buffer() << std::endl; 260 size_t offset = 4; // Skip lifetime. 261 262 if (version_ == SSL_LIBRARY_VERSION_TLS_1_3) { 263 offset += 4; // Skip ticket_age_add. 264 uint32_t nonce_len = 0; 265 EXPECT_TRUE(filter->buffer().Read(offset, 1, &nonce_len)); 266 offset += 1 + nonce_len; 267 } 268 269 offset += 2; // Skip the ticket length. 270 271 // This bit parses the contents of the ticket, which would ordinarily be 272 // encrypted. Start by checking that we have the right version. This needs 273 // to be updated every time that TLS_EX_SESS_TICKET_VERSION is changed. But 274 // we don't use the #define. That way, any time that code is updated, this 275 // test will fail unless it is manually checked. 276 uint32_t ticket_version; 277 EXPECT_TRUE(filter->buffer().Read(offset, 2, &ticket_version)); 278 EXPECT_EQ(0x010aU, ticket_version); 279 offset += 2; 280 281 // Check the protocol version number. 282 uint32_t tls_version = 0; 283 EXPECT_TRUE(filter->buffer().Read(offset, sizeof(version_), &tls_version)); 284 EXPECT_EQ(version_, static_cast<decltype(version_)>(tls_version)); 285 offset += sizeof(version_); 286 287 // Check the cipher suite. 288 uint32_t suite = 0; 289 EXPECT_TRUE(filter->buffer().Read(offset, 2, &suite)); 290 client_->CheckCipherSuite(static_cast<uint16_t>(suite)); 291 } 292 293 class MiscFuzzTest : public ::testing::Test {}; 294 295 FUZZ_F(MiscFuzzTest, UnfuzzedSslOption) { 296 PRIntn val; 297 SECStatus rv; 298 299 for (PRInt32 option = 0; option < std::numeric_limits<PRUint8>::max(); 300 ++option) { 301 rv = SSL_OptionGetDefault(option, &val); 302 // The return value should either be a failure (=> there is no such 303 // option) or the the option should be in the fuzzed options. 304 EXPECT_TRUE(rv == SECFailure || gFuzzedSslOptions.count(option)); 305 } 306 } 307 308 INSTANTIATE_TEST_SUITE_P( 309 FuzzStream, TlsFuzzTest, 310 ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream, 311 TlsConnectTestBase::kTlsVAll)); 312 INSTANTIATE_TEST_SUITE_P( 313 FuzzDatagram, TlsFuzzTest, 314 ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram, 315 TlsConnectTestBase::kTlsV11Plus)); 316 } // namespace nss_test