summaryrefslogtreecommitdiff
path: root/chromium/net/cert/nss_cert_database.h
blob: 42447f95a733b1b7efed148d9cf5769f3f56be0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_CERT_NSS_CERT_DATABASE_H_
#define NET_CERT_NSS_CERT_DATABASE_H_

#include <stdint.h>
#include <string>
#include <vector>

#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "crypto/scoped_nss_types.h"
#include "net/base/net_errors.h"
#include "net/base/net_export.h"
#include "net/cert/cert_type.h"
#include "net/cert/x509_certificate.h"

namespace base {
template <class ObserverType>
class ObserverListThreadSafe;
class TaskRunner;
}

namespace net {

class CryptoModule;
typedef std::vector<scoped_refptr<CryptoModule> > CryptoModuleList;

// Provides functions to manipulate the NSS certificate stores.
// Forwards notifications about certificate changes to the global CertDatabase
// singleton.
class NET_EXPORT NSSCertDatabase {
 public:
  class NET_EXPORT Observer {
   public:
    virtual ~Observer() {}

    // Will be called when a new certificate is added.
    // Called with |cert| == NULL after importing a list of certificates
    // in ImportFromPKCS12().
    virtual void OnCertAdded(const X509Certificate* cert) {}

    // Will be called when a certificate is removed.
    virtual void OnCertRemoved(const X509Certificate* cert) {}

    // Will be called when a CA certificate is changed.
    // Called with |cert| == NULL after importing a list of certificates
    // in ImportCACerts().
    virtual void OnCACertChanged(const X509Certificate* cert) {}

   protected:
    Observer() {}

   private:
    DISALLOW_COPY_AND_ASSIGN(Observer);
  };

  // Stores per-certificate error codes for import failures.
  struct NET_EXPORT ImportCertFailure {
   public:
    ImportCertFailure(const scoped_refptr<X509Certificate>& cert, int err);
    ~ImportCertFailure();

    scoped_refptr<X509Certificate> certificate;
    int net_error;
  };
  typedef std::vector<ImportCertFailure> ImportCertFailureList;

  // Constants that define which usages a certificate is trusted for.
  // They are used in combination with CertType to specify trust for each type
  // of certificate.
  // For a CA_CERT, they specify that the CA is trusted for issuing server and
  // client certs of each type.
  // For SERVER_CERT, only TRUSTED_SSL makes sense, and specifies the cert is
  // trusted as a server.
  // For EMAIL_CERT, only TRUSTED_EMAIL makes sense, and specifies the cert is
  // trusted for email.
  // DISTRUSTED_* specifies that the cert should not be trusted for the given
  // usage, regardless of whether it would otherwise inherit trust from the
  // issuer chain.
  // Use TRUST_DEFAULT to inherit trust as normal.
  // NOTE: The actual constants are defined using an enum instead of static
  // consts due to compilation/linkage constraints with template functions.
  typedef uint32_t TrustBits;
  enum {
    TRUST_DEFAULT         =      0,
    TRUSTED_SSL           = 1 << 0,
    TRUSTED_EMAIL         = 1 << 1,
    TRUSTED_OBJ_SIGN      = 1 << 2,
    DISTRUSTED_SSL        = 1 << 3,
    DISTRUSTED_EMAIL      = 1 << 4,
    DISTRUSTED_OBJ_SIGN   = 1 << 5,
  };

  typedef base::Callback<void(scoped_ptr<CertificateList> certs)>
      ListCertsCallback;

  typedef base::Callback<void(bool)> DeleteCertCallback;

  // Creates a NSSCertDatabase that will store public information (such as
  // certificates and trust records) in |public_slot|, and private information
  // (such as keys) in |private_slot|.
  // In general, code should avoid creating an NSSCertDatabase directly,
  // as doing so requires making opinionated decisions about where to store
  // data, and instead prefer to be passed an existing NSSCertDatabase
  // instance.
  // |public_slot| must not be NULL, |private_slot| can be NULL. Both slots can
  // be identical.
  NSSCertDatabase(crypto::ScopedPK11Slot public_slot,
                  crypto::ScopedPK11Slot private_slot);
  virtual ~NSSCertDatabase();

  // Get a list of unique certificates in the certificate database (one
  // instance of all certificates).
  // DEPRECATED by |ListCerts|. See http://crbug.com/340460.
  virtual void ListCertsSync(CertificateList* certs);

  // Asynchronously get a list of unique certificates in the certificate
  // database (one instance of all certificates). Note that the callback may be
  // run even after the database is deleted.
  virtual void ListCerts(const ListCertsCallback& callback);

  // Get a list of certificates in the certificate database of the given slot.
  // Note that the callback may be run even after the database is deleted.
  // Must be called on the IO thread and it calls |callback| on the IO thread.
  // This does not block by retrieving the certs asynchronously on a worker
  // thread. Never calls |callback| synchronously.
  virtual void ListCertsInSlot(const ListCertsCallback& callback,
                               PK11SlotInfo* slot);

#if defined(OS_CHROMEOS)
  // Get the slot for system-wide key data. May be NULL if the system token was
  // not explicitly set.
  // Note: The System slot is set after the NSSCertDatabase is constructed and
  // this call returns synchronously. Thus, it is possible to call this function
  // before SetSystemSlot is called and get a NULL result.
  // See https://crbug.com/399554 .
  virtual crypto::ScopedPK11Slot GetSystemSlot() const;
#endif

  // Get the default slot for public key data.
  crypto::ScopedPK11Slot GetPublicSlot() const;

  // Get the default slot for private key or mixed private/public key data.
  // Can return NULL.
  crypto::ScopedPK11Slot GetPrivateSlot() const;

  // Get the default module for public key data.
  // The returned pointer must be stored in a scoped_refptr<CryptoModule>.
  // DEPRECATED: use GetPublicSlot instead.
  // TODO(mattm): remove usage of this method and remove it.
  CryptoModule* GetPublicModule() const;

  // Get the default module for private key or mixed private/public key data.
  // The returned pointer must be stored in a scoped_refptr<CryptoModule>.
  // DEPRECATED: use GetPrivateSlot instead.
  // TODO(mattm): remove usage of this method and remove it.
  CryptoModule* GetPrivateModule() const;

  // Get all modules.
  // If |need_rw| is true, only writable modules will be returned.
  // TODO(mattm): come up with better alternative to CryptoModuleList.
  virtual void ListModules(CryptoModuleList* modules, bool need_rw) const;

  // Import certificates and private keys from PKCS #12 blob into the module.
  // If |is_extractable| is false, mark the private key as being unextractable
  // from the module.
  // Returns OK or a network error code such as ERR_PKCS12_IMPORT_BAD_PASSWORD
  // or ERR_PKCS12_IMPORT_ERROR. |imported_certs|, if non-NULL, returns a list
  // of certs that were imported.
  int ImportFromPKCS12(CryptoModule* module,
                       const std::string& data,
                       const base::string16& password,
                       bool is_extractable,
                       CertificateList* imported_certs);

  // Export the given certificates and private keys into a PKCS #12 blob,
  // storing into |output|.
  // Returns the number of certificates successfully exported.
  int ExportToPKCS12(const CertificateList& certs,
                     const base::string16& password,
                     std::string* output) const;

  // Uses similar logic to nsNSSCertificateDB::handleCACertDownload to find the
  // root.  Assumes the list is an ordered hierarchy with the root being either
  // the first or last element.
  // TODO(mattm): improve this to handle any order.
  X509Certificate* FindRootInList(const CertificateList& certificates) const;

  // Import CA certificates.
  // Tries to import all the certificates given.  The root will be trusted
  // according to |trust_bits|.  Any certificates that could not be imported
  // will be listed in |not_imported|.
  // Returns false if there is an internal error, otherwise true is returned and
  // |not_imported| should be checked for any certificates that were not
  // imported.
  bool ImportCACerts(const CertificateList& certificates,
                     TrustBits trust_bits,
                     ImportCertFailureList* not_imported);

  // Import server certificate.  The first cert should be the server cert.  Any
  // additional certs should be intermediate/CA certs and will be imported but
  // not given any trust.
  // Any certificates that could not be imported will be listed in
  // |not_imported|.
  // |trust_bits| can be set to explicitly trust or distrust the certificate, or
  // use TRUST_DEFAULT to inherit trust as normal.
  // Returns false if there is an internal error, otherwise true is returned and
  // |not_imported| should be checked for any certificates that were not
  // imported.
  bool ImportServerCert(const CertificateList& certificates,
                        TrustBits trust_bits,
                        ImportCertFailureList* not_imported);

  // Get trust bits for certificate.
  TrustBits GetCertTrust(const X509Certificate* cert, CertType type) const;

  // IsUntrusted returns true if |cert| is specifically untrusted. These
  // certificates are stored in the database for the specific purpose of
  // rejecting them.
  bool IsUntrusted(const X509Certificate* cert) const;

  // Set trust values for certificate.
  // Returns true on success or false on failure.
  bool SetCertTrust(const X509Certificate* cert,
                    CertType type,
                    TrustBits trust_bits);

  // Delete certificate and associated private key (if one exists).
  // |cert| is still valid when this function returns. Returns true on
  // success.
  bool DeleteCertAndKey(X509Certificate* cert);

  // Like DeleteCertAndKey but does not block by running the removal on a worker
  // thread. This must be called on IO thread and it will run |callback| on IO
  // thread. Never calls |callback| synchronously.
  void DeleteCertAndKeyAsync(const scoped_refptr<X509Certificate>& cert,
                             const DeleteCertCallback& callback);

  // Check whether cert is stored in a readonly slot.
  bool IsReadOnly(const X509Certificate* cert) const;

  // Check whether cert is stored in a hardware slot.
  bool IsHardwareBacked(const X509Certificate* cert) const;

  // Overrides task runner that's used for running slow tasks.
  void SetSlowTaskRunnerForTest(
      const scoped_refptr<base::TaskRunner>& task_runner);

 protected:
  // Certificate listing implementation used by |ListCerts*| and
  // |ListCertsSync|. Static so it may safely be used on the worker thread.
  // If |slot| is NULL, obtains the certs of all slots, otherwise only of
  // |slot|.
  static void ListCertsImpl(crypto::ScopedPK11Slot slot,
                            CertificateList* certs);

  // Gets task runner that should be used for slow tasks like certificate
  // listing. Defaults to a base::WorkerPool runner, but may be overriden
  // in tests (see SetSlowTaskRunnerForTest).
  scoped_refptr<base::TaskRunner> GetSlowTaskRunner() const;

 protected:
  // Broadcasts notifications to all registered observers.
  void NotifyObserversOfCertAdded(const X509Certificate* cert);
  void NotifyObserversOfCertRemoved(const X509Certificate* cert);
  void NotifyObserversOfCACertChanged(const X509Certificate* cert);

 private:
  // Registers |observer| to receive notifications of certificate changes.  The
  // thread on which this is called is the thread on which |observer| will be
  // called back with notifications.
  // NOTE: Observers registered here will only receive notifications generated
  // directly through the NSSCertDatabase, but not those from the CertDatabase.
  // CertDatabase observers will receive all certificate notifications.
  void AddObserver(Observer* observer);

  // Unregisters |observer| from receiving notifications.  This must be called
  // on the same thread on which AddObserver() was called.
  void RemoveObserver(Observer* observer);

  // Notifies observers of the removal of |cert| and calls |callback| with
  // |success| as argument.
  void NotifyCertRemovalAndCallBack(scoped_refptr<X509Certificate> cert,
                                    const DeleteCertCallback& callback,
                                    bool success);

  // Certificate removal implementation used by |DeleteCertAndKey*|. Static so
  // it may safely be used on the worker thread.
  static bool DeleteCertAndKeyImpl(scoped_refptr<X509Certificate> cert);

  crypto::ScopedPK11Slot public_slot_;
  crypto::ScopedPK11Slot private_slot_;

  // A helper observer that forwards events from this database to CertDatabase.
  scoped_ptr<Observer> cert_notification_forwarder_;

  // Task runner that should be used in tests if set.
  scoped_refptr<base::TaskRunner> slow_task_runner_for_test_;

  const scoped_refptr<base::ObserverListThreadSafe<Observer>> observer_list_;

  base::WeakPtrFactory<NSSCertDatabase> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(NSSCertDatabase);
};

}  // namespace net

#endif  // NET_CERT_NSS_CERT_DATABASE_H_