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"
8 #include "base/location.h"
9 #include "chromeos/dbus/cryptohome_client.h"
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
;
35 TPMTokenInfo::TPMTokenInfo()
36 : tpm_is_enabled(false),
40 TPMTokenInfo::~TPMTokenInfo() {}
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
));
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());
70 state_
= STATE_STARTED
;
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
),
81 state_(TPMTokenInfoGetter::STATE_INITIAL
),
84 base::TimeDelta::FromMilliseconds(kInitialRequestDelayMs
)),
85 cryptohome_client_(cryptohome_client
),
89 void TPMTokenInfoGetter::Continue() {
95 cryptohome_client_
->TpmIsEnabled(
96 base::Bind(&TPMTokenInfoGetter::OnTpmIsEnabled
,
97 weak_factory_
.GetWeakPtr()));
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(
107 base::Bind(&TPMTokenInfoGetter::OnPkcs11GetTpmTokenInfo
,
108 weak_factory_
.GetWeakPtr()));
116 void TPMTokenInfoGetter::RetryLater() {
117 delayed_task_runner_
->PostDelayedTask(
119 base::Bind(&TPMTokenInfoGetter::Continue
, weak_factory_
.GetWeakPtr()),
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
) {
131 if (!tpm_is_enabled
) {
133 callback_
.Run(TPMTokenInfo());
137 state_
= STATE_TPM_ENABLED
;
141 void TPMTokenInfoGetter::OnPkcs11GetTpmTokenInfo(
142 DBusMethodCallStatus call_status
,
143 const std::string
& token_name
,
144 const std::string
& user_pin
,
146 if (call_status
== DBUS_METHOD_CALL_FAILURE
|| token_slot_id
== -1) {
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