Bug 1483128 - Test that randoms aren't fixed, r=ekr
authorMartin Thomson <martin.thomson@gmail.com>
Tue, 28 Aug 2018 11:58:00 +1000 (2018-08-28)
changeset 14484 f182a11fbe532b1b9edb76a57a0d4609d9d8ab75
parent 14483 a4de0e81d1ccdb153817fbeda86d2182eec6f726
child 14485 22c307916092cb7ff109d40325c9d8b506459f00
push id3184
push usermartin.thomson@gmail.com
push dateMon, 03 Sep 2018 00:15:31 +0000 (2018-09-03)
reviewersekr
bugs1483128
Bug 1483128 - Test that randoms aren't fixed, r=ekr We can't easily test that ClientHello.random and ServerHello.random are truly random in these tests, but we can catch mistakes the likes of which produced this bug. This just runs a few handshakes and tests that none of the random values are equal to any other, or they are equal to zero.
gtests/ssl_gtest/ssl_loopback_unittest.cc
gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc
--- a/gtests/ssl_gtest/ssl_loopback_unittest.cc
+++ b/gtests/ssl_gtest/ssl_loopback_unittest.cc
@@ -536,16 +536,57 @@ TEST_F(TlsConnectTest, OneNRecordSplitti
   big_buffer.Allocate(1 + 16384 + 20);
   server_->SendBuffer(big_buffer);
   ASSERT_EQ(3U, records->count());
   EXPECT_EQ(ExpectedCbcLen(1), records->record(0).buffer.len());
   EXPECT_EQ(ExpectedCbcLen(16384), records->record(1).buffer.len());
   EXPECT_EQ(ExpectedCbcLen(20), records->record(2).buffer.len());
 }
 
+// We can't test for randomness easily here, but we can test that we don't
+// produce a zero value, or produce the same value twice.  There are 5 values
+// here: two ClientHello.random, two ServerHello.random, and one zero value.
+// Matrix them and fail if any are the same.
+TEST_P(TlsConnectGeneric, CheckRandoms) {
+  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
+
+  static const size_t random_len = 32;
+  uint8_t crandom1[random_len], srandom1[random_len];
+  uint8_t z[random_len] = {0};
+
+  auto ch = MakeTlsFilter<TlsHandshakeRecorder>(client_, ssl_hs_client_hello);
+  auto sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
+  Connect();
+  ASSERT_TRUE(ch->buffer().len() > (random_len + 2));
+  ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
+  memcpy(crandom1, ch->buffer().data() + 2, random_len);
+  memcpy(srandom1, sh->buffer().data() + 2, random_len);
+  EXPECT_NE(0, memcmp(crandom1, srandom1, random_len));
+  EXPECT_NE(0, memcmp(crandom1, z, random_len));
+  EXPECT_NE(0, memcmp(srandom1, z, random_len));
+
+  Reset();
+  ch = MakeTlsFilter<TlsHandshakeRecorder>(client_, ssl_hs_client_hello);
+  sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
+  Connect();
+  ASSERT_TRUE(ch->buffer().len() > (random_len + 2));
+  ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
+  const uint8_t* crandom2 = ch->buffer().data() + 2;
+  const uint8_t* srandom2 = sh->buffer().data() + 2;
+
+  EXPECT_NE(0, memcmp(crandom2, srandom2, random_len));
+  EXPECT_NE(0, memcmp(crandom2, z, random_len));
+  EXPECT_NE(0, memcmp(srandom2, z, random_len));
+
+  EXPECT_NE(0, memcmp(crandom1, crandom2, random_len));
+  EXPECT_NE(0, memcmp(crandom1, srandom2, random_len));
+  EXPECT_NE(0, memcmp(srandom1, crandom2, random_len));
+  EXPECT_NE(0, memcmp(srandom1, srandom2, random_len));
+}
+
 INSTANTIATE_TEST_CASE_P(
     GenericStream, TlsConnectGeneric,
     ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
                        TlsConnectTestBase::kTlsVAll));
 INSTANTIATE_TEST_CASE_P(
     GenericDatagram, TlsConnectGeneric,
     ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram,
                        TlsConnectTestBase::kTlsV11Plus));
--- a/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc
+++ b/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc
@@ -345,16 +345,40 @@ TEST_P(SSLv2ClientHelloTest, RequireSafe
 TEST_P(SSLv2ClientHelloTest, RequireSafeRenegotiationWithSCSV) {
   server_->SetOption(SSL_REQUIRE_SAFE_NEGOTIATION, PR_TRUE);
   std::vector<uint16_t> cipher_suites = {TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
                                          TLS_EMPTY_RENEGOTIATION_INFO_SCSV};
   SetAvailableCipherSuites(cipher_suites);
   Connect();
 }
 
+TEST_P(SSLv2ClientHelloTest, CheckServerRandom) {
+  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
+  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
+
+  static const size_t random_len = 32;
+  uint8_t srandom1[random_len];
+  uint8_t z[random_len] = {0};
+
+  auto sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
+  Connect();
+  ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
+  memcpy(srandom1, sh->buffer().data() + 2, random_len);
+  EXPECT_NE(0, memcmp(srandom1, z, random_len));
+
+  Reset();
+  sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
+  Connect();
+  ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
+  const uint8_t* srandom2 = sh->buffer().data() + 2;
+
+  EXPECT_NE(0, memcmp(srandom2, z, random_len));
+  EXPECT_NE(0, memcmp(srandom1, srandom2, random_len));
+}
+
 // Connect to the server with TLS 1.1, signalling that this is a fallback from
 // a higher version. As the server doesn't support anything higher than TLS 1.1
 // it must accept the connection.
 TEST_F(SSLv2ClientHelloTestF, FallbackSCSV) {
   EnsureTlsSetup();
   SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_1);
   ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_1);