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

Side by Side Diff: chrome/browser/chromeos/platform_keys/platform_keys_nss.cc

Issue 430563002: Enable system token in platformKeys api. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 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 | Annotate | Revision Log
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/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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698