Chromium Code Reviews| 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/platform_keys/platform_keys.h" | 5 #include "chrome/browser/chromeos/platform_keys/platform_keys.h" |
| 6 | 6 |
| 7 #include <cryptohi.h> | 7 #include <cryptohi.h> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 65 // The task runner on which the NSS operation was called. Any reply must be | 65 // The task runner on which the NSS operation was called. Any reply must be |
| 66 // posted to this runner. | 66 // posted to this runner. |
| 67 scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; | 67 scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; |
| 68 | 68 |
| 69 private: | 69 private: |
| 70 DISALLOW_COPY_AND_ASSIGN(NSSOperationState); | 70 DISALLOW_COPY_AND_ASSIGN(NSSOperationState); |
| 71 }; | 71 }; |
| 72 | 72 |
| 73 typedef base::Callback<void(net::NSSCertDatabase* cert_db)> GetCertDBCallback; | 73 typedef base::Callback<void(net::NSSCertDatabase* cert_db)> GetCertDBCallback; |
| 74 | 74 |
| 75 // Called back with the NSSCertDatabase associated to the given |token_id|. | 75 // Called back with the NSSCertDatabase associated to the given |context|. |
|
Joao da Silva
2014/07/30 08:46:38
There is no |context| here
pneubeck (no reviews)
2014/07/30 13:53:45
Done.
| |
| 76 // Calls |callback| if the database was successfully retrieved. Used by | 76 // If |token_id| is not empty, sets |slot_| of the state accordingly and calls |
| 77 // |callback| if the database was successfully retrieved. Used by | |
| 77 // GetCertDatabaseOnIOThread. | 78 // GetCertDatabaseOnIOThread. |
| 78 void DidGetCertDBOnIOThread(const GetCertDBCallback& callback, | 79 void DidGetCertDBOnIOThread(const std::string& token_id, |
| 80 const GetCertDBCallback& callback, | |
| 79 NSSOperationState* state, | 81 NSSOperationState* state, |
| 80 net::NSSCertDatabase* cert_db) { | 82 net::NSSCertDatabase* cert_db) { |
| 81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 82 if (!cert_db) { | 84 if (!cert_db) { |
| 83 LOG(ERROR) << "Couldn't get NSSCertDatabase."; | 85 LOG(ERROR) << "Couldn't get NSSCertDatabase."; |
| 84 state->OnError(FROM_HERE, kErrorInternal); | 86 state->OnError(FROM_HERE, kErrorInternal); |
| 85 return; | 87 return; |
| 86 } | 88 } |
| 87 | 89 |
| 88 state->slot_ = cert_db->GetPrivateSlot(); | 90 if (!token_id.empty()) { |
| 89 if (!state->slot_) { | 91 if (token_id == kTokenIdUser) |
| 90 LOG(ERROR) << "No private slot"; | 92 state->slot_ = cert_db->GetPrivateSlot(); |
| 91 state->OnError(FROM_HERE, kErrorInternal); | 93 else if (token_id == kTokenIdSystem) |
|
Joao da Silva
2014/07/30 08:46:38
Why isn't kTokenIdUser and kTokenIdSystem an enum?
pneubeck (no reviews)
2014/07/30 13:53:45
Explained now at the declaration comment.
| |
| 92 return; | 94 state->slot_ = cert_db->GetSystemSlot(); |
| 95 | |
| 96 if (!state->slot_) { | |
| 97 LOG(ERROR) << "Slot for token id '" << token_id << "' not available."; | |
| 98 state->OnError(FROM_HERE, kErrorInternal); | |
| 99 return; | |
| 100 } | |
| 93 } | 101 } |
| 94 | 102 |
| 95 callback.Run(cert_db); | 103 callback.Run(cert_db); |
| 96 } | 104 } |
| 97 | 105 |
| 98 // Retrieves the NSSCertDatabase from |context|. Must be called on the IO | 106 // Retrieves the NSSCertDatabase from |context| and, if |token_id| is not empty, |
| 99 // thread. | 107 // the slot for |token_id|. |
| 100 void GetCertDatabaseOnIOThread(content::ResourceContext* context, | 108 // Must be called on the IO thread. |
| 109 void GetCertDatabaseOnIOThread(const std::string& token_id, | |
| 101 const GetCertDBCallback& callback, | 110 const GetCertDBCallback& callback, |
| 111 content::ResourceContext* context, | |
| 102 NSSOperationState* state) { | 112 NSSOperationState* state) { |
| 103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 104 net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext( | 114 net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext( |
| 105 context, base::Bind(&DidGetCertDBOnIOThread, callback, state)); | 115 context, base::Bind(&DidGetCertDBOnIOThread, token_id, callback, state)); |
| 106 | 116 |
| 107 if (cert_db) | 117 if (cert_db) |
| 108 DidGetCertDBOnIOThread(callback, state, cert_db); | 118 DidGetCertDBOnIOThread(token_id, callback, state, cert_db); |
| 109 } | 119 } |
| 110 | 120 |
| 111 // Asynchronously fetches the NSSCertDatabase and PK11Slot for |token_id|. | 121 // Asynchronously fetches the NSSCertDatabase for |browser_context| and, if |
| 112 // Stores the slot in |state| and passes the database to |callback|. Will run | 122 // |token| is not empty, the slot for |token_id|. Stores the slot in |state| |
|
Joao da Silva
2014/07/30 08:46:39
|token| -> |token_id|
pneubeck (no reviews)
2014/07/30 13:53:45
Done.
| |
| 113 // |callback| on the IO thread. | 123 // and passes the database to |callback|. Will run |callback| on the IO thread. |
| 114 void GetCertDatabase(const std::string& token_id, | 124 void GetCertDatabase(const std::string& token_id, |
| 115 const GetCertDBCallback& callback, | 125 const GetCertDBCallback& callback, |
| 116 BrowserContext* browser_context, | 126 BrowserContext* browser_context, |
| 117 NSSOperationState* state) { | 127 NSSOperationState* state) { |
| 118 // TODO(pneubeck): Decide which DB to retrieve depending on |token_id|. | |
| 119 BrowserThread::PostTask(BrowserThread::IO, | 128 BrowserThread::PostTask(BrowserThread::IO, |
| 120 FROM_HERE, | 129 FROM_HERE, |
| 121 base::Bind(&GetCertDatabaseOnIOThread, | 130 base::Bind(&GetCertDatabaseOnIOThread, |
| 131 token_id, | |
| 132 callback, | |
| 122 browser_context->GetResourceContext(), | 133 browser_context->GetResourceContext(), |
| 123 callback, | |
| 124 state)); | 134 state)); |
| 125 } | 135 } |
| 126 | 136 |
| 127 class GenerateRSAKeyState : public NSSOperationState { | 137 class GenerateRSAKeyState : public NSSOperationState { |
| 128 public: | 138 public: |
| 129 GenerateRSAKeyState(unsigned int modulus_length_bits, | 139 GenerateRSAKeyState(unsigned int modulus_length_bits, |
| 130 const subtle::GenerateKeyCallback& callback); | 140 const subtle::GenerateKeyCallback& callback); |
| 131 virtual ~GenerateRSAKeyState() {} | 141 virtual ~GenerateRSAKeyState() {} |
| 132 | 142 |
| 133 virtual void OnError(const tracked_objects::Location& from, | 143 virtual void OnError(const tracked_objects::Location& from, |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 origin_task_runner_->PostTask(from, base::Bind(callback_, error_message)); | 253 origin_task_runner_->PostTask(from, base::Bind(callback_, error_message)); |
| 244 } | 254 } |
| 245 | 255 |
| 246 scoped_refptr<net::X509Certificate> certificate_; | 256 scoped_refptr<net::X509Certificate> certificate_; |
| 247 | 257 |
| 248 private: | 258 private: |
| 249 // Must be called on origin thread, use CallBack() therefore. | 259 // Must be called on origin thread, use CallBack() therefore. |
| 250 RemoveCertificateCallback callback_; | 260 RemoveCertificateCallback callback_; |
| 251 }; | 261 }; |
| 252 | 262 |
| 263 class GetTokensState : public NSSOperationState { | |
| 264 public: | |
| 265 explicit GetTokensState(const GetTokensCallback& callback); | |
| 266 virtual ~GetTokensState() {} | |
| 267 | |
| 268 virtual void OnError(const tracked_objects::Location& from, | |
| 269 const std::string& error_message) OVERRIDE { | |
| 270 CallBack(from, | |
| 271 scoped_ptr<std::vector<std::string> >() /* no token ids */, | |
| 272 error_message); | |
| 273 } | |
| 274 | |
| 275 void CallBack(const tracked_objects::Location& from, | |
| 276 scoped_ptr<std::vector<std::string> > token_ids, | |
| 277 const std::string& error_message) { | |
| 278 origin_task_runner_->PostTask( | |
| 279 from, base::Bind(callback_, base::Passed(&token_ids), error_message)); | |
| 280 } | |
| 281 | |
| 282 private: | |
| 283 // Must be called on origin thread, use CallBack() therefore. | |
|
Joao da Silva
2014/07/30 08:46:38
, therefore use Callback().
pneubeck (no reviews)
2014/07/30 13:53:45
Done.
| |
| 284 GetTokensCallback callback_; | |
| 285 }; | |
| 286 | |
| 253 NSSOperationState::NSSOperationState() | 287 NSSOperationState::NSSOperationState() |
| 254 : origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) { | 288 : origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) { |
| 255 } | 289 } |
| 256 | 290 |
| 257 GenerateRSAKeyState::GenerateRSAKeyState( | 291 GenerateRSAKeyState::GenerateRSAKeyState( |
| 258 unsigned int modulus_length_bits, | 292 unsigned int modulus_length_bits, |
| 259 const subtle::GenerateKeyCallback& callback) | 293 const subtle::GenerateKeyCallback& callback) |
| 260 : modulus_length_bits_(modulus_length_bits), callback_(callback) { | 294 : modulus_length_bits_(modulus_length_bits), callback_(callback) { |
| 261 } | 295 } |
| 262 | 296 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 280 const ImportCertificateCallback& callback) | 314 const ImportCertificateCallback& callback) |
| 281 : certificate_(certificate), callback_(callback) { | 315 : certificate_(certificate), callback_(callback) { |
| 282 } | 316 } |
| 283 | 317 |
| 284 RemoveCertificateState::RemoveCertificateState( | 318 RemoveCertificateState::RemoveCertificateState( |
| 285 scoped_refptr<net::X509Certificate> certificate, | 319 scoped_refptr<net::X509Certificate> certificate, |
| 286 const RemoveCertificateCallback& callback) | 320 const RemoveCertificateCallback& callback) |
| 287 : certificate_(certificate), callback_(callback) { | 321 : certificate_(certificate), callback_(callback) { |
| 288 } | 322 } |
| 289 | 323 |
| 324 GetTokensState::GetTokensState(const GetTokensCallback& callback) | |
| 325 : callback_(callback) { | |
| 326 } | |
| 327 | |
| 290 // Does the actual key generation on a worker thread. Used by | 328 // Does the actual key generation on a worker thread. Used by |
| 291 // GenerateRSAKeyWithDB(). | 329 // GenerateRSAKeyWithDB(). |
| 292 void GenerateRSAKeyOnWorkerThread(scoped_ptr<GenerateRSAKeyState> state) { | 330 void GenerateRSAKeyOnWorkerThread(scoped_ptr<GenerateRSAKeyState> state) { |
| 293 scoped_ptr<crypto::RSAPrivateKey> rsa_key( | 331 scoped_ptr<crypto::RSAPrivateKey> rsa_key( |
| 294 crypto::RSAPrivateKey::CreateSensitive(state->slot_.get(), | 332 crypto::RSAPrivateKey::CreateSensitive(state->slot_.get(), |
| 295 state->modulus_length_bits_)); | 333 state->modulus_length_bits_)); |
| 296 if (!rsa_key) { | 334 if (!rsa_key) { |
| 297 LOG(ERROR) << "Couldn't create key."; | 335 LOG(ERROR) << "Couldn't create key."; |
| 298 state->OnError(FROM_HERE, kErrorInternal); | 336 state->OnError(FROM_HERE, kErrorInternal); |
| 299 return; | 337 return; |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 440 const net::Error cert_status = | 478 const net::Error cert_status = |
| 441 static_cast<net::Error>(db->CheckUserCert(state->certificate_)); | 479 static_cast<net::Error>(db->CheckUserCert(state->certificate_)); |
| 442 if (cert_status == net::ERR_NO_PRIVATE_KEY_FOR_CERT) { | 480 if (cert_status == net::ERR_NO_PRIVATE_KEY_FOR_CERT) { |
| 443 state->OnError(FROM_HERE, kErrorKeyNotFound); | 481 state->OnError(FROM_HERE, kErrorKeyNotFound); |
| 444 return; | 482 return; |
| 445 } else if (cert_status != net::OK) { | 483 } else if (cert_status != net::OK) { |
| 446 state->OnError(FROM_HERE, net::ErrorToString(cert_status)); | 484 state->OnError(FROM_HERE, net::ErrorToString(cert_status)); |
| 447 return; | 485 return; |
| 448 } | 486 } |
| 449 | 487 |
| 488 // Check that the private key is in the correct slot. | |
| 489 PK11SlotInfo* slot = | |
| 490 PK11_KeyForCertExists(state->certificate_->os_cert_handle(), NULL, NULL); | |
| 491 if (slot != state->slot_) { | |
| 492 state->OnError(FROM_HERE, kErrorKeyNotFound); | |
| 493 return; | |
| 494 } | |
| 495 | |
| 450 const net::Error import_status = | 496 const net::Error import_status = |
| 451 static_cast<net::Error>(db->AddUserCert(state->certificate_.get())); | 497 static_cast<net::Error>(db->AddUserCert(state->certificate_.get())); |
| 452 if (import_status != net::OK) { | 498 if (import_status != net::OK) { |
| 453 LOG(ERROR) << "Could not import certificate."; | 499 LOG(ERROR) << "Could not import certificate."; |
| 454 state->OnError(FROM_HERE, net::ErrorToString(import_status)); | 500 state->OnError(FROM_HERE, net::ErrorToString(import_status)); |
| 455 return; | 501 return; |
| 456 } | 502 } |
| 457 | 503 |
| 458 state->CallBack(FROM_HERE, std::string() /* no error */); | 504 state->CallBack(FROM_HERE, std::string() /* no error */); |
| 459 } | 505 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 483 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 529 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 484 // Get the pointer before base::Passed clears |state|. | 530 // Get the pointer before base::Passed clears |state|. |
| 485 scoped_refptr<net::X509Certificate> certificate = state->certificate_; | 531 scoped_refptr<net::X509Certificate> certificate = state->certificate_; |
| 486 bool certificate_found = certificate->os_cert_handle()->isperm; | 532 bool certificate_found = certificate->os_cert_handle()->isperm; |
| 487 cert_db->DeleteCertAndKeyAsync( | 533 cert_db->DeleteCertAndKeyAsync( |
| 488 certificate, | 534 certificate, |
| 489 base::Bind( | 535 base::Bind( |
| 490 &DidRemoveCertificate, base::Passed(&state), certificate_found)); | 536 &DidRemoveCertificate, base::Passed(&state), certificate_found)); |
| 491 } | 537 } |
| 492 | 538 |
| 539 // Does the actual work to determine which tokens are available. | |
| 540 void GetTokensWithDB(scoped_ptr<GetTokensState> state, | |
| 541 net::NSSCertDatabase* cert_db) { | |
| 542 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 543 scoped_ptr<std::vector<std::string> > token_ids(new std::vector<std::string>); | |
| 544 | |
| 545 // The user's token is always available. | |
| 546 token_ids->push_back(kTokenIdUser); | |
| 547 if (cert_db->GetSystemSlot()) | |
| 548 token_ids->push_back(kTokenIdSystem); | |
|
Joao da Silva
2014/07/30 08:46:39
Doesn't this depend on state->slot_, based on what
pneubeck (no reviews)
2014/07/30 13:53:45
GetCertDatabase always gets the DB for the browser
| |
| 549 | |
| 550 state->CallBack(FROM_HERE, token_ids.Pass(), std::string() /* no error */); | |
| 551 } | |
| 552 | |
| 493 } // namespace | 553 } // namespace |
| 494 | 554 |
| 495 namespace subtle { | 555 namespace subtle { |
| 496 | 556 |
| 497 void GenerateRSAKey(const std::string& token_id, | 557 void GenerateRSAKey(const std::string& token_id, |
| 498 unsigned int modulus_length_bits, | 558 unsigned int modulus_length_bits, |
| 499 const GenerateKeyCallback& callback, | 559 const GenerateKeyCallback& callback, |
| 500 BrowserContext* browser_context) { | 560 BrowserContext* browser_context) { |
| 501 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 561 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 502 scoped_ptr<GenerateRSAKeyState> state( | 562 scoped_ptr<GenerateRSAKeyState> state( |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 581 NSSOperationState* state_ptr = state.get(); | 641 NSSOperationState* state_ptr = state.get(); |
| 582 | 642 |
| 583 // The NSSCertDatabase object is not required. But in case it's not available | 643 // The NSSCertDatabase object is not required. But in case it's not available |
| 584 // we would get more informative error messages. | 644 // we would get more informative error messages. |
| 585 GetCertDatabase(token_id, | 645 GetCertDatabase(token_id, |
| 586 base::Bind(&RemoveCertificateWithDB, base::Passed(&state)), | 646 base::Bind(&RemoveCertificateWithDB, base::Passed(&state)), |
| 587 browser_context, | 647 browser_context, |
| 588 state_ptr); | 648 state_ptr); |
| 589 } | 649 } |
| 590 | 650 |
| 651 void GetTokens(const GetTokensCallback& callback, | |
| 652 content::BrowserContext* browser_context) { | |
| 653 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 654 scoped_ptr<GetTokensState> state(new GetTokensState(callback)); | |
| 655 // Get the pointer to |state| before base::Passed releases |state|. | |
| 656 NSSOperationState* state_ptr = state.get(); | |
| 657 GetCertDatabase(std::string() /* don't get any specific slot */, | |
| 658 base::Bind(&GetTokensWithDB, base::Passed(&state)), | |
| 659 browser_context, | |
| 660 state_ptr); | |
| 661 } | |
| 662 | |
| 591 } // namespace platform_keys | 663 } // namespace platform_keys |
| 592 | 664 |
| 593 } // namespace chromeos | 665 } // namespace chromeos |
| OLD | NEW |