• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/chromeos/platform_keys/platform_keys.h"
6 
7 #include <cryptohi.h>
8 
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/compiler_specific.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "base/threading/worker_pool.h"
19 #include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h"
20 #include "chrome/browser/net/nss_context.h"
21 #include "content/public/browser/browser_context.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "crypto/rsa_private_key.h"
24 #include "net/base/crypto_module.h"
25 #include "net/base/net_errors.h"
26 #include "net/cert/cert_database.h"
27 #include "net/cert/nss_cert_database.h"
28 #include "net/cert/x509_certificate.h"
29 
30 using content::BrowserContext;
31 using content::BrowserThread;
32 
33 namespace {
34 const char kErrorInternal[] = "Internal Error.";
35 const char kErrorKeyNotFound[] = "Key not found.";
36 const char kErrorCertificateNotFound[] = "Certificate could not be found.";
37 const char kErrorAlgorithmNotSupported[] = "Algorithm not supported.";
38 
39 // The current maximal RSA modulus length that ChromeOS's TPM supports for key
40 // generation.
41 const unsigned int kMaxRSAModulusLengthBits = 2048;
42 }
43 
44 namespace chromeos {
45 
46 namespace platform_keys {
47 
48 namespace {
49 
50 // Base class to store state that is common to all NSS database operations and
51 // to provide convenience methods to call back.
52 // Keeps track of the originating task runner.
53 class NSSOperationState {
54  public:
55   NSSOperationState();
~NSSOperationState()56   virtual ~NSSOperationState() {}
57 
58   // Called if an error occurred during the execution of the NSS operation
59   // described by this object.
60   virtual void OnError(const tracked_objects::Location& from,
61                        const std::string& error_message) = 0;
62 
63   crypto::ScopedPK11Slot slot_;
64 
65   // The task runner on which the NSS operation was called. Any reply must be
66   // posted to this runner.
67   scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
68 
69  private:
70   DISALLOW_COPY_AND_ASSIGN(NSSOperationState);
71 };
72 
73 typedef base::Callback<void(net::NSSCertDatabase* cert_db)> GetCertDBCallback;
74 
75 // Called back with the NSSCertDatabase associated to the given |token_id|.
76 // Calls |callback| if the database was successfully retrieved. Used by
77 // GetCertDatabaseOnIOThread.
DidGetCertDBOnIOThread(const GetCertDBCallback & callback,NSSOperationState * state,net::NSSCertDatabase * cert_db)78 void DidGetCertDBOnIOThread(const GetCertDBCallback& callback,
79                             NSSOperationState* state,
80                             net::NSSCertDatabase* cert_db) {
81   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
82   if (!cert_db) {
83     LOG(ERROR) << "Couldn't get NSSCertDatabase.";
84     state->OnError(FROM_HERE, kErrorInternal);
85     return;
86   }
87 
88   state->slot_ = cert_db->GetPrivateSlot();
89   if (!state->slot_) {
90     LOG(ERROR) << "No private slot";
91     state->OnError(FROM_HERE, kErrorInternal);
92     return;
93   }
94 
95   callback.Run(cert_db);
96 }
97 
98 // Retrieves the NSSCertDatabase from |context|. Must be called on the IO
99 // thread.
GetCertDatabaseOnIOThread(content::ResourceContext * context,const GetCertDBCallback & callback,NSSOperationState * state)100 void GetCertDatabaseOnIOThread(content::ResourceContext* context,
101                                const GetCertDBCallback& callback,
102                                NSSOperationState* state) {
103   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
104   net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext(
105       context, base::Bind(&DidGetCertDBOnIOThread, callback, state));
106 
107   if (cert_db)
108     DidGetCertDBOnIOThread(callback, state, cert_db);
109 }
110 
111 // Asynchronously fetches the NSSCertDatabase and PK11Slot for |token_id|.
112 // Stores the slot in |state| and passes the database to |callback|. Will run
113 // |callback| on the IO thread.
GetCertDatabase(const std::string & token_id,const GetCertDBCallback & callback,BrowserContext * browser_context,NSSOperationState * state)114 void GetCertDatabase(const std::string& token_id,
115                      const GetCertDBCallback& callback,
116                      BrowserContext* browser_context,
117                      NSSOperationState* state) {
118   // TODO(pneubeck): Decide which DB to retrieve depending on |token_id|.
119   BrowserThread::PostTask(BrowserThread::IO,
120                           FROM_HERE,
121                           base::Bind(&GetCertDatabaseOnIOThread,
122                                      browser_context->GetResourceContext(),
123                                      callback,
124                                      state));
125 }
126 
127 class GenerateRSAKeyState : public NSSOperationState {
128  public:
129   GenerateRSAKeyState(unsigned int modulus_length_bits,
130                       const subtle::GenerateKeyCallback& callback);
~GenerateRSAKeyState()131   virtual ~GenerateRSAKeyState() {}
132 
OnError(const tracked_objects::Location & from,const std::string & error_message)133   virtual void OnError(const tracked_objects::Location& from,
134                        const std::string& error_message) OVERRIDE {
135     CallBack(from, std::string() /* no public key */, error_message);
136   }
137 
CallBack(const tracked_objects::Location & from,const std::string & public_key_spki_der,const std::string & error_message)138   void CallBack(const tracked_objects::Location& from,
139                 const std::string& public_key_spki_der,
140                 const std::string& error_message) {
141     origin_task_runner_->PostTask(
142         from, base::Bind(callback_, public_key_spki_der, error_message));
143   }
144 
145   const unsigned int modulus_length_bits_;
146 
147  private:
148   // Must be called on origin thread, use CallBack() therefore.
149   subtle::GenerateKeyCallback callback_;
150 };
151 
152 class SignState : public NSSOperationState {
153  public:
154   SignState(const std::string& public_key,
155             HashAlgorithm hash_algorithm,
156             const std::string& data,
157             const subtle::SignCallback& callback);
~SignState()158   virtual ~SignState() {}
159 
OnError(const tracked_objects::Location & from,const std::string & error_message)160   virtual void OnError(const tracked_objects::Location& from,
161                        const std::string& error_message) OVERRIDE {
162     CallBack(from, std::string() /* no signature */, error_message);
163   }
164 
CallBack(const tracked_objects::Location & from,const std::string & signature,const std::string & error_message)165   void CallBack(const tracked_objects::Location& from,
166                 const std::string& signature,
167                 const std::string& error_message) {
168     origin_task_runner_->PostTask(
169         from, base::Bind(callback_, signature, error_message));
170   }
171 
172   const std::string public_key_;
173   HashAlgorithm hash_algorithm_;
174   const std::string data_;
175 
176  private:
177   // Must be called on origin thread, use CallBack() therefore.
178   subtle::SignCallback callback_;
179 };
180 
181 class GetCertificatesState : public NSSOperationState {
182  public:
183   explicit GetCertificatesState(const GetCertificatesCallback& callback);
~GetCertificatesState()184   virtual ~GetCertificatesState() {}
185 
OnError(const tracked_objects::Location & from,const std::string & error_message)186   virtual void OnError(const tracked_objects::Location& from,
187                        const std::string& error_message) OVERRIDE {
188     CallBack(from,
189              scoped_ptr<net::CertificateList>() /* no certificates */,
190              error_message);
191   }
192 
CallBack(const tracked_objects::Location & from,scoped_ptr<net::CertificateList> certs,const std::string & error_message)193   void CallBack(const tracked_objects::Location& from,
194                 scoped_ptr<net::CertificateList> certs,
195                 const std::string& error_message) {
196     origin_task_runner_->PostTask(
197         from, base::Bind(callback_, base::Passed(&certs), error_message));
198   }
199 
200   scoped_ptr<net::CertificateList> certs_;
201 
202  private:
203   // Must be called on origin thread, use CallBack() therefore.
204   GetCertificatesCallback callback_;
205 };
206 
207 class ImportCertificateState : public NSSOperationState {
208  public:
209   ImportCertificateState(scoped_refptr<net::X509Certificate> certificate,
210                          const ImportCertificateCallback& callback);
~ImportCertificateState()211   virtual ~ImportCertificateState() {}
212 
OnError(const tracked_objects::Location & from,const std::string & error_message)213   virtual void OnError(const tracked_objects::Location& from,
214                        const std::string& error_message) OVERRIDE {
215     CallBack(from, error_message);
216   }
217 
CallBack(const tracked_objects::Location & from,const std::string & error_message)218   void CallBack(const tracked_objects::Location& from,
219                 const std::string& error_message) {
220     origin_task_runner_->PostTask(from, base::Bind(callback_, error_message));
221   }
222 
223   scoped_refptr<net::X509Certificate> certificate_;
224 
225  private:
226   // Must be called on origin thread, use CallBack() therefore.
227   ImportCertificateCallback callback_;
228 };
229 
230 class RemoveCertificateState : public NSSOperationState {
231  public:
232   RemoveCertificateState(scoped_refptr<net::X509Certificate> certificate,
233                          const RemoveCertificateCallback& callback);
~RemoveCertificateState()234   virtual ~RemoveCertificateState() {}
235 
OnError(const tracked_objects::Location & from,const std::string & error_message)236   virtual void OnError(const tracked_objects::Location& from,
237                        const std::string& error_message) OVERRIDE {
238     CallBack(from, error_message);
239   }
240 
CallBack(const tracked_objects::Location & from,const std::string & error_message)241   void CallBack(const tracked_objects::Location& from,
242                 const std::string& error_message) {
243     origin_task_runner_->PostTask(from, base::Bind(callback_, error_message));
244   }
245 
246   scoped_refptr<net::X509Certificate> certificate_;
247 
248  private:
249   // Must be called on origin thread, use CallBack() therefore.
250   RemoveCertificateCallback callback_;
251 };
252 
NSSOperationState()253 NSSOperationState::NSSOperationState()
254     : origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
255 }
256 
GenerateRSAKeyState(unsigned int modulus_length_bits,const subtle::GenerateKeyCallback & callback)257 GenerateRSAKeyState::GenerateRSAKeyState(
258     unsigned int modulus_length_bits,
259     const subtle::GenerateKeyCallback& callback)
260     : modulus_length_bits_(modulus_length_bits), callback_(callback) {
261 }
262 
SignState(const std::string & public_key,HashAlgorithm hash_algorithm,const std::string & data,const subtle::SignCallback & callback)263 SignState::SignState(const std::string& public_key,
264                      HashAlgorithm hash_algorithm,
265                      const std::string& data,
266                      const subtle::SignCallback& callback)
267     : public_key_(public_key),
268       hash_algorithm_(hash_algorithm),
269       data_(data),
270       callback_(callback) {
271 }
272 
GetCertificatesState(const GetCertificatesCallback & callback)273 GetCertificatesState::GetCertificatesState(
274     const GetCertificatesCallback& callback)
275     : callback_(callback) {
276 }
277 
ImportCertificateState(scoped_refptr<net::X509Certificate> certificate,const ImportCertificateCallback & callback)278 ImportCertificateState::ImportCertificateState(
279     scoped_refptr<net::X509Certificate> certificate,
280     const ImportCertificateCallback& callback)
281     : certificate_(certificate), callback_(callback) {
282 }
283 
RemoveCertificateState(scoped_refptr<net::X509Certificate> certificate,const RemoveCertificateCallback & callback)284 RemoveCertificateState::RemoveCertificateState(
285     scoped_refptr<net::X509Certificate> certificate,
286     const RemoveCertificateCallback& callback)
287     : certificate_(certificate), callback_(callback) {
288 }
289 
290 // Does the actual key generation on a worker thread. Used by
291 // GenerateRSAKeyWithDB().
GenerateRSAKeyOnWorkerThread(scoped_ptr<GenerateRSAKeyState> state)292 void GenerateRSAKeyOnWorkerThread(scoped_ptr<GenerateRSAKeyState> state) {
293   scoped_ptr<crypto::RSAPrivateKey> rsa_key(
294       crypto::RSAPrivateKey::CreateSensitive(state->slot_.get(),
295                                              state->modulus_length_bits_));
296   if (!rsa_key) {
297     LOG(ERROR) << "Couldn't create key.";
298     state->OnError(FROM_HERE, kErrorInternal);
299     return;
300   }
301 
302   std::vector<uint8> public_key_spki_der;
303   if (!rsa_key->ExportPublicKey(&public_key_spki_der)) {
304     // TODO(pneubeck): Remove rsa_key from storage.
305     LOG(ERROR) << "Couldn't export public key.";
306     state->OnError(FROM_HERE, kErrorInternal);
307     return;
308   }
309   state->CallBack(
310       FROM_HERE,
311       std::string(public_key_spki_der.begin(), public_key_spki_der.end()),
312       std::string() /* no error */);
313 }
314 
315 // Continues generating a RSA key with the obtained NSSCertDatabase. Used by
316 // GenerateRSAKey().
GenerateRSAKeyWithDB(scoped_ptr<GenerateRSAKeyState> state,net::NSSCertDatabase * cert_db)317 void GenerateRSAKeyWithDB(scoped_ptr<GenerateRSAKeyState> state,
318                           net::NSSCertDatabase* cert_db) {
319   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
320   // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|.
321   base::WorkerPool::PostTask(
322       FROM_HERE,
323       base::Bind(&GenerateRSAKeyOnWorkerThread, base::Passed(&state)),
324       true /*task is slow*/);
325 }
326 
327 // Does the actual signing on a worker thread. Used by RSASignWithDB().
RSASignOnWorkerThread(scoped_ptr<SignState> state)328 void RSASignOnWorkerThread(scoped_ptr<SignState> state) {
329   const uint8* public_key_uint8 =
330       reinterpret_cast<const uint8*>(state->public_key_.data());
331   std::vector<uint8> public_key_vector(
332       public_key_uint8, public_key_uint8 + state->public_key_.size());
333 
334   // TODO(pneubeck): This searches all slots. Change to look only at |slot_|.
335   scoped_ptr<crypto::RSAPrivateKey> rsa_key(
336       crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector));
337   if (!rsa_key || rsa_key->key()->pkcs11Slot != state->slot_) {
338     state->OnError(FROM_HERE, kErrorKeyNotFound);
339     return;
340   }
341 
342   SECOidTag sign_alg_tag = SEC_OID_UNKNOWN;
343   switch (state->hash_algorithm_) {
344     case HASH_ALGORITHM_SHA1:
345       sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
346       break;
347     case HASH_ALGORITHM_SHA256:
348       sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
349       break;
350     case HASH_ALGORITHM_SHA384:
351       sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
352       break;
353     case HASH_ALGORITHM_SHA512:
354       sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
355       break;
356   }
357 
358   SECItem sign_result = {siBuffer, NULL, 0};
359   if (SEC_SignData(&sign_result,
360                    reinterpret_cast<const unsigned char*>(state->data_.data()),
361                    state->data_.size(),
362                    rsa_key->key(),
363                    sign_alg_tag) != SECSuccess) {
364     LOG(ERROR) << "Couldn't sign.";
365     state->OnError(FROM_HERE, kErrorInternal);
366     return;
367   }
368 
369   std::string signature(reinterpret_cast<const char*>(sign_result.data),
370                         sign_result.len);
371   state->CallBack(FROM_HERE, signature, std::string() /* no error */);
372 }
373 
374 // Continues signing with the obtained NSSCertDatabase. Used by Sign().
RSASignWithDB(scoped_ptr<SignState> state,net::NSSCertDatabase * cert_db)375 void RSASignWithDB(scoped_ptr<SignState> state, net::NSSCertDatabase* cert_db) {
376   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
377   // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|.
378   base::WorkerPool::PostTask(
379       FROM_HERE,
380       base::Bind(&RSASignOnWorkerThread, base::Passed(&state)),
381       true /*task is slow*/);
382 }
383 
384 // Filters the obtained certificates on a worker thread. Used by
385 // DidGetCertificates().
FilterCertificatesOnWorkerThread(scoped_ptr<GetCertificatesState> state)386 void FilterCertificatesOnWorkerThread(scoped_ptr<GetCertificatesState> state) {
387   scoped_ptr<net::CertificateList> client_certs(new net::CertificateList);
388   for (net::CertificateList::const_iterator it = state->certs_->begin();
389        it != state->certs_->end();
390        ++it) {
391     net::X509Certificate::OSCertHandle cert_handle = (*it)->os_cert_handle();
392     crypto::ScopedPK11Slot cert_slot(PK11_KeyForCertExists(cert_handle,
393                                                            NULL,    // keyPtr
394                                                            NULL));  // wincx
395 
396     // Keep only user certificates, i.e. certs for which the private key is
397     // present and stored in the queried slot.
398     if (cert_slot != state->slot_)
399       continue;
400 
401     client_certs->push_back(*it);
402   }
403 
404   state->CallBack(FROM_HERE, client_certs.Pass(), std::string() /* no error */);
405 }
406 
407 // Passes the obtained certificates to the worker thread for filtering. Used by
408 // GetCertificatesWithDB().
DidGetCertificates(scoped_ptr<GetCertificatesState> state,scoped_ptr<net::CertificateList> all_certs)409 void DidGetCertificates(scoped_ptr<GetCertificatesState> state,
410                         scoped_ptr<net::CertificateList> all_certs) {
411   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
412   state->certs_ = all_certs.Pass();
413   base::WorkerPool::PostTask(
414       FROM_HERE,
415       base::Bind(&FilterCertificatesOnWorkerThread, base::Passed(&state)),
416       true /*task is slow*/);
417 }
418 
419 // Continues getting certificates with the obtained NSSCertDatabase. Used by
420 // GetCertificates().
GetCertificatesWithDB(scoped_ptr<GetCertificatesState> state,net::NSSCertDatabase * cert_db)421 void GetCertificatesWithDB(scoped_ptr<GetCertificatesState> state,
422                            net::NSSCertDatabase* cert_db) {
423   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
424   // Get the pointer to slot before base::Passed releases |state|.
425   PK11SlotInfo* slot = state->slot_.get();
426   cert_db->ListCertsInSlot(
427       base::Bind(&DidGetCertificates, base::Passed(&state)), slot);
428 }
429 
430 // Does the actual certificate importing on the IO thread. Used by
431 // ImportCertificate().
ImportCertificateWithDB(scoped_ptr<ImportCertificateState> state,net::NSSCertDatabase * cert_db)432 void ImportCertificateWithDB(scoped_ptr<ImportCertificateState> state,
433                              net::NSSCertDatabase* cert_db) {
434   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
435   // TODO(pneubeck): Use |state->slot_| to verify that we're really importing to
436   // the correct token.
437   // |cert_db| is not required, ignore it.
438   net::CertDatabase* db = net::CertDatabase::GetInstance();
439 
440   const net::Error cert_status =
441       static_cast<net::Error>(db->CheckUserCert(state->certificate_));
442   if (cert_status == net::ERR_NO_PRIVATE_KEY_FOR_CERT) {
443     state->OnError(FROM_HERE, kErrorKeyNotFound);
444     return;
445   } else if (cert_status != net::OK) {
446     state->OnError(FROM_HERE, net::ErrorToString(cert_status));
447     return;
448   }
449 
450   const net::Error import_status =
451       static_cast<net::Error>(db->AddUserCert(state->certificate_.get()));
452   if (import_status != net::OK) {
453     LOG(ERROR) << "Could not import certificate.";
454     state->OnError(FROM_HERE, net::ErrorToString(import_status));
455     return;
456   }
457 
458   state->CallBack(FROM_HERE, std::string() /* no error */);
459 }
460 
461 // Called on IO thread after the certificate removal is finished.
DidRemoveCertificate(scoped_ptr<RemoveCertificateState> state,bool certificate_found,bool success)462 void DidRemoveCertificate(scoped_ptr<RemoveCertificateState> state,
463                           bool certificate_found,
464                           bool success) {
465   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
466   // CertificateNotFound error has precedence over an internal error.
467   if (!certificate_found) {
468     state->OnError(FROM_HERE, kErrorCertificateNotFound);
469     return;
470   }
471   if (!success) {
472     state->OnError(FROM_HERE, kErrorInternal);
473     return;
474   }
475 
476   state->CallBack(FROM_HERE, std::string() /* no error */);
477 }
478 
479 // Does the actual certificate removal on the IO thread. Used by
480 // RemoveCertificate().
RemoveCertificateWithDB(scoped_ptr<RemoveCertificateState> state,net::NSSCertDatabase * cert_db)481 void RemoveCertificateWithDB(scoped_ptr<RemoveCertificateState> state,
482                              net::NSSCertDatabase* cert_db) {
483   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
484   // Get the pointer before base::Passed clears |state|.
485   scoped_refptr<net::X509Certificate> certificate = state->certificate_;
486   bool certificate_found = certificate->os_cert_handle()->isperm;
487   cert_db->DeleteCertAndKeyAsync(
488       certificate,
489       base::Bind(
490           &DidRemoveCertificate, base::Passed(&state), certificate_found));
491 }
492 
493 }  // namespace
494 
495 namespace subtle {
496 
GenerateRSAKey(const std::string & token_id,unsigned int modulus_length_bits,const GenerateKeyCallback & callback,BrowserContext * browser_context)497 void GenerateRSAKey(const std::string& token_id,
498                     unsigned int modulus_length_bits,
499                     const GenerateKeyCallback& callback,
500                     BrowserContext* browser_context) {
501   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
502   scoped_ptr<GenerateRSAKeyState> state(
503       new GenerateRSAKeyState(modulus_length_bits, callback));
504 
505   if (modulus_length_bits > kMaxRSAModulusLengthBits) {
506     state->OnError(FROM_HERE, kErrorAlgorithmNotSupported);
507     return;
508   }
509 
510   // Get the pointer to |state| before base::Passed releases |state|.
511   NSSOperationState* state_ptr = state.get();
512   GetCertDatabase(token_id,
513                   base::Bind(&GenerateRSAKeyWithDB, base::Passed(&state)),
514                   browser_context,
515                   state_ptr);
516 }
517 
Sign(const std::string & token_id,const std::string & public_key,HashAlgorithm hash_algorithm,const std::string & data,const SignCallback & callback,BrowserContext * browser_context)518 void Sign(const std::string& token_id,
519           const std::string& public_key,
520           HashAlgorithm hash_algorithm,
521           const std::string& data,
522           const SignCallback& callback,
523           BrowserContext* browser_context) {
524   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
525   scoped_ptr<SignState> state(
526       new SignState(public_key, hash_algorithm, data, callback));
527   // Get the pointer to |state| before base::Passed releases |state|.
528   NSSOperationState* state_ptr = state.get();
529 
530   // The NSSCertDatabase object is not required. But in case it's not available
531   // we would get more informative error messages and we can double check that
532   // we use a key of the correct token.
533   GetCertDatabase(token_id,
534                   base::Bind(&RSASignWithDB, base::Passed(&state)),
535                   browser_context,
536                   state_ptr);
537 }
538 
539 }  // namespace subtle
540 
GetCertificates(const std::string & token_id,const GetCertificatesCallback & callback,BrowserContext * browser_context)541 void GetCertificates(const std::string& token_id,
542                      const GetCertificatesCallback& callback,
543                      BrowserContext* browser_context) {
544   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
545   scoped_ptr<GetCertificatesState> state(new GetCertificatesState(callback));
546   // Get the pointer to |state| before base::Passed releases |state|.
547   NSSOperationState* state_ptr = state.get();
548   GetCertDatabase(token_id,
549                   base::Bind(&GetCertificatesWithDB, base::Passed(&state)),
550                   browser_context,
551                   state_ptr);
552 }
553 
ImportCertificate(const std::string & token_id,scoped_refptr<net::X509Certificate> certificate,const ImportCertificateCallback & callback,BrowserContext * browser_context)554 void ImportCertificate(const std::string& token_id,
555                        scoped_refptr<net::X509Certificate> certificate,
556                        const ImportCertificateCallback& callback,
557                        BrowserContext* browser_context) {
558   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
559   scoped_ptr<ImportCertificateState> state(
560       new ImportCertificateState(certificate, callback));
561   // Get the pointer to |state| before base::Passed releases |state|.
562   NSSOperationState* state_ptr = state.get();
563 
564   // The NSSCertDatabase object is not required. But in case it's not available
565   // we would get more informative error messages and we can double check that
566   // we use a key of the correct token.
567   GetCertDatabase(token_id,
568                   base::Bind(&ImportCertificateWithDB, base::Passed(&state)),
569                   browser_context,
570                   state_ptr);
571 }
572 
RemoveCertificate(const std::string & token_id,scoped_refptr<net::X509Certificate> certificate,const RemoveCertificateCallback & callback,BrowserContext * browser_context)573 void RemoveCertificate(const std::string& token_id,
574                        scoped_refptr<net::X509Certificate> certificate,
575                        const RemoveCertificateCallback& callback,
576                        BrowserContext* browser_context) {
577   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
578   scoped_ptr<RemoveCertificateState> state(
579       new RemoveCertificateState(certificate, callback));
580   // Get the pointer to |state| before base::Passed releases |state|.
581   NSSOperationState* state_ptr = state.get();
582 
583   // The NSSCertDatabase object is not required. But in case it's not available
584   // we would get more informative error messages.
585   GetCertDatabase(token_id,
586                   base::Bind(&RemoveCertificateWithDB, base::Passed(&state)),
587                   browser_context,
588                   state_ptr);
589 }
590 
591 }  // namespace platform_keys
592 
593 }  // namespace chromeos
594