OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/variations/variations_seed_store.h" | 5 #include "components/variations/variations_seed_store.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/macros.h" | 8 #include "base/macros.h" |
9 #include "base/test/histogram_tester.h" | |
9 #include "build/build_config.h" | 10 #include "build/build_config.h" |
10 #include "components/prefs/testing_pref_service.h" | 11 #include "components/prefs/testing_pref_service.h" |
11 #include "components/variations/pref_names.h" | 12 #include "components/variations/pref_names.h" |
12 #include "components/variations/proto/study.pb.h" | 13 #include "components/variations/proto/study.pb.h" |
13 #include "components/variations/proto/variations_seed.pb.h" | 14 #include "components/variations/proto/variations_seed.pb.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
15 #include "third_party/zlib/google/compression_utils.h" | 16 #include "third_party/zlib/google/compression_utils.h" |
16 | 17 |
17 #if defined(OS_ANDROID) | 18 #if defined(OS_ANDROID) |
18 #include "components/variations/android/variations_seed_bridge.h" | 19 #include "components/variations/android/variations_seed_bridge.h" |
19 #endif // OS_ANDROID | 20 #endif // OS_ANDROID |
20 | 21 |
21 namespace variations { | 22 namespace variations { |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 class TestVariationsSeedStore : public VariationsSeedStore { | 26 class TestVariationsSeedStore : public VariationsSeedStore { |
26 public: | 27 public: |
27 explicit TestVariationsSeedStore(PrefService* local_state) | 28 explicit TestVariationsSeedStore(PrefService* local_state) |
28 : VariationsSeedStore(local_state) {} | 29 : VariationsSeedStore(local_state) {} |
29 ~TestVariationsSeedStore() override {} | 30 ~TestVariationsSeedStore() override {} |
30 | 31 |
31 bool StoreSeedForTesting(const std::string& seed_data) { | 32 bool StoreSeedForTesting(const std::string& seed_data) { |
32 return StoreSeedData(seed_data, std::string(), std::string(), | 33 return StoreSeedData(seed_data, std::string(), std::string(), |
33 base::Time::Now(), false, false, nullptr); | 34 base::Time::Now(), false, false, nullptr); |
34 } | 35 } |
35 | 36 |
36 VariationsSeedStore::VerifySignatureResult VerifySeedSignature( | 37 bool SignatureVerificationEnabled() override { return false; } |
37 const std::string& seed_bytes, | |
38 const std::string& base64_seed_signature) override { | |
39 return VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_ENUM_SIZE; | |
40 } | |
41 | 38 |
42 private: | 39 private: |
43 DISALLOW_COPY_AND_ASSIGN(TestVariationsSeedStore); | 40 DISALLOW_COPY_AND_ASSIGN(TestVariationsSeedStore); |
44 }; | 41 }; |
45 | 42 |
46 | 43 |
47 // Populates |seed| with simple test data. The resulting seed will contain one | 44 // Populates |seed| with simple test data. The resulting seed will contain one |
48 // study called "test", which contains one experiment called "abc" with | 45 // study called "test", which contains one experiment called "abc" with |
49 // probability weight 100. |seed|'s study field will be cleared before adding | 46 // probability weight 100. |seed|'s study field will be cleared before adding |
50 // the new study. | 47 // the new study. |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
152 base::Base64Encode(Compress(uncompressed_seed_data), | 149 base::Base64Encode(Compress(uncompressed_seed_data), |
153 &compressed_base64_seed_data); | 150 &compressed_base64_seed_data); |
154 | 151 |
155 // Set seed and valid signature in prefs. | 152 // Set seed and valid signature in prefs. |
156 prefs.SetString(prefs::kVariationsCompressedSeed, | 153 prefs.SetString(prefs::kVariationsCompressedSeed, |
157 compressed_base64_seed_data); | 154 compressed_base64_seed_data); |
158 prefs.SetString(prefs::kVariationsSeedSignature, base64_seed_signature); | 155 prefs.SetString(prefs::kVariationsSeedSignature, base64_seed_signature); |
159 | 156 |
160 VariationsSeedStore seed_store(&prefs); | 157 VariationsSeedStore seed_store(&prefs); |
161 variations::VariationsSeed loaded_seed; | 158 variations::VariationsSeed loaded_seed; |
162 seed_store.LoadSeed(&loaded_seed); | 159 EXPECT_TRUE(seed_store.LoadSeed(&loaded_seed)); |
163 std::string invalid_signature = seed_store.GetInvalidSignature(); | 160 std::string invalid_signature = seed_store.GetInvalidSignature(); |
164 // Valid signature so we get an empty string. | 161 // Valid signature so we get an empty string. |
165 EXPECT_EQ(std::string(), invalid_signature); | 162 EXPECT_EQ(std::string(), invalid_signature); |
166 | 163 |
167 prefs.SetString(prefs::kVariationsSeedSignature, | 164 prefs.SetString(prefs::kVariationsSeedSignature, |
168 base64_seed_signature_invalid); | 165 base64_seed_signature_invalid); |
169 seed_store.LoadSeed(&loaded_seed); | 166 #if defined(OS_IOS) || defined(OS_ANDROID) |
167 EXPECT_TRUE(seed_store.LoadSeed(&loaded_seed)); | |
168 #else | |
169 EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed)); | |
170 #endif | |
170 // Invalid signature, so we should get the signature itself, except on mobile | 171 // Invalid signature, so we should get the signature itself, except on mobile |
171 // where we should get an empty string because verification is not enabled. | 172 // where we should get an empty string because verification is not enabled. |
172 invalid_signature = seed_store.GetInvalidSignature(); | 173 invalid_signature = seed_store.GetInvalidSignature(); |
173 #if defined(OS_IOS) || defined(OS_ANDROID) | 174 #if defined(OS_IOS) || defined(OS_ANDROID) |
174 EXPECT_EQ(std::string(), invalid_signature); | 175 EXPECT_EQ(std::string(), invalid_signature); |
175 #else | 176 #else |
176 EXPECT_EQ(base64_seed_signature_invalid, invalid_signature); | 177 EXPECT_EQ(base64_seed_signature_invalid, invalid_signature); |
177 #endif | 178 #endif |
178 | 179 |
179 prefs.SetString(prefs::kVariationsSeedSignature, std::string()); | 180 prefs.SetString(prefs::kVariationsSeedSignature, std::string()); |
180 seed_store.LoadSeed(&loaded_seed); | 181 #if defined(OS_IOS) || defined(OS_ANDROID) |
182 EXPECT_TRUE(seed_store.LoadSeed(&loaded_seed)); | |
183 #else | |
184 EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed)); | |
185 #endif | |
181 invalid_signature = seed_store.GetInvalidSignature(); | 186 invalid_signature = seed_store.GetInvalidSignature(); |
182 // Empty signature, not considered invalid. | 187 // Empty signature, not considered invalid. |
183 EXPECT_EQ(std::string(), invalid_signature); | 188 EXPECT_EQ(std::string(), invalid_signature); |
184 } | 189 } |
185 | 190 |
186 TEST(VariationsSeedStoreTest, StoreSeedData) { | 191 TEST(VariationsSeedStoreTest, StoreSeedData) { |
187 const variations::VariationsSeed seed = CreateTestSeed(); | 192 const variations::VariationsSeed seed = CreateTestSeed(); |
188 const std::string serialized_seed = SerializeSeed(seed); | 193 const std::string serialized_seed = SerializeSeed(seed); |
189 | 194 |
190 TestingPrefServiceSimple prefs; | 195 TestingPrefServiceSimple prefs; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
270 VariationsSeedStore::RegisterPrefs(prefs.registry()); | 275 VariationsSeedStore::RegisterPrefs(prefs.registry()); |
271 TestVariationsSeedStore seed_store(&prefs); | 276 TestVariationsSeedStore seed_store(&prefs); |
272 | 277 |
273 variations::VariationsSeed parsed_seed; | 278 variations::VariationsSeed parsed_seed; |
274 EXPECT_FALSE(seed_store.StoreSeedData(compressed_seed, std::string(), | 279 EXPECT_FALSE(seed_store.StoreSeedData(compressed_seed, std::string(), |
275 std::string(), base::Time::Now(), false, | 280 std::string(), base::Time::Now(), false, |
276 true, &parsed_seed)); | 281 true, &parsed_seed)); |
277 } | 282 } |
278 | 283 |
279 TEST(VariationsSeedStoreTest, VerifySeedSignature) { | 284 TEST(VariationsSeedStoreTest, VerifySeedSignature) { |
285 TestingPrefServiceSimple prefs; | |
286 VariationsSeedStore::RegisterPrefs(prefs.registry()); | |
287 | |
288 #if defined(OS_IOS) || defined(OS_ANDROID) | |
289 // Signature verification is not enabled on mobile. | |
290 ASSERT_FALSE(VariationsSeedStore(&prefs).SignatureVerificationEnabled()); | |
Alexei Svitkine (slow)
2017/06/13 15:26:37
Could we just enable verification for the test?
Ilya Sherman
2017/06/13 22:33:34
Done.
| |
291 return; | |
292 #endif | |
293 | |
280 // The below seed and signature pair were generated using the server's | 294 // The below seed and signature pair were generated using the server's |
281 // private key. | 295 // private key. |
282 const std::string base64_seed_data = | 296 const std::string uncompressed_base64_seed_data = |
283 "CigxZDI5NDY0ZmIzZDc4ZmYxNTU2ZTViNTUxYzY0NDdjYmM3NGU1ZmQwEr0BCh9VTUEtVW5p" | 297 "CigxZDI5NDY0ZmIzZDc4ZmYxNTU2ZTViNTUxYzY0NDdjYmM3NGU1ZmQwEr0BCh9VTUEtVW5p" |
284 "Zm9ybWl0eS1UcmlhbC0xMC1QZXJjZW50GICckqUFOAFCB2RlZmF1bHRKCwoHZGVmYXVsdBAB" | 298 "Zm9ybWl0eS1UcmlhbC0xMC1QZXJjZW50GICckqUFOAFCB2RlZmF1bHRKCwoHZGVmYXVsdBAB" |
285 "SgwKCGdyb3VwXzAxEAFKDAoIZ3JvdXBfMDIQAUoMCghncm91cF8wMxABSgwKCGdyb3VwXzA0" | 299 "SgwKCGdyb3VwXzAxEAFKDAoIZ3JvdXBfMDIQAUoMCghncm91cF8wMxABSgwKCGdyb3VwXzA0" |
286 "EAFKDAoIZ3JvdXBfMDUQAUoMCghncm91cF8wNhABSgwKCGdyb3VwXzA3EAFKDAoIZ3JvdXBf" | 300 "EAFKDAoIZ3JvdXBfMDUQAUoMCghncm91cF8wNhABSgwKCGdyb3VwXzA3EAFKDAoIZ3JvdXBf" |
287 "MDgQAUoMCghncm91cF8wORAB"; | 301 "MDgQAUoMCghncm91cF8wORAB"; |
288 const std::string base64_seed_signature = | 302 const std::string base64_seed_signature = |
289 "MEQCIDD1IVxjzWYncun+9IGzqYjZvqxxujQEayJULTlbTGA/AiAr0oVmEgVUQZBYq5VLOSvy" | 303 "MEQCIDD1IVxjzWYncun+9IGzqYjZvqxxujQEayJULTlbTGA/AiAr0oVmEgVUQZBYq5VLOSvy" |
290 "96JkMYgzTkHPwbv7K/CmgA=="; | 304 "96JkMYgzTkHPwbv7K/CmgA=="; |
291 | 305 |
292 std::string seed_data; | 306 std::string seed_data; |
293 EXPECT_TRUE(base::Base64Decode(base64_seed_data, &seed_data)); | 307 ASSERT_TRUE(base::Base64Decode(uncompressed_base64_seed_data, &seed_data)); |
294 | 308 VariationsSeed seed; |
295 VariationsSeedStore seed_store(NULL); | 309 ASSERT_TRUE(seed.ParseFromString(seed_data)); |
296 | 310 std::string base64_seed_data = SerializeSeedBase64(seed); |
297 #if defined(OS_IOS) || defined(OS_ANDROID) | |
298 // Signature verification is not enabled on mobile. | |
299 if (seed_store.VerifySeedSignature(seed_data, base64_seed_signature) == | |
300 VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_ENUM_SIZE) { | |
301 return; | |
302 } | |
303 #endif | |
304 | 311 |
305 // The above inputs should be valid. | 312 // The above inputs should be valid. |
306 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_VALID, | 313 { |
307 seed_store.VerifySeedSignature(seed_data, base64_seed_signature)); | 314 prefs.SetString(prefs::kVariationsCompressedSeed, base64_seed_data); |
315 prefs.SetString(prefs::kVariationsSeedSignature, base64_seed_signature); | |
316 VariationsSeedStore seed_store(&prefs); | |
317 | |
318 base::HistogramTester histogram_tester; | |
319 VariationsSeed seed; | |
320 EXPECT_TRUE(seed_store.LoadSeed(&seed)); | |
321 histogram_tester.ExpectUniqueSample( | |
322 "Variations.LoadSeedSignature", | |
323 static_cast<base::HistogramBase::Sample>( | |
324 VerifySignatureResult::VALID_SIGNATURE), | |
325 1); | |
326 } | |
308 | 327 |
309 // If there's no signature, the corresponding result should be returned. | 328 // If there's no signature, the corresponding result should be returned. |
310 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_MISSING, | 329 { |
311 seed_store.VerifySeedSignature(seed_data, std::string())); | 330 prefs.SetString(prefs::kVariationsCompressedSeed, base64_seed_data); |
331 prefs.SetString(prefs::kVariationsSeedSignature, std::string()); | |
332 VariationsSeedStore seed_store(&prefs); | |
312 | 333 |
313 // Using non-base64 encoded value as signature (e.g. seed data) should fail. | 334 base::HistogramTester histogram_tester; |
314 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_DECODE_FAILED, | 335 VariationsSeed seed; |
315 seed_store.VerifySeedSignature(seed_data, seed_data)); | 336 EXPECT_FALSE(seed_store.LoadSeed(&seed)); |
337 histogram_tester.ExpectUniqueSample( | |
338 "Variations.LoadSeedSignature", | |
339 static_cast<base::HistogramBase::Sample>( | |
340 VerifySignatureResult::MISSING_SIGNATURE), | |
341 1); | |
342 } | |
343 | |
344 // Using non-base64 encoded value as signature should fail. | |
345 { | |
346 prefs.SetString(prefs::kVariationsCompressedSeed, base64_seed_data); | |
347 prefs.SetString(prefs::kVariationsSeedSignature, | |
348 "not a base64-encoded string"); | |
349 VariationsSeedStore seed_store(&prefs); | |
350 | |
351 base::HistogramTester histogram_tester; | |
352 VariationsSeed seed; | |
353 EXPECT_FALSE(seed_store.LoadSeed(&seed)); | |
354 histogram_tester.ExpectUniqueSample( | |
355 "Variations.LoadSeedSignature", | |
356 static_cast<base::HistogramBase::Sample>( | |
357 VerifySignatureResult::DECODE_FAILED), | |
358 1); | |
359 } | |
316 | 360 |
317 // Using a different signature (e.g. the base64 seed data) should fail. | 361 // Using a different signature (e.g. the base64 seed data) should fail. |
318 // OpenSSL doesn't distinguish signature decode failure from the | 362 // OpenSSL doesn't distinguish signature decode failure from the |
319 // signature not matching. | 363 // signature not matching. |
320 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_INVALID_SEED, | 364 { |
321 seed_store.VerifySeedSignature(seed_data, base64_seed_data)); | 365 prefs.SetString(prefs::kVariationsCompressedSeed, base64_seed_data); |
366 prefs.SetString(prefs::kVariationsSeedSignature, base64_seed_data); | |
367 VariationsSeedStore seed_store(&prefs); | |
368 | |
369 base::HistogramTester histogram_tester; | |
370 VariationsSeed seed; | |
371 EXPECT_FALSE(seed_store.LoadSeed(&seed)); | |
372 histogram_tester.ExpectUniqueSample( | |
373 "Variations.LoadSeedSignature", | |
374 static_cast<base::HistogramBase::Sample>( | |
375 VerifySignatureResult::INVALID_SEED), | |
376 1); | |
377 } | |
322 | 378 |
323 // Using a different seed should not match the signature. | 379 // Using a different seed should not match the signature. |
324 seed_data[0] = 'x'; | 380 { |
325 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_INVALID_SEED, | 381 VariationsSeed wrong_seed; |
326 seed_store.VerifySeedSignature(seed_data, base64_seed_signature)); | 382 ASSERT_TRUE(wrong_seed.ParseFromString(seed_data)); |
383 (*wrong_seed.mutable_study(0)->mutable_name())[0] = 'x'; | |
384 std::string base64_wrong_seed_data = SerializeSeedBase64(wrong_seed); | |
385 | |
386 prefs.SetString(prefs::kVariationsCompressedSeed, base64_wrong_seed_data); | |
387 prefs.SetString(prefs::kVariationsSeedSignature, base64_seed_signature); | |
388 VariationsSeedStore seed_store(&prefs); | |
389 | |
390 base::HistogramTester histogram_tester; | |
391 VariationsSeed seed; | |
392 EXPECT_FALSE(seed_store.LoadSeed(&seed)); | |
393 histogram_tester.ExpectUniqueSample( | |
394 "Variations.LoadSeedSignature", | |
395 static_cast<base::HistogramBase::Sample>( | |
396 VerifySignatureResult::INVALID_SEED), | |
397 1); | |
398 } | |
327 } | 399 } |
328 | 400 |
329 TEST(VariationsSeedStoreTest, ApplyDeltaPatch) { | 401 TEST(VariationsSeedStoreTest, ApplyDeltaPatch) { |
330 // Sample seeds and the server produced delta between them to verify that the | 402 // Sample seeds and the server produced delta between them to verify that the |
331 // client code is able to decode the deltas produced by the server. | 403 // client code is able to decode the deltas produced by the server. |
332 const std::string base64_before_seed_data = | 404 const std::string base64_before_seed_data = |
333 "CigxN2E4ZGJiOTI4ODI0ZGU3ZDU2MGUyODRlODY1ZDllYzg2NzU1MTE0ElgKDFVNQVN0YWJp" | 405 "CigxN2E4ZGJiOTI4ODI0ZGU3ZDU2MGUyODRlODY1ZDllYzg2NzU1MTE0ElgKDFVNQVN0YWJp" |
334 "bGl0eRjEyomgBTgBQgtTZXBhcmF0ZUxvZ0oLCgdEZWZhdWx0EABKDwoLU2VwYXJhdGVMb2cQ" | 406 "bGl0eRjEyomgBTgBQgtTZXBhcmF0ZUxvZ0oLCgdEZWZhdWx0EABKDwoLU2VwYXJhdGVMb2cQ" |
335 "ZFIVEgszNC4wLjE4MDEuMCAAIAEgAiADEkQKIFVNQS1Vbmlmb3JtaXR5LVRyaWFsLTEwMC1Q" | 407 "ZFIVEgszNC4wLjE4MDEuMCAAIAEgAiADEkQKIFVNQS1Vbmlmb3JtaXR5LVRyaWFsLTEwMC1Q" |
336 "ZXJjZW50GIDjhcAFOAFCCGdyb3VwXzAxSgwKCGdyb3VwXzAxEAFgARJPCh9VTUEtVW5pZm9y" | 408 "ZXJjZW50GIDjhcAFOAFCCGdyb3VwXzAxSgwKCGdyb3VwXzAxEAFgARJPCh9VTUEtVW5pZm9y" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
394 &response_date, &is_gzip_compressed); | 466 &response_date, &is_gzip_compressed); |
395 EXPECT_EQ("", seed_data); | 467 EXPECT_EQ("", seed_data); |
396 EXPECT_EQ("", seed_signature); | 468 EXPECT_EQ("", seed_signature); |
397 EXPECT_EQ("", seed_country); | 469 EXPECT_EQ("", seed_country); |
398 EXPECT_EQ("", response_date); | 470 EXPECT_EQ("", response_date); |
399 EXPECT_FALSE(is_gzip_compressed); | 471 EXPECT_FALSE(is_gzip_compressed); |
400 } | 472 } |
401 #endif // OS_ANDROID | 473 #endif // OS_ANDROID |
402 | 474 |
403 } // namespace variations | 475 } // namespace variations |
OLD | NEW |