1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_CERT_NSS_CERT_DATABASE_H_ 6 #define NET_CERT_NSS_CERT_DATABASE_H_ 7 8 #include <stdint.h> 9 10 #include <memory> 11 #include <string> 12 #include <vector> 13 14 #include "base/functional/callback_forward.h" 15 #include "base/memory/scoped_refptr.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/observer_list_threadsafe.h" 18 #include "build/build_config.h" 19 #include "build/chromeos_buildflags.h" 20 #include "crypto/scoped_nss_types.h" 21 #include "net/base/net_errors.h" 22 #include "net/base/net_export.h" 23 #include "net/cert/cert_type.h" 24 #include "net/cert/scoped_nss_types.h" 25 #include "net/cert/x509_certificate.h" 26 27 namespace net { 28 29 // Provides functions to manipulate the NSS certificate stores. 30 // Forwards notifications about certificate changes to the global CertDatabase 31 // singleton. 32 class NET_EXPORT NSSCertDatabase { 33 public: 34 class NET_EXPORT Observer { 35 public: 36 Observer(const Observer&) = delete; 37 Observer& operator=(const Observer&) = delete; 38 39 virtual ~Observer() = default; 40 41 // Will be called when a certificate is added, removed, or trust settings 42 // are changed. OnTrustStoreChanged()43 virtual void OnTrustStoreChanged() {} OnClientCertStoreChanged()44 virtual void OnClientCertStoreChanged() {} 45 46 protected: 47 Observer() = default; 48 }; 49 50 // Holds an NSS certificate along with additional information. 51 struct CertInfo { 52 CertInfo(); 53 CertInfo(CertInfo&& other); 54 ~CertInfo(); 55 CertInfo& operator=(CertInfo&& other); 56 57 // The certificate itself. 58 ScopedCERTCertificate cert; 59 60 // The certificate is stored on a read-only slot. 61 bool on_read_only_slot = false; 62 63 // The certificate is untrusted. 64 bool untrusted = false; 65 66 // The certificate is trusted for web navigations according to the trust 67 // bits stored in the database. 68 bool web_trust_anchor = false; 69 70 // The certificate is hardware-backed. 71 bool hardware_backed = false; 72 73 // The certificate is device-wide. 74 // Note: can be true only on Chrome OS. 75 bool device_wide = false; 76 }; 77 78 // Stores per-certificate error codes for import failures. 79 struct NET_EXPORT ImportCertFailure { 80 public: 81 ImportCertFailure(ScopedCERTCertificate cert, int err); 82 ImportCertFailure(ImportCertFailure&& other); 83 ~ImportCertFailure(); 84 85 ScopedCERTCertificate certificate; 86 int net_error; 87 }; 88 typedef std::vector<ImportCertFailure> ImportCertFailureList; 89 90 // Constants that define which usages a certificate is trusted for. 91 // They are used in combination with CertType to specify trust for each type 92 // of certificate. 93 // For a CA_CERT, they specify that the CA is trusted for issuing server and 94 // client certs of each type. 95 // For SERVER_CERT, only TRUSTED_SSL makes sense, and specifies the cert is 96 // trusted as a server. 97 // For EMAIL_CERT, only TRUSTED_EMAIL makes sense, and specifies the cert is 98 // trusted for email. 99 // DISTRUSTED_* specifies that the cert should not be trusted for the given 100 // usage, regardless of whether it would otherwise inherit trust from the 101 // issuer chain. 102 // Use TRUST_DEFAULT to inherit trust as normal. 103 // NOTE: The actual constants are defined using an enum instead of static 104 // consts due to compilation/linkage constraints with template functions. 105 typedef uint32_t TrustBits; 106 enum { 107 TRUST_DEFAULT = 0, 108 TRUSTED_SSL = 1 << 0, 109 TRUSTED_EMAIL = 1 << 1, 110 TRUSTED_OBJ_SIGN = 1 << 2, 111 DISTRUSTED_SSL = 1 << 3, 112 DISTRUSTED_EMAIL = 1 << 4, 113 DISTRUSTED_OBJ_SIGN = 1 << 5, 114 }; 115 116 using CertInfoList = std::vector<CertInfo>; 117 118 using ListCertsInfoCallback = 119 base::OnceCallback<void(CertInfoList certs_info)>; 120 121 using ListCertsCallback = 122 base::OnceCallback<void(ScopedCERTCertificateList certs)>; 123 124 using DeleteCertCallback = base::OnceCallback<void(bool)>; 125 126 // Creates a NSSCertDatabase that will store public information (such as 127 // certificates and trust records) in |public_slot|, and private information 128 // (such as keys) in |private_slot|. 129 // In general, code should avoid creating an NSSCertDatabase directly, 130 // as doing so requires making opinionated decisions about where to store 131 // data, and instead prefer to be passed an existing NSSCertDatabase 132 // instance. 133 // |public_slot| must not be NULL, |private_slot| can be NULL. Both slots can 134 // be identical. 135 NSSCertDatabase(crypto::ScopedPK11Slot public_slot, 136 crypto::ScopedPK11Slot private_slot); 137 138 NSSCertDatabase(const NSSCertDatabase&) = delete; 139 NSSCertDatabase& operator=(const NSSCertDatabase&) = delete; 140 141 virtual ~NSSCertDatabase(); 142 143 // Asynchronously get a list of unique certificates in the certificate 144 // database (one instance of all certificates). Note that the callback may be 145 // run even after the database is deleted. 146 virtual void ListCerts(ListCertsCallback callback); 147 148 // Get a list of certificates in the certificate database of the given slot. 149 // Note that the callback may be run even after the database is deleted. Must 150 // be called on the IO thread. This does not block by retrieving the certs 151 // asynchronously on a worker thread. 152 virtual void ListCertsInSlot(ListCertsCallback callback, PK11SlotInfo* slot); 153 154 enum class NSSRootsHandling { 155 kInclude, 156 kExclude, 157 }; 158 // Asynchronously get a list of certificates along with additional 159 // information. Note that the callback may be run even after the database is 160 // deleted. 161 // The `nss_roots_handling` parameter controls whether to include or exclude 162 // NSS built-in roots from the returned list. 163 // TODO(https://crbug.com/1412591): remove the `nss_roots_handling` parameter. 164 virtual void ListCertsInfo(ListCertsInfoCallback callback, 165 NSSRootsHandling nss_roots_handling); 166 167 #if BUILDFLAG(IS_CHROMEOS) 168 // Get the slot for system-wide key data. May be NULL if the system token was 169 // not enabled for this database. 170 virtual crypto::ScopedPK11Slot GetSystemSlot() const; 171 172 // Checks whether |cert| is stored on |slot|. 173 static bool IsCertificateOnSlot(CERTCertificate* cert, PK11SlotInfo* slot); 174 #endif // BUILDFLAG(IS_CHROMEOS) 175 176 // Get the default slot for public key data. 177 crypto::ScopedPK11Slot GetPublicSlot() const; 178 179 // Get the default slot for private key or mixed private/public key data. 180 // Can return NULL. 181 crypto::ScopedPK11Slot GetPrivateSlot() const; 182 183 // Get all modules. 184 // If |need_rw| is true, only writable modules will be returned. 185 virtual void ListModules(std::vector<crypto::ScopedPK11Slot>* modules, 186 bool need_rw) const; 187 188 // Set trust values for certificate. 189 // Returns true on success or false on failure. 190 virtual bool SetCertTrust(CERTCertificate* cert, 191 CertType type, 192 TrustBits trust_bits); 193 194 // Import certificates and private keys from PKCS #12 blob into the module. 195 // If |is_extractable| is false, mark the private key as being unextractable 196 // from the module. 197 // Returns OK or a network error code such as ERR_PKCS12_IMPORT_BAD_PASSWORD 198 // or ERR_PKCS12_IMPORT_ERROR. |imported_certs|, if non-NULL, returns a list 199 // of certs that were imported. 200 int ImportFromPKCS12(PK11SlotInfo* slot_info, 201 const std::string& data, 202 const std::u16string& password, 203 bool is_extractable, 204 ScopedCERTCertificateList* imported_certs); 205 206 // Export the given certificates and private keys into a PKCS #12 blob, 207 // storing into |output|. 208 // Returns the number of certificates successfully exported. NSS has to be 209 // initialized before the method is called. 210 static int ExportToPKCS12(const ScopedCERTCertificateList& certs, 211 const std::u16string& password, 212 std::string* output); 213 214 // Uses similar logic to nsNSSCertificateDB::handleCACertDownload to find the 215 // root. Assumes the list is an ordered hierarchy with the root being either 216 // the first or last element. 217 // TODO(mattm): improve this to handle any order. 218 CERTCertificate* FindRootInList( 219 const ScopedCERTCertificateList& certificates) const; 220 221 // Import a user certificate. The private key for the user certificate must 222 // already be installed, otherwise we return ERR_NO_PRIVATE_KEY_FOR_CERT. 223 // Returns OK or a network error code. 224 int ImportUserCert(const std::string& data); 225 int ImportUserCert(CERTCertificate* cert); 226 227 // Import CA certificates. 228 // Tries to import all the certificates given. The root will be trusted 229 // according to |trust_bits|. Any certificates that could not be imported 230 // will be listed in |not_imported|. 231 // Returns false if there is an internal error, otherwise true is returned and 232 // |not_imported| should be checked for any certificates that were not 233 // imported. 234 bool ImportCACerts(const ScopedCERTCertificateList& certificates, 235 TrustBits trust_bits, 236 ImportCertFailureList* not_imported); 237 238 // Import server certificate. The first cert should be the server cert. Any 239 // additional certs should be intermediate/CA certs and will be imported but 240 // not given any trust. 241 // Any certificates that could not be imported will be listed in 242 // |not_imported|. 243 // |trust_bits| can be set to explicitly trust or distrust the certificate, or 244 // use TRUST_DEFAULT to inherit trust as normal. 245 // Returns false if there is an internal error, otherwise true is returned and 246 // |not_imported| should be checked for any certificates that were not 247 // imported. 248 bool ImportServerCert(const ScopedCERTCertificateList& certificates, 249 TrustBits trust_bits, 250 ImportCertFailureList* not_imported); 251 252 // Get trust bits for certificate. 253 TrustBits GetCertTrust(const CERTCertificate* cert, CertType type) const; 254 255 // Delete certificate and associated private key (if one exists). 256 // |cert| is still valid when this function returns. Returns true on 257 // success. 258 bool DeleteCertAndKey(CERTCertificate* cert); 259 260 // Like DeleteCertAndKey but does not block by running the removal on a worker 261 // thread. This must be called on IO thread and it will run |callback| on IO 262 // thread. Never calls |callback| synchronously. 263 void DeleteCertAndKeyAsync(ScopedCERTCertificate cert, 264 DeleteCertCallback callback); 265 266 // IsUntrusted returns true if |cert| is specifically untrusted. These 267 // certificates are stored in the database for the specific purpose of 268 // rejecting them. 269 // TODO(mattm): that's not actually what this method does. (It also marks 270 // certs that are self-issued and don't have any specific trust as untrusted, 271 // which is wrong.) 272 static bool IsUntrusted(const CERTCertificate* cert); 273 274 // IsWebTrustAnchor returns true if |cert| is explicitly trusted for web 275 // navigations according to the trust bits stored in the database. 276 static bool IsWebTrustAnchor(const CERTCertificate* cert); 277 278 // Check whether cert is stored in a readonly slot. 279 // TODO(mattm): this is ill-defined if the cert exists on both readonly and 280 // non-readonly slots. 281 static bool IsReadOnly(const CERTCertificate* cert); 282 283 // Check whether cert is stored in a hardware slot. 284 // This should only be invoked on a worker thread due to expensive operations 285 // behind it. 286 static bool IsHardwareBacked(const CERTCertificate* cert); 287 288 // Registers |observer| to receive notifications of certificate changes. The 289 // thread on which this is called is the thread on which |observer| will be 290 // called back with notifications. 291 // NOTE: Observers registered here will only receive notifications generated 292 // directly through the NSSCertDatabase, but not those from the CertDatabase. 293 // CertDatabase observers will receive all certificate notifications. 294 void AddObserver(Observer* observer); 295 296 // Unregisters |observer| from receiving notifications. This must be called 297 // on the same thread on which AddObserver() was called. 298 void RemoveObserver(Observer* observer); 299 300 protected: 301 // Returns a list of certificates extracted from |certs_info| list ignoring 302 // additional information. 303 static ScopedCERTCertificateList ExtractCertificates(CertInfoList certs_info); 304 305 // Certificate listing implementation used by |ListCerts*|. Static so it may 306 // safely be used on the worker thread. If |slot| is nullptr, obtains the 307 // certs of all slots, otherwise only of |slot|. 308 static ScopedCERTCertificateList ListCertsImpl(crypto::ScopedPK11Slot slot); 309 310 // Implements the logic behind returning a list of certificates along with 311 // additional information about every certificate. 312 // If |add_certs_info| is false, doesn't compute the certificate additional 313 // information, the corresponding CertInfo struct fields will be left on their 314 // default values. 315 // Static so it may safely be used on the worker thread. If |slot| is nullptr, 316 // obtains the certs of all slots, otherwise only of |slot|. 317 // The |nss_roots_handling| parameter controls whether to include or exclude 318 // NSS built-in roots from the resulting cert list. 319 static CertInfoList ListCertsInfoImpl(crypto::ScopedPK11Slot slot, 320 bool add_certs_info, 321 NSSRootsHandling nss_roots_handling); 322 323 // Broadcasts notifications to all registered observers. 324 void NotifyObserversTrustStoreChanged(); 325 void NotifyObserversClientCertStoreChanged(); 326 327 private: 328 enum class DeleteCertAndKeyResult { 329 ERROR, 330 OK_FOUND_KEY, 331 OK_NO_KEY, 332 }; 333 // Notifies observers of the removal of a cert and calls |callback| with 334 // |success| as argument. 335 void NotifyCertRemovalAndCallBack(DeleteCertCallback callback, 336 DeleteCertAndKeyResult result); 337 338 // Certificate removal implementation used by |DeleteCertAndKey*|. Static so 339 // it may safely be used on the worker thread. 340 static DeleteCertAndKeyResult DeleteCertAndKeyImpl(CERTCertificate* cert); 341 // Like above, but taking a ScopedCERTCertificate. This is a workaround for 342 // base::Bind not having a way to own a unique_ptr but pass it to the 343 // function as a raw pointer. 344 static DeleteCertAndKeyResult DeleteCertAndKeyImplScoped( 345 ScopedCERTCertificate cert); 346 347 crypto::ScopedPK11Slot public_slot_; 348 crypto::ScopedPK11Slot private_slot_; 349 350 // A helper observer that forwards events from this database to CertDatabase. 351 std::unique_ptr<Observer> cert_notification_forwarder_; 352 353 const scoped_refptr<base::ObserverListThreadSafe<Observer>> observer_list_; 354 355 base::WeakPtrFactory<NSSCertDatabase> weak_factory_{this}; 356 }; 357 358 } // namespace net 359 360 #endif // NET_CERT_NSS_CERT_DATABASE_H_ 361