File: nss_cert_database.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (362 lines) | stat: -rw-r--r-- 15,111 bytes parent folder | download | duplicates (6)
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
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
// Copyright 2012 The Chromium Authors
// 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 <memory>
#include <string>
#include <vector>

#include "base/functional/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list_threadsafe.h"
#include "build/build_config.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/scoped_nss_types.h"
#include "net/cert/x509_certificate.h"

namespace net {

// 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:
    Observer(const Observer&) = delete;
    Observer& operator=(const Observer&) = delete;

    virtual ~Observer() = default;

    // Will be called when a certificate is added, removed, or trust settings
    // are changed.
    virtual void OnTrustStoreChanged() {}
    virtual void OnClientCertStoreChanged() {}

   protected:
    Observer() = default;
  };

  // Holds an NSS certificate along with additional information.
  struct CertInfo {
    CertInfo();
    CertInfo(CertInfo&& other);
    ~CertInfo();
    CertInfo& operator=(CertInfo&& other);

    // The certificate itself.
    ScopedCERTCertificate cert;

    // The certificate is stored on a read-only slot.
    bool on_read_only_slot = false;

    // The certificate is untrusted.
    bool untrusted = false;

    // The certificate is trusted for web navigations according to the trust
    // bits stored in the database.
    bool web_trust_anchor = false;

    // The certificate is hardware-backed.
    bool hardware_backed = false;

    // The certificate is device-wide.
    // Note: can be true only on Chrome OS.
    bool device_wide = false;
  };

  // Stores per-certificate error codes for import failures.
  struct NET_EXPORT ImportCertFailure {
   public:
    ImportCertFailure(ScopedCERTCertificate cert, int err);
    ImportCertFailure(ImportCertFailure&& other);
    ~ImportCertFailure();

    ScopedCERTCertificate 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,
  };

  using CertInfoList = std::vector<CertInfo>;

  using ListCertsInfoCallback =
      base::OnceCallback<void(CertInfoList certs_info)>;

  using ListCertsCallback =
      base::OnceCallback<void(ScopedCERTCertificateList certs)>;

  using DeleteCertCallback = base::OnceCallback<void(bool)>;

  // 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);

  NSSCertDatabase(const NSSCertDatabase&) = delete;
  NSSCertDatabase& operator=(const NSSCertDatabase&) = delete;

  virtual ~NSSCertDatabase();

  // 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(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. This does not block by retrieving the certs
  // asynchronously on a worker thread.
  virtual void ListCertsInSlot(ListCertsCallback callback, PK11SlotInfo* slot);

  enum class NSSRootsHandling {
    kInclude,
    // TODO(crbug.com/390333881): kExclude is only used by the old cert
    // manager. Remove this and any other no-longer needed NSSCertDatabase
    // features once the new cert manager is fully launched.
    kExclude,
  };
  // Asynchronously get a list of certificates along with additional
  // information. Note that the callback may be run even after the database is
  // deleted.
  // The `nss_roots_handling` parameter controls whether to include or exclude
  // NSS built-in roots from the returned list.
  // TODO(crbug.com/40890963): remove the `nss_roots_handling` parameter.
  virtual void ListCertsInfo(ListCertsInfoCallback callback,
                             NSSRootsHandling nss_roots_handling);

#if BUILDFLAG(IS_CHROMEOS)
  // Get the slot for system-wide key data. May be NULL if the system token was
  // not enabled for this database.
  virtual crypto::ScopedPK11Slot GetSystemSlot() const;

  // Checks whether |cert| is stored on |slot|.
  static bool IsCertificateOnSlot(CERTCertificate* cert, PK11SlotInfo* slot);
#endif  // BUILDFLAG(IS_CHROMEOS)

  // 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 all modules.
  // If |need_rw| is true, only writable modules will be returned.
  virtual void ListModules(std::vector<crypto::ScopedPK11Slot>* modules,
                           bool need_rw) const;

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

  // 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(PK11SlotInfo* slot_info,
                       const std::string& data,
                       const std::u16string& password,
                       bool is_extractable,
                       ScopedCERTCertificateList* imported_certs);

  // Export the given certificates and private keys into a PKCS #12 blob,
  // storing into |output|.
  // Returns the number of certificates successfully exported. NSS has to be
  // initialized before the method is called.
  static int ExportToPKCS12(const ScopedCERTCertificateList& certs,
                            const std::u16string& password,
                            std::string* output);

  // 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.
  CERTCertificate* FindRootInList(
      const ScopedCERTCertificateList& certificates) const;

  // Import a user certificate. The private key for the user certificate must
  // already be installed, otherwise we return ERR_NO_PRIVATE_KEY_FOR_CERT.
  // Returns OK or a network error code.
  int ImportUserCert(const std::string& data);
  int ImportUserCert(CERTCertificate* cert);

  // 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 ScopedCERTCertificateList& 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 ScopedCERTCertificateList& certificates,
                        TrustBits trust_bits,
                        ImportCertFailureList* not_imported);

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

  // Delete certificate and associated private key (if one exists).
  // |cert| is still valid when this function returns. Returns true on
  // success.
  bool DeleteCertAndKey(CERTCertificate* 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(ScopedCERTCertificate cert,
                             DeleteCertCallback callback);

  // IsUntrusted returns true if |cert| is specifically untrusted. These
  // certificates are stored in the database for the specific purpose of
  // rejecting them.
  // TODO(mattm): that's not actually what this method does. (It also marks
  // certs that are self-issued and don't have any specific trust as untrusted,
  // which is wrong.)
  static bool IsUntrusted(const CERTCertificate* cert);

  // IsWebTrustAnchor returns true if |cert| is explicitly trusted for web
  // navigations according to the trust bits stored in the database.
  static bool IsWebTrustAnchor(const CERTCertificate* cert);

  // Check whether cert is stored in a readonly slot.
  // TODO(mattm): this is ill-defined if the cert exists on both readonly and
  // non-readonly slots.
  static bool IsReadOnly(const CERTCertificate* cert);

  // Check whether cert is stored in a hardware slot.
  // This should only be invoked on a worker thread due to expensive operations
  // behind it.
  static bool IsHardwareBacked(const CERTCertificate* cert);

  // 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);

 protected:
  // Returns a list of certificates extracted from |certs_info| list ignoring
  // additional information.
  static ScopedCERTCertificateList ExtractCertificates(CertInfoList certs_info);

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

  // Implements the logic behind returning a list of certificates along with
  // additional information about every certificate.
  // If |add_certs_info| is false, doesn't compute the certificate additional
  // information, the corresponding CertInfo struct fields will be left on their
  // default values.
  // Static so it may safely be used on the worker thread. If |slot| is nullptr,
  // obtains the certs of all slots, otherwise only of |slot|.
  // The |nss_roots_handling| parameter controls whether to include or exclude
  // NSS built-in roots from the resulting cert list.
  static CertInfoList ListCertsInfoImpl(crypto::ScopedPK11Slot slot,
                                        bool add_certs_info,
                                        NSSRootsHandling nss_roots_handling);

  // Broadcasts notifications to all registered observers.
  void NotifyObserversTrustStoreChanged();
  void NotifyObserversClientCertStoreChanged();

 private:
  enum class DeleteCertAndKeyResult {
    ERROR,
    OK_FOUND_KEY,
    OK_NO_KEY,
  };
  // Notifies observers of the removal of a cert and calls |callback| with
  // |success| as argument.
  void NotifyCertRemovalAndCallBack(DeleteCertCallback callback,
                                    DeleteCertAndKeyResult result);

  // Certificate removal implementation used by |DeleteCertAndKey*|. Static so
  // it may safely be used on the worker thread.
  static DeleteCertAndKeyResult DeleteCertAndKeyImpl(CERTCertificate* cert);
  // Like above, but taking a ScopedCERTCertificate. This is a workaround for
  // base::Bind not having a way to own a unique_ptr but pass it to the
  // function as a raw pointer.
  static DeleteCertAndKeyResult DeleteCertAndKeyImplScoped(
      ScopedCERTCertificate cert);

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

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

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

  base::WeakPtrFactory<NSSCertDatabase> weak_factory_{this};
};

}  // namespace net

#endif  // NET_CERT_NSS_CERT_DATABASE_H_