Home | History | Annotate | Download | only in crypto
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/quic/crypto/quic_crypto_client_config.h"
      6 
      7 #include "net/quic/crypto/proof_verifier.h"
      8 #include "net/quic/quic_server_id.h"
      9 #include "net/quic/test_tools/mock_random.h"
     10 #include "net/quic/test_tools/quic_test_utils.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 
     13 using std::string;
     14 using std::vector;
     15 
     16 namespace net {
     17 namespace test {
     18 namespace {
     19 
     20 class TestProofVerifyDetails : public ProofVerifyDetails {
     21   virtual ~TestProofVerifyDetails() {}
     22 
     23   // ProofVerifyDetails implementation
     24   virtual ProofVerifyDetails* Clone() const OVERRIDE {
     25     return new TestProofVerifyDetails;
     26   }
     27 };
     28 
     29 }  // namespace
     30 
     31 TEST(QuicCryptoClientConfigTest, CachedState_IsEmpty) {
     32   QuicCryptoClientConfig::CachedState state;
     33   EXPECT_TRUE(state.IsEmpty());
     34 }
     35 
     36 TEST(QuicCryptoClientConfigTest, CachedState_IsComplete) {
     37   QuicCryptoClientConfig::CachedState state;
     38   EXPECT_FALSE(state.IsComplete(QuicWallTime::FromUNIXSeconds(0)));
     39 }
     40 
     41 TEST(QuicCryptoClientConfigTest, CachedState_GenerationCounter) {
     42   QuicCryptoClientConfig::CachedState state;
     43   EXPECT_EQ(0u, state.generation_counter());
     44   state.SetProofInvalid();
     45   EXPECT_EQ(1u, state.generation_counter());
     46 }
     47 
     48 TEST(QuicCryptoClientConfigTest, CachedState_SetProofVerifyDetails) {
     49   QuicCryptoClientConfig::CachedState state;
     50   EXPECT_TRUE(state.proof_verify_details() == NULL);
     51   ProofVerifyDetails* details = new TestProofVerifyDetails;
     52   state.SetProofVerifyDetails(details);
     53   EXPECT_EQ(details, state.proof_verify_details());
     54 }
     55 
     56 TEST(QuicCryptoClientConfigTest, CachedState_InitializeFrom) {
     57   QuicCryptoClientConfig::CachedState state;
     58   QuicCryptoClientConfig::CachedState other;
     59   state.set_source_address_token("TOKEN");
     60   // TODO(rch): Populate other fields of |state|.
     61   other.InitializeFrom(state);
     62   EXPECT_EQ(state.server_config(), other.server_config());
     63   EXPECT_EQ(state.source_address_token(), other.source_address_token());
     64   EXPECT_EQ(state.certs(), other.certs());
     65   EXPECT_EQ(1u, other.generation_counter());
     66 }
     67 
     68 TEST(QuicCryptoClientConfigTest, InchoateChlo) {
     69   QuicCryptoClientConfig::CachedState state;
     70   QuicCryptoClientConfig config;
     71   QuicCryptoNegotiatedParameters params;
     72   CryptoHandshakeMessage msg;
     73   QuicServerId server_id("www.google.com", 80, false, PRIVACY_MODE_DISABLED);
     74   config.FillInchoateClientHello(server_id, QuicVersionMax(), &state,
     75                                  &params, &msg);
     76 
     77   QuicTag cver;
     78   EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kVER, &cver));
     79   EXPECT_EQ(QuicVersionToQuicTag(QuicVersionMax()), cver);
     80 }
     81 
     82 TEST(QuicCryptoClientConfigTest, PreferAesGcm) {
     83   QuicCryptoClientConfig config;
     84   config.SetDefaults();
     85   if (config.aead.size() > 1)
     86     EXPECT_NE(kAESG, config.aead[0]);
     87   config.PreferAesGcm();
     88   EXPECT_EQ(kAESG, config.aead[0]);
     89 }
     90 
     91 TEST(QuicCryptoClientConfigTest, InchoateChloSecure) {
     92   QuicCryptoClientConfig::CachedState state;
     93   QuicCryptoClientConfig config;
     94   QuicCryptoNegotiatedParameters params;
     95   CryptoHandshakeMessage msg;
     96   QuicServerId server_id("www.google.com", 443, true, PRIVACY_MODE_DISABLED);
     97   config.FillInchoateClientHello(server_id, QuicVersionMax(), &state,
     98                                  &params, &msg);
     99 
    100   QuicTag pdmd;
    101   EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kPDMD, &pdmd));
    102   EXPECT_EQ(kX509, pdmd);
    103 }
    104 
    105 TEST(QuicCryptoClientConfigTest, InchoateChloSecureNoEcdsa) {
    106   QuicCryptoClientConfig::CachedState state;
    107   QuicCryptoClientConfig config;
    108   config.DisableEcdsa();
    109   QuicCryptoNegotiatedParameters params;
    110   CryptoHandshakeMessage msg;
    111   QuicServerId server_id("www.google.com", 443, true, PRIVACY_MODE_DISABLED);
    112   config.FillInchoateClientHello(server_id, QuicVersionMax(), &state,
    113                                  &params, &msg);
    114 
    115   QuicTag pdmd;
    116   EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kPDMD, &pdmd));
    117   EXPECT_EQ(kX59R, pdmd);
    118 }
    119 
    120 TEST(QuicCryptoClientConfigTest, FillClientHello) {
    121   QuicCryptoClientConfig::CachedState state;
    122   QuicCryptoClientConfig config;
    123   QuicCryptoNegotiatedParameters params;
    124   QuicConnectionId kConnectionId = 1234;
    125   string error_details;
    126   MockRandom rand;
    127   CryptoHandshakeMessage chlo;
    128   QuicServerId server_id("www.google.com", 80, false, PRIVACY_MODE_DISABLED);
    129   config.FillClientHello(server_id,
    130                          kConnectionId,
    131                          QuicVersionMax(),
    132                          &state,
    133                          QuicWallTime::Zero(),
    134                          &rand,
    135                          NULL,  // channel_id_key
    136                          &params,
    137                          &chlo,
    138                          &error_details);
    139 
    140   // Verify that certain QuicTags have been set correctly in the CHLO.
    141   QuicTag cver;
    142   EXPECT_EQ(QUIC_NO_ERROR, chlo.GetUint32(kVER, &cver));
    143   EXPECT_EQ(QuicVersionToQuicTag(QuicVersionMax()), cver);
    144 }
    145 
    146 TEST(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) {
    147   QuicVersionVector supported_versions = QuicSupportedVersions();
    148   if (supported_versions.size() == 1) {
    149     // No downgrade attack is possible if the client only supports one version.
    150     return;
    151   }
    152   QuicTagVector supported_version_tags;
    153   for (size_t i = supported_versions.size(); i > 0; --i) {
    154     supported_version_tags.push_back(
    155         QuicVersionToQuicTag(supported_versions[i - 1]));
    156   }
    157   CryptoHandshakeMessage msg;
    158   msg.set_tag(kSHLO);
    159   msg.SetVector(kVER, supported_version_tags);
    160 
    161   QuicCryptoClientConfig::CachedState cached;
    162   QuicCryptoNegotiatedParameters out_params;
    163   string error;
    164   QuicCryptoClientConfig config;
    165   EXPECT_EQ(QUIC_VERSION_NEGOTIATION_MISMATCH,
    166             config.ProcessServerHello(msg, 0, supported_versions,
    167                                       &cached, &out_params, &error));
    168   EXPECT_EQ("Downgrade attack detected", error);
    169 }
    170 
    171 TEST(QuicCryptoClientConfigTest, InitializeFrom) {
    172   QuicCryptoClientConfig config;
    173   QuicServerId canonical_server_id("www.google.com", 80, false,
    174                                    PRIVACY_MODE_DISABLED);
    175   QuicCryptoClientConfig::CachedState* state =
    176       config.LookupOrCreate(canonical_server_id);
    177   // TODO(rch): Populate other fields of |state|.
    178   state->set_source_address_token("TOKEN");
    179   state->SetProofValid();
    180 
    181   QuicServerId other_server_id("mail.google.com", 80, false,
    182                                PRIVACY_MODE_DISABLED);
    183   config.InitializeFrom(other_server_id, canonical_server_id, &config);
    184   QuicCryptoClientConfig::CachedState* other =
    185       config.LookupOrCreate(other_server_id);
    186 
    187   EXPECT_EQ(state->server_config(), other->server_config());
    188   EXPECT_EQ(state->source_address_token(), other->source_address_token());
    189   EXPECT_EQ(state->certs(), other->certs());
    190   EXPECT_EQ(1u, other->generation_counter());
    191 }
    192 
    193 TEST(QuicCryptoClientConfigTest, Canonical) {
    194   QuicCryptoClientConfig config;
    195   config.AddCanonicalSuffix(".google.com");
    196   QuicServerId canonical_id1("www.google.com", 80, false,
    197                              PRIVACY_MODE_DISABLED);
    198   QuicServerId canonical_id2("mail.google.com", 80, false,
    199                              PRIVACY_MODE_DISABLED);
    200   QuicCryptoClientConfig::CachedState* state =
    201       config.LookupOrCreate(canonical_id1);
    202   // TODO(rch): Populate other fields of |state|.
    203   state->set_source_address_token("TOKEN");
    204   state->SetProofValid();
    205 
    206   QuicCryptoClientConfig::CachedState* other =
    207       config.LookupOrCreate(canonical_id2);
    208 
    209   EXPECT_TRUE(state->IsEmpty());
    210   EXPECT_EQ(state->server_config(), other->server_config());
    211   EXPECT_EQ(state->source_address_token(), other->source_address_token());
    212   EXPECT_EQ(state->certs(), other->certs());
    213   EXPECT_EQ(1u, other->generation_counter());
    214 
    215   QuicServerId different_id("mail.google.org", 80, false,
    216                             PRIVACY_MODE_DISABLED);
    217   EXPECT_TRUE(config.LookupOrCreate(different_id)->IsEmpty());
    218 }
    219 
    220 TEST(QuicCryptoClientConfigTest, CanonicalNotUsedIfNotValid) {
    221   QuicCryptoClientConfig config;
    222   config.AddCanonicalSuffix(".google.com");
    223   QuicServerId canonical_id1("www.google.com", 80, false,
    224                              PRIVACY_MODE_DISABLED);
    225   QuicServerId canonical_id2("mail.google.com", 80, false,
    226                              PRIVACY_MODE_DISABLED);
    227   QuicCryptoClientConfig::CachedState* state =
    228       config.LookupOrCreate(canonical_id1);
    229   // TODO(rch): Populate other fields of |state|.
    230   state->set_source_address_token("TOKEN");
    231 
    232   // Do not set the proof as valid, and check that it is not used
    233   // as a canonical entry.
    234   EXPECT_TRUE(config.LookupOrCreate(canonical_id2)->IsEmpty());
    235 }
    236 
    237 TEST(QuicCryptoClientConfigTest, ClearCachedStates) {
    238   QuicCryptoClientConfig config;
    239   QuicServerId server_id("www.google.com", 80, false, PRIVACY_MODE_DISABLED);
    240   QuicCryptoClientConfig::CachedState* state = config.LookupOrCreate(server_id);
    241   // TODO(rch): Populate other fields of |state|.
    242   vector<string> certs(1);
    243   certs[0] = "Hello Cert";
    244   state->SetProof(certs, "signature");
    245   state->set_source_address_token("TOKEN");
    246   state->SetProofValid();
    247   EXPECT_EQ(1u, state->generation_counter());
    248 
    249   // Verify LookupOrCreate returns the same data.
    250   QuicCryptoClientConfig::CachedState* other = config.LookupOrCreate(server_id);
    251 
    252   EXPECT_EQ(state, other);
    253   EXPECT_EQ(1u, other->generation_counter());
    254 
    255   // Clear the cached states.
    256   config.ClearCachedStates();
    257 
    258   // Verify LookupOrCreate doesn't have any data.
    259   QuicCryptoClientConfig::CachedState* cleared_cache =
    260       config.LookupOrCreate(server_id);
    261 
    262   EXPECT_EQ(state, cleared_cache);
    263   EXPECT_FALSE(cleared_cache->proof_valid());
    264   EXPECT_TRUE(cleared_cache->server_config().empty());
    265   EXPECT_TRUE(cleared_cache->certs().empty());
    266   EXPECT_TRUE(cleared_cache->signature().empty());
    267   EXPECT_EQ(2u, cleared_cache->generation_counter());
    268 }
    269 
    270 }  // namespace test
    271 }  // namespace net
    272