Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chromeos / tpm / tpm_token_info_getter.cc
blob6f6dfe7b3b1fb3eb767422a8836cc780678b8bb3
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 "chromeos/tpm/tpm_token_info_getter.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "chromeos/dbus/cryptohome_client.h"
11 namespace {
13 const int64 kInitialRequestDelayMs = 100;
14 const int64 kMaxRequestDelayMs = 300000; // 5 minutes
16 // Calculates the delay before running next attempt to initiatialize the TPM
17 // token, if |last_delay| was the last or initial delay.
18 base::TimeDelta GetNextRequestDelayMs(base::TimeDelta last_delay) {
19 // This implements an exponential backoff, as we don't know in which order of
20 // magnitude the TPM token changes it's state.
21 base::TimeDelta next_delay = last_delay * 2;
23 // Cap the delay to prevent an overflow. This threshold is arbitrarily chosen.
24 const base::TimeDelta max_delay =
25 base::TimeDelta::FromMilliseconds(kMaxRequestDelayMs);
26 if (next_delay > max_delay)
27 next_delay = max_delay;
28 return next_delay;
31 } // namespace
33 namespace chromeos {
35 TPMTokenInfo::TPMTokenInfo()
36 : tpm_is_enabled(false),
37 token_slot_id(-1) {
40 TPMTokenInfo::~TPMTokenInfo() {}
42 // static
43 scoped_ptr<TPMTokenInfoGetter> TPMTokenInfoGetter::CreateForUserToken(
44 const std::string& user_id,
45 CryptohomeClient* cryptohome_client,
46 const scoped_refptr<base::TaskRunner>& delayed_task_runner) {
47 CHECK(!user_id.empty());
48 return scoped_ptr<TPMTokenInfoGetter>(
49 new TPMTokenInfoGetter(
50 TYPE_USER, user_id, cryptohome_client, delayed_task_runner));
53 // static
54 scoped_ptr<TPMTokenInfoGetter> TPMTokenInfoGetter::CreateForSystemToken(
55 CryptohomeClient* cryptohome_client,
56 const scoped_refptr<base::TaskRunner>& delayed_task_runner) {
57 return scoped_ptr<TPMTokenInfoGetter>(
58 new TPMTokenInfoGetter(
59 TYPE_SYSTEM, std::string(), cryptohome_client, delayed_task_runner));
62 TPMTokenInfoGetter::~TPMTokenInfoGetter() {}
64 void TPMTokenInfoGetter::Start(const TPMTokenInfoCallback& callback) {
65 CHECK(state_ == STATE_INITIAL);
66 CHECK(!callback.is_null());
68 callback_ = callback;
70 state_ = STATE_STARTED;
71 Continue();
74 TPMTokenInfoGetter::TPMTokenInfoGetter(
75 TPMTokenInfoGetter::Type type,
76 const std::string& user_id,
77 CryptohomeClient* cryptohome_client,
78 const scoped_refptr<base::TaskRunner>& delayed_task_runner)
79 : delayed_task_runner_(delayed_task_runner),
80 type_(type),
81 state_(TPMTokenInfoGetter::STATE_INITIAL),
82 user_id_(user_id),
83 tpm_request_delay_(
84 base::TimeDelta::FromMilliseconds(kInitialRequestDelayMs)),
85 cryptohome_client_(cryptohome_client),
86 weak_factory_(this) {
89 void TPMTokenInfoGetter::Continue() {
90 switch (state_) {
91 case STATE_INITIAL:
92 NOTREACHED();
93 break;
94 case STATE_STARTED:
95 cryptohome_client_->TpmIsEnabled(
96 base::Bind(&TPMTokenInfoGetter::OnTpmIsEnabled,
97 weak_factory_.GetWeakPtr()));
98 break;
99 case STATE_TPM_ENABLED:
100 if (type_ == TYPE_SYSTEM) {
101 cryptohome_client_->Pkcs11GetTpmTokenInfo(
102 base::Bind(&TPMTokenInfoGetter::OnPkcs11GetTpmTokenInfo,
103 weak_factory_.GetWeakPtr()));
104 } else { // if (type_ == TYPE_USER)
105 cryptohome_client_->Pkcs11GetTpmTokenInfoForUser(
106 user_id_,
107 base::Bind(&TPMTokenInfoGetter::OnPkcs11GetTpmTokenInfo,
108 weak_factory_.GetWeakPtr()));
110 break;
111 case STATE_DONE:
112 NOTREACHED();
116 void TPMTokenInfoGetter::RetryLater() {
117 delayed_task_runner_->PostDelayedTask(
118 FROM_HERE,
119 base::Bind(&TPMTokenInfoGetter::Continue, weak_factory_.GetWeakPtr()),
120 tpm_request_delay_);
121 tpm_request_delay_ = GetNextRequestDelayMs(tpm_request_delay_);
124 void TPMTokenInfoGetter::OnTpmIsEnabled(DBusMethodCallStatus call_status,
125 bool tpm_is_enabled) {
126 if (call_status != DBUS_METHOD_CALL_SUCCESS) {
127 RetryLater();
128 return;
131 if (!tpm_is_enabled) {
132 state_ = STATE_DONE;
133 callback_.Run(TPMTokenInfo());
134 return;
137 state_ = STATE_TPM_ENABLED;
138 Continue();
141 void TPMTokenInfoGetter::OnPkcs11GetTpmTokenInfo(
142 DBusMethodCallStatus call_status,
143 const std::string& token_name,
144 const std::string& user_pin,
145 int token_slot_id) {
146 if (call_status == DBUS_METHOD_CALL_FAILURE || token_slot_id == -1) {
147 RetryLater();
148 return;
151 state_ = STATE_DONE;
153 TPMTokenInfo token_info;
154 token_info.tpm_is_enabled = true;
155 token_info.token_name = token_name;
156 token_info.user_pin = user_pin;
157 token_info.token_slot_id = token_slot_id;
159 callback_.Run(token_info);
162 } // namespace chromeos