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_
|