1 // Copyright 2020 The Chromium Authors
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 "components/metrics/entropy_state.h"
6
7 #include <string>
8
9 #include "base/command_line.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "components/metrics/metrics_pref_names.h"
13 #include "components/metrics/metrics_service.h"
14 #include "components/metrics/metrics_switches.h"
15 #include "components/prefs/testing_pref_service.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace metrics {
19
20 class EntropyStateTest : public testing::Test {
21 public:
EntropyStateTest()22 EntropyStateTest() { MetricsService::RegisterPrefs(prefs_.registry()); }
23
24 EntropyStateTest(const EntropyStateTest&) = delete;
25 EntropyStateTest& operator=(const EntropyStateTest&) = delete;
26
27 protected:
28 TestingPrefServiceSimple prefs_;
29 };
30
TEST_F(EntropyStateTest,LowEntropySourceNotReset)31 TEST_F(EntropyStateTest, LowEntropySourceNotReset) {
32 EntropyState entropy_state(&prefs_);
33 // Get the low entropy source once, to initialize it.
34 entropy_state.GetLowEntropySource();
35
36 // Now, set it to 0 and ensure it doesn't get reset.
37 entropy_state.low_entropy_source_ = 0;
38 EXPECT_EQ(0, entropy_state.GetLowEntropySource());
39 // Call it another time, just to make sure.
40 EXPECT_EQ(0, entropy_state.GetLowEntropySource());
41 }
42
TEST_F(EntropyStateTest,PseudoLowEntropySourceNotReset)43 TEST_F(EntropyStateTest, PseudoLowEntropySourceNotReset) {
44 EntropyState entropy_state(&prefs_);
45 // Get the pseudo low entropy source once, to initialize it.
46 entropy_state.GetPseudoLowEntropySource();
47
48 // Now, set it to 0 and ensure it doesn't get reset.
49 entropy_state.pseudo_low_entropy_source_ = 0;
50 EXPECT_EQ(0, entropy_state.GetPseudoLowEntropySource());
51 // Call it another time, just to make sure.
52 EXPECT_EQ(0, entropy_state.GetPseudoLowEntropySource());
53 }
54
TEST_F(EntropyStateTest,HaveNoLowEntropySource)55 TEST_F(EntropyStateTest, HaveNoLowEntropySource) {
56 EntropyState entropy_state(&prefs_);
57 // If we have none of the new, old, or pseudo low entropy sources stored in
58 // prefs, then the new source should be created...
59 int new_low_source = entropy_state.GetLowEntropySource();
60 EXPECT_TRUE(EntropyState::IsValidLowEntropySource(new_low_source))
61 << new_low_source;
62 int pseudo_low_source = entropy_state.GetPseudoLowEntropySource();
63 EXPECT_TRUE(EntropyState::IsValidLowEntropySource(pseudo_low_source))
64 << pseudo_low_source;
65 // ...but the old source should not...
66 EXPECT_EQ(EntropyState::kLowEntropySourceNotSet,
67 entropy_state.GetOldLowEntropySource());
68 // ...and the high entropy source should include the *new* low entropy source.
69 std::string high_source = entropy_state.GetHighEntropySource(
70 "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
71 EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(new_low_source),
72 base::CompareCase::SENSITIVE))
73 << high_source;
74 }
75
TEST_F(EntropyStateTest,HaveOnlyNewLowEntropySource)76 TEST_F(EntropyStateTest, HaveOnlyNewLowEntropySource) {
77 // If we have the new low entropy sources stored in prefs, but not the old
78 // one...
79 const int new_low_source = 1234;
80 prefs_.SetInteger(prefs::kMetricsLowEntropySource, new_low_source);
81
82 EntropyState entropy_state(&prefs_);
83 // ...then the new source should be loaded...
84 EXPECT_EQ(new_low_source, entropy_state.GetLowEntropySource());
85 // ...but the old source should not be created...
86 EXPECT_EQ(EntropyState::kLowEntropySourceNotSet,
87 entropy_state.GetOldLowEntropySource());
88 // ...and the high entropy source should include the *new* low entropy source.
89 std::string high_source = entropy_state.GetHighEntropySource(
90 "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
91 EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(new_low_source),
92 base::CompareCase::SENSITIVE))
93 << high_source;
94 }
95
TEST_F(EntropyStateTest,HaveOnlyOldLowEntropySource)96 TEST_F(EntropyStateTest, HaveOnlyOldLowEntropySource) {
97 // If we have the old low entropy sources stored in prefs, but not the new
98 // one...
99 const int old_low_source = 5678;
100 prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, old_low_source);
101
102 // ...then the new source should be created...
103 EntropyState entropy_state(&prefs_);
104
105 int new_low_source = entropy_state.GetLowEntropySource();
106 EXPECT_TRUE(EntropyState::IsValidLowEntropySource(new_low_source))
107 << new_low_source;
108 // ...and the old source should be loaded...
109 EXPECT_EQ(old_low_source, entropy_state.GetOldLowEntropySource());
110 // ...and the high entropy source should include the *old* low entropy source.
111 std::string high_source = entropy_state.GetHighEntropySource(
112 "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
113 EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(old_low_source),
114 base::CompareCase::SENSITIVE))
115 << high_source;
116 }
117
TEST_F(EntropyStateTest,HaveAllLowEntropySources)118 TEST_F(EntropyStateTest, HaveAllLowEntropySources) {
119 // If we have all three of new, old, and pseudo low entropy sources in
120 // prefs...
121 const int new_low_source = 1234;
122 const int old_low_source = 5678;
123 const int pseudo_low_source = 4321;
124 prefs_.SetInteger(prefs::kMetricsLowEntropySource, new_low_source);
125 prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, old_low_source);
126 prefs_.SetInteger(prefs::kMetricsPseudoLowEntropySource, pseudo_low_source);
127
128 // ...then all three should be loaded...
129 EntropyState entropy_state(&prefs_);
130
131 EXPECT_EQ(new_low_source, entropy_state.GetLowEntropySource());
132 EXPECT_EQ(old_low_source, entropy_state.GetOldLowEntropySource());
133 EXPECT_EQ(pseudo_low_source, entropy_state.GetPseudoLowEntropySource());
134 // ...and the high entropy source should include the *old* low entropy source.
135 std::string high_source = entropy_state.GetHighEntropySource(
136 "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
137 EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(old_low_source),
138 base::CompareCase::SENSITIVE))
139 << high_source;
140 }
141
TEST_F(EntropyStateTest,CorruptNewLowEntropySources)142 TEST_F(EntropyStateTest, CorruptNewLowEntropySources) {
143 EntropyState entropy_state(&prefs_);
144 const int corrupt_sources[] = {-12345, -1, 8000, 12345};
145 for (int corrupt_source : corrupt_sources) {
146 // If the new low entropy source has been corrupted...
147 EXPECT_FALSE(EntropyState::IsValidLowEntropySource(corrupt_source))
148 << corrupt_source;
149 prefs_.SetInteger(prefs::kMetricsLowEntropySource, corrupt_source);
150 // ...then a new source should be created.
151 int loaded_source = entropy_state.GetLowEntropySource();
152 EXPECT_TRUE(EntropyState::IsValidLowEntropySource(loaded_source))
153 << loaded_source;
154 }
155 }
156
TEST_F(EntropyStateTest,CorruptOldLowEntropySources)157 TEST_F(EntropyStateTest, CorruptOldLowEntropySources) {
158 EntropyState entropy_state(&prefs_);
159 const int corrupt_sources[] = {-12345, -1, 8000, 12345};
160 for (int corrupt_source : corrupt_sources) {
161 // If the old low entropy source has been corrupted...
162 EXPECT_FALSE(EntropyState::IsValidLowEntropySource(corrupt_source))
163 << corrupt_source;
164 prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, corrupt_source);
165 // ...then it should be ignored.
166 EXPECT_EQ(EntropyState::kLowEntropySourceNotSet,
167 entropy_state.GetOldLowEntropySource());
168 }
169 }
170
171 #if BUILDFLAG(IS_CHROMEOS_LACROS)
TEST_F(EntropyStateTest,ClearPrefs)172 TEST_F(EntropyStateTest, ClearPrefs) {
173 // On Lacros we expect that there will be no clearing of prefs.
174 prefs_.SetInteger(prefs::kMetricsLowEntropySource, 1234);
175 prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, 5678);
176 prefs_.SetInteger(prefs::kMetricsPseudoLowEntropySource, 4321);
177 prefs_.SetString(prefs::kMetricsLimitedEntropyRandomizationSource,
178 "00000000000000000000000000000001");
179
180 EntropyState::ClearPrefs(&prefs_);
181
182 EXPECT_TRUE(prefs_.HasPrefPath(prefs::kMetricsLowEntropySource));
183 EXPECT_TRUE(prefs_.HasPrefPath(prefs::kMetricsOldLowEntropySource));
184 EXPECT_TRUE(prefs_.HasPrefPath(prefs::kMetricsPseudoLowEntropySource));
185 EXPECT_TRUE(
186 prefs_.HasPrefPath(prefs::kMetricsLimitedEntropyRandomizationSource));
187 }
188
TEST_F(EntropyStateTest,SetExternalPrefs)189 TEST_F(EntropyStateTest, SetExternalPrefs) {
190 prefs_.ClearPref(prefs::kMetricsLowEntropySource);
191 prefs_.ClearPref(prefs::kMetricsOldLowEntropySource);
192 prefs_.ClearPref(prefs::kMetricsPseudoLowEntropySource);
193 prefs_.ClearPref(prefs::kMetricsLimitedEntropyRandomizationSource);
194
195 std::string limited_entropy_randomization_source =
196 "00000000000000000000000000000001";
197 EntropyState::SetExternalPrefs(&prefs_, 1234, 4567, 3456,
198 limited_entropy_randomization_source);
199
200 EXPECT_EQ(prefs_.GetInteger(prefs::kMetricsLowEntropySource), 1234);
201 EXPECT_EQ(prefs_.GetInteger(prefs::kMetricsOldLowEntropySource), 4567);
202 EXPECT_EQ(prefs_.GetInteger(prefs::kMetricsPseudoLowEntropySource), 3456);
203 EXPECT_EQ(prefs_.GetString(prefs::kMetricsLimitedEntropyRandomizationSource),
204 limited_entropy_randomization_source);
205 }
206
TEST_F(EntropyStateTest,SetEmptyStringToLimitedEntropyRandomizationSource)207 TEST_F(EntropyStateTest, SetEmptyStringToLimitedEntropyRandomizationSource) {
208 prefs_.ClearPref(prefs::kMetricsLimitedEntropyRandomizationSource);
209
210 EntropyState::SetExternalPrefs(&prefs_, 1234, 4567, 3456, std::string_view());
211
212 EXPECT_FALSE(
213 prefs_.HasPrefPath(prefs::kMetricsLimitedEntropyRandomizationSource));
214 }
215
216 #else
217
TEST_F(EntropyStateTest,ClearPrefs)218 TEST_F(EntropyStateTest, ClearPrefs) {
219 prefs_.SetInteger(prefs::kMetricsLowEntropySource, 1234);
220 prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, 5678);
221 prefs_.SetInteger(prefs::kMetricsPseudoLowEntropySource, 4321);
222 prefs_.SetString(prefs::kMetricsLimitedEntropyRandomizationSource,
223 "00000000000000000000000000000001");
224
225 EntropyState::ClearPrefs(&prefs_);
226
227 EXPECT_FALSE(prefs_.HasPrefPath(prefs::kMetricsLowEntropySource));
228 EXPECT_FALSE(prefs_.HasPrefPath(prefs::kMetricsOldLowEntropySource));
229 EXPECT_FALSE(prefs_.HasPrefPath(prefs::kMetricsPseudoLowEntropySource));
230 EXPECT_FALSE(
231 prefs_.HasPrefPath(prefs::kMetricsLimitedEntropyRandomizationSource));
232 }
233 #endif
234
TEST_F(EntropyStateTest,ClearingPrefWillNotResetValuesDuringSession)235 TEST_F(EntropyStateTest, ClearingPrefWillNotResetValuesDuringSession) {
236 // Setting test values in prefs;
237 prefs_.SetInteger(prefs::kMetricsLowEntropySource, 1234);
238 prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, 5678);
239 prefs_.SetInteger(prefs::kMetricsPseudoLowEntropySource, 4321);
240 prefs_.SetString(prefs::kMetricsLimitedEntropyRandomizationSource,
241 "00000000000000000000000000000001");
242 EntropyState entropy_state(&prefs_);
243
244 // Generates all managed values. This should load the values from prefs.
245 auto low = entropy_state.GetLowEntropySource();
246 auto old_low = entropy_state.GetOldLowEntropySource();
247 auto pseudo_low = entropy_state.GetPseudoLowEntropySource();
248 auto high = entropy_state.GetHighEntropySource(
249 "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
250 auto limited = entropy_state.GetLimitedEntropyRandomizationSource();
251
252 EntropyState::ClearPrefs(&prefs_);
253
254 // Clearing values in prefs should not result in returning different values.
255 EXPECT_EQ(low, entropy_state.GetLowEntropySource());
256 EXPECT_EQ(old_low, entropy_state.GetOldLowEntropySource());
257 EXPECT_EQ(pseudo_low, entropy_state.GetPseudoLowEntropySource());
258 EXPECT_EQ(high, entropy_state.GetHighEntropySource(
259 "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF"));
260 EXPECT_EQ(limited, entropy_state.GetLimitedEntropyRandomizationSource());
261 }
262
TEST_F(EntropyStateTest,GenerateLimitedEntropyRandomizationSourceWhenNotAvailable)263 TEST_F(EntropyStateTest,
264 GenerateLimitedEntropyRandomizationSourceWhenNotAvailable) {
265 // Pref for limited entropy randomization source is unset.
266 EXPECT_FALSE(
267 prefs_.HasPrefPath(prefs::kMetricsLimitedEntropyRandomizationSource));
268
269 // Generate a new limited entropy randomization source.
270 EntropyState entropy_state(&prefs_);
271 entropy_state.GetLimitedEntropyRandomizationSource();
272
273 // There should be a generated value and it should be stored in prefs.
274 auto getter_value = entropy_state.GetLimitedEntropyRandomizationSource();
275 auto pref_value =
276 prefs_.GetString(prefs::kMetricsLimitedEntropyRandomizationSource);
277 EXPECT_NE("", getter_value);
278 EXPECT_EQ(getter_value, pref_value);
279 }
280
TEST_F(EntropyStateTest,LoadLimitedEntropyRandomizationSourceFromPref)281 TEST_F(EntropyStateTest, LoadLimitedEntropyRandomizationSourceFromPref) {
282 // There is a previously generated limited entropy randomization source stored
283 // in prefs.
284 auto* test_value = "00000000000000000000000000000001";
285 prefs_.SetString(prefs::kMetricsLimitedEntropyRandomizationSource,
286 test_value);
287
288 // This should load the previous value from prefs.
289 EntropyState entropy_state(&prefs_);
290 entropy_state.GetLimitedEntropyRandomizationSource();
291
292 // Verify that the previous value was returned.
293 EXPECT_EQ(test_value, entropy_state.GetLimitedEntropyRandomizationSource());
294 // Verify that the value stored in prefs is not altered.
295 EXPECT_EQ(test_value,
296 prefs_.GetString(prefs::kMetricsLimitedEntropyRandomizationSource));
297 }
298
TEST_F(EntropyStateTest,LimitedEntropyRandomizationSourceNotReset)299 TEST_F(EntropyStateTest, LimitedEntropyRandomizationSourceNotReset) {
300 EntropyState entropy_state(&prefs_);
301
302 // Attempts to generate the limited entropy randomization source twice.
303 auto first_call_value = entropy_state.GetLimitedEntropyRandomizationSource();
304 auto second_call_value = entropy_state.GetLimitedEntropyRandomizationSource();
305
306 // The generated value should not be empty.
307 EXPECT_NE("", first_call_value);
308 // The values returned from the two calls should be identical.
309 EXPECT_EQ(first_call_value, second_call_value);
310 }
311
TEST_F(EntropyStateTest,ResetLimitedEntropyRandomizationSourceThroughCmdLine)312 TEST_F(EntropyStateTest, ResetLimitedEntropyRandomizationSourceThroughCmdLine) {
313 // Setup a command line flag to reset the variations state.
314 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
315 command_line->AppendSwitch(switches::kResetVariationState);
316 // ...and store a previously generated limited entropy randomization source
317 // value in prefs.
318 auto* test_value = "00000000000000000000000000000001";
319 prefs_.SetString(prefs::kMetricsLimitedEntropyRandomizationSource,
320 test_value);
321
322 // Attempts to generate a limited entropy randomization source value.
323 EntropyState entropy_state(&prefs_);
324 entropy_state.GetLimitedEntropyRandomizationSource();
325
326 // The generated value should not be the one in prefs initially.
327 EXPECT_NE(test_value, entropy_state.GetLimitedEntropyRandomizationSource());
328 // There should be a new value, and the new value should overwrite the one in
329 // prefs initially.
330 EXPECT_EQ(entropy_state.GetLimitedEntropyRandomizationSource(),
331 prefs_.GetString(prefs::kMetricsLimitedEntropyRandomizationSource));
332 }
333
TEST_F(EntropyStateTest,ValidLimitedEntropyRandomizationSource)334 TEST_F(EntropyStateTest, ValidLimitedEntropyRandomizationSource) {
335 const char* test_values[] = {
336 "00000000000000000000000000000001",
337 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
338 "0123456789ABCDEF0123456789ABCDEF",
339 };
340 for (auto* test_value : test_values) {
341 EXPECT_TRUE(
342 EntropyState::IsValidLimitedEntropyRandomizationSource(test_value))
343 << "Expect EntropyState::IsValidLimitedEntropyRandomizationSource("
344 << test_value << ") to be true.";
345 }
346 }
347
TEST_F(EntropyStateTest,InvalidLimitedEntropyRandomizationSource)348 TEST_F(EntropyStateTest, InvalidLimitedEntropyRandomizationSource) {
349 const char* test_values[] = {
350 // The empty string is not a valid limited entropy randomization source.
351 "",
352 // A value with all zero is a not a valid `base::UnguessableToken`.
353 "00000000000000000000000000000000",
354 // Not a hex string representing 128 bits.
355 "1234",
356 // A string with valid length of 128 bits but 'X' is not a hex value.
357 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
358 // A invalid hex string because of the lower case letters.
359 "0123456789abcdef0123456789abcdef",
360 };
361 for (auto* test_value : test_values) {
362 EXPECT_FALSE(
363 EntropyState::IsValidLimitedEntropyRandomizationSource(test_value))
364 << "Expect EntropyState::IsValidLimitedEntropyRandomizationSource("
365 << test_value << ") to be false.";
366 }
367 }
368
369 } // namespace metrics
370