Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(321)

Side by Side Diff: components/cert_database/cert_database_service_io_part_chromeos.cc

Issue 419013003: Replace c/b/nss_context by a KeyedService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Flattened components/cert_database folders. Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "components/cert_database/cert_database_service_io_part_chromeos.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/location.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "chromeos/dbus/cryptohome_client.h"
14 #include "crypto/nss_util.h"
15 #include "crypto/nss_util_internal.h"
16 #include "net/cert/nss_cert_database_chromeos.h"
17
18 namespace cert_database {
19
20 namespace {
21
22 void DidGetTPMInfoOnUICallBackToIO(
23 const chromeos::CryptohomeClient::Pkcs11GetTpmTokenInfoCallback& callback,
24 scoped_refptr<base::SingleThreadTaskRunner> origin_thread,
25 chromeos::DBusMethodCallStatus call_status,
26 const std::string& label,
27 const std::string& user_pin,
28 int slot_id) {
29 DVLOG(1) << "Got TPM info for slot " << slot_id;
30 origin_thread->PostTask(
31 FROM_HERE, base::Bind(callback, call_status, label, user_pin, slot_id));
32 }
33
34 void GetTPMInfoForUserOnUIThread(
35 const std::string& user_email,
36 const chromeos::CryptohomeClient::Pkcs11GetTpmTokenInfoCallback& callback,
37 scoped_refptr<base::SingleThreadTaskRunner> origin_thread,
38 chromeos::CryptohomeClient* cryptohome_client) {
39 DVLOG(1) << "Getting TPM info from cryptohome for "
40 << " " << user_email;
41 cryptohome_client->Pkcs11GetTpmTokenInfoForUser(
42 user_email,
43 base::Bind(&DidGetTPMInfoOnUICallBackToIO, callback, origin_thread));
44 }
45
46 void GetTPMInfoForUserOnIOThread(
47 const std::string& user_email,
48 const chromeos::CryptohomeClient::Pkcs11GetTpmTokenInfoCallback& callback,
49 scoped_refptr<base::SequencedTaskRunner> dbus_task_runner,
50 chromeos::CryptohomeClient* cryptohome_client) {
51 dbus_task_runner->PostTask(FROM_HERE,
52 base::Bind(&GetTPMInfoForUserOnUIThread,
53 user_email,
54 callback,
55 base::ThreadTaskRunnerHandle::Get(),
56 cryptohome_client));
57 }
58
59 } // namespace
60
61 class CertDatabaseServiceIOPartChromeOS::Internal {
62 public:
63 Internal(const std::string& user_email,
64 const std::string& username_hash,
65 bool use_system_key_slot,
66 const base::FilePath& path,
67 const scoped_refptr<base::SequencedTaskRunner>& dbus_task_runner,
68 chromeos::CryptohomeClient* cryptohome_client,
69 CertDatabaseServiceIOPartChromeOS* io_part)
70 : user_email_(user_email),
71 username_hash_(username_hash),
72 use_system_key_slot_(use_system_key_slot),
73 path_(path),
74 dbus_task_runner_(dbus_task_runner),
75 state_(NOT_STARTED),
76 system_tpm_token_status_(SYSTEM_TPM_TOKEN_STATUS_UNDETERMINED),
77 cryptohome_client_(cryptohome_client),
78 io_part_(io_part),
79 weak_ptr_factory_(this) {
80 CHECK(dbus_task_runner_.get());
81 CHECK(cryptohome_client_);
82 CHECK(io_part_);
83 }
84
85 void Run() {
86 thread_checker_.DetachFromThread();
87 thread_checker_.CalledOnValidThread();
88 DCHECK_EQ(NOT_STARTED, state_);
89
90 VLOG(1) << "Initialize NSS for chromeos user " << username_hash_;
91 crypto::InitializeNSSForChromeOSUser(username_hash_, path_);
92 RunNextStep(TPM_TOKEN_STATE_UNKNOWN);
93 }
94
95 typedef base::Callback<void(bool system_tpm_token_enabled)>
96 SystemTPMTokenReadyCallback;
97 SystemTPMTokenReadyCallback GetSystemTPMTokenReadyCallback() {
98 return base::Bind(&Internal::OnSystemTPMTokenReady,
99 weak_ptr_factory_.GetWeakPtr());
100 }
101
102 private:
103 enum SystemTPMTokenStatus {
104 SYSTEM_TPM_TOKEN_STATUS_UNDETERMINED,
105 SYSTEM_TPM_TOKEN_STATUS_ENABLED,
106 SYSTEM_TPM_TOKEN_STATUS_DISABLED
107 };
108
109 enum State {
110 NOT_STARTED,
111 TPM_TOKEN_STATE_UNKNOWN,
112 TPM_TOKEN_ENABLED_AND_READY,
113 INITIALIZED_NSS_FOR_USER,
114 GOT_PRIVATE_SLOT_FOR_USER,
115 WAITING_FOR_SYSTEM_TPM_TOKEN,
116 SYSTEM_TPM_TOKEN_READY,
117 GOT_SYSTEM_SLOT,
118 CREATED_NSS_CERTDB
119 };
120
121 void RunNextStep(const State& next_state) {
122 DCHECK(thread_checker_.CalledOnValidThread());
123
124 VLOG(1) << "State transition " << state_ << " -> " << next_state;
125 state_ = next_state;
126 switch (state_) {
127 case NOT_STARTED:
128 NOTREACHED();
129 break;
130 case TPM_TOKEN_STATE_UNKNOWN:
131 CheckTPMTokenState();
132 break;
133 case TPM_TOKEN_ENABLED_AND_READY:
134 GetTPMTokenInfo();
135 break;
136 case INITIALIZED_NSS_FOR_USER:
137 GetPrivateSlot();
138 break;
139 case GOT_PRIVATE_SLOT_FOR_USER:
140 if (!use_system_key_slot_) {
141 RunNextStep(GOT_SYSTEM_SLOT);
142 } else if (system_tpm_token_status_ ==
143 SYSTEM_TPM_TOKEN_STATUS_UNDETERMINED) {
144 state_ = WAITING_FOR_SYSTEM_TPM_TOKEN;
145 } else {
146 RunNextStep(SYSTEM_TPM_TOKEN_READY);
147 }
148 break;
149 case WAITING_FOR_SYSTEM_TPM_TOKEN:
150 // This step is waiting for OnSystemTPMTokenReady to be called.
151 NOTREACHED();
152 break;
153 case SYSTEM_TPM_TOKEN_READY:
154 GetSystemSlot();
155 break;
156 case GOT_SYSTEM_SLOT:
157 CreateCertDatabase();
158 break;
159 case CREATED_NSS_CERTDB:
160 NOTREACHED();
161 }
162 }
163
164 void FinishWithState(const State& state) {
165 VLOG(1) << "FinishWithState " << state;
166 state_ = state;
167 }
168
169 void CheckTPMTokenState() {
170 // Check if it's OK to initialize TPM for the user before continuing. This
171 // may not be the case if the TPM slot initialization was previously
172 // requested for the same user.
173 if (!crypto::ShouldInitializeTPMForChromeOSUser(username_hash_)) {
174 RunNextStep(INITIALIZED_NSS_FOR_USER);
175 return;
176 }
177
178 crypto::WillInitializeTPMForChromeOSUser(username_hash_);
179
180 if (crypto::IsTPMTokenEnabledForNSS()) {
181 base::Closure tpm_token_ready_callback =
182 base::Bind(&Internal::RunNextStep,
183 weak_ptr_factory_.GetWeakPtr(),
184 TPM_TOKEN_ENABLED_AND_READY);
185 if (crypto::IsTPMTokenReady(tpm_token_ready_callback))
186 tpm_token_ready_callback.Run();
187 else
188 DVLOG(1) << "Waiting for tpm ready ...";
189 } else {
190 crypto::InitializePrivateSoftwareSlotForChromeOSUser(username_hash_);
191 RunNextStep(INITIALIZED_NSS_FOR_USER);
192 }
193 }
194
195 void GetTPMTokenInfo() {
196 GetTPMInfoForUserOnIOThread(
197 user_email_,
198 base::Bind(&Internal::GotTPMTokenInfo, weak_ptr_factory_.GetWeakPtr()),
199 dbus_task_runner_,
200 cryptohome_client_);
201 }
202
203 void GotTPMTokenInfo(chromeos::DBusMethodCallStatus call_status,
204 const std::string& label,
205 const std::string& user_pin,
206 int slot_id) {
207 DCHECK(thread_checker_.CalledOnValidThread());
208
209 if (call_status == chromeos::DBUS_METHOD_CALL_FAILURE) {
210 // TODO(pneubeck, tbarzic): Retry instead of just failing.
211 // https://crbug.com/426349
212 LOG(ERROR) << "DBus error while getting TPM info for " << username_hash_;
213 crypto::InitializePrivateSoftwareSlotForChromeOSUser(username_hash_);
214 } else {
215 crypto::InitializeTPMForChromeOSUser(username_hash_, slot_id);
216 }
217 RunNextStep(INITIALIZED_NSS_FOR_USER);
218 }
219
220 void GetPrivateSlot() {
221 base::Callback<void(crypto::ScopedPK11Slot)> callback =
222 base::Bind(&Internal::GotPrivateSlot, weak_ptr_factory_.GetWeakPtr());
223
224 crypto::ScopedPK11Slot private_slot(
225 crypto::GetPrivateSlotForChromeOSUser(username_hash_, callback));
226 if (private_slot)
227 callback.Run(private_slot.Pass());
228 }
229
230 void GotPrivateSlot(crypto::ScopedPK11Slot private_slot) {
231 DCHECK(thread_checker_.CalledOnValidThread());
232 DCHECK(private_slot);
233
234 private_slot_ = private_slot.Pass();
235 RunNextStep(GOT_PRIVATE_SLOT_FOR_USER);
236 }
237
238 // This is called from external once the TPM token is ready. Must be called at
239 // most once and after Run().
240 void OnSystemTPMTokenReady(bool system_tpm_token_enabled) {
241 DCHECK(thread_checker_.CalledOnValidThread());
242 DCHECK_NE(NOT_STARTED, state_);
243 DCHECK_EQ(SYSTEM_TPM_TOKEN_STATUS_UNDETERMINED, system_tpm_token_status_);
244
245 if (!use_system_key_slot_)
246 return;
247 if (system_tpm_token_enabled)
248 system_tpm_token_status_ = SYSTEM_TPM_TOKEN_STATUS_ENABLED;
249 else
250 system_tpm_token_status_ = SYSTEM_TPM_TOKEN_STATUS_DISABLED;
251 if (state_ == WAITING_FOR_SYSTEM_TPM_TOKEN)
252 RunNextStep(SYSTEM_TPM_TOKEN_READY);
253 }
254
255 void GetSystemSlot() {
256 if (!use_system_key_slot_ ||
257 system_tpm_token_status_ == SYSTEM_TPM_TOKEN_STATUS_DISABLED) {
258 VLOG(2) << "Skip system key slot initialization";
259 RunNextStep(GOT_SYSTEM_SLOT);
260 return;
261 }
262
263 base::Callback<void(crypto::ScopedPK11Slot)> callback =
264 base::Bind(&Internal::GotSystemSlot, weak_ptr_factory_.GetWeakPtr());
265
266 crypto::ScopedPK11Slot system_slot = crypto::GetSystemNSSKeySlot(callback);
267 if (system_slot)
268 callback.Run(system_slot.Pass());
269 }
270
271 void GotSystemSlot(crypto::ScopedPK11Slot system_slot) {
272 if (!system_slot)
273 LOG(ERROR) << "Could not get the system key slot.";
274 system_slot_ = system_slot.Pass();
275 RunNextStep(GOT_SYSTEM_SLOT);
276 }
277
278 void CreateCertDatabase() {
279 crypto::ScopedPK11Slot public_slot =
280 crypto::GetPublicSlotForChromeOSUser(username_hash_);
281
282 scoped_ptr<net::NSSCertDatabaseChromeOS> db(
283 new net::NSSCertDatabaseChromeOS(public_slot.Pass(),
284 private_slot_.Pass()));
285 if (system_slot_)
286 db->SetSystemSlot(system_slot_.Pass());
287
288 FinishWithState(CREATED_NSS_CERTDB);
289 io_part_->DidCreateNSSCertDatabase(db.Pass()); // Will delete this.
290 }
291
292 const std::string user_email_;
293 const std::string username_hash_;
294 bool use_system_key_slot_;
295 const base::FilePath path_;
296 scoped_refptr<base::SequencedTaskRunner> dbus_task_runner_;
297 State state_;
298 crypto::ScopedPK11Slot private_slot_;
299 SystemTPMTokenStatus system_tpm_token_status_;
300 crypto::ScopedPK11Slot system_slot_;
301 chromeos::CryptohomeClient* cryptohome_client_;
302 CertDatabaseServiceIOPartChromeOS* io_part_;
303 base::ThreadChecker thread_checker_;
304 base::WeakPtrFactory<Internal> weak_ptr_factory_;
305
306 DISALLOW_COPY_AND_ASSIGN(Internal);
307 };
308
309 CertDatabaseServiceIOPartChromeOS::CertDatabaseServiceIOPartChromeOS(
310 const std::string& user_email,
311 const std::string& username_hash,
312 bool use_system_key_slot,
313 const base::FilePath& path,
314 const scoped_refptr<base::SequencedTaskRunner>& dbus_task_runner,
315 chromeos::CryptohomeClient* cryptohome_client)
316 : internal_(new Internal(user_email,
317 username_hash,
318 use_system_key_slot,
319 path,
320 dbus_task_runner,
321 cryptohome_client,
322 this)) {
323 }
324
325 CertDatabaseServiceIOPartChromeOS::~CertDatabaseServiceIOPartChromeOS() {
326 }
327
328 void CertDatabaseServiceIOPartChromeOS::Init() {
329 CertDatabaseServiceIOPart::Init();
330 internal_->Run();
331 }
332
333 void CertDatabaseServiceIOPartChromeOS::DidCreateNSSCertDatabase(
334 scoped_ptr<net::NSSCertDatabase> db) {
335 internal_.reset();
336 SetNSSCertDatabase(db.Pass());
337 }
338
339 CertDatabaseServiceIOPartChromeOS::SystemTPMTokenReadyCallback
340 CertDatabaseServiceIOPartChromeOS::GetSystemTPMTokenReadyCallback() {
341 CHECK(!IsInitialized());
342 return internal_->GetSystemTPMTokenReadyCallback();
343 }
344
345 } // namespace cert_database
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698