| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |