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 |