1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/platform_keys/platform_keys.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <cryptohi.h>
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/bind.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/bind_helpers.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/callback.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/compiler_specific.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/location.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/logging.h"
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/macros.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/single_thread_task_runner.h"
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/thread_task_runner_handle.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/threading/worker_pool.h"
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h"
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/net/nss_context.h"
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/browser/browser_context.h"
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "crypto/rsa_private_key.h"
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/base/crypto_module.h"
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/base/net_errors.h"
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/cert/cert_database.h"
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/cert/nss_cert_database.h"
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/cert/x509_certificate.h"
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using content::BrowserContext;
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using content::BrowserThread;
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char kErrorInternal[] = "Internal Error.";
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char kErrorKeyNotFound[] = "Key not found.";
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char kErrorCertificateNotFound[] = "Certificate could not be found.";
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char kErrorAlgorithmNotSupported[] = "Algorithm not supported.";
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// The current maximal RSA modulus length that ChromeOS's TPM supports for key
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// generation.
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const unsigned int kMaxRSAModulusLengthBits = 2048;
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace chromeos {
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace platform_keys {
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Base class to store state that is common to all NSS database operations and
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// to provide convenience methods to call back.
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Keeps track of the originating task runner.
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class NSSOperationState {
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NSSOperationState();
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~NSSOperationState() {}
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Called if an error occurred during the execution of the NSS operation
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // described by this object.
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnError(const tracked_objects::Location& from,
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       const std::string& error_message) = 0;
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  crypto::ScopedPK11Slot slot_;
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The task runner on which the NSS operation was called. Any reply must be
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // posted to this runner.
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NSSOperationState);
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)typedef base::Callback<void(net::NSSCertDatabase* cert_db)> GetCertDBCallback;
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Used by GetCertDatabaseOnIOThread and called back with the requested
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// NSSCertDatabase.
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// If |token_id| is not empty, sets |slot_| of |state| accordingly and calls
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// |callback| if the database was successfully retrieved.
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DidGetCertDBOnIOThread(const std::string& token_id,
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            const GetCertDBCallback& callback,
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            NSSOperationState* state,
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            net::NSSCertDatabase* cert_db) {
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!cert_db) {
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR) << "Couldn't get NSSCertDatabase.";
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    state->OnError(FROM_HERE, kErrorInternal);
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!token_id.empty()) {
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (token_id == kTokenIdUser)
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      state->slot_ = cert_db->GetPrivateSlot();
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    else if (token_id == kTokenIdSystem)
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      state->slot_ = cert_db->GetSystemSlot();
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!state->slot_) {
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      LOG(ERROR) << "Slot for token id '" << token_id << "' not available.";
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      state->OnError(FROM_HERE, kErrorInternal);
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(cert_db);
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Retrieves the NSSCertDatabase from |context| and, if |token_id| is not empty,
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the slot for |token_id|.
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Must be called on the IO thread.
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void GetCertDatabaseOnIOThread(const std::string& token_id,
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               const GetCertDBCallback& callback,
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               content::ResourceContext* context,
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               NSSOperationState* state) {
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext(
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      context, base::Bind(&DidGetCertDBOnIOThread, token_id, callback, state));
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (cert_db)
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DidGetCertDBOnIOThread(token_id, callback, state, cert_db);
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Asynchronously fetches the NSSCertDatabase for |browser_context| and, if
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// |token_id| is not empty, the slot for |token_id|. Stores the slot in |state|
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// and passes the database to |callback|. Will run |callback| on the IO thread.
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void GetCertDatabase(const std::string& token_id,
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     const GetCertDBCallback& callback,
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     BrowserContext* browser_context,
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     NSSOperationState* state) {
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO,
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          FROM_HERE,
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          base::Bind(&GetCertDatabaseOnIOThread,
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     token_id,
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     callback,
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     browser_context->GetResourceContext(),
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     state));
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class GenerateRSAKeyState : public NSSOperationState {
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GenerateRSAKeyState(unsigned int modulus_length_bits,
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                      const subtle::GenerateKeyCallback& callback);
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~GenerateRSAKeyState() {}
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnError(const tracked_objects::Location& from,
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       const std::string& error_message) OVERRIDE {
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CallBack(from, std::string() /* no public key */, error_message);
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void CallBack(const tracked_objects::Location& from,
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                const std::string& public_key_spki_der,
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                const std::string& error_message) {
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    origin_task_runner_->PostTask(
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        from, base::Bind(callback_, public_key_spki_der, error_message));
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const unsigned int modulus_length_bits_;
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Must be called on origin thread, therefore use CallBack().
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  subtle::GenerateKeyCallback callback_;
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class SignState : public NSSOperationState {
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SignState(const std::string& public_key,
1656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            HashAlgorithm hash_algorithm,
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            const std::string& data,
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            const subtle::SignCallback& callback);
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~SignState() {}
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnError(const tracked_objects::Location& from,
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       const std::string& error_message) OVERRIDE {
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CallBack(from, std::string() /* no signature */, error_message);
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void CallBack(const tracked_objects::Location& from,
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                const std::string& signature,
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                const std::string& error_message) {
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    origin_task_runner_->PostTask(
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        from, base::Bind(callback_, signature, error_message));
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const std::string public_key_;
1836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  HashAlgorithm hash_algorithm_;
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const std::string data_;
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Must be called on origin thread, therefore use CallBack().
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  subtle::SignCallback callback_;
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class GetCertificatesState : public NSSOperationState {
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  explicit GetCertificatesState(const GetCertificatesCallback& callback);
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~GetCertificatesState() {}
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnError(const tracked_objects::Location& from,
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       const std::string& error_message) OVERRIDE {
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CallBack(from,
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             scoped_ptr<net::CertificateList>() /* no certificates */,
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             error_message);
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void CallBack(const tracked_objects::Location& from,
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                scoped_ptr<net::CertificateList> certs,
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                const std::string& error_message) {
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    origin_task_runner_->PostTask(
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        from, base::Bind(callback_, base::Passed(&certs), error_message));
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<net::CertificateList> certs_;
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Must be called on origin thread, therefore use CallBack().
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetCertificatesCallback callback_;
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class ImportCertificateState : public NSSOperationState {
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ImportCertificateState(scoped_refptr<net::X509Certificate> certificate,
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                         const ImportCertificateCallback& callback);
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~ImportCertificateState() {}
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnError(const tracked_objects::Location& from,
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       const std::string& error_message) OVERRIDE {
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CallBack(from, error_message);
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void CallBack(const tracked_objects::Location& from,
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                const std::string& error_message) {
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    origin_task_runner_->PostTask(from, base::Bind(callback_, error_message));
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<net::X509Certificate> certificate_;
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Must be called on origin thread, therefore use CallBack().
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ImportCertificateCallback callback_;
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class RemoveCertificateState : public NSSOperationState {
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RemoveCertificateState(scoped_refptr<net::X509Certificate> certificate,
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                         const RemoveCertificateCallback& callback);
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~RemoveCertificateState() {}
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnError(const tracked_objects::Location& from,
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       const std::string& error_message) OVERRIDE {
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CallBack(from, error_message);
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void CallBack(const tracked_objects::Location& from,
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                const std::string& error_message) {
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    origin_task_runner_->PostTask(from, base::Bind(callback_, error_message));
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<net::X509Certificate> certificate_;
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Must be called on origin thread, therefore use CallBack().
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RemoveCertificateCallback callback_;
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class GetTokensState : public NSSOperationState {
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public:
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  explicit GetTokensState(const GetTokensCallback& callback);
2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual ~GetTokensState() {}
2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void OnError(const tracked_objects::Location& from,
2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       const std::string& error_message) OVERRIDE {
2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CallBack(from,
2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             scoped_ptr<std::vector<std::string> >() /* no token ids */,
2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             error_message);
2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void CallBack(const tracked_objects::Location& from,
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                scoped_ptr<std::vector<std::string> > token_ids,
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                const std::string& error_message) {
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    origin_task_runner_->PostTask(
2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        from, base::Bind(callback_, base::Passed(&token_ids), error_message));
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private:
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Must be called on origin thread, therefore use CallBack().
2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GetTokensCallback callback_;
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)NSSOperationState::NSSOperationState()
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)GenerateRSAKeyState::GenerateRSAKeyState(
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    unsigned int modulus_length_bits,
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const subtle::GenerateKeyCallback& callback)
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : modulus_length_bits_(modulus_length_bits), callback_(callback) {
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SignState::SignState(const std::string& public_key,
2986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                     HashAlgorithm hash_algorithm,
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     const std::string& data,
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     const subtle::SignCallback& callback)
3016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    : public_key_(public_key),
3026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      hash_algorithm_(hash_algorithm),
3036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      data_(data),
3046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      callback_(callback) {
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)GetCertificatesState::GetCertificatesState(
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GetCertificatesCallback& callback)
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : callback_(callback) {
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ImportCertificateState::ImportCertificateState(
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<net::X509Certificate> certificate,
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ImportCertificateCallback& callback)
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : certificate_(certificate), callback_(callback) {
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)RemoveCertificateState::RemoveCertificateState(
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<net::X509Certificate> certificate,
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const RemoveCertificateCallback& callback)
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : certificate_(certificate), callback_(callback) {
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)GetTokensState::GetTokensState(const GetTokensCallback& callback)
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : callback_(callback) {
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Does the actual key generation on a worker thread. Used by
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// GenerateRSAKeyWithDB().
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void GenerateRSAKeyOnWorkerThread(scoped_ptr<GenerateRSAKeyState> state) {
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<crypto::RSAPrivateKey> rsa_key(
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      crypto::RSAPrivateKey::CreateSensitive(state->slot_.get(),
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                             state->modulus_length_bits_));
334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!rsa_key) {
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR) << "Couldn't create key.";
336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    state->OnError(FROM_HERE, kErrorInternal);
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<uint8> public_key_spki_der;
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!rsa_key->ExportPublicKey(&public_key_spki_der)) {
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(pneubeck): Remove rsa_key from storage.
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR) << "Couldn't export public key.";
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    state->OnError(FROM_HERE, kErrorInternal);
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  state->CallBack(
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      std::string(public_key_spki_der.begin(), public_key_spki_der.end()),
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      std::string() /* no error */);
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Continues generating a RSA key with the obtained NSSCertDatabase. Used by
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// GenerateRSAKey().
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void GenerateRSAKeyWithDB(scoped_ptr<GenerateRSAKeyState> state,
356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          net::NSSCertDatabase* cert_db) {
357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|.
359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WorkerPool::PostTask(
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&GenerateRSAKeyOnWorkerThread, base::Passed(&state)),
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      true /*task is slow*/);
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Does the actual signing on a worker thread. Used by RSASignWithDB().
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RSASignOnWorkerThread(scoped_ptr<SignState> state) {
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const uint8* public_key_uint8 =
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      reinterpret_cast<const uint8*>(state->public_key_.data());
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<uint8> public_key_vector(
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      public_key_uint8, public_key_uint8 + state->public_key_.size());
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(pneubeck): This searches all slots. Change to look only at |slot_|.
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<crypto::RSAPrivateKey> rsa_key(
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector));
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!rsa_key || rsa_key->key()->pkcs11Slot != state->slot_) {
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    state->OnError(FROM_HERE, kErrorKeyNotFound);
377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  SECOidTag sign_alg_tag = SEC_OID_UNKNOWN;
3816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  switch (state->hash_algorithm_) {
3826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    case HASH_ALGORITHM_SHA1:
3836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
3846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      break;
3856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    case HASH_ALGORITHM_SHA256:
3866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
3876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      break;
3886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    case HASH_ALGORITHM_SHA384:
3896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
3906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      break;
3916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    case HASH_ALGORITHM_SHA512:
3926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
3936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      break;
3946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
3956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SECItem sign_result = {siBuffer, NULL, 0};
397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (SEC_SignData(&sign_result,
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   reinterpret_cast<const unsigned char*>(state->data_.data()),
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   state->data_.size(),
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   rsa_key->key(),
4016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                   sign_alg_tag) != SECSuccess) {
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR) << "Couldn't sign.";
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    state->OnError(FROM_HERE, kErrorInternal);
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string signature(reinterpret_cast<const char*>(sign_result.data),
408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        sign_result.len);
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  state->CallBack(FROM_HERE, signature, std::string() /* no error */);
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Continues signing with the obtained NSSCertDatabase. Used by Sign().
413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RSASignWithDB(scoped_ptr<SignState> state, net::NSSCertDatabase* cert_db) {
414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|.
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WorkerPool::PostTask(
417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&RSASignOnWorkerThread, base::Passed(&state)),
419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      true /*task is slow*/);
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Filters the obtained certificates on a worker thread. Used by
423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// DidGetCertificates().
424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void FilterCertificatesOnWorkerThread(scoped_ptr<GetCertificatesState> state) {
425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<net::CertificateList> client_certs(new net::CertificateList);
426cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (net::CertificateList::const_iterator it = state->certs_->begin();
427cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       it != state->certs_->end();
428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       ++it) {
429cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net::X509Certificate::OSCertHandle cert_handle = (*it)->os_cert_handle();
430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    crypto::ScopedPK11Slot cert_slot(PK11_KeyForCertExists(cert_handle,
431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                           NULL,    // keyPtr
432cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                           NULL));  // wincx
433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Keep only user certificates, i.e. certs for which the private key is
435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // present and stored in the queried slot.
436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (cert_slot != state->slot_)
437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continue;
438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    client_certs->push_back(*it);
440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  state->CallBack(FROM_HERE, client_certs.Pass(), std::string() /* no error */);
443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Passes the obtained certificates to the worker thread for filtering. Used by
446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// GetCertificatesWithDB().
447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DidGetCertificates(scoped_ptr<GetCertificatesState> state,
448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        scoped_ptr<net::CertificateList> all_certs) {
449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  state->certs_ = all_certs.Pass();
451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WorkerPool::PostTask(
452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&FilterCertificatesOnWorkerThread, base::Passed(&state)),
454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      true /*task is slow*/);
455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Continues getting certificates with the obtained NSSCertDatabase. Used by
458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// GetCertificates().
459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void GetCertificatesWithDB(scoped_ptr<GetCertificatesState> state,
460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           net::NSSCertDatabase* cert_db) {
461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Get the pointer to slot before base::Passed releases |state|.
463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PK11SlotInfo* slot = state->slot_.get();
464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cert_db->ListCertsInSlot(
465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&DidGetCertificates, base::Passed(&state)), slot);
466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Does the actual certificate importing on the IO thread. Used by
469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// ImportCertificate().
470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ImportCertificateWithDB(scoped_ptr<ImportCertificateState> state,
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                             net::NSSCertDatabase* cert_db) {
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(pneubeck): Use |state->slot_| to verify that we're really importing to
474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // the correct token.
475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // |cert_db| is not required, ignore it.
476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  net::CertDatabase* db = net::CertDatabase::GetInstance();
477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const net::Error cert_status =
4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      static_cast<net::Error>(db->CheckUserCert(state->certificate_.get()));
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (cert_status == net::ERR_NO_PRIVATE_KEY_FOR_CERT) {
481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    state->OnError(FROM_HERE, kErrorKeyNotFound);
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (cert_status != net::OK) {
484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    state->OnError(FROM_HERE, net::ErrorToString(cert_status));
485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Check that the private key is in the correct slot.
4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PK11SlotInfo* slot =
4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      PK11_KeyForCertExists(state->certificate_->os_cert_handle(), NULL, NULL);
4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (slot != state->slot_) {
4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    state->OnError(FROM_HERE, kErrorKeyNotFound);
4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const net::Error import_status =
497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      static_cast<net::Error>(db->AddUserCert(state->certificate_.get()));
498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (import_status != net::OK) {
499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR) << "Could not import certificate.";
500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    state->OnError(FROM_HERE, net::ErrorToString(import_status));
501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  state->CallBack(FROM_HERE, std::string() /* no error */);
505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Called on IO thread after the certificate removal is finished.
508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DidRemoveCertificate(scoped_ptr<RemoveCertificateState> state,
509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          bool certificate_found,
510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          bool success) {
511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // CertificateNotFound error has precedence over an internal error.
513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!certificate_found) {
514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    state->OnError(FROM_HERE, kErrorCertificateNotFound);
515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!success) {
518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    state->OnError(FROM_HERE, kErrorInternal);
519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
521cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  state->CallBack(FROM_HERE, std::string() /* no error */);
523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Does the actual certificate removal on the IO thread. Used by
526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// RemoveCertificate().
527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RemoveCertificateWithDB(scoped_ptr<RemoveCertificateState> state,
528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                             net::NSSCertDatabase* cert_db) {
529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Get the pointer before base::Passed clears |state|.
531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<net::X509Certificate> certificate = state->certificate_;
532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool certificate_found = certificate->os_cert_handle()->isperm;
533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cert_db->DeleteCertAndKeyAsync(
534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      certificate,
535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(
536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          &DidRemoveCertificate, base::Passed(&state), certificate_found));
537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Does the actual work to determine which tokens are available.
5405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void GetTokensWithDB(scoped_ptr<GetTokensState> state,
5415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     net::NSSCertDatabase* cert_db) {
5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<std::vector<std::string> > token_ids(new std::vector<std::string>);
5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // The user's token is always available.
5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  token_ids->push_back(kTokenIdUser);
5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (cert_db->GetSystemSlot())
5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    token_ids->push_back(kTokenIdSystem);
5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->CallBack(FROM_HERE, token_ids.Pass(), std::string() /* no error */);
5515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace subtle {
556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
557cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void GenerateRSAKey(const std::string& token_id,
558f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                    unsigned int modulus_length_bits,
559cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    const GenerateKeyCallback& callback,
560f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                    BrowserContext* browser_context) {
561cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
562cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<GenerateRSAKeyState> state(
563f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      new GenerateRSAKeyState(modulus_length_bits, callback));
564cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
565f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (modulus_length_bits > kMaxRSAModulusLengthBits) {
566cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    state->OnError(FROM_HERE, kErrorAlgorithmNotSupported);
567cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
568cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
569cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
570cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Get the pointer to |state| before base::Passed releases |state|.
571cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NSSOperationState* state_ptr = state.get();
572cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetCertDatabase(token_id,
573cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  base::Bind(&GenerateRSAKeyWithDB, base::Passed(&state)),
574f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  browser_context,
575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  state_ptr);
576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
577cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
578cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Sign(const std::string& token_id,
579cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          const std::string& public_key,
5806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          HashAlgorithm hash_algorithm,
581cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          const std::string& data,
582cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          const SignCallback& callback,
583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          BrowserContext* browser_context) {
584cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
5856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  scoped_ptr<SignState> state(
5866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      new SignState(public_key, hash_algorithm, data, callback));
587cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Get the pointer to |state| before base::Passed releases |state|.
588cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NSSOperationState* state_ptr = state.get();
589cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The NSSCertDatabase object is not required. But in case it's not available
591cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // we would get more informative error messages and we can double check that
592cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // we use a key of the correct token.
593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetCertDatabase(token_id,
594cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  base::Bind(&RSASignWithDB, base::Passed(&state)),
595f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  browser_context,
596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  state_ptr);
597cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
598cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
599f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace subtle
600f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void GetCertificates(const std::string& token_id,
602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     const GetCertificatesCallback& callback,
603f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     BrowserContext* browser_context) {
604cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
605cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<GetCertificatesState> state(new GetCertificatesState(callback));
606cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Get the pointer to |state| before base::Passed releases |state|.
607cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NSSOperationState* state_ptr = state.get();
608cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetCertDatabase(token_id,
609cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  base::Bind(&GetCertificatesWithDB, base::Passed(&state)),
610f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  browser_context,
611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  state_ptr);
612cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
614cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ImportCertificate(const std::string& token_id,
615cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       scoped_refptr<net::X509Certificate> certificate,
616cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       const ImportCertificateCallback& callback,
617f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       BrowserContext* browser_context) {
618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
619cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<ImportCertificateState> state(
620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new ImportCertificateState(certificate, callback));
621cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Get the pointer to |state| before base::Passed releases |state|.
622cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NSSOperationState* state_ptr = state.get();
623cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
624cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The NSSCertDatabase object is not required. But in case it's not available
625cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // we would get more informative error messages and we can double check that
626cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // we use a key of the correct token.
627cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetCertDatabase(token_id,
628cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  base::Bind(&ImportCertificateWithDB, base::Passed(&state)),
629f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  browser_context,
630cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  state_ptr);
631cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
632cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
633cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RemoveCertificate(const std::string& token_id,
634cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       scoped_refptr<net::X509Certificate> certificate,
635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       const RemoveCertificateCallback& callback,
636f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       BrowserContext* browser_context) {
637cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
638cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<RemoveCertificateState> state(
639cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new RemoveCertificateState(certificate, callback));
640cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Get the pointer to |state| before base::Passed releases |state|.
641cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NSSOperationState* state_ptr = state.get();
642cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
643cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The NSSCertDatabase object is not required. But in case it's not available
644cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // we would get more informative error messages.
645cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetCertDatabase(token_id,
646cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  base::Bind(&RemoveCertificateWithDB, base::Passed(&state)),
647f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  browser_context,
648cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  state_ptr);
649cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
650cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void GetTokens(const GetTokensCallback& callback,
6525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               content::BrowserContext* browser_context) {
6535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
6545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<GetTokensState> state(new GetTokensState(callback));
6555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Get the pointer to |state| before base::Passed releases |state|.
6565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  NSSOperationState* state_ptr = state.get();
6575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GetCertDatabase(std::string() /* don't get any specific slot */,
6585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  base::Bind(&GetTokensWithDB, base::Passed(&state)),
6595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  browser_context,
6605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  state_ptr);
6615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
6625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
663cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace platform_keys
664cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
665cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace chromeos
666