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
13using std::string;
14using std::vector;
15
16namespace net {
17namespace test {
18namespace {
19
20class 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
31TEST(QuicCryptoClientConfigTest, CachedState_IsEmpty) {
32  QuicCryptoClientConfig::CachedState state;
33  EXPECT_TRUE(state.IsEmpty());
34}
35
36TEST(QuicCryptoClientConfigTest, CachedState_IsComplete) {
37  QuicCryptoClientConfig::CachedState state;
38  EXPECT_FALSE(state.IsComplete(QuicWallTime::FromUNIXSeconds(0)));
39}
40
41TEST(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
48TEST(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
56TEST(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
68TEST(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
82TEST(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
91TEST(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
105TEST(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
120TEST(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
146TEST(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
171TEST(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
193TEST(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
220TEST(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
237TEST(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