Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / quic / crypto / quic_crypto_client_config_test.cc
blob0e1ea792f8698e9cf13d3462a91d59c5df0c7b4f
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.
5 #include "net/quic/crypto/quic_crypto_client_config.h"
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"
13 using std::string;
14 using std::vector;
16 namespace net {
17 namespace test {
18 namespace {
20 class TestProofVerifyDetails : public ProofVerifyDetails {
21 ~TestProofVerifyDetails() override {}
23 // ProofVerifyDetails implementation
24 ProofVerifyDetails* Clone() const override {
25 return new TestProofVerifyDetails;
29 } // namespace
31 TEST(QuicCryptoClientConfigTest, CachedState_IsEmpty) {
32 QuicCryptoClientConfig::CachedState state;
33 EXPECT_TRUE(state.IsEmpty());
36 TEST(QuicCryptoClientConfigTest, CachedState_IsComplete) {
37 QuicCryptoClientConfig::CachedState state;
38 EXPECT_FALSE(state.IsComplete(QuicWallTime::FromUNIXSeconds(0)));
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());
48 TEST(QuicCryptoClientConfigTest, CachedState_SetProofVerifyDetails) {
49 QuicCryptoClientConfig::CachedState state;
50 EXPECT_TRUE(state.proof_verify_details() == nullptr);
51 ProofVerifyDetails* details = new TestProofVerifyDetails;
52 state.SetProofVerifyDetails(details);
53 EXPECT_EQ(details, state.proof_verify_details());
56 TEST(QuicCryptoClientConfigTest, CachedState_ServerDesignatedConnectionId) {
57 QuicCryptoClientConfig::CachedState state;
58 EXPECT_FALSE(state.has_server_designated_connection_id());
60 QuicConnectionId connection_id = 1234;
61 state.add_server_designated_connection_id(connection_id);
62 EXPECT_TRUE(state.has_server_designated_connection_id());
63 EXPECT_EQ(connection_id, state.GetNextServerDesignatedConnectionId());
64 EXPECT_FALSE(state.has_server_designated_connection_id());
66 // Allow the ID to be set multiple times. It's unusual that this would
67 // happen, but not impossible.
68 ++connection_id;
69 state.add_server_designated_connection_id(connection_id);
70 EXPECT_TRUE(state.has_server_designated_connection_id());
71 EXPECT_EQ(connection_id, state.GetNextServerDesignatedConnectionId());
72 ++connection_id;
73 state.add_server_designated_connection_id(connection_id);
74 EXPECT_EQ(connection_id, state.GetNextServerDesignatedConnectionId());
75 EXPECT_FALSE(state.has_server_designated_connection_id());
77 // Test FIFO behavior.
78 const QuicConnectionId first_cid = 0xdeadbeef;
79 const QuicConnectionId second_cid = 0xfeedbead;
80 state.add_server_designated_connection_id(first_cid);
81 state.add_server_designated_connection_id(second_cid);
82 EXPECT_TRUE(state.has_server_designated_connection_id());
83 EXPECT_EQ(first_cid, state.GetNextServerDesignatedConnectionId());
84 EXPECT_EQ(second_cid, state.GetNextServerDesignatedConnectionId());
87 TEST(QuicCryptoClientConfigTest, CachedState_ServerIdConsumedBeforeSet) {
88 QuicCryptoClientConfig::CachedState state;
89 EXPECT_FALSE(state.has_server_designated_connection_id());
90 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
91 EXPECT_DEBUG_DEATH(state.GetNextServerDesignatedConnectionId(),
92 "Attempting to consume a connection id "
93 "that was never designated.");
94 #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
97 TEST(QuicCryptoClientConfigTest, CachedState_ServerNonce) {
98 QuicCryptoClientConfig::CachedState state;
99 EXPECT_FALSE(state.has_server_nonce());
101 string server_nonce = "nonce_1";
102 state.add_server_nonce(server_nonce);
103 EXPECT_TRUE(state.has_server_nonce());
104 EXPECT_EQ(server_nonce, state.GetNextServerNonce());
105 EXPECT_FALSE(state.has_server_nonce());
107 // Allow the ID to be set multiple times. It's unusual that this would
108 // happen, but not impossible.
109 server_nonce = "nonce_2";
110 state.add_server_nonce(server_nonce);
111 EXPECT_TRUE(state.has_server_nonce());
112 EXPECT_EQ(server_nonce, state.GetNextServerNonce());
113 server_nonce = "nonce_3";
114 state.add_server_nonce(server_nonce);
115 EXPECT_EQ(server_nonce, state.GetNextServerNonce());
116 EXPECT_FALSE(state.has_server_nonce());
118 // Test FIFO behavior.
119 const string first_nonce = "first_nonce";
120 const string second_nonce = "second_nonce";
121 state.add_server_nonce(first_nonce);
122 state.add_server_nonce(second_nonce);
123 EXPECT_TRUE(state.has_server_nonce());
124 EXPECT_EQ(first_nonce, state.GetNextServerNonce());
125 EXPECT_EQ(second_nonce, state.GetNextServerNonce());
128 TEST(QuicCryptoClientConfigTest, CachedState_ServerNonceConsumedBeforeSet) {
129 QuicCryptoClientConfig::CachedState state;
130 EXPECT_FALSE(state.has_server_nonce());
131 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
132 EXPECT_DEBUG_DEATH(state.GetNextServerNonce(),
133 "Attempting to consume a server nonce "
134 "that was never designated.");
135 #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
138 TEST(QuicCryptoClientConfigTest, CachedState_InitializeFrom) {
139 QuicCryptoClientConfig::CachedState state;
140 QuicCryptoClientConfig::CachedState other;
141 state.set_source_address_token("TOKEN");
142 // TODO(rch): Populate other fields of |state|.
143 other.InitializeFrom(state);
144 EXPECT_EQ(state.server_config(), other.server_config());
145 EXPECT_EQ(state.source_address_token(), other.source_address_token());
146 EXPECT_EQ(state.certs(), other.certs());
147 EXPECT_EQ(1u, other.generation_counter());
148 EXPECT_FALSE(state.has_server_designated_connection_id());
149 EXPECT_FALSE(state.has_server_nonce());
152 TEST(QuicCryptoClientConfigTest, InchoateChlo) {
153 QuicCryptoClientConfig::CachedState state;
154 QuicCryptoClientConfig config;
155 QuicCryptoNegotiatedParameters params;
156 CryptoHandshakeMessage msg;
157 QuicServerId server_id("www.google.com", 80, false, PRIVACY_MODE_DISABLED);
158 config.FillInchoateClientHello(server_id, QuicVersionMax(), &state,
159 &params, &msg);
161 QuicTag cver;
162 EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kVER, &cver));
163 EXPECT_EQ(QuicVersionToQuicTag(QuicVersionMax()), cver);
166 TEST(QuicCryptoClientConfigTest, PreferAesGcm) {
167 QuicCryptoClientConfig config;
168 if (config.aead.size() > 1)
169 EXPECT_NE(kAESG, config.aead[0]);
170 config.PreferAesGcm();
171 EXPECT_EQ(kAESG, config.aead[0]);
174 TEST(QuicCryptoClientConfigTest, InchoateChloSecure) {
175 QuicCryptoClientConfig::CachedState state;
176 QuicCryptoClientConfig config;
177 QuicCryptoNegotiatedParameters params;
178 CryptoHandshakeMessage msg;
179 QuicServerId server_id("www.google.com", 443, true, PRIVACY_MODE_DISABLED);
180 config.FillInchoateClientHello(server_id, QuicVersionMax(), &state,
181 &params, &msg);
183 QuicTag pdmd;
184 EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kPDMD, &pdmd));
185 EXPECT_EQ(kX509, pdmd);
188 TEST(QuicCryptoClientConfigTest, InchoateChloSecureNoEcdsa) {
189 QuicCryptoClientConfig::CachedState state;
190 QuicCryptoClientConfig config;
191 config.DisableEcdsa();
192 QuicCryptoNegotiatedParameters params;
193 CryptoHandshakeMessage msg;
194 QuicServerId server_id("www.google.com", 443, true, PRIVACY_MODE_DISABLED);
195 config.FillInchoateClientHello(server_id, QuicVersionMax(), &state,
196 &params, &msg);
198 QuicTag pdmd;
199 EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kPDMD, &pdmd));
200 EXPECT_EQ(kX59R, pdmd);
203 TEST(QuicCryptoClientConfigTest, FillClientHello) {
204 QuicCryptoClientConfig::CachedState state;
205 QuicCryptoClientConfig config;
206 QuicCryptoNegotiatedParameters params;
207 QuicConnectionId kConnectionId = 1234;
208 string error_details;
209 MockRandom rand;
210 CryptoHandshakeMessage chlo;
211 QuicServerId server_id("www.google.com", 80, false, PRIVACY_MODE_DISABLED);
212 config.FillClientHello(server_id,
213 kConnectionId,
214 QuicVersionMax(),
215 &state,
216 QuicWallTime::Zero(),
217 &rand,
218 nullptr, // channel_id_key
219 &params,
220 &chlo,
221 &error_details);
223 // Verify that certain QuicTags have been set correctly in the CHLO.
224 QuicTag cver;
225 EXPECT_EQ(QUIC_NO_ERROR, chlo.GetUint32(kVER, &cver));
226 EXPECT_EQ(QuicVersionToQuicTag(QuicVersionMax()), cver);
229 TEST(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) {
230 QuicVersionVector supported_versions = QuicSupportedVersions();
231 if (supported_versions.size() == 1) {
232 // No downgrade attack is possible if the client only supports one version.
233 return;
235 QuicTagVector supported_version_tags;
236 for (size_t i = supported_versions.size(); i > 0; --i) {
237 supported_version_tags.push_back(
238 QuicVersionToQuicTag(supported_versions[i - 1]));
240 CryptoHandshakeMessage msg;
241 msg.set_tag(kSHLO);
242 msg.SetVector(kVER, supported_version_tags);
244 QuicCryptoClientConfig::CachedState cached;
245 QuicCryptoNegotiatedParameters out_params;
246 string error;
247 QuicCryptoClientConfig config;
248 EXPECT_EQ(QUIC_VERSION_NEGOTIATION_MISMATCH,
249 config.ProcessServerHello(msg, 0, supported_versions,
250 &cached, &out_params, &error));
251 EXPECT_EQ("Downgrade attack detected", error);
254 TEST(QuicCryptoClientConfigTest, InitializeFrom) {
255 QuicCryptoClientConfig config;
256 QuicServerId canonical_server_id("www.google.com", 80, false,
257 PRIVACY_MODE_DISABLED);
258 QuicCryptoClientConfig::CachedState* state =
259 config.LookupOrCreate(canonical_server_id);
260 // TODO(rch): Populate other fields of |state|.
261 state->set_source_address_token("TOKEN");
262 state->SetProofValid();
264 QuicServerId other_server_id("mail.google.com", 80, false,
265 PRIVACY_MODE_DISABLED);
266 config.InitializeFrom(other_server_id, canonical_server_id, &config);
267 QuicCryptoClientConfig::CachedState* other =
268 config.LookupOrCreate(other_server_id);
270 EXPECT_EQ(state->server_config(), other->server_config());
271 EXPECT_EQ(state->source_address_token(), other->source_address_token());
272 EXPECT_EQ(state->certs(), other->certs());
273 EXPECT_EQ(1u, other->generation_counter());
276 TEST(QuicCryptoClientConfigTest, Canonical) {
277 QuicCryptoClientConfig config;
278 config.AddCanonicalSuffix(".google.com");
279 QuicServerId canonical_id1("www.google.com", 80, false,
280 PRIVACY_MODE_DISABLED);
281 QuicServerId canonical_id2("mail.google.com", 80, false,
282 PRIVACY_MODE_DISABLED);
283 QuicCryptoClientConfig::CachedState* state =
284 config.LookupOrCreate(canonical_id1);
285 // TODO(rch): Populate other fields of |state|.
286 state->set_source_address_token("TOKEN");
287 state->SetProofValid();
289 QuicCryptoClientConfig::CachedState* other =
290 config.LookupOrCreate(canonical_id2);
292 EXPECT_TRUE(state->IsEmpty());
293 EXPECT_EQ(state->server_config(), other->server_config());
294 EXPECT_EQ(state->source_address_token(), other->source_address_token());
295 EXPECT_EQ(state->certs(), other->certs());
296 EXPECT_EQ(1u, other->generation_counter());
298 QuicServerId different_id("mail.google.org", 80, false,
299 PRIVACY_MODE_DISABLED);
300 EXPECT_TRUE(config.LookupOrCreate(different_id)->IsEmpty());
303 TEST(QuicCryptoClientConfigTest, CanonicalNotUsedIfNotValid) {
304 QuicCryptoClientConfig config;
305 config.AddCanonicalSuffix(".google.com");
306 QuicServerId canonical_id1("www.google.com", 80, false,
307 PRIVACY_MODE_DISABLED);
308 QuicServerId canonical_id2("mail.google.com", 80, false,
309 PRIVACY_MODE_DISABLED);
310 QuicCryptoClientConfig::CachedState* state =
311 config.LookupOrCreate(canonical_id1);
312 // TODO(rch): Populate other fields of |state|.
313 state->set_source_address_token("TOKEN");
315 // Do not set the proof as valid, and check that it is not used
316 // as a canonical entry.
317 EXPECT_TRUE(config.LookupOrCreate(canonical_id2)->IsEmpty());
320 TEST(QuicCryptoClientConfigTest, ClearCachedStates) {
321 QuicCryptoClientConfig config;
322 QuicServerId server_id("www.google.com", 80, false, PRIVACY_MODE_DISABLED);
323 QuicCryptoClientConfig::CachedState* state = config.LookupOrCreate(server_id);
324 // TODO(rch): Populate other fields of |state|.
325 vector<string> certs(1);
326 certs[0] = "Hello Cert";
327 state->SetProof(certs, "signature");
328 state->set_source_address_token("TOKEN");
329 state->SetProofValid();
330 EXPECT_EQ(1u, state->generation_counter());
332 // Verify LookupOrCreate returns the same data.
333 QuicCryptoClientConfig::CachedState* other = config.LookupOrCreate(server_id);
335 EXPECT_EQ(state, other);
336 EXPECT_EQ(1u, other->generation_counter());
338 // Clear the cached states.
339 config.ClearCachedStates();
341 // Verify LookupOrCreate doesn't have any data.
342 QuicCryptoClientConfig::CachedState* cleared_cache =
343 config.LookupOrCreate(server_id);
345 EXPECT_EQ(state, cleared_cache);
346 EXPECT_FALSE(cleared_cache->proof_valid());
347 EXPECT_TRUE(cleared_cache->server_config().empty());
348 EXPECT_TRUE(cleared_cache->certs().empty());
349 EXPECT_TRUE(cleared_cache->signature().empty());
350 EXPECT_EQ(2u, cleared_cache->generation_counter());
353 // Creates a minimal dummy reject message that will pass the client-config
354 // validation tests.
355 void FillInDummyReject(CryptoHandshakeMessage* rej, bool reject_is_stateless) {
356 if (reject_is_stateless) {
357 rej->set_tag(kSREJ);
358 } else {
359 rej->set_tag(kREJ);
362 // Minimum SCFG that passes config validation checks.
363 // clang-format off
364 unsigned char scfg[] = {
365 // SCFG
366 0x53, 0x43, 0x46, 0x47,
367 // num entries
368 0x01, 0x00,
369 // padding
370 0x00, 0x00,
371 // EXPY
372 0x45, 0x58, 0x50, 0x59,
373 // EXPY end offset
374 0x08, 0x00, 0x00, 0x00,
375 // Value
376 '1', '2', '3', '4',
377 '5', '6', '7', '8'
379 // clang-format on
380 rej->SetValue(kSCFG, scfg);
381 rej->SetStringPiece(kServerNonceTag, "SERVER_NONCE");
382 vector<QuicTag> reject_reasons;
383 reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
384 rej->SetVector(kRREJ, reject_reasons);
387 TEST(QuicCryptoClientConfigTest, ProcessReject) {
388 CryptoHandshakeMessage rej;
389 FillInDummyReject(&rej, /* stateless */ false);
391 // Now process the rejection.
392 QuicCryptoClientConfig::CachedState cached;
393 QuicCryptoNegotiatedParameters out_params;
394 string error;
395 QuicCryptoClientConfig config;
396 EXPECT_EQ(QUIC_NO_ERROR, config.ProcessRejection(
397 rej, QuicWallTime::FromUNIXSeconds(0), &cached,
398 true, // is_https
399 &out_params, &error));
400 EXPECT_FALSE(cached.has_server_designated_connection_id());
401 EXPECT_FALSE(cached.has_server_nonce());
404 TEST(QuicCryptoClientConfigTest, ProcessStatelessReject) {
405 // Create a dummy reject message and mark it as stateless.
406 CryptoHandshakeMessage rej;
407 FillInDummyReject(&rej, /* stateless */ true);
408 const QuicConnectionId kConnectionId = 0xdeadbeef;
409 const string server_nonce = "SERVER_NONCE";
410 rej.SetValue(kRCID, kConnectionId);
411 rej.SetStringPiece(kServerNonceTag, server_nonce);
413 // Now process the rejection.
414 QuicCryptoClientConfig::CachedState cached;
415 QuicCryptoNegotiatedParameters out_params;
416 string error;
417 QuicCryptoClientConfig config;
418 EXPECT_EQ(QUIC_NO_ERROR, config.ProcessRejection(
419 rej, QuicWallTime::FromUNIXSeconds(0), &cached,
420 true, // is_https
421 &out_params, &error));
422 EXPECT_TRUE(cached.has_server_designated_connection_id());
423 EXPECT_EQ(kConnectionId, cached.GetNextServerDesignatedConnectionId());
424 EXPECT_EQ(server_nonce, cached.GetNextServerNonce());
427 TEST(QuicCryptoClientConfigTest, BadlyFormattedStatelessReject) {
428 // Create a dummy reject message and mark it as stateless. Do not
429 // add an server-designated connection-id.
430 CryptoHandshakeMessage rej;
431 FillInDummyReject(&rej, /* stateless */ true);
433 // Now process the rejection.
434 QuicCryptoClientConfig::CachedState cached;
435 QuicCryptoNegotiatedParameters out_params;
436 string error;
437 QuicCryptoClientConfig config;
438 EXPECT_EQ(
439 QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND,
440 config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0), &cached,
441 true, // is_https
442 &out_params, &error));
443 EXPECT_FALSE(cached.has_server_designated_connection_id());
444 EXPECT_EQ("Missing kRCID", error);
447 } // namespace test
448 } // namespace net