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 ¶ms, &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 ¶ms, &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 ¶ms, &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 ¶ms, 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