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

Side by Side Diff: chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc

Issue 1138123003: Delay creating easy signin TPM keys until TPM is initialized (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: pneubeck comments Created 5 years, 7 months 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager. h" 5 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager. h"
6 6
7 #include <cryptohi.h> 7 #include <cryptohi.h>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 14 matching lines...) Expand all
25 #include "crypto/nss_util_internal.h" 25 #include "crypto/nss_util_internal.h"
26 #include "crypto/rsa_private_key.h" 26 #include "crypto/rsa_private_key.h"
27 #include "crypto/scoped_nss_types.h" 27 #include "crypto/scoped_nss_types.h"
28 28
29 namespace { 29 namespace {
30 30
31 // The modulus length for RSA keys used by easy sign-in. 31 // The modulus length for RSA keys used by easy sign-in.
32 const int kKeyModulusLength = 2048; 32 const int kKeyModulusLength = 2048;
33 33
34 // Relays |GetSystemSlotOnIOThread| callback to |response_task_runner|. 34 // Relays |GetSystemSlotOnIOThread| callback to |response_task_runner|.
35 void RunCallbackOnThreadRunner( 35 void RunCallbackOnTaskRunner(
36 const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner, 36 const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner,
37 const base::Callback<void(crypto::ScopedPK11Slot)>& callback, 37 const base::Callback<void(crypto::ScopedPK11Slot)>& callback,
38 crypto::ScopedPK11Slot slot) { 38 crypto::ScopedPK11Slot slot) {
39 response_task_runner->PostTask(FROM_HERE, 39 response_task_runner->PostTask(FROM_HERE,
40 base::Bind(callback, base::Passed(&slot))); 40 base::Bind(callback, base::Passed(&slot)));
41 } 41 }
42 42
43 // Gets TPM system slot. Must be called on IO thread. 43 // Gets TPM system slot. Must be called on IO thread.
44 // The callback wil be relayed to |response_task_runner|. 44 // The callback wil be relayed to |response_task_runner|.
45 void GetSystemSlotOnIOThread( 45 void GetSystemSlotOnIOThread(
46 const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner, 46 const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner,
47 const base::Callback<void(crypto::ScopedPK11Slot)>& callback) { 47 const base::Callback<void(crypto::ScopedPK11Slot)>& callback) {
48 base::Callback<void(crypto::ScopedPK11Slot)> callback_on_origin_thread = 48 base::Callback<void(crypto::ScopedPK11Slot)> callback_on_origin_thread =
49 base::Bind(&RunCallbackOnThreadRunner, response_task_runner, callback); 49 base::Bind(&RunCallbackOnTaskRunner, response_task_runner, callback);
50 50
51 crypto::ScopedPK11Slot system_slot = 51 crypto::ScopedPK11Slot system_slot =
52 crypto::GetSystemNSSKeySlot(callback_on_origin_thread); 52 crypto::GetSystemNSSKeySlot(callback_on_origin_thread);
53 if (system_slot) 53 if (system_slot)
54 callback_on_origin_thread.Run(system_slot.Pass()); 54 callback_on_origin_thread.Run(system_slot.Pass());
55 } 55 }
56 56
57 // Relays |EnsureUserTpmInitializedOnIOThread| callback to
58 // |response_task_runner|, ignoring |slot|.
59 void RunCallbackWithoutSlotOnTaskRunner(
60 const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner,
61 const base::Closure& callback,
62 crypto::ScopedPK11Slot slot) {
63 response_task_runner->PostTask(FROM_HERE, callback);
64 }
65
66 void EnsureUserTPMInitializedOnIOThread(
67 const std::string& username_hash,
68 const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner,
69 const base::Closure& callback) {
70 base::Callback<void(crypto::ScopedPK11Slot)> callback_on_origin_thread =
71 base::Bind(&RunCallbackWithoutSlotOnTaskRunner, response_task_runner,
72 callback);
73
74 crypto::ScopedPK11Slot private_slot = crypto::GetPrivateSlotForChromeOSUser(
75 username_hash, callback_on_origin_thread);
76 if (private_slot)
77 callback_on_origin_thread.Run(private_slot.Pass());
78 }
79
57 // Checks if a private RSA key associated with |public_key| can be found in 80 // Checks if a private RSA key associated with |public_key| can be found in
58 // |slot|. 81 // |slot|.
59 // Must be called on a worker thread. 82 // Must be called on a worker thread.
60 scoped_ptr<crypto::RSAPrivateKey> GetPrivateKeyOnWorkerThread( 83 scoped_ptr<crypto::RSAPrivateKey> GetPrivateKeyOnWorkerThread(
61 PK11SlotInfo* slot, 84 PK11SlotInfo* slot,
62 const std::string& public_key) { 85 const std::string& public_key) {
63 const uint8* public_key_uint8 = 86 const uint8* public_key_uint8 =
64 reinterpret_cast<const uint8*>(public_key.data()); 87 reinterpret_cast<const uint8*>(public_key.data());
65 std::vector<uint8> public_key_vector( 88 std::vector<uint8> public_key_vector(
66 public_key_uint8, public_key_uint8 + public_key.size()); 89 public_key_uint8, public_key_uint8 + public_key.size());
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 if (!g_browser_process) 184 if (!g_browser_process)
162 return; 185 return;
163 PrefService* local_state = g_browser_process->local_state(); 186 PrefService* local_state = g_browser_process->local_state();
164 if (!local_state) 187 if (!local_state)
165 return; 188 return;
166 189
167 DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockLocalStateTpmKeys); 190 DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockLocalStateTpmKeys);
168 update->RemoveWithoutPathExpansion(user_id, NULL); 191 update->RemoveWithoutPathExpansion(user_id, NULL);
169 } 192 }
170 193
171 EasyUnlockTpmKeyManager::EasyUnlockTpmKeyManager(const std::string& user_id, 194 EasyUnlockTpmKeyManager::EasyUnlockTpmKeyManager(
172 PrefService* local_state) 195 const std::string& user_id,
196 const std::string& username_hash,
197 PrefService* local_state)
173 : user_id_(user_id), 198 : user_id_(user_id),
199 username_hash_(username_hash),
174 local_state_(local_state), 200 local_state_(local_state),
175 create_tpm_key_state_(CREATE_TPM_KEY_NOT_STARTED), 201 create_tpm_key_state_(CREATE_TPM_KEY_NOT_STARTED),
176 get_tpm_slot_weak_ptr_factory_(this), 202 get_tpm_slot_weak_ptr_factory_(this),
177 weak_ptr_factory_(this) { 203 weak_ptr_factory_(this) {
178 } 204 }
179 205
180 EasyUnlockTpmKeyManager::~EasyUnlockTpmKeyManager() { 206 EasyUnlockTpmKeyManager::~EasyUnlockTpmKeyManager() {
181 } 207 }
182 208
183 bool EasyUnlockTpmKeyManager::PrepareTpmKey( 209 bool EasyUnlockTpmKeyManager::PrepareTpmKey(
184 bool check_private_key, 210 bool check_private_key,
185 const base::Closure& callback) { 211 const base::Closure& callback) {
186 CHECK(!user_id_.empty()); 212 CHECK(!user_id_.empty());
213 CHECK(!username_hash_.empty());
187 214
188 if (create_tpm_key_state_ == CREATE_TPM_KEY_DONE) 215 if (create_tpm_key_state_ == CREATE_TPM_KEY_DONE)
189 return true; 216 return true;
190 217
191 std::string key = GetPublicTpmKey(user_id_); 218 std::string key = GetPublicTpmKey(user_id_);
192 if (!check_private_key && !key.empty() && 219 if (!check_private_key && !key.empty() &&
193 create_tpm_key_state_ == CREATE_TPM_KEY_NOT_STARTED) { 220 create_tpm_key_state_ == CREATE_TPM_KEY_NOT_STARTED) {
194 return true; 221 return true;
195 } 222 }
196 223
197 prepare_tpm_key_callbacks_.push_back(callback); 224 prepare_tpm_key_callbacks_.push_back(callback);
198 225
199 if (create_tpm_key_state_ == CREATE_TPM_KEY_NOT_STARTED) { 226 if (create_tpm_key_state_ == CREATE_TPM_KEY_NOT_STARTED) {
200 create_tpm_key_state_ = CREATE_TPM_KEY_WAITING_FOR_SYSTEM_SLOT; 227 create_tpm_key_state_ = CREATE_TPM_KEY_WAITING_FOR_USER_SLOT;
201 228
202 base::Callback<void(crypto::ScopedPK11Slot)> create_key_with_system_slot = 229 base::Closure on_user_tpm_ready =
203 base::Bind(&EasyUnlockTpmKeyManager::CreateKeyInSystemSlot, 230 base::Bind(&EasyUnlockTpmKeyManager::OnUserTPMInitialized,
204 get_tpm_slot_weak_ptr_factory_.GetWeakPtr(), 231 get_tpm_slot_weak_ptr_factory_.GetWeakPtr(), key);
205 key);
206 232
207 content::BrowserThread::PostTask( 233 content::BrowserThread::PostTask(
208 content::BrowserThread::IO, 234 content::BrowserThread::IO, FROM_HERE,
209 FROM_HERE, 235 base::Bind(&EnsureUserTPMInitializedOnIOThread, username_hash_,
210 base::Bind(&GetSystemSlotOnIOThread, 236 base::ThreadTaskRunnerHandle::Get(), on_user_tpm_ready));
211 base::ThreadTaskRunnerHandle::Get(),
212 create_key_with_system_slot));
213 } 237 }
214 238
215 return false; 239 return false;
216 } 240 }
217 241
218 bool EasyUnlockTpmKeyManager::StartGetSystemSlotTimeoutMs(size_t timeout_ms) { 242 bool EasyUnlockTpmKeyManager::StartGetSystemSlotTimeoutMs(size_t timeout_ms) {
219 if (create_tpm_key_state_ == CREATE_TPM_KEY_DONE || 243 if (StartedCreatingTpmKeys())
220 create_tpm_key_state_ == CREATE_TPM_KEY_GOT_SYSTEM_SLOT) {
221 return false; 244 return false;
222 }
223 245
224 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 246 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
225 FROM_HERE, 247 FROM_HERE,
226 base::Bind(&EasyUnlockTpmKeyManager::OnTpmKeyCreated, 248 base::Bind(&EasyUnlockTpmKeyManager::OnTpmKeyCreated,
227 get_tpm_slot_weak_ptr_factory_.GetWeakPtr(), 249 get_tpm_slot_weak_ptr_factory_.GetWeakPtr(),
228 std::string()), 250 std::string()),
229 base::TimeDelta::FromMilliseconds(timeout_ms)); 251 base::TimeDelta::FromMilliseconds(timeout_ms));
230 return true; 252 return true;
231 } 253 }
232 254
(...skipping 27 matching lines...) Expand all
260 key, data, callback); 282 key, data, callback);
261 283
262 content::BrowserThread::PostTask( 284 content::BrowserThread::PostTask(
263 content::BrowserThread::IO, 285 content::BrowserThread::IO,
264 FROM_HERE, 286 FROM_HERE,
265 base::Bind(&GetSystemSlotOnIOThread, 287 base::Bind(&GetSystemSlotOnIOThread,
266 base::ThreadTaskRunnerHandle::Get(), 288 base::ThreadTaskRunnerHandle::Get(),
267 sign_with_system_slot)); 289 sign_with_system_slot));
268 } 290 }
269 291
292 bool EasyUnlockTpmKeyManager::StartedCreatingTpmKeys() const {
293 return create_tpm_key_state_ == CREATE_TPM_KEY_GOT_SYSTEM_SLOT ||
294 create_tpm_key_state_ == CREATE_TPM_KEY_DONE;
295 }
296
270 void EasyUnlockTpmKeyManager::SetKeyInLocalState(const std::string& user_id, 297 void EasyUnlockTpmKeyManager::SetKeyInLocalState(const std::string& user_id,
271 const std::string& value) { 298 const std::string& value) {
272 if (!local_state_) 299 if (!local_state_)
273 return; 300 return;
274 301
275 std::string encoded; 302 std::string encoded;
276 base::Base64Encode(value, &encoded); 303 base::Base64Encode(value, &encoded);
277 DictionaryPrefUpdate update(local_state_, 304 DictionaryPrefUpdate update(local_state_,
278 prefs::kEasyUnlockLocalStateTpmKeys); 305 prefs::kEasyUnlockLocalStateTpmKeys);
279 update->SetStringWithoutPathExpansion(user_id, encoded); 306 update->SetStringWithoutPathExpansion(user_id, encoded);
280 } 307 }
281 308
309 void EasyUnlockTpmKeyManager::OnUserTPMInitialized(
310 const std::string& public_key) {
311 create_tpm_key_state_ = CREATE_TPM_KEY_WAITING_FOR_SYSTEM_SLOT;
312
313 base::Callback<void(crypto::ScopedPK11Slot)> create_key_with_system_slot =
314 base::Bind(&EasyUnlockTpmKeyManager::CreateKeyInSystemSlot,
315 get_tpm_slot_weak_ptr_factory_.GetWeakPtr(), public_key);
316
317 content::BrowserThread::PostTask(
318 content::BrowserThread::IO, FROM_HERE,
319 base::Bind(&GetSystemSlotOnIOThread, base::ThreadTaskRunnerHandle::Get(),
320 create_key_with_system_slot));
321 }
322
282 void EasyUnlockTpmKeyManager::CreateKeyInSystemSlot( 323 void EasyUnlockTpmKeyManager::CreateKeyInSystemSlot(
283 const std::string& public_key, 324 const std::string& public_key,
284 crypto::ScopedPK11Slot system_slot) { 325 crypto::ScopedPK11Slot system_slot) {
285 CHECK(system_slot); 326 CHECK(system_slot);
286
287 create_tpm_key_state_ = CREATE_TPM_KEY_GOT_SYSTEM_SLOT; 327 create_tpm_key_state_ = CREATE_TPM_KEY_GOT_SYSTEM_SLOT;
288 328
289 // If there are any delayed tasks posted using |StartGetSystemSlotTimeoutMs|, 329 // If there are any delayed tasks posted using |StartGetSystemSlotTimeoutMs|,
290 // this will cancel them. 330 // this will cancel them.
291 // Note that this would cancel other pending |CreateKeyInSystemSlot| tasks, 331 // Note that this would cancel other pending |CreateKeyInSystemSlot| tasks,
292 // but there should be at most one such task at a time. 332 // but there should be at most one such task at a time.
293 get_tpm_slot_weak_ptr_factory_.InvalidateWeakPtrs(); 333 get_tpm_slot_weak_ptr_factory_.InvalidateWeakPtrs();
294 334
295 base::WorkerPool::PostTask( 335 base::WorkerPool::PostTask(
296 FROM_HERE, 336 FROM_HERE,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 // If key creation failed, reset the state machine. 386 // If key creation failed, reset the state machine.
347 create_tpm_key_state_ = 387 create_tpm_key_state_ =
348 public_key.empty() ? CREATE_TPM_KEY_NOT_STARTED : CREATE_TPM_KEY_DONE; 388 public_key.empty() ? CREATE_TPM_KEY_NOT_STARTED : CREATE_TPM_KEY_DONE;
349 } 389 }
350 390
351 void EasyUnlockTpmKeyManager::OnDataSigned( 391 void EasyUnlockTpmKeyManager::OnDataSigned(
352 const base::Callback<void(const std::string&)>& callback, 392 const base::Callback<void(const std::string&)>& callback,
353 const std::string& signature) { 393 const std::string& signature) {
354 callback.Run(signature); 394 callback.Run(signature);
355 } 395 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698