[Ozone-Drm] Add support for async content protection
[chromium-blink-merge.git] / chromeos / tpm / tpm_token_info_getter_unittest.cc
blob7d53474ae92cb8ed8fe7e054667144cc83851f1b
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
3 // found in the LICENSE file.
5 #include <string>
6 #include <vector>
8 #include "base/bind.h"
9 #include "base/location.h"
10 #include "base/macros.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/task_runner.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "chromeos/dbus/fake_cryptohome_client.h"
17 #include "chromeos/tpm/tpm_token_info_getter.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 namespace {
22 // The struct holding information returned by TPMTokenInfoGetter::Start
23 // callback.
24 struct TestTPMTokenInfo {
25 TestTPMTokenInfo() : enabled(false), slot_id(-2) {}
27 bool IsReady() const {
28 return slot_id >= 0;
31 bool enabled;
32 std::string name;
33 std::string pin;
34 int slot_id;
37 // Callback for TPMTokenInfoGetter::Start. It records the values returned
38 // by TPMTokenInfoGetter to |info|.
39 void RecordGetterResult(TestTPMTokenInfo* target,
40 const chromeos::TPMTokenInfo& source) {
41 target->enabled = source.tpm_is_enabled;
42 target->name = source.token_name;
43 target->pin = source.user_pin;
44 target->slot_id = source.token_slot_id;
47 // Task runner for handling delayed tasks posted by TPMTokenInfoGetter when
48 // retrying failed cryptohome method calls. It just records the requested
49 // delay and immediately runs the task. The task is run asynchronously to be
50 // closer to what's actually happening in production.
51 // The delays used by TPMTokenGetter should be monotonically increasing, so
52 // the fake task runner does not handle task reordering based on the delays.
53 class FakeTaskRunner : public base::TaskRunner {
54 public:
55 // |delays|: Vector to which the dalays seen by the task runner are saved.
56 explicit FakeTaskRunner(std::vector<int64>* delays) : delays_(delays) {}
58 // base::TaskRunner overrides:
59 bool PostDelayedTask(const tracked_objects::Location& from_here,
60 const base::Closure& task,
61 base::TimeDelta delay) override {
62 delays_->push_back(delay.InMilliseconds());
63 base::ThreadTaskRunnerHandle::Get()->PostTask(from_here, task);
64 return true;
66 bool RunsTasksOnCurrentThread() const override { return true; }
68 protected:
69 ~FakeTaskRunner() override {}
71 private:
72 // The vector of delays.
73 std::vector<int64>* delays_;
75 DISALLOW_COPY_AND_ASSIGN(FakeTaskRunner);
78 // Implementation of CryptohomeClient used in these tests. Note that
79 // TestCryptohomeClient implements FakeCryptohomeClient purely for convenience
80 // of not having to implement whole CryptohomeClient interface.
81 // TestCryptohomeClient overrides all CryptohomeClient methods used in
82 // TPMTokenInfoGetter tests.
83 class TestCryptohomeClient : public chromeos::FakeCryptohomeClient {
84 public:
85 // |user_id|: The user associated with the TPMTokenInfoGetter that will be
86 // using the TestCryptohomeClient. Should be empty for system token.
87 explicit TestCryptohomeClient(const std::string& user_id)
88 : user_id_(user_id),
89 tpm_is_enabled_(true),
90 tpm_is_enabled_failure_count_(0),
91 tpm_is_enabled_succeeded_(false),
92 get_tpm_token_info_failure_count_(0),
93 get_tpm_token_info_not_set_count_(0),
94 get_tpm_token_info_succeeded_(false) {
97 ~TestCryptohomeClient() override {}
99 void set_tpm_is_enabled(bool value) {
100 tpm_is_enabled_ = value;
103 void set_tpm_is_enabled_failure_count(int value) {
104 ASSERT_GT(value, 0);
105 tpm_is_enabled_failure_count_ = value;
108 void set_get_tpm_token_info_failure_count(int value) {
109 ASSERT_GT(value, 0);
110 get_tpm_token_info_failure_count_ = value;
113 void set_get_tpm_token_info_not_set_count(int value) {
114 ASSERT_GT(value, 0);
115 get_tpm_token_info_not_set_count_ = value;
118 // Sets the tpm tpken info to be reported by the test CryptohomeClient.
119 // If there is |Pkcs11GetTpmTokenInfo| in progress, runs the pending
120 // callback with the set tpm token info.
121 void SetTPMTokenInfo(const std::string& token_name,
122 const std::string& pin,
123 int slot_id) {
124 tpm_token_info_.name = token_name;
125 tpm_token_info_.pin = pin;
126 tpm_token_info_.slot_id = slot_id;
128 ASSERT_TRUE(tpm_token_info_.IsReady());
130 InvokeGetTpmTokenInfoCallbackIfReady();
133 private:
134 // FakeCryptohomeClient override.
135 void TpmIsEnabled(const chromeos::BoolDBusMethodCallback& callback) override {
136 ASSERT_FALSE(tpm_is_enabled_succeeded_);
137 if (tpm_is_enabled_failure_count_ > 0) {
138 --tpm_is_enabled_failure_count_;
139 base::ThreadTaskRunnerHandle::Get()->PostTask(
140 FROM_HERE,
141 base::Bind(callback, chromeos::DBUS_METHOD_CALL_FAILURE, false));
142 } else {
143 tpm_is_enabled_succeeded_ = true;
144 base::ThreadTaskRunnerHandle::Get()->PostTask(
145 FROM_HERE,
146 base::Bind(callback,
147 chromeos::DBUS_METHOD_CALL_SUCCESS, tpm_is_enabled_));
151 void Pkcs11GetTpmTokenInfo(
152 const Pkcs11GetTpmTokenInfoCallback& callback) override {
153 ASSERT_TRUE(user_id_.empty());
155 HandleGetTpmTokenInfo(callback);
158 void Pkcs11GetTpmTokenInfoForUser(
159 const std::string& user_id,
160 const Pkcs11GetTpmTokenInfoCallback& callback) override {
161 ASSERT_FALSE(user_id_.empty());
162 ASSERT_EQ(user_id_, user_id);
164 HandleGetTpmTokenInfo(callback);
167 // Handles Pkcs11GetTpmTokenInfo calls (both for system and user token). The
168 // CryptohomeClient method overrides should make sure that |user_id_| is
169 // properly set before calling this.
170 void HandleGetTpmTokenInfo(const Pkcs11GetTpmTokenInfoCallback& callback) {
171 ASSERT_TRUE(tpm_is_enabled_succeeded_);
172 ASSERT_FALSE(get_tpm_token_info_succeeded_);
173 ASSERT_TRUE(pending_get_tpm_token_info_callback_.is_null());
175 if (get_tpm_token_info_failure_count_ > 0) {
176 --get_tpm_token_info_failure_count_;
177 base::ThreadTaskRunnerHandle::Get()->PostTask(
178 FROM_HERE,
179 base::Bind(callback,
180 chromeos::DBUS_METHOD_CALL_FAILURE,
181 std::string() /* token name */,
182 std::string() /* user pin */,
183 -1 /* slot id */));
184 return;
187 if (get_tpm_token_info_not_set_count_ > 0) {
188 --get_tpm_token_info_not_set_count_;
189 base::ThreadTaskRunnerHandle::Get()->PostTask(
190 FROM_HERE,
191 base::Bind(callback,
192 chromeos::DBUS_METHOD_CALL_SUCCESS,
193 std::string() /* token name */,
194 std::string() /* user pin */,
195 -1 /* slot id */));
196 return;
199 pending_get_tpm_token_info_callback_ = callback;
200 InvokeGetTpmTokenInfoCallbackIfReady();
203 void InvokeGetTpmTokenInfoCallbackIfReady() {
204 if (!tpm_token_info_.IsReady() ||
205 pending_get_tpm_token_info_callback_.is_null())
206 return;
208 get_tpm_token_info_succeeded_ = true;
209 // Called synchronously for convenience (to avoid using extra RunLoop in
210 // tests). Unlike with other Cryptohome callbacks, TPMTokenInfoGetter does
211 // not rely on this callback being called asynchronously.
212 pending_get_tpm_token_info_callback_.Run(
213 chromeos::DBUS_METHOD_CALL_SUCCESS,
214 tpm_token_info_.name,
215 tpm_token_info_.pin,
216 tpm_token_info_.slot_id);
219 std::string user_id_;
220 bool tpm_is_enabled_;
221 int tpm_is_enabled_failure_count_;
222 bool tpm_is_enabled_succeeded_;
223 int get_tpm_token_info_failure_count_;
224 int get_tpm_token_info_not_set_count_;
225 bool get_tpm_token_info_succeeded_;
226 Pkcs11GetTpmTokenInfoCallback pending_get_tpm_token_info_callback_;
227 TestTPMTokenInfo tpm_token_info_;
229 DISALLOW_COPY_AND_ASSIGN(TestCryptohomeClient);
232 class SystemTPMTokenInfoGetterTest : public testing::Test {
233 public:
234 SystemTPMTokenInfoGetterTest() {}
235 ~SystemTPMTokenInfoGetterTest() override {}
237 void SetUp() override {
238 cryptohome_client_.reset(new TestCryptohomeClient(std::string()));
239 tpm_token_info_getter_ =
240 chromeos::TPMTokenInfoGetter::CreateForSystemToken(
241 cryptohome_client_.get(),
242 scoped_refptr<base::TaskRunner>(new FakeTaskRunner(&delays_)));
245 protected:
246 scoped_ptr<TestCryptohomeClient> cryptohome_client_;
247 scoped_ptr<chromeos::TPMTokenInfoGetter> tpm_token_info_getter_;
249 std::vector<int64> delays_;
251 private:
252 base::MessageLoop message_loop_;
254 DISALLOW_COPY_AND_ASSIGN(SystemTPMTokenInfoGetterTest);
257 class UserTPMTokenInfoGetterTest : public testing::Test {
258 public:
259 UserTPMTokenInfoGetterTest() : user_id_("user") {}
260 ~UserTPMTokenInfoGetterTest() override {}
262 void SetUp() override {
263 cryptohome_client_.reset(new TestCryptohomeClient(user_id_));
264 tpm_token_info_getter_ =
265 chromeos::TPMTokenInfoGetter::CreateForUserToken(
266 user_id_,
267 cryptohome_client_.get(),
268 scoped_refptr<base::TaskRunner>(new FakeTaskRunner(&delays_)));
271 protected:
272 scoped_ptr<TestCryptohomeClient> cryptohome_client_;
273 scoped_ptr<chromeos::TPMTokenInfoGetter> tpm_token_info_getter_;
275 std::string user_id_;
276 std::vector<int64> delays_;
278 private:
279 base::MessageLoop message_loop_;
281 DISALLOW_COPY_AND_ASSIGN(UserTPMTokenInfoGetterTest);
284 TEST_F(SystemTPMTokenInfoGetterTest, BasicFlow) {
285 TestTPMTokenInfo reported_info;
286 tpm_token_info_getter_->Start(
287 base::Bind(&RecordGetterResult, &reported_info));
288 base::RunLoop().RunUntilIdle();
290 EXPECT_FALSE(reported_info.IsReady());
291 cryptohome_client_->SetTPMTokenInfo("TOKEN_1", "2222", 1);
293 EXPECT_TRUE(reported_info.IsReady());
294 EXPECT_TRUE(reported_info.enabled);
295 EXPECT_EQ("TOKEN_1", reported_info.name);
296 EXPECT_EQ("2222", reported_info.pin);
297 EXPECT_EQ(1, reported_info.slot_id);
299 EXPECT_EQ(std::vector<int64>(), delays_);
302 TEST_F(SystemTPMTokenInfoGetterTest, TokenSlotIdEqualsZero) {
303 TestTPMTokenInfo reported_info;
304 tpm_token_info_getter_->Start(
305 base::Bind(&RecordGetterResult, &reported_info));
306 base::RunLoop().RunUntilIdle();
308 EXPECT_FALSE(reported_info.IsReady());
309 cryptohome_client_->SetTPMTokenInfo("TOKEN_0", "2222", 0);
311 EXPECT_TRUE(reported_info.IsReady());
312 base::RunLoop().RunUntilIdle();
314 EXPECT_TRUE(reported_info.enabled);
315 EXPECT_EQ("TOKEN_0", reported_info.name);
316 EXPECT_EQ("2222", reported_info.pin);
317 EXPECT_EQ(0, reported_info.slot_id);
319 EXPECT_EQ(std::vector<int64>(), delays_);
322 TEST_F(SystemTPMTokenInfoGetterTest, TPMNotEnabled) {
323 cryptohome_client_->set_tpm_is_enabled(false);
325 TestTPMTokenInfo reported_info;
326 tpm_token_info_getter_->Start(
327 base::Bind(&RecordGetterResult, &reported_info));
328 base::RunLoop().RunUntilIdle();
330 EXPECT_FALSE(reported_info.IsReady());
331 EXPECT_FALSE(reported_info.enabled);
333 EXPECT_EQ(std::vector<int64>(), delays_);
336 TEST_F(SystemTPMTokenInfoGetterTest, TpmEnabledCallFails) {
337 cryptohome_client_->set_tpm_is_enabled_failure_count(1);
339 TestTPMTokenInfo reported_info;
340 tpm_token_info_getter_->Start(
341 base::Bind(&RecordGetterResult, &reported_info));
342 base::RunLoop().RunUntilIdle();
344 EXPECT_FALSE(reported_info.IsReady());
345 cryptohome_client_->SetTPMTokenInfo("TOKEN_1", "2222", 1);
347 EXPECT_TRUE(reported_info.IsReady());
348 EXPECT_TRUE(reported_info.enabled);
349 EXPECT_EQ("TOKEN_1", reported_info.name);
350 EXPECT_EQ("2222", reported_info.pin);
351 EXPECT_EQ(1, reported_info.slot_id);
353 const int64 kExpectedDelays[] = {100};
354 EXPECT_EQ(std::vector<int64>(kExpectedDelays,
355 kExpectedDelays + arraysize(kExpectedDelays)),
356 delays_);
359 TEST_F(SystemTPMTokenInfoGetterTest, GetTpmTokenInfoInitiallyNotReady) {
360 cryptohome_client_->set_get_tpm_token_info_not_set_count(1);
362 TestTPMTokenInfo reported_info;
363 tpm_token_info_getter_->Start(
364 base::Bind(&RecordGetterResult, &reported_info));
365 base::RunLoop().RunUntilIdle();
367 EXPECT_FALSE(reported_info.IsReady());
368 cryptohome_client_->SetTPMTokenInfo("TOKEN_1", "2222", 1);
370 EXPECT_TRUE(reported_info.IsReady());
371 EXPECT_TRUE(reported_info.enabled);
372 EXPECT_EQ("TOKEN_1", reported_info.name);
373 EXPECT_EQ("2222", reported_info.pin);
374 EXPECT_EQ(1, reported_info.slot_id);
376 const int64 kExpectedDelays[] = {100};
377 EXPECT_EQ(std::vector<int64>(kExpectedDelays,
378 kExpectedDelays + arraysize(kExpectedDelays)),
379 delays_);
382 TEST_F(SystemTPMTokenInfoGetterTest, GetTpmTokenInfoInitiallyFails) {
383 cryptohome_client_->set_get_tpm_token_info_failure_count(1);
385 TestTPMTokenInfo reported_info;
386 tpm_token_info_getter_->Start(
387 base::Bind(&RecordGetterResult, &reported_info));
388 base::RunLoop().RunUntilIdle();
390 EXPECT_FALSE(reported_info.IsReady());
391 cryptohome_client_->SetTPMTokenInfo("TOKEN_1", "2222", 1);
393 EXPECT_TRUE(reported_info.IsReady());
394 EXPECT_TRUE(reported_info.enabled);
395 EXPECT_EQ("TOKEN_1", reported_info.name);
396 EXPECT_EQ("2222", reported_info.pin);
397 EXPECT_EQ(1, reported_info.slot_id);
399 const int64 kExpectedDelays[] = {100};
400 EXPECT_EQ(std::vector<int64>(kExpectedDelays,
401 kExpectedDelays + arraysize(kExpectedDelays)),
402 delays_);
405 TEST_F(SystemTPMTokenInfoGetterTest, RetryDelaysIncreaseExponentially) {
406 cryptohome_client_->set_tpm_is_enabled_failure_count(2);
407 cryptohome_client_->set_get_tpm_token_info_failure_count(1);
408 cryptohome_client_->set_get_tpm_token_info_not_set_count(3);
410 TestTPMTokenInfo reported_info;
411 tpm_token_info_getter_->Start(
412 base::Bind(&RecordGetterResult, &reported_info));
413 base::RunLoop().RunUntilIdle();
415 EXPECT_FALSE(reported_info.IsReady());
416 cryptohome_client_->SetTPMTokenInfo("TOKEN_1", "2222", 2);
418 EXPECT_TRUE(reported_info.IsReady());
419 EXPECT_TRUE(reported_info.enabled);
420 EXPECT_EQ("TOKEN_1", reported_info.name);
421 EXPECT_EQ("2222", reported_info.pin);
422 EXPECT_EQ(2, reported_info.slot_id);
424 int64 kExpectedDelays[] = { 100, 200, 400, 800, 1600, 3200 };
425 ASSERT_EQ(
426 std::vector<int64>(kExpectedDelays,
427 kExpectedDelays + arraysize(kExpectedDelays)),
428 delays_);
431 TEST_F(SystemTPMTokenInfoGetterTest, RetryDelayBounded) {
432 cryptohome_client_->set_tpm_is_enabled_failure_count(4);
433 cryptohome_client_->set_get_tpm_token_info_failure_count(5);
434 cryptohome_client_->set_get_tpm_token_info_not_set_count(6);
436 TestTPMTokenInfo reported_info;
437 tpm_token_info_getter_->Start(
438 base::Bind(&RecordGetterResult, &reported_info));
439 base::RunLoop().RunUntilIdle();
441 EXPECT_FALSE(reported_info.IsReady());
442 cryptohome_client_->SetTPMTokenInfo("TOKEN_1", "2222", 1);
444 EXPECT_TRUE(reported_info.IsReady());
445 EXPECT_TRUE(reported_info.enabled);
446 EXPECT_EQ("TOKEN_1", reported_info.name);
447 EXPECT_EQ("2222", reported_info.pin);
448 EXPECT_EQ(1, reported_info.slot_id);
450 int64 kExpectedDelays[] = {
451 100, 200, 400, 800, 1600, 3200, 6400, 12800, 25600, 51200, 102400, 204800,
452 300000, 300000, 300000
454 ASSERT_EQ(
455 std::vector<int64>(kExpectedDelays,
456 kExpectedDelays + arraysize(kExpectedDelays)),
457 delays_);
460 TEST_F(UserTPMTokenInfoGetterTest, BasicFlow) {
461 TestTPMTokenInfo reported_info;
462 tpm_token_info_getter_->Start(
463 base::Bind(&RecordGetterResult, &reported_info));
464 base::RunLoop().RunUntilIdle();
466 EXPECT_FALSE(reported_info.IsReady());
467 cryptohome_client_->SetTPMTokenInfo("TOKEN_1", "2222", 1);
469 EXPECT_TRUE(reported_info.IsReady());
470 EXPECT_TRUE(reported_info.enabled);
471 EXPECT_EQ("TOKEN_1", reported_info.name);
472 EXPECT_EQ("2222", reported_info.pin);
473 EXPECT_EQ(1, reported_info.slot_id);
475 EXPECT_EQ(std::vector<int64>(), delays_);
478 TEST_F(UserTPMTokenInfoGetterTest, GetTpmTokenInfoInitiallyFails) {
479 cryptohome_client_->set_get_tpm_token_info_failure_count(1);
481 TestTPMTokenInfo reported_info;
482 tpm_token_info_getter_->Start(
483 base::Bind(&RecordGetterResult, &reported_info));
484 base::RunLoop().RunUntilIdle();
486 EXPECT_FALSE(reported_info.IsReady());
487 cryptohome_client_->SetTPMTokenInfo("TOKEN_1", "2222", 1);
489 EXPECT_TRUE(reported_info.IsReady());
490 EXPECT_TRUE(reported_info.enabled);
491 EXPECT_EQ("TOKEN_1", reported_info.name);
492 EXPECT_EQ("2222", reported_info.pin);
493 EXPECT_EQ(1, reported_info.slot_id);
495 const int64 kExpectedDelays[] = {100};
496 EXPECT_EQ(std::vector<int64>(kExpectedDelays,
497 kExpectedDelays + arraysize(kExpectedDelays)),
498 delays_);
501 TEST_F(UserTPMTokenInfoGetterTest, GetTpmTokenInfoInitiallyNotReady) {
502 cryptohome_client_->set_get_tpm_token_info_not_set_count(1);
504 TestTPMTokenInfo reported_info;
505 tpm_token_info_getter_->Start(
506 base::Bind(&RecordGetterResult, &reported_info));
507 base::RunLoop().RunUntilIdle();
509 EXPECT_FALSE(reported_info.IsReady());
510 cryptohome_client_->SetTPMTokenInfo("TOKEN_1", "2222", 1);
512 EXPECT_TRUE(reported_info.IsReady());
513 EXPECT_TRUE(reported_info.enabled);
514 EXPECT_EQ("TOKEN_1", reported_info.name);
515 EXPECT_EQ("2222", reported_info.pin);
516 EXPECT_EQ(1, reported_info.slot_id);
518 const int64 kExpectedDelays[] = {100};
519 EXPECT_EQ(std::vector<int64>(kExpectedDelays,
520 kExpectedDelays + arraysize(kExpectedDelays)),
521 delays_);
524 } // namespace