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"
20 class TestProofVerifyDetails
: public ProofVerifyDetails
{
21 ~TestProofVerifyDetails() override
{}
23 // ProofVerifyDetails implementation
24 ProofVerifyDetails
* Clone() const override
{
25 return new TestProofVerifyDetails
;
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.
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());
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
,
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
,
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
,
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
;
210 CryptoHandshakeMessage chlo
;
211 QuicServerId
server_id("www.google.com", 80, false, PRIVACY_MODE_DISABLED
);
212 config
.FillClientHello(server_id
,
216 QuicWallTime::Zero(),
218 nullptr, // channel_id_key
223 // Verify that certain QuicTags have been set correctly in the CHLO.
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.
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
;
242 msg
.SetVector(kVER
, supported_version_tags
);
244 QuicCryptoClientConfig::CachedState cached
;
245 QuicCryptoNegotiatedParameters out_params
;
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
355 void FillInDummyReject(CryptoHandshakeMessage
* rej
, bool reject_is_stateless
) {
356 if (reject_is_stateless
) {
362 // Minimum SCFG that passes config validation checks.
364 unsigned char scfg
[] = {
366 0x53, 0x43, 0x46, 0x47,
372 0x45, 0x58, 0x50, 0x59,
374 0x08, 0x00, 0x00, 0x00,
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
;
395 QuicCryptoClientConfig config
;
396 EXPECT_EQ(QUIC_NO_ERROR
, config
.ProcessRejection(
397 rej
, QuicWallTime::FromUNIXSeconds(0), &cached
,
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
;
417 QuicCryptoClientConfig config
;
418 EXPECT_EQ(QUIC_NO_ERROR
, config
.ProcessRejection(
419 rej
, QuicWallTime::FromUNIXSeconds(0), &cached
,
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
;
437 QuicCryptoClientConfig config
;
439 QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
,
440 config
.ProcessRejection(rej
, QuicWallTime::FromUNIXSeconds(0), &cached
,
442 &out_params
, &error
));
443 EXPECT_FALSE(cached
.has_server_designated_connection_id());
444 EXPECT_EQ("Missing kRCID", error
);