tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsNSSComponent.cpp (79724B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 *
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "nsNSSComponent.h"
      8 
      9 #include "BinaryPath.h"
     10 #include "CryptoTask.h"
     11 #include "EnterpriseRoots.h"
     12 #include "ExtendedValidation.h"
     13 #include "NSSCertDBTrustDomain.h"
     14 #include "PKCS11ModuleDB.h"
     15 #include "SSLTokensCache.h"
     16 #include "ScopedNSSTypes.h"
     17 #include "cert.h"
     18 #include "cert_storage/src/cert_storage.h"
     19 #include "certdb.h"
     20 #include "mozilla/AppShutdown.h"
     21 #include "mozilla/Atomics.h"
     22 #include "mozilla/Assertions.h"
     23 #include "mozilla/Base64.h"
     24 #include "mozilla/EndianUtils.h"
     25 #include "mozilla/FilePreferences.h"
     26 #include "mozilla/Preferences.h"
     27 #include "mozilla/ProfilerLabels.h"
     28 #include "mozilla/ProfilerMarkers.h"
     29 #include "mozilla/PublicSSL.h"
     30 #include "mozilla/Services.h"
     31 #include "mozilla/StaticMutex.h"
     32 #include "mozilla/StaticPrefs_security.h"
     33 #include "mozilla/StaticPtr.h"
     34 #include "mozilla/SyncRunnable.h"
     35 #include "mozilla/TimeStamp.h"
     36 #include "mozilla/Vector.h"
     37 #include "mozilla/dom/Promise.h"
     38 #include "mozilla/glean/SecurityManagerSslMetrics.h"
     39 #include "mozilla/net/SocketProcessParent.h"
     40 #include "mozpkix/pkixnss.h"
     41 #include "nsAppDirectoryServiceDefs.h"
     42 #include "nsCRT.h"
     43 #include "nsClientAuthRemember.h"
     44 #include "nsComponentManagerUtils.h"
     45 #include "nsDirectoryServiceDefs.h"
     46 #include "nsICertOverrideService.h"
     47 #include "nsIFile.h"
     48 #include "nsIOService.h"
     49 #include "nsIObserverService.h"
     50 #include "nsIPrompt.h"
     51 #include "nsIProperties.h"
     52 #include "nsISerialEventTarget.h"
     53 #include "nsISiteSecurityService.h"
     54 #include "nsITimer.h"
     55 #include "nsITokenPasswordDialogs.h"
     56 #include "nsIWindowWatcher.h"
     57 #include "nsIXULRuntime.h"
     58 #include "nsLiteralString.h"
     59 #include "nsNSSHelper.h"
     60 #include "nsNSSIOLayer.h"
     61 #include "nsNetCID.h"
     62 #include "nsPK11TokenDB.h"
     63 #include "nsPrintfCString.h"
     64 #include "nsServiceManagerUtils.h"
     65 #include "nsThreadUtils.h"
     66 #include "nsXULAppAPI.h"
     67 #include "nss.h"
     68 #include "p12plcy.h"
     69 #include "pk11pub.h"
     70 #include "prmem.h"
     71 #include "secerr.h"
     72 #include "secmod.h"
     73 #include "ssl.h"
     74 #include "sslerr.h"
     75 #include "sslproto.h"
     76 
     77 #if defined(XP_LINUX) && !defined(ANDROID)
     78 #  include <linux/magic.h>
     79 #  include <sys/vfs.h>
     80 #endif
     81 
     82 using namespace mozilla;
     83 using namespace mozilla::psm;
     84 
     85 LazyLogModule gPIPNSSLog("pipnss");
     86 
     87 int nsNSSComponent::mInstanceCount = 0;
     88 
     89 // Forward declaration.
     90 nsresult CommonInit();
     91 
     92 template <const glean::impl::QuantityMetric* metric>
     93 class MOZ_RAII AutoGleanTimer {
     94 public:
     95  explicit AutoGleanTimer(TimeStamp aStart = TimeStamp::Now())
     96      : mStart(aStart) {}
     97 
     98  ~AutoGleanTimer() {
     99    TimeStamp end = TimeStamp::Now();
    100    uint32_t delta = static_cast<uint32_t>((end - mStart).ToMilliseconds());
    101    metric->Set(delta);
    102  }
    103 
    104 private:
    105  const TimeStamp mStart;
    106 };
    107 
    108 // Take an nsIFile and get a UTF-8-encoded c-string representation of the
    109 // location of that file (encapsulated in an nsACString).
    110 // This operation is generally to be avoided, except when interacting with
    111 // third-party or legacy libraries that cannot handle `nsIFile`s (such as NSS).
    112 // |result| is encoded in UTF-8.
    113 nsresult FileToCString(const nsCOMPtr<nsIFile>& file, nsACString& result) {
    114 #ifdef XP_WIN
    115  nsAutoString path;
    116  nsresult rv = file->GetPath(path);
    117  if (NS_SUCCEEDED(rv)) {
    118    CopyUTF16toUTF8(path, result);
    119  }
    120  return rv;
    121 #else
    122  return file->GetNativePath(result);
    123 #endif
    124 }
    125 
    126 void TruncateFromLastDirectorySeparator(nsCString& path) {
    127  static const nsAutoCString kSeparatorString(
    128      mozilla::FilePreferences::kPathSeparator);
    129  int32_t index = path.RFind(kSeparatorString);
    130  if (index == kNotFound) {
    131    return;
    132  }
    133  path.Truncate(index);
    134 }
    135 
    136 bool LoadIPCClientCerts() {
    137  if (!LoadIPCClientCertsModule()) {
    138    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to load ipcclientcerts"));
    139    return false;
    140  }
    141  return true;
    142 }
    143 
    144 // This function can be called from chrome or content or socket processes
    145 // to ensure that NSS is initialized.
    146 bool EnsureNSSInitializedChromeOrContent() {
    147  static Atomic<bool> initialized(false);
    148 
    149  if (initialized) {
    150    return true;
    151  }
    152 
    153  // If this is not the main thread (i.e. probably a worker) then forward this
    154  // call to the main thread.
    155  if (!NS_IsMainThread()) {
    156    nsCOMPtr<nsIThread> mainThread;
    157    nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
    158    if (NS_FAILED(rv)) {
    159      return false;
    160    }
    161 
    162    // Forward to the main thread synchronously.
    163    mozilla::SyncRunnable::DispatchToThread(
    164        mainThread,
    165        NS_NewRunnableFunction("EnsureNSSInitializedChromeOrContent", []() {
    166          EnsureNSSInitializedChromeOrContent();
    167        }));
    168 
    169    return initialized;
    170  }
    171 
    172  if (XRE_IsParentProcess()) {
    173    nsCOMPtr<nsISupports> nss = do_GetService(PSM_COMPONENT_CONTRACTID);
    174    if (!nss) {
    175      return false;
    176    }
    177    initialized = true;
    178    return true;
    179  }
    180 
    181  if (NSS_IsInitialized()) {
    182    initialized = true;
    183    return true;
    184  }
    185 
    186  if (NSS_NoDB_Init(nullptr) != SECSuccess) {
    187    return false;
    188  }
    189 
    190  if (XRE_IsSocketProcess()) {
    191    if (NS_FAILED(CommonInit())) {
    192      return false;
    193    }
    194    // If ipcclientcerts fails to load, client certificate authentication won't
    195    // work (if networking is done on the socket process). This is preferable
    196    // to stopping the program entirely, so treat this as best-effort.
    197    (void)NS_WARN_IF(!LoadIPCClientCerts());
    198    initialized = true;
    199    return true;
    200  }
    201 
    202  if (NS_FAILED(mozilla::psm::InitializeCipherSuite())) {
    203    return false;
    204  }
    205 
    206  mozilla::psm::DisableMD5();
    207  mozilla::pkix::RegisterErrorTable();
    208  initialized = true;
    209  return true;
    210 }
    211 
    212 static const uint32_t OCSP_TIMEOUT_MILLISECONDS_SOFT_MAX = 5000;
    213 static const uint32_t OCSP_TIMEOUT_MILLISECONDS_HARD_MAX = 20000;
    214 
    215 void nsNSSComponent::GetRevocationBehaviorFromPrefs(
    216    /*out*/ CertVerifier::OcspDownloadConfig* odc,
    217    /*out*/ CertVerifier::OcspStrictConfig* osc,
    218    /*out*/ uint32_t* certShortLifetimeInDays,
    219    /*out*/ TimeDuration& softTimeout,
    220    /*out*/ TimeDuration& hardTimeout) {
    221  MOZ_ASSERT(NS_IsMainThread());
    222  MOZ_ASSERT(odc);
    223  MOZ_ASSERT(osc);
    224  MOZ_ASSERT(certShortLifetimeInDays);
    225 
    226  // 0 = disabled
    227  // 1 = enabled for everything (default)
    228  // 2 = enabled for EV certificates only
    229  uint32_t ocspLevel = StaticPrefs::security_OCSP_enabled();
    230  switch (ocspLevel) {
    231    case 0:
    232      *odc = CertVerifier::ocspOff;
    233      break;
    234    case 2:
    235      *odc = CertVerifier::ocspEVOnly;
    236      break;
    237    default:
    238      *odc = CertVerifier::ocspOn;
    239      break;
    240  }
    241 
    242  *osc = StaticPrefs::security_OCSP_require() ? CertVerifier::ocspStrict
    243                                              : CertVerifier::ocspRelaxed;
    244 
    245  *certShortLifetimeInDays =
    246      StaticPrefs::security_pki_cert_short_lifetime_in_days();
    247 
    248  uint32_t softTimeoutMillis =
    249      StaticPrefs::security_OCSP_timeoutMilliseconds_soft();
    250  softTimeoutMillis =
    251      std::min(softTimeoutMillis, OCSP_TIMEOUT_MILLISECONDS_SOFT_MAX);
    252  softTimeout = TimeDuration::FromMilliseconds(softTimeoutMillis);
    253 
    254  uint32_t hardTimeoutMillis =
    255      StaticPrefs::security_OCSP_timeoutMilliseconds_hard();
    256  hardTimeoutMillis =
    257      std::min(hardTimeoutMillis, OCSP_TIMEOUT_MILLISECONDS_HARD_MAX);
    258  hardTimeout = TimeDuration::FromMilliseconds(hardTimeoutMillis);
    259 }
    260 
    261 nsNSSComponent::nsNSSComponent()
    262    : mLoadableCertsLoadedMonitor("nsNSSComponent.mLoadableCertsLoadedMonitor"),
    263      mLoadableCertsLoaded(false),
    264      mLoadableCertsLoadedResult(NS_ERROR_FAILURE),
    265      mMutex("nsNSSComponent.mMutex"),
    266      mMitmDetecionEnabled(false) {
    267  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::ctor\n"));
    268  MOZ_RELEASE_ASSERT(NS_IsMainThread());
    269 
    270  MOZ_ASSERT(mInstanceCount == 0,
    271             "nsNSSComponent is a singleton, but instantiated multiple times!");
    272  ++mInstanceCount;
    273 }
    274 
    275 nsNSSComponent::~nsNSSComponent() {
    276  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::dtor\n"));
    277  MOZ_RELEASE_ASSERT(NS_IsMainThread());
    278 
    279  // All cleanup code requiring services needs to happen in xpcom_shutdown
    280 
    281  PrepareForShutdown();
    282  nsSSLIOLayerHelpers::GlobalCleanup();
    283  --mInstanceCount;
    284 
    285  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::dtor finished\n"));
    286 }
    287 
    288 void nsNSSComponent::UnloadEnterpriseRoots() {
    289  MOZ_ASSERT(NS_IsMainThread());
    290  if (!NS_IsMainThread()) {
    291    return;
    292  }
    293  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("UnloadEnterpriseRoots"));
    294  MutexAutoLock lock(mMutex);
    295  mEnterpriseCerts.Clear();
    296  setValidationOptions(lock);
    297  ClearSSLExternalAndInternalSessionCache();
    298 }
    299 
    300 class BackgroundImportEnterpriseCertsTask final : public CryptoTask {
    301 public:
    302  explicit BackgroundImportEnterpriseCertsTask(nsNSSComponent* nssComponent)
    303      : mNSSComponent(nssComponent) {}
    304 
    305 private:
    306  virtual nsresult CalculateResult() override {
    307    mNSSComponent->ImportEnterpriseRoots();
    308    mNSSComponent->UpdateCertVerifierWithEnterpriseRoots();
    309    return NS_OK;
    310  }
    311 
    312  virtual void CallCallback(nsresult rv) override {
    313    nsCOMPtr<nsIObserverService> observerService =
    314        mozilla::services::GetObserverService();
    315    if (observerService) {
    316      observerService->NotifyObservers(nullptr, "psm:enterprise-certs-imported",
    317                                       nullptr);
    318    }
    319  }
    320 
    321  RefPtr<nsNSSComponent> mNSSComponent;
    322 };
    323 
    324 void nsNSSComponent::MaybeImportEnterpriseRoots() {
    325  MOZ_ASSERT(NS_IsMainThread());
    326  if (!NS_IsMainThread()) {
    327    return;
    328  }
    329  bool importEnterpriseRoots = StaticPrefs::security_enterprise_roots_enabled();
    330  if (importEnterpriseRoots) {
    331    RefPtr<BackgroundImportEnterpriseCertsTask> task =
    332        new BackgroundImportEnterpriseCertsTask(this);
    333    (void)task->Dispatch();
    334  }
    335 }
    336 
    337 void nsNSSComponent::ImportEnterpriseRoots() {
    338  MOZ_ASSERT(!NS_IsMainThread());
    339  if (NS_IsMainThread()) {
    340    return;
    341  }
    342 
    343  nsTArray<EnterpriseCert> enterpriseCerts;
    344  nsresult rv = GatherEnterpriseCerts(enterpriseCerts);
    345  if (NS_SUCCEEDED(rv)) {
    346    MutexAutoLock lock(mMutex);
    347    mEnterpriseCerts = std::move(enterpriseCerts);
    348  } else {
    349    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed gathering enterprise roots"));
    350  }
    351 }
    352 
    353 nsresult nsNSSComponent::CommonGetEnterpriseCerts(
    354    nsTArray<nsTArray<uint8_t>>& enterpriseCerts, bool getRoots) {
    355  nsresult rv = BlockUntilLoadableCertsLoaded();
    356  if (NS_FAILED(rv)) {
    357    return rv;
    358  }
    359 
    360  enterpriseCerts.Clear();
    361  MutexAutoLock nsNSSComponentLock(mMutex);
    362  for (const auto& cert : mEnterpriseCerts) {
    363    nsTArray<uint8_t> certCopy;
    364    // mEnterpriseCerts includes both roots and intermediates.
    365    if (cert.GetIsRoot() == getRoots) {
    366      cert.CopyBytes(certCopy);
    367      enterpriseCerts.AppendElement(std::move(certCopy));
    368    }
    369  }
    370  return NS_OK;
    371 }
    372 
    373 NS_IMETHODIMP
    374 nsNSSComponent::GetEnterpriseRoots(
    375    nsTArray<nsTArray<uint8_t>>& enterpriseRoots) {
    376  return CommonGetEnterpriseCerts(enterpriseRoots, true);
    377 }
    378 
    379 nsresult BytesArrayToPEM(const nsTArray<nsTArray<uint8_t>>& bytesArray,
    380                         nsACString& pemArray) {
    381  for (const auto& bytes : bytesArray) {
    382    nsAutoCString base64;
    383    nsresult rv = Base64Encode(reinterpret_cast<const char*>(bytes.Elements()),
    384                               bytes.Length(), base64);
    385    if (NS_FAILED(rv)) {
    386      return rv;
    387    }
    388    if (!pemArray.IsEmpty()) {
    389      pemArray.AppendLiteral("\n");
    390    }
    391    pemArray.AppendLiteral("-----BEGIN CERTIFICATE-----\n");
    392    for (size_t i = 0; i < base64.Length() / 64; i++) {
    393      pemArray.Append(Substring(base64, i * 64, 64));
    394      pemArray.AppendLiteral("\n");
    395    }
    396    if (base64.Length() % 64 != 0) {
    397      size_t chunks = base64.Length() / 64;
    398      pemArray.Append(Substring(base64, chunks * 64));
    399      pemArray.AppendLiteral("\n");
    400    }
    401    pemArray.AppendLiteral("-----END CERTIFICATE-----");
    402  }
    403  return NS_OK;
    404 }
    405 
    406 NS_IMETHODIMP
    407 nsNSSComponent::GetEnterpriseRootsPEM(nsACString& enterpriseRootsPEM) {
    408  nsTArray<nsTArray<uint8_t>> enterpriseRoots;
    409  nsresult rv = GetEnterpriseRoots(enterpriseRoots);
    410  if (NS_FAILED(rv)) {
    411    return rv;
    412  }
    413  return BytesArrayToPEM(enterpriseRoots, enterpriseRootsPEM);
    414 }
    415 
    416 NS_IMETHODIMP
    417 nsNSSComponent::GetEnterpriseIntermediates(
    418    nsTArray<nsTArray<uint8_t>>& enterpriseIntermediates) {
    419  return CommonGetEnterpriseCerts(enterpriseIntermediates, false);
    420 }
    421 
    422 NS_IMETHODIMP
    423 nsNSSComponent::GetEnterpriseIntermediatesPEM(
    424    nsACString& enterpriseIntermediatesPEM) {
    425  nsTArray<nsTArray<uint8_t>> enterpriseIntermediates;
    426  nsresult rv = GetEnterpriseIntermediates(enterpriseIntermediates);
    427  if (NS_FAILED(rv)) {
    428    return rv;
    429  }
    430  return BytesArrayToPEM(enterpriseIntermediates, enterpriseIntermediatesPEM);
    431 }
    432 
    433 NS_IMETHODIMP
    434 nsNSSComponent::AddEnterpriseIntermediate(
    435    const nsTArray<uint8_t>& intermediateBytes) {
    436  nsresult rv = BlockUntilLoadableCertsLoaded();
    437  if (NS_FAILED(rv)) {
    438    return rv;
    439  }
    440  EnterpriseCert intermediate(intermediateBytes.Elements(),
    441                              intermediateBytes.Length(), false);
    442  {
    443    MutexAutoLock nsNSSComponentLock(mMutex);
    444    mEnterpriseCerts.AppendElement(std::move(intermediate));
    445  }
    446 
    447  UpdateCertVerifierWithEnterpriseRoots();
    448  return NS_OK;
    449 }
    450 
    451 class LoadLoadableCertsTask final : public Runnable {
    452 public:
    453  LoadLoadableCertsTask(nsNSSComponent* nssComponent,
    454                        bool importEnterpriseRoots, nsAutoCString&& greBinDir)
    455      : Runnable("LoadLoadableCertsTask"),
    456        mNSSComponent(nssComponent),
    457        mImportEnterpriseRoots(importEnterpriseRoots),
    458        mGreBinDir(std::move(greBinDir)) {
    459    MOZ_ASSERT(nssComponent);
    460  }
    461 
    462  ~LoadLoadableCertsTask() = default;
    463 
    464  nsresult Dispatch();
    465 
    466 private:
    467  NS_IMETHOD Run() override;
    468  nsresult LoadLoadableRoots();
    469  RefPtr<nsNSSComponent> mNSSComponent;
    470  bool mImportEnterpriseRoots;
    471  nsAutoCString mGreBinDir;
    472 };
    473 
    474 nsresult LoadLoadableCertsTask::Dispatch() {
    475  // The stream transport service (note: not the socket transport service) can
    476  // be used to perform background tasks or I/O that would otherwise block the
    477  // main thread.
    478  nsCOMPtr<nsIEventTarget> target(
    479      do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID));
    480  if (!target) {
    481    return NS_ERROR_FAILURE;
    482  }
    483  return target->Dispatch(this, NS_DISPATCH_NORMAL);
    484 }
    485 
    486 NS_IMETHODIMP
    487 LoadLoadableCertsTask::Run() {
    488  AutoGleanTimer<&glean::networking::loading_certs_task> timer;
    489 
    490  nsresult loadLoadableRootsResult = LoadLoadableRoots();
    491  if (NS_WARN_IF(NS_FAILED(loadLoadableRootsResult))) {
    492    MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("LoadLoadableRoots failed"));
    493    // We don't return loadLoadableRootsResult here because then
    494    // BlockUntilLoadableCertsLoaded will just wait forever. Instead we'll save
    495    // its value (below) so we can inform code that relies on the roots module
    496    // being present that loading it failed.
    497  }
    498 
    499  // Loading EV information will only succeed if we've successfully loaded the
    500  // loadable roots module.
    501  if (NS_SUCCEEDED(loadLoadableRootsResult)) {
    502    if (NS_FAILED(LoadExtendedValidationInfo())) {
    503      // This isn't a show-stopper in the same way that failing to load the
    504      // roots module is.
    505      MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("failed to load EV info"));
    506    }
    507  }
    508 
    509  if (mImportEnterpriseRoots) {
    510    mNSSComponent->ImportEnterpriseRoots();
    511    mNSSComponent->UpdateCertVerifierWithEnterpriseRoots();
    512  }
    513 
    514  if (StaticPrefs::security_osclientcerts_autoload()) {
    515    bool success = LoadOSClientCertsModule();
    516    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    517            ("loading OS client certs module %s",
    518             success ? "succeeded" : "failed"));
    519  }
    520 
    521  {
    522    MonitorAutoLock rootsLoadedLock(mNSSComponent->mLoadableCertsLoadedMonitor);
    523    mNSSComponent->mLoadableCertsLoaded = true;
    524    // Cache the result of LoadLoadableRoots so BlockUntilLoadableCertsLoaded
    525    // can return it to all callers later (we use that particular result because
    526    // if that operation fails, it's unlikely that any TLS connection will
    527    // succeed whereas the browser may still be able to operate if the other
    528    // tasks fail).
    529    mNSSComponent->mLoadableCertsLoadedResult = loadLoadableRootsResult;
    530    mNSSComponent->mLoadableCertsLoadedMonitor.NotifyAll();
    531  }
    532  return NS_OK;
    533 }
    534 
    535 class BackgroundLoadOSClientCertsModuleTask final : public CryptoTask {
    536 public:
    537  explicit BackgroundLoadOSClientCertsModuleTask() {}
    538 
    539 private:
    540  virtual nsresult CalculateResult() override {
    541    bool success = LoadOSClientCertsModule();
    542    return success ? NS_OK : NS_ERROR_FAILURE;
    543  }
    544 
    545  virtual void CallCallback(nsresult rv) override {
    546    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    547            ("loading OS client certs module %s",
    548             NS_SUCCEEDED(rv) ? "succeeded" : "failed"));
    549    nsCOMPtr<nsIObserverService> observerService =
    550        mozilla::services::GetObserverService();
    551    if (observerService) {
    552      observerService->NotifyObservers(
    553          nullptr, "psm:load-os-client-certs-module-task-ran", nullptr);
    554    }
    555  }
    556 };
    557 
    558 void AsyncLoadOrUnloadOSClientCertsModule(bool load) {
    559  if (load) {
    560    RefPtr<BackgroundLoadOSClientCertsModuleTask> task =
    561        new BackgroundLoadOSClientCertsModuleTask();
    562    (void)task->Dispatch();
    563  } else {
    564    UniqueSECMODModule osClientCertsModule(
    565        SECMOD_FindModule(kOSClientCertsModuleName.get()));
    566    if (osClientCertsModule) {
    567      SECMOD_UnloadUserModule(osClientCertsModule.get());
    568    }
    569  }
    570 }
    571 
    572 nsresult nsNSSComponent::BlockUntilLoadableCertsLoaded() {
    573  MonitorAutoLock rootsLoadedLock(mLoadableCertsLoadedMonitor);
    574  while (!mLoadableCertsLoaded) {
    575    rootsLoadedLock.Wait();
    576  }
    577  MOZ_ASSERT(mLoadableCertsLoaded);
    578 
    579  return mLoadableCertsLoadedResult;
    580 }
    581 
    582 #ifndef MOZ_NO_SMART_CARDS
    583 static StaticMutex sCheckForSmartCardChangesMutex MOZ_UNANNOTATED;
    584 MOZ_RUNINIT static TimeStamp sLastCheckedForSmartCardChanges = TimeStamp::Now();
    585 #endif
    586 
    587 nsresult nsNSSComponent::CheckForSmartCardChanges() {
    588 #ifndef MOZ_NO_SMART_CARDS
    589  {
    590    StaticMutexAutoLock lock(sCheckForSmartCardChangesMutex);
    591    // Do this at most once every 3 seconds.
    592    TimeStamp now = TimeStamp::Now();
    593    if (now - sLastCheckedForSmartCardChanges <
    594        TimeDuration::FromSeconds(3.0)) {
    595      return NS_OK;
    596    }
    597    sLastCheckedForSmartCardChanges = now;
    598  }
    599 
    600  // SECMOD_UpdateSlotList attempts to acquire the list lock as well, so we
    601  // have to do this in three steps.
    602  Vector<UniqueSECMODModule> modulesWithRemovableSlots;
    603  {
    604    AutoSECMODListReadLock secmodLock;
    605    SECMODModuleList* list = SECMOD_GetDefaultModuleList();
    606    while (list) {
    607      if (SECMOD_LockedModuleHasRemovableSlots(list->module)) {
    608        UniqueSECMODModule module(SECMOD_ReferenceModule(list->module));
    609        if (!modulesWithRemovableSlots.append(std::move(module))) {
    610          return NS_ERROR_OUT_OF_MEMORY;
    611        }
    612      }
    613      list = list->next;
    614    }
    615  }
    616  for (auto& module : modulesWithRemovableSlots) {
    617    // Best-effort.
    618    (void)SECMOD_UpdateSlotList(module.get());
    619  }
    620  AutoSECMODListReadLock secmodLock;
    621  for (auto& module : modulesWithRemovableSlots) {
    622    for (int i = 0; i < module->slotCount; i++) {
    623      // We actually don't care about the return value here - we just need to
    624      // call this to get NSS to update its view of this slot.
    625      (void)PK11_IsPresent(module->slots[i]);
    626    }
    627  }
    628 #endif
    629 
    630  return NS_OK;
    631 }
    632 
    633 #ifdef MOZ_SYSTEM_NSS
    634 // Returns by reference the path to the directory containing the file that has
    635 // been loaded as MOZ_DLL_PREFIX nss3 MOZ_DLL_SUFFIX.
    636 // |result| is encoded in UTF-8.
    637 static nsresult GetNSS3Directory(nsCString& result) {
    638  MOZ_ASSERT(NS_IsMainThread());
    639 
    640  UniquePRString nss3Path(
    641      PR_GetLibraryFilePathname(MOZ_DLL_PREFIX "nss3" MOZ_DLL_SUFFIX,
    642                                reinterpret_cast<PRFuncPtr>(NSS_Initialize)));
    643  if (!nss3Path) {
    644    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nss not loaded?"));
    645    return NS_ERROR_FAILURE;
    646  }
    647  nsCOMPtr<nsIFile> nss3File;
    648  nsresult rv = NS_NewNativeLocalFile(nsDependentCString(nss3Path.get()),
    649                                      getter_AddRefs(nss3File));
    650  if (NS_FAILED(rv)) {
    651    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    652            ("couldn't initialize file with path '%s'", nss3Path.get()));
    653    return rv;
    654  }
    655  nsCOMPtr<nsIFile> nss3Directory;
    656  rv = nss3File->GetParent(getter_AddRefs(nss3Directory));
    657  if (NS_FAILED(rv)) {
    658    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't get parent directory?"));
    659    return rv;
    660  }
    661  return FileToCString(nss3Directory, result);
    662 }
    663 #endif  // MOZ_SYSTEM_NSS
    664 
    665 // Returns by reference the path to the desired directory, based on the current
    666 // settings in the directory service.
    667 // |result| is encoded in UTF-8.
    668 static nsresult GetDirectoryPath(const char* directoryKey, nsCString& result) {
    669  MOZ_ASSERT(NS_IsMainThread());
    670 
    671  nsCOMPtr<nsIProperties> directoryService(
    672      do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
    673  if (!directoryService) {
    674    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("could not get directory service"));
    675    return NS_ERROR_FAILURE;
    676  }
    677  nsCOMPtr<nsIFile> directory;
    678  nsresult rv = directoryService->Get(directoryKey, NS_GET_IID(nsIFile),
    679                                      getter_AddRefs(directory));
    680  if (NS_FAILED(rv)) {
    681    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    682            ("could not get '%s' from directory service", directoryKey));
    683    return rv;
    684  }
    685  return FileToCString(directory, result);
    686 }
    687 
    688 nsresult LoadLoadableCertsTask::LoadLoadableRoots() {
    689  // We first start checking if the MOZ_SYSTEM_NSS is used
    690  // If it's not - we check if there is nssckbi library in bin directory
    691  // If not found again - we finally load the library from XUL
    692 #ifdef MOZ_SYSTEM_NSS
    693 
    694  // First try checking the OS' default library search path.
    695  nsAutoCString emptyString;
    696  if (mozilla::psm::LoadLoadableRoots(emptyString)) {
    697    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    698            ("loaded CKBI from from OS default library path"));
    699    return NS_OK;
    700  }
    701 
    702  // Trying the library provided by NSS
    703  nsAutoCString nss3Dir;
    704  nsresult rv = GetNSS3Directory(nss3Dir);
    705 
    706  if (NS_SUCCEEDED(rv)) {
    707    if (mozilla::psm::LoadLoadableRoots(nss3Dir)) {
    708      MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    709              ("loaded CKBI from %s", nss3Dir.get()));
    710      return NS_OK;
    711    }
    712  } else {
    713    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    714            ("could not determine where nss was loaded from"));
    715  }
    716 
    717 #endif  // MOZ_SYSTEM_NSS
    718 
    719  if (mozilla::psm::LoadLoadableRoots(mGreBinDir)) {
    720    mozilla::glean::pkcs11::external_trust_anchor_module_loaded.Set(true);
    721    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    722            ("loaded external CKBI from gre directory"));
    723    return NS_OK;
    724  }
    725 
    726  mozilla::glean::pkcs11::external_trust_anchor_module_loaded.Set(false);
    727 
    728  if (LoadLoadableRootsFromXul()) {
    729    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("loaded CKBI from xul"));
    730    return NS_OK;
    731  }
    732 
    733  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("could not load loadable roots"));
    734  return NS_ERROR_FAILURE;
    735 }
    736 
    737 // Table of pref names and SSL cipher ID
    738 typedef struct {
    739  const char* pref;
    740  int32_t id;
    741  bool (*prefGetter)();
    742 } CipherPref;
    743 
    744 // Update the switch statement in AccumulateCipherSuite in nsNSSCallbacks.cpp
    745 // when you add/remove cipher suites here.
    746 static const CipherPref sCipherPrefs[] = {
    747    {"security.ssl3.ecdhe_rsa_aes_128_gcm_sha256",
    748     TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
    749     StaticPrefs::security_ssl3_ecdhe_rsa_aes_128_gcm_sha256},
    750    {"security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256",
    751     TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
    752     StaticPrefs::security_ssl3_ecdhe_ecdsa_aes_128_gcm_sha256},
    753    {"security.ssl3.ecdhe_ecdsa_chacha20_poly1305_sha256",
    754     TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
    755     StaticPrefs::security_ssl3_ecdhe_ecdsa_chacha20_poly1305_sha256},
    756    {"security.ssl3.ecdhe_rsa_chacha20_poly1305_sha256",
    757     TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
    758     StaticPrefs::security_ssl3_ecdhe_rsa_chacha20_poly1305_sha256},
    759    {"security.ssl3.ecdhe_ecdsa_aes_256_gcm_sha384",
    760     TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
    761     StaticPrefs::security_ssl3_ecdhe_ecdsa_aes_256_gcm_sha384},
    762    {"security.ssl3.ecdhe_rsa_aes_256_gcm_sha384",
    763     TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
    764     StaticPrefs::security_ssl3_ecdhe_rsa_aes_256_gcm_sha384},
    765    {"security.ssl3.ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
    766     StaticPrefs::security_ssl3_ecdhe_rsa_aes_128_sha},
    767    {"security.ssl3.ecdhe_ecdsa_aes_128_sha",
    768     TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
    769     StaticPrefs::security_ssl3_ecdhe_ecdsa_aes_128_sha},
    770    {"security.ssl3.ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
    771     StaticPrefs::security_ssl3_ecdhe_rsa_aes_256_sha},
    772    {"security.ssl3.ecdhe_ecdsa_aes_256_sha",
    773     TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
    774     StaticPrefs::security_ssl3_ecdhe_ecdsa_aes_256_sha},
    775    {"security.ssl3.dhe_rsa_aes_128_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
    776     StaticPrefs::security_ssl3_dhe_rsa_aes_128_sha},
    777    {"security.ssl3.dhe_rsa_aes_256_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
    778     StaticPrefs::security_ssl3_dhe_rsa_aes_256_sha},
    779    {"security.tls13.aes_128_gcm_sha256", TLS_AES_128_GCM_SHA256,
    780     StaticPrefs::security_tls13_aes_128_gcm_sha256},
    781    {"security.tls13.chacha20_poly1305_sha256", TLS_CHACHA20_POLY1305_SHA256,
    782     StaticPrefs::security_tls13_chacha20_poly1305_sha256},
    783    {"security.tls13.aes_256_gcm_sha384", TLS_AES_256_GCM_SHA384,
    784     StaticPrefs::security_tls13_aes_256_gcm_sha384},
    785    {"security.ssl3.rsa_aes_128_gcm_sha256", TLS_RSA_WITH_AES_128_GCM_SHA256,
    786     StaticPrefs::security_ssl3_rsa_aes_128_gcm_sha256},
    787    {"security.ssl3.rsa_aes_256_gcm_sha384", TLS_RSA_WITH_AES_256_GCM_SHA384,
    788     StaticPrefs::security_ssl3_rsa_aes_256_gcm_sha384},
    789    {"security.ssl3.rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA,
    790     StaticPrefs::security_ssl3_rsa_aes_128_sha},
    791    {"security.ssl3.rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA,
    792     StaticPrefs::security_ssl3_rsa_aes_256_sha},
    793 };
    794 
    795 // These ciphersuites can only be enabled if deprecated versions of TLS are
    796 // also enabled (via the preference "security.tls.version.enable-deprecated").
    797 static const CipherPref sDeprecatedTLS1CipherPrefs[] = {
    798    {"security.ssl3.deprecated.rsa_des_ede3_sha", TLS_RSA_WITH_3DES_EDE_CBC_SHA,
    799     StaticPrefs::security_ssl3_deprecated_rsa_des_ede3_sha},
    800 };
    801 
    802 // This function will convert from pref values like 1, 2, ...
    803 // to the internal values of SSL_LIBRARY_VERSION_TLS_1_0,
    804 // SSL_LIBRARY_VERSION_TLS_1_1, ...
    805 /*static*/
    806 void nsNSSComponent::FillTLSVersionRange(SSLVersionRange& rangeOut,
    807                                         uint32_t minFromPrefs,
    808                                         uint32_t maxFromPrefs,
    809                                         SSLVersionRange defaults) {
    810  rangeOut = defaults;
    811  // determine what versions are supported
    812  SSLVersionRange supported;
    813  if (SSL_VersionRangeGetSupported(ssl_variant_stream, &supported) !=
    814      SECSuccess) {
    815    return;
    816  }
    817 
    818  // Clip the defaults by what NSS actually supports to enable
    819  // working with a system NSS with different ranges.
    820  rangeOut.min = std::max(rangeOut.min, supported.min);
    821  rangeOut.max = std::min(rangeOut.max, supported.max);
    822 
    823  // convert min/maxFromPrefs to the internal representation
    824  minFromPrefs += SSL_LIBRARY_VERSION_3_0;
    825  maxFromPrefs += SSL_LIBRARY_VERSION_3_0;
    826  // if min/maxFromPrefs are invalid, use defaults
    827  if (minFromPrefs > maxFromPrefs || minFromPrefs < supported.min ||
    828      maxFromPrefs > supported.max ||
    829      minFromPrefs < SSL_LIBRARY_VERSION_TLS_1_0) {
    830    return;
    831  }
    832 
    833  // fill out rangeOut
    834  rangeOut.min = (uint16_t)minFromPrefs;
    835  rangeOut.max = (uint16_t)maxFromPrefs;
    836 }
    837 
    838 static void ConfigureTLSSessionIdentifiers() {
    839  bool disableSessionIdentifiers =
    840      StaticPrefs::security_ssl_disable_session_identifiers();
    841  SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, !disableSessionIdentifiers);
    842  SSL_OptionSetDefault(SSL_NO_CACHE, disableSessionIdentifiers);
    843 }
    844 
    845 nsresult CommonInit() {
    846  SSL_OptionSetDefault(SSL_ENABLE_SSL2, false);
    847  SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, false);
    848 
    849  nsresult rv = nsNSSComponent::SetEnabledTLSVersions();
    850  if (NS_FAILED(rv)) {
    851    return rv;
    852  }
    853 
    854  ConfigureTLSSessionIdentifiers();
    855 
    856  SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION,
    857                       StaticPrefs::security_ssl_require_safe_negotiation());
    858  SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_REQUIRES_XTN);
    859  SSL_OptionSetDefault(SSL_ENABLE_EXTENDED_MASTER_SECRET, true);
    860  SSL_OptionSetDefault(SSL_ENABLE_HELLO_DOWNGRADE_CHECK,
    861                       StaticPrefs::security_tls_hello_downgrade_check());
    862  SSL_OptionSetDefault(SSL_ENABLE_FALSE_START,
    863                       StaticPrefs::security_ssl_enable_false_start());
    864  // SSL_ENABLE_ALPN also requires calling SSL_SetNextProtoNego in order for
    865  // the extensions to be negotiated.
    866  // WebRTC does not do that so it will not use ALPN even when this preference
    867  // is true.
    868  SSL_OptionSetDefault(SSL_ENABLE_ALPN,
    869                       StaticPrefs::security_ssl_enable_alpn());
    870  SSL_OptionSetDefault(SSL_ENABLE_0RTT_DATA,
    871                       StaticPrefs::security_tls_enable_0rtt_data());
    872  SSL_OptionSetDefault(SSL_ENABLE_POST_HANDSHAKE_AUTH,
    873                       StaticPrefs::security_tls_enable_post_handshake_auth());
    874  SSL_OptionSetDefault(
    875      SSL_ENABLE_DELEGATED_CREDENTIALS,
    876      StaticPrefs::security_tls_enable_delegated_credentials());
    877  SSL_OptionSetDefault(SSL_DB_LOAD_CERTIFICATE_CHAIN, false);
    878 
    879  rv = InitializeCipherSuite();
    880  if (NS_FAILED(rv)) {
    881    MOZ_LOG(gPIPNSSLog, LogLevel::Error,
    882            ("Unable to initialize cipher suite settings\n"));
    883    return rv;
    884  }
    885 
    886  DisableMD5();
    887 
    888  mozilla::pkix::RegisterErrorTable();
    889  nsSSLIOLayerHelpers::GlobalInit();
    890 
    891  return NS_OK;
    892 }
    893 
    894 void PrepareForShutdownInSocketProcess() {
    895  MOZ_ASSERT(XRE_IsSocketProcess());
    896  nsSSLIOLayerHelpers::GlobalCleanup();
    897 }
    898 
    899 bool HandleTLSPrefChange(const nsCString& prefName) {
    900  // Note that the code in this function should be kept in sync with
    901  // gCallbackSecurityPrefs in nsIOService.cpp.
    902  bool prefFound = true;
    903  if (prefName.EqualsLiteral("security.tls.version.min") ||
    904      prefName.EqualsLiteral("security.tls.version.max") ||
    905      prefName.EqualsLiteral("security.tls.version.enable-deprecated")) {
    906    (void)nsNSSComponent::SetEnabledTLSVersions();
    907  } else if (prefName.EqualsLiteral("security.tls.hello_downgrade_check")) {
    908    SSL_OptionSetDefault(SSL_ENABLE_HELLO_DOWNGRADE_CHECK,
    909                         StaticPrefs::security_tls_hello_downgrade_check());
    910  } else if (prefName.EqualsLiteral("security.ssl.require_safe_negotiation")) {
    911    SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION,
    912                         StaticPrefs::security_ssl_require_safe_negotiation());
    913  } else if (prefName.EqualsLiteral("security.ssl.enable_false_start")) {
    914    SSL_OptionSetDefault(SSL_ENABLE_FALSE_START,
    915                         StaticPrefs::security_ssl_enable_false_start());
    916  } else if (prefName.EqualsLiteral("security.ssl.enable_alpn")) {
    917    SSL_OptionSetDefault(SSL_ENABLE_ALPN,
    918                         StaticPrefs::security_ssl_enable_alpn());
    919  } else if (prefName.EqualsLiteral("security.tls.enable_0rtt_data")) {
    920    SSL_OptionSetDefault(SSL_ENABLE_0RTT_DATA,
    921                         StaticPrefs::security_tls_enable_0rtt_data());
    922  } else if (prefName.EqualsLiteral(
    923                 "security.tls.enable_post_handshake_auth")) {
    924    SSL_OptionSetDefault(
    925        SSL_ENABLE_POST_HANDSHAKE_AUTH,
    926        StaticPrefs::security_tls_enable_post_handshake_auth());
    927  } else if (prefName.EqualsLiteral(
    928                 "security.tls.enable_delegated_credentials")) {
    929    SSL_OptionSetDefault(
    930        SSL_ENABLE_DELEGATED_CREDENTIALS,
    931        StaticPrefs::security_tls_enable_delegated_credentials());
    932  } else if (prefName.EqualsLiteral(
    933                 "security.ssl.disable_session_identifiers")) {
    934    ConfigureTLSSessionIdentifiers();
    935  } else {
    936    prefFound = false;
    937  }
    938  return prefFound;
    939 }
    940 
    941 namespace {
    942 
    943 class CipherSuiteChangeObserver : public nsIObserver {
    944 public:
    945  NS_DECL_ISUPPORTS
    946  NS_DECL_NSIOBSERVER
    947 
    948  static nsresult StartObserve();
    949 
    950 protected:
    951  virtual ~CipherSuiteChangeObserver() = default;
    952 
    953 private:
    954  static StaticRefPtr<CipherSuiteChangeObserver> sObserver;
    955  CipherSuiteChangeObserver() = default;
    956 };
    957 
    958 NS_IMPL_ISUPPORTS(CipherSuiteChangeObserver, nsIObserver)
    959 
    960 // static
    961 StaticRefPtr<CipherSuiteChangeObserver> CipherSuiteChangeObserver::sObserver;
    962 
    963 // static
    964 nsresult CipherSuiteChangeObserver::StartObserve() {
    965  MOZ_ASSERT(NS_IsMainThread(),
    966             "CipherSuiteChangeObserver::StartObserve() can only be accessed "
    967             "on the main thread");
    968  if (!sObserver) {
    969    RefPtr<CipherSuiteChangeObserver> observer =
    970        new CipherSuiteChangeObserver();
    971    nsresult rv = Preferences::AddStrongObserver(observer.get(), "security.");
    972    if (NS_FAILED(rv)) {
    973      sObserver = nullptr;
    974      return rv;
    975    }
    976 
    977    nsCOMPtr<nsIObserverService> observerService =
    978        mozilla::services::GetObserverService();
    979    observerService->AddObserver(observer, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
    980                                 false);
    981 
    982    sObserver = observer;
    983  }
    984  return NS_OK;
    985 }
    986 
    987 // Enables or disabled ciphersuites from deprecated versions of TLS as
    988 // appropriate. If security.tls.version.enable-deprecated is true, these
    989 // ciphersuites may be enabled, if the corresponding preference is true.
    990 // Otherwise, these ciphersuites will be disabled.
    991 void SetDeprecatedTLS1CipherPrefs() {
    992  if (StaticPrefs::security_tls_version_enable_deprecated()) {
    993    for (const auto& deprecatedTLS1CipherPref : sDeprecatedTLS1CipherPrefs) {
    994      SSL_CipherPrefSetDefault(deprecatedTLS1CipherPref.id,
    995                               deprecatedTLS1CipherPref.prefGetter());
    996    }
    997  } else {
    998    for (const auto& deprecatedTLS1CipherPref : sDeprecatedTLS1CipherPrefs) {
    999      SSL_CipherPrefSetDefault(deprecatedTLS1CipherPref.id, false);
   1000    }
   1001  }
   1002 }
   1003 
   1004 // static
   1005 void SetKyberPolicy() {
   1006  if (StaticPrefs::security_tls_enable_kyber()) {
   1007    NSS_SetAlgorithmPolicy(SEC_OID_MLKEM768X25519, NSS_USE_ALG_IN_SSL_KX, 0);
   1008  } else {
   1009    NSS_SetAlgorithmPolicy(SEC_OID_MLKEM768X25519, 0, NSS_USE_ALG_IN_SSL_KX);
   1010  }
   1011 }
   1012 
   1013 nsresult CipherSuiteChangeObserver::Observe(nsISupports* /*aSubject*/,
   1014                                            const char* aTopic,
   1015                                            const char16_t* someData) {
   1016  MOZ_ASSERT(NS_IsMainThread(),
   1017             "CipherSuiteChangeObserver::Observe can only be accessed on main "
   1018             "thread");
   1019  if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
   1020    NS_ConvertUTF16toUTF8 prefName(someData);
   1021    // Look through the cipher table and set according to pref setting
   1022    for (const auto& cipherPref : sCipherPrefs) {
   1023      if (prefName.Equals(cipherPref.pref)) {
   1024        SSL_CipherPrefSetDefault(cipherPref.id, cipherPref.prefGetter());
   1025        break;
   1026      }
   1027    }
   1028    SetDeprecatedTLS1CipherPrefs();
   1029    SetKyberPolicy();
   1030    nsNSSComponent::DoClearSSLExternalAndInternalSessionCache();
   1031  } else if (nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
   1032    Preferences::RemoveObserver(this, "security.");
   1033    MOZ_ASSERT(sObserver.get() == this);
   1034    sObserver = nullptr;
   1035    nsCOMPtr<nsIObserverService> observerService =
   1036        mozilla::services::GetObserverService();
   1037    observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
   1038  }
   1039  return NS_OK;
   1040 }
   1041 
   1042 }  // namespace
   1043 
   1044 void nsNSSComponent::setValidationOptions(
   1045    const mozilla::MutexAutoLock& proofOfLock) {
   1046  // We access prefs so this must be done on the main thread.
   1047  mMutex.AssertCurrentThreadOwns();
   1048  MOZ_ASSERT(NS_IsMainThread());
   1049  if (NS_WARN_IF(!NS_IsMainThread())) {
   1050    return;
   1051  }
   1052 
   1053  CertVerifier::CertificateTransparencyMode ctMode =
   1054      GetCertificateTransparencyMode();
   1055  nsCString skipCTForHosts;
   1056  Preferences::GetCString(
   1057      "security.pki.certificate_transparency.disable_for_hosts",
   1058      skipCTForHosts);
   1059  nsAutoCString skipCTForSPKIHashesBase64;
   1060  Preferences::GetCString(
   1061      "security.pki.certificate_transparency.disable_for_spki_hashes",
   1062      skipCTForSPKIHashesBase64);
   1063  nsTArray<CopyableTArray<uint8_t>> skipCTForSPKIHashes;
   1064  for (const auto& spkiHashBase64 : skipCTForSPKIHashesBase64.Split(',')) {
   1065    nsAutoCString spkiHashString;
   1066    if (NS_SUCCEEDED(Base64Decode(spkiHashBase64, spkiHashString))) {
   1067      nsTArray<uint8_t> spkiHash(spkiHashString.Data(),
   1068                                 spkiHashString.Length());
   1069      skipCTForSPKIHashes.AppendElement(std::move(spkiHash));
   1070    }
   1071  }
   1072  CertVerifier::CertificateTransparencyConfig ctConfig(
   1073      ctMode, std::move(skipCTForHosts), std::move(skipCTForSPKIHashes));
   1074 
   1075  CRLiteMode defaultCRLiteMode = CRLiteMode::Enforce;
   1076  CRLiteMode crliteMode =
   1077      static_cast<CRLiteMode>(StaticPrefs::security_pki_crlite_mode());
   1078  switch (crliteMode) {
   1079    case CRLiteMode::Disabled:
   1080    case CRLiteMode::TelemetryOnly:
   1081    case CRLiteMode::Enforce:
   1082      break;
   1083    default:
   1084      crliteMode = defaultCRLiteMode;
   1085      break;
   1086  }
   1087 
   1088  CertVerifier::OcspDownloadConfig odc;
   1089  CertVerifier::OcspStrictConfig osc;
   1090  uint32_t certShortLifetimeInDays;
   1091  TimeDuration softTimeout;
   1092  TimeDuration hardTimeout;
   1093 
   1094  GetRevocationBehaviorFromPrefs(&odc, &osc, &certShortLifetimeInDays,
   1095                                 softTimeout, hardTimeout);
   1096 
   1097  mDefaultCertVerifier = new SharedCertVerifier(
   1098      odc, osc, softTimeout, hardTimeout, certShortLifetimeInDays,
   1099      std::move(ctConfig), crliteMode, mEnterpriseCerts);
   1100 }
   1101 
   1102 void nsNSSComponent::UpdateCertVerifierWithEnterpriseRoots() {
   1103  MutexAutoLock lock(mMutex);
   1104  if (!mDefaultCertVerifier) {
   1105    return;
   1106  }
   1107 
   1108  RefPtr<SharedCertVerifier> oldCertVerifier = mDefaultCertVerifier;
   1109  nsCString skipCTForHosts(oldCertVerifier->mCTConfig.mSkipForHosts);
   1110  CertVerifier::CertificateTransparencyConfig ctConfig(
   1111      oldCertVerifier->mCTConfig.mMode, std::move(skipCTForHosts),
   1112      oldCertVerifier->mCTConfig.mSkipForSPKIHashes.Clone());
   1113  mDefaultCertVerifier = new SharedCertVerifier(
   1114      oldCertVerifier->mOCSPDownloadConfig,
   1115      oldCertVerifier->mOCSPStrict ? CertVerifier::ocspStrict
   1116                                   : CertVerifier::ocspRelaxed,
   1117      oldCertVerifier->mOCSPTimeoutSoft, oldCertVerifier->mOCSPTimeoutHard,
   1118      oldCertVerifier->mCertShortLifetimeInDays, std::move(ctConfig),
   1119      oldCertVerifier->mCRLiteMode, mEnterpriseCerts);
   1120 }
   1121 
   1122 // Enable the TLS versions given in the prefs, defaulting to TLS 1.0 (min) and
   1123 // TLS 1.2 (max) when the prefs aren't set or set to invalid values.
   1124 nsresult nsNSSComponent::SetEnabledTLSVersions() {
   1125  // Keep these values in sync with all.js.
   1126  // 1 means TLS 1.0, 2 means TLS 1.1, etc.
   1127  static const uint32_t PSM_DEFAULT_MIN_TLS_VERSION = 3;
   1128  static const uint32_t PSM_DEFAULT_MAX_TLS_VERSION = 4;
   1129  static const uint32_t PSM_DEPRECATED_TLS_VERSION = 1;
   1130 
   1131  uint32_t minFromPrefs = StaticPrefs::security_tls_version_min();
   1132  uint32_t maxFromPrefs = StaticPrefs::security_tls_version_max();
   1133 
   1134  // This override should be removed some time after
   1135  // PSM_DEFAULT_MIN_TLS_VERSION is increased to 3.
   1136  bool enableDeprecated = StaticPrefs::security_tls_version_enable_deprecated();
   1137  if (enableDeprecated) {
   1138    minFromPrefs = std::min(minFromPrefs, PSM_DEPRECATED_TLS_VERSION);
   1139  }
   1140 
   1141  SSLVersionRange defaults = {
   1142      SSL_LIBRARY_VERSION_3_0 + PSM_DEFAULT_MIN_TLS_VERSION,
   1143      SSL_LIBRARY_VERSION_3_0 + PSM_DEFAULT_MAX_TLS_VERSION};
   1144  SSLVersionRange filledInRange;
   1145  FillTLSVersionRange(filledInRange, minFromPrefs, maxFromPrefs, defaults);
   1146 
   1147  SECStatus srv =
   1148      SSL_VersionRangeSetDefault(ssl_variant_stream, &filledInRange);
   1149  if (srv != SECSuccess) {
   1150    return NS_ERROR_FAILURE;
   1151  }
   1152 
   1153  return NS_OK;
   1154 }
   1155 
   1156 #if defined(XP_WIN) || (defined(XP_LINUX) && !defined(ANDROID))
   1157 // If the profile directory is on a networked drive, we want to set the
   1158 // environment variable NSS_SDB_USE_CACHE to yes (as long as it hasn't been set
   1159 // before).
   1160 static void SetNSSDatabaseCacheModeAsAppropriate() {
   1161  MOZ_ASSERT(NS_IsMainThread());
   1162 
   1163  nsCOMPtr<nsIFile> profileFile;
   1164  nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
   1165                                       getter_AddRefs(profileFile));
   1166  if (NS_FAILED(rv)) {
   1167    // We're probably running without a profile directory, so this is
   1168    // irrelevant.
   1169    return;
   1170  }
   1171 
   1172  static const char sNSS_SDB_USE_CACHE[] = "NSS_SDB_USE_CACHE";
   1173  static const char sNSS_SDB_USE_CACHE_WITH_VALUE[] = "NSS_SDB_USE_CACHE=yes";
   1174  auto profilePath = profileFile->NativePath();
   1175 
   1176 #  if defined(XP_LINUX) && !defined(ANDROID)
   1177  struct statfs statfs_s;
   1178  if (statfs(profilePath.get(), &statfs_s) == 0 &&
   1179      statfs_s.f_type == NFS_SUPER_MAGIC && !PR_GetEnv(sNSS_SDB_USE_CACHE)) {
   1180    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   1181            ("profile is remote (and NSS_SDB_USE_CACHE wasn't set): "
   1182             "setting NSS_SDB_USE_CACHE"));
   1183    PR_SetEnv(sNSS_SDB_USE_CACHE_WITH_VALUE);
   1184  } else {
   1185    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("not setting NSS_SDB_USE_CACHE"));
   1186  }
   1187 #  endif  // defined(XP_LINUX) && !defined(ANDROID)
   1188 
   1189 #  ifdef XP_WIN
   1190  wchar_t volPath[MAX_PATH];
   1191  if (::GetVolumePathNameW(profilePath.get(), volPath, MAX_PATH) &&
   1192      ::GetDriveTypeW(volPath) == DRIVE_REMOTE &&
   1193      !PR_GetEnv(sNSS_SDB_USE_CACHE)) {
   1194    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   1195            ("profile is remote (and NSS_SDB_USE_CACHE wasn't set): "
   1196             "setting NSS_SDB_USE_CACHE"));
   1197    PR_SetEnv(sNSS_SDB_USE_CACHE_WITH_VALUE);
   1198  } else {
   1199    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("not setting NSS_SDB_USE_CACHE"));
   1200  }
   1201 #  endif  // XP_WIN
   1202 }
   1203 #endif  // defined(XP_WIN) || (defined(XP_LINUX) && !defined(ANDROID))
   1204 
   1205 static nsresult GetNSSProfilePath(nsAutoCString& aProfilePath) {
   1206  aProfilePath.Truncate();
   1207  nsCOMPtr<nsIFile> profileFile;
   1208  nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
   1209                                       getter_AddRefs(profileFile));
   1210  if (NS_FAILED(rv)) {
   1211    NS_WARNING(
   1212        "NSS will be initialized without a profile directory. "
   1213        "Some things may not work as expected.");
   1214    return NS_OK;
   1215  }
   1216 
   1217 #if defined(XP_WIN)
   1218  // SQLite always takes UTF-8 file paths regardless of the current system
   1219  // code page.
   1220  nsAutoString u16ProfilePath;
   1221  rv = profileFile->GetPath(u16ProfilePath);
   1222  CopyUTF16toUTF8(u16ProfilePath, aProfilePath);
   1223 #else
   1224  rv = profileFile->GetNativePath(aProfilePath);
   1225 #endif
   1226  if (NS_FAILED(rv)) {
   1227    MOZ_LOG(gPIPNSSLog, LogLevel::Error,
   1228            ("Could not get native path for profile directory.\n"));
   1229    return rv;
   1230  }
   1231 
   1232  MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   1233          ("NSS profile at '%s'\n", aProfilePath.get()));
   1234  return NS_OK;
   1235 }
   1236 
   1237 #ifndef ANDROID
   1238 // Given a profile path, attempt to rename the PKCS#11 module DB to
   1239 // "pkcs11.txt.fips". In the case of a catastrophic failure (e.g. out of
   1240 // memory), returns a failing nsresult. If execution could conceivably proceed,
   1241 // returns NS_OK even if renaming the file didn't work. This simplifies the
   1242 // logic of the calling code.
   1243 // |profilePath| is encoded in UTF-8.
   1244 static nsresult AttemptToRenamePKCS11ModuleDB(const nsACString& profilePath) {
   1245  nsCOMPtr<nsIFile> profileDir;
   1246  // |profilePath| is encoded in UTF-8 because SQLite always takes UTF-8 file
   1247  // paths regardless of the current system code page.
   1248  MOZ_TRY(NS_NewUTF8LocalFile(profilePath, getter_AddRefs(profileDir)));
   1249  const char* moduleDBFilename = "pkcs11.txt";
   1250  nsAutoCString destModuleDBFilename(moduleDBFilename);
   1251  destModuleDBFilename.Append(".fips");
   1252  nsCOMPtr<nsIFile> dbFile;
   1253  nsresult rv = profileDir->Clone(getter_AddRefs(dbFile));
   1254  if (NS_FAILED(rv) || !dbFile) {
   1255    return NS_ERROR_FAILURE;
   1256  }
   1257  rv = dbFile->AppendNative(nsAutoCString(moduleDBFilename));
   1258  if (NS_FAILED(rv)) {
   1259    return rv;
   1260  }
   1261  // If the PKCS#11 module DB doesn't exist, renaming it won't help.
   1262  bool exists;
   1263  rv = dbFile->Exists(&exists);
   1264  if (NS_FAILED(rv)) {
   1265    return rv;
   1266  }
   1267  // This is strange, but not a catastrophic failure.
   1268  if (!exists) {
   1269    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   1270            ("%s doesn't exist?", moduleDBFilename));
   1271    return NS_OK;
   1272  }
   1273  nsCOMPtr<nsIFile> destDBFile;
   1274  rv = profileDir->Clone(getter_AddRefs(destDBFile));
   1275  if (NS_FAILED(rv) || !destDBFile) {
   1276    return NS_ERROR_FAILURE;
   1277  }
   1278  rv = destDBFile->AppendNative(destModuleDBFilename);
   1279  if (NS_FAILED(rv)) {
   1280    return rv;
   1281  }
   1282  // If the destination exists, presumably we've already tried this. Doing it
   1283  // again won't help.
   1284  rv = destDBFile->Exists(&exists);
   1285  if (NS_FAILED(rv)) {
   1286    return rv;
   1287  }
   1288  // Unfortunate, but not a catastrophic failure.
   1289  if (exists) {
   1290    MOZ_LOG(
   1291        gPIPNSSLog, LogLevel::Debug,
   1292        ("%s already exists - not overwriting", destModuleDBFilename.get()));
   1293    return NS_OK;
   1294  }
   1295  // Now do the actual move.
   1296  // This may fail on, e.g., a read-only file system. This would be unfortunate,
   1297  // but again it isn't catastropic and we would want to fall back to
   1298  // initializing NSS in no-DB mode.
   1299  (void)dbFile->MoveToNative(profileDir, destModuleDBFilename);
   1300  return NS_OK;
   1301 }
   1302 #endif  // ifndef ANDROID
   1303 
   1304 // Given a profile directory, attempt to initialize NSS. If nocertdb is true,
   1305 // (or if we don't have a profile directory) simply initialize NSS in no DB mode
   1306 // and return. Otherwise, first attempt to initialize in read/write mode, and
   1307 // then read-only mode if that fails. If both attempts fail, we may be failing
   1308 // to initialize an NSS DB collection that has FIPS mode enabled. Attempt to
   1309 // ascertain if this is the case, and if so, rename the offending PKCS#11 module
   1310 // DB so we can (hopefully) initialize NSS in read-write mode. Again attempt
   1311 // read-only mode if that fails. Finally, fall back to no DB mode. On Android
   1312 // we can skip the FIPS workaround since it was never possible to enable FIPS
   1313 // there anyway.
   1314 // |profilePath| is encoded in UTF-8.
   1315 static nsresult InitializeNSSWithFallbacks(const nsACString& profilePath,
   1316                                           bool nocertdb, bool safeMode) {
   1317  if (nocertdb || profilePath.IsEmpty()) {
   1318    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   1319            ("nocertdb mode or empty profile path -> NSS_NoDB_Init"));
   1320    SECStatus srv = NSS_NoDB_Init(nullptr);
   1321 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
   1322    if (srv != SECSuccess) {
   1323      MOZ_CRASH_UNSAFE_PRINTF("InitializeNSSWithFallbacks failed: %d",
   1324                              PR_GetError());
   1325    }
   1326 #endif
   1327    return srv == SECSuccess ? NS_OK : NS_ERROR_FAILURE;
   1328  }
   1329 
   1330  // Try read/write mode. If we're in safeMode, we won't load PKCS#11 modules.
   1331 #ifndef ANDROID
   1332  PRErrorCode savedPRErrorCode1;
   1333 #endif  // ifndef ANDROID
   1334  PKCS11DBConfig safeModeDBConfig =
   1335      safeMode ? PKCS11DBConfig::DoNotLoadModules : PKCS11DBConfig::LoadModules;
   1336  SECStatus srv = ::mozilla::psm::InitializeNSS(
   1337      profilePath, NSSDBConfig::ReadWrite, safeModeDBConfig);
   1338  if (srv == SECSuccess) {
   1339    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized NSS in r/w mode"));
   1340    return NS_OK;
   1341  }
   1342 #ifndef ANDROID
   1343  savedPRErrorCode1 = PR_GetError();
   1344  PRErrorCode savedPRErrorCode2;
   1345 #endif  // ifndef ANDROID
   1346  // That failed. Try read-only mode.
   1347  srv = ::mozilla::psm::InitializeNSS(profilePath, NSSDBConfig::ReadOnly,
   1348                                      safeModeDBConfig);
   1349  if (srv == SECSuccess) {
   1350    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized NSS in r-o mode"));
   1351    return NS_OK;
   1352  }
   1353 #ifndef ANDROID
   1354  savedPRErrorCode2 = PR_GetError();
   1355 
   1356  MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   1357          ("failed to initialize NSS with codes %d %d", savedPRErrorCode1,
   1358           savedPRErrorCode2));
   1359 #endif  // ifndef ANDROID
   1360 
   1361 #ifndef ANDROID
   1362  // That failed as well. Maybe we're trying to load a PKCS#11 module DB that is
   1363  // in FIPS mode, but we don't support FIPS? Test load NSS without PKCS#11
   1364  // modules. If that succeeds, that's probably what's going on.
   1365  if (!safeMode && (savedPRErrorCode1 == SEC_ERROR_LEGACY_DATABASE ||
   1366                    savedPRErrorCode2 == SEC_ERROR_LEGACY_DATABASE ||
   1367                    savedPRErrorCode1 == SEC_ERROR_PKCS11_DEVICE_ERROR ||
   1368                    savedPRErrorCode2 == SEC_ERROR_PKCS11_DEVICE_ERROR)) {
   1369    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("attempting no-module db init"));
   1370    // It would make sense to initialize NSS in read-only mode here since this
   1371    // is just a test to see if the PKCS#11 module DB being in FIPS mode is the
   1372    // problem, but for some reason the combination of read-only and no-moddb
   1373    // flags causes NSS initialization to fail, so unfortunately we have to use
   1374    // read-write mode.
   1375    srv = ::mozilla::psm::InitializeNSS(profilePath, NSSDBConfig::ReadWrite,
   1376                                        PKCS11DBConfig::DoNotLoadModules);
   1377    if (srv == SECSuccess) {
   1378      MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("FIPS may be the problem"));
   1379      // Unload NSS so we can attempt to fix this situation for the user.
   1380      srv = NSS_Shutdown();
   1381      if (srv != SECSuccess) {
   1382 #  ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
   1383        MOZ_CRASH_UNSAFE_PRINTF("InitializeNSSWithFallbacks failed: %d",
   1384                                PR_GetError());
   1385 #  endif
   1386        return NS_ERROR_FAILURE;
   1387      }
   1388      MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("trying to rename module db"));
   1389      // If this fails non-catastrophically, we'll attempt to initialize NSS
   1390      // again in r/w then r-o mode (both of which will fail), and then we'll
   1391      // fall back to NSS_NoDB_Init, which is the behavior we want.
   1392      nsresult rv = AttemptToRenamePKCS11ModuleDB(profilePath);
   1393      if (NS_FAILED(rv)) {
   1394 #  ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
   1395        // An nsresult is a uint32_t, but at least one of our compilers doesn't
   1396        // like this format string unless we include the cast. <shruggie emoji>
   1397        MOZ_CRASH_UNSAFE_PRINTF("InitializeNSSWithFallbacks failed: %u",
   1398                                (uint32_t)rv);
   1399 #  endif
   1400        return rv;
   1401      }
   1402      srv = ::mozilla::psm::InitializeNSS(profilePath, NSSDBConfig::ReadWrite,
   1403                                          PKCS11DBConfig::LoadModules);
   1404      if (srv == SECSuccess) {
   1405        MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized in r/w mode"));
   1406        return NS_OK;
   1407      }
   1408      srv = ::mozilla::psm::InitializeNSS(profilePath, NSSDBConfig::ReadOnly,
   1409                                          PKCS11DBConfig::LoadModules);
   1410      if (srv == SECSuccess) {
   1411        MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized in r-o mode"));
   1412        return NS_OK;
   1413      }
   1414    }
   1415  }
   1416 #endif
   1417 
   1418  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("last-resort NSS_NoDB_Init"));
   1419  srv = NSS_NoDB_Init(nullptr);
   1420 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
   1421  if (srv != SECSuccess) {
   1422    MOZ_CRASH_UNSAFE_PRINTF("InitializeNSSWithFallbacks failed: %d",
   1423                            PR_GetError());
   1424  }
   1425 #endif
   1426  return srv == SECSuccess ? NS_OK : NS_ERROR_FAILURE;
   1427 }
   1428 
   1429 #if defined(NIGHTLY_BUILD) && !defined(ANDROID)
   1430 // dbType is either "cert9.db" or "key4.db"
   1431 void UnmigrateOneCertDB(const nsCOMPtr<nsIFile>& profileDirectory,
   1432                        const nsACString& dbType) {
   1433  nsCOMPtr<nsIFile> dbFile;
   1434  nsresult rv = profileDirectory->Clone(getter_AddRefs(dbFile));
   1435  if (NS_FAILED(rv)) {
   1436    return;
   1437  }
   1438  rv = dbFile->AppendNative(dbType);
   1439  if (NS_FAILED(rv)) {
   1440    return;
   1441  }
   1442  bool exists;
   1443  rv = dbFile->Exists(&exists);
   1444  if (NS_FAILED(rv)) {
   1445    return;
   1446  }
   1447  // If the unprefixed DB already exists, don't overwrite it.
   1448  if (exists) {
   1449    return;
   1450  }
   1451  nsCOMPtr<nsIFile> prefixedDBFile;
   1452  rv = profileDirectory->Clone(getter_AddRefs(prefixedDBFile));
   1453  if (NS_FAILED(rv)) {
   1454    return;
   1455  }
   1456  nsAutoCString prefixedDBName("gecko-no-share-");
   1457  prefixedDBName.Append(dbType);
   1458  rv = prefixedDBFile->AppendNative(prefixedDBName);
   1459  if (NS_FAILED(rv)) {
   1460    return;
   1461  }
   1462  (void)prefixedDBFile->MoveToNative(nullptr, dbType);
   1463 }
   1464 
   1465 void UnmigrateFromPrefixedCertDBs() {
   1466  nsCOMPtr<nsIFile> profileDirectory;
   1467  nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
   1468                                       getter_AddRefs(profileDirectory));
   1469  if (NS_FAILED(rv)) {
   1470    return;
   1471  }
   1472  UnmigrateOneCertDB(profileDirectory, "cert9.db"_ns);
   1473  UnmigrateOneCertDB(profileDirectory, "key4.db"_ns);
   1474 }
   1475 #endif  // defined(NIGHTLY_BUILD) && !defined(ANDROID)
   1476 
   1477 nsresult nsNSSComponent::InitializeNSS() {
   1478  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::InitializeNSS\n"));
   1479  AUTO_PROFILER_LABEL("nsNSSComponent::InitializeNSS", OTHER);
   1480  AUTO_PROFILER_MARKER("nsNSSComponent::InitializeNSS", OTHER);
   1481 
   1482  static_assert(
   1483      nsINSSErrorsService::NSS_SEC_ERROR_BASE == SEC_ERROR_BASE &&
   1484          nsINSSErrorsService::NSS_SEC_ERROR_LIMIT == SEC_ERROR_LIMIT &&
   1485          nsINSSErrorsService::NSS_SSL_ERROR_BASE == SSL_ERROR_BASE &&
   1486          nsINSSErrorsService::NSS_SSL_ERROR_LIMIT == SSL_ERROR_LIMIT,
   1487      "You must update the values in nsINSSErrorsService.idl");
   1488 
   1489  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("NSS Initialization beginning\n"));
   1490 
   1491  nsAutoCString profileStr;
   1492  nsresult rv = GetNSSProfilePath(profileStr);
   1493  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
   1494  if (NS_FAILED(rv)) {
   1495    return NS_ERROR_NOT_AVAILABLE;
   1496  }
   1497 
   1498 #if defined(NIGHTLY_BUILD) && !defined(ANDROID)
   1499  if (!profileStr.IsEmpty()) {
   1500    UnmigrateFromPrefixedCertDBs();
   1501  }
   1502 #endif
   1503 
   1504 #if defined(XP_WIN) || (defined(XP_LINUX) && !defined(ANDROID))
   1505  SetNSSDatabaseCacheModeAsAppropriate();
   1506 #endif
   1507 
   1508  bool nocertdb = StaticPrefs::security_nocertdb_AtStartup();
   1509  bool inSafeMode = true;
   1510  nsCOMPtr<nsIXULRuntime> runtime(do_GetService("@mozilla.org/xre/runtime;1"));
   1511  // There might not be an nsIXULRuntime in embedded situations. This will
   1512  // default to assuming we are in safe mode (as a result, no external PKCS11
   1513  // modules will be loaded).
   1514  if (runtime) {
   1515    rv = runtime->GetInSafeMode(&inSafeMode);
   1516    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
   1517    if (NS_FAILED(rv)) {
   1518      return rv;
   1519    }
   1520  }
   1521  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("inSafeMode: %u\n", inSafeMode));
   1522 
   1523  rv = InitializeNSSWithFallbacks(profileStr, nocertdb, inSafeMode);
   1524  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
   1525  if (NS_FAILED(rv)) {
   1526    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to initialize NSS"));
   1527    return rv;
   1528  }
   1529 
   1530  PK11_SetPasswordFunc(PK11PasswordPrompt);
   1531 
   1532  // Register an observer so we can inform NSS when these prefs change
   1533  Preferences::AddStrongObserver(this, "security.");
   1534 
   1535  rv = CommonInit();
   1536 
   1537  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
   1538  if (NS_FAILED(rv)) {
   1539    return NS_ERROR_UNEXPECTED;
   1540  }
   1541 
   1542  nsCOMPtr<nsICertOverrideService> certOverrideService(
   1543      do_GetService(NS_CERTOVERRIDE_CONTRACTID));
   1544  nsCOMPtr<nsIClientAuthRememberService> clientAuthRememberService(
   1545      do_GetService(NS_CLIENTAUTHREMEMBERSERVICE_CONTRACTID));
   1546  nsCOMPtr<nsISiteSecurityService> siteSecurityService(
   1547      do_GetService(NS_SSSERVICE_CONTRACTID));
   1548  nsCOMPtr<nsICertStorage> certStorage(do_GetService(NS_CERT_STORAGE_CID));
   1549 
   1550  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("NSS Initialization done\n"));
   1551 
   1552  {
   1553    MutexAutoLock lock(mMutex);
   1554 
   1555    // ensure we have initial values for various root hashes
   1556 #ifdef DEBUG
   1557    mTestBuiltInRootHash.Truncate();
   1558    Preferences::GetCString("security.test.built_in_root_hash",
   1559                            mTestBuiltInRootHash);
   1560 #endif
   1561    mMitmCanaryIssuer.Truncate();
   1562    Preferences::GetString("security.pki.mitm_canary_issuer",
   1563                           mMitmCanaryIssuer);
   1564    mMitmDetecionEnabled =
   1565        Preferences::GetBool("security.pki.mitm_canary_issuer.enabled", true);
   1566 
   1567    // Set dynamic options from prefs.
   1568    setValidationOptions(lock);
   1569 
   1570    bool importEnterpriseRoots =
   1571        StaticPrefs::security_enterprise_roots_enabled();
   1572 
   1573    nsAutoCString greBinDir;
   1574    rv = GetDirectoryPath(NS_GRE_BIN_DIR, greBinDir);
   1575    if (NS_FAILED(rv)) {
   1576      return rv;
   1577    }
   1578 
   1579    RefPtr<LoadLoadableCertsTask> loadLoadableCertsTask(
   1580        new LoadLoadableCertsTask(this, importEnterpriseRoots,
   1581                                  std::move(greBinDir)));
   1582    rv = loadLoadableCertsTask->Dispatch();
   1583    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
   1584    if (NS_FAILED(rv)) {
   1585      return rv;
   1586    }
   1587 
   1588    return NS_OK;
   1589  }
   1590 }
   1591 
   1592 void nsNSSComponent::PrepareForShutdown() {
   1593  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::PrepareForShutdown"));
   1594  MOZ_RELEASE_ASSERT(NS_IsMainThread());
   1595 
   1596  PK11_SetPasswordFunc((PK11PasswordFunc) nullptr);
   1597 
   1598  Preferences::RemoveObserver(this, "security.");
   1599 
   1600  // Release the default CertVerifier. This will cause any held NSS resources
   1601  // to be released.
   1602  {
   1603    MutexAutoLock lock(mMutex);
   1604    mDefaultCertVerifier = nullptr;
   1605  }
   1606 
   1607  // Unload osclientcerts so it drops any held resources and stops its
   1608  // background thread.
   1609  AsyncLoadOrUnloadOSClientCertsModule(false);
   1610 
   1611  // We don't actually shut down NSS - XPCOM does, after all threads have been
   1612  // joined and the component manager has been shut down (and so there shouldn't
   1613  // be any XPCOM objects holding NSS resources).
   1614 }
   1615 
   1616 nsresult nsNSSComponent::Init() {
   1617  MOZ_RELEASE_ASSERT(NS_IsMainThread());
   1618  if (!NS_IsMainThread()) {
   1619    return NS_ERROR_NOT_SAME_THREAD;
   1620  }
   1621 
   1622  MOZ_ASSERT(XRE_IsParentProcess());
   1623  if (!XRE_IsParentProcess()) {
   1624    return NS_ERROR_NOT_AVAILABLE;
   1625  }
   1626 
   1627  AutoGleanTimer<&glean::networking::nss_initialization> timer;
   1628 
   1629  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Beginning NSS initialization\n"));
   1630 
   1631  nsresult rv = InitializeNSS();
   1632  if (NS_FAILED(rv)) {
   1633    MOZ_LOG(gPIPNSSLog, LogLevel::Error,
   1634            ("nsNSSComponent::InitializeNSS() failed\n"));
   1635    return rv;
   1636  }
   1637 
   1638  rv = RegisterObservers();
   1639  if (NS_FAILED(rv)) {
   1640    return rv;
   1641  }
   1642 
   1643  return NS_OK;
   1644 }
   1645 
   1646 // nsISupports Implementation for the class
   1647 NS_IMPL_ISUPPORTS(nsNSSComponent, nsINSSComponent, nsIObserver)
   1648 
   1649 static const char* const PROFILE_BEFORE_CHANGE_TOPIC = "profile-before-change";
   1650 
   1651 NS_IMETHODIMP
   1652 nsNSSComponent::Observe(nsISupports* aSubject, const char* aTopic,
   1653                        const char16_t* someData) {
   1654  // In some tests, we don't receive a "profile-before-change" topic. However,
   1655  // we still have to shut down before the storage service shuts down, because
   1656  // closing the sql-backed softoken requires sqlite still be available. Thus,
   1657  // we observe "xpcom-shutdown" just in case.
   1658  if (nsCRT::strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC) == 0 ||
   1659      nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
   1660    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   1661            ("receiving profile change or XPCOM shutdown notification"));
   1662    PrepareForShutdown();
   1663  } else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
   1664    bool clearSessionCache = true;
   1665    NS_ConvertUTF16toUTF8 prefName(someData);
   1666 
   1667    if (HandleTLSPrefChange(prefName)) {
   1668      MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("HandleTLSPrefChange done"));
   1669    } else if (
   1670        prefName.EqualsLiteral("security.OCSP.enabled") ||
   1671        prefName.EqualsLiteral("security.OCSP.require") ||
   1672        prefName.EqualsLiteral("security.pki.cert_short_lifetime_in_days") ||
   1673        prefName.EqualsLiteral("security.ssl.enable_ocsp_stapling") ||
   1674        prefName.EqualsLiteral("security.ssl.enable_ocsp_must_staple") ||
   1675        prefName.EqualsLiteral("security.pki.certificate_transparency.mode") ||
   1676        prefName.EqualsLiteral(
   1677            "security.pki.certificate_transparency.disable_for_hosts") ||
   1678        prefName.EqualsLiteral(
   1679            "security.pki.certificate_transparency.disable_for_spki_hashes") ||
   1680        prefName.EqualsLiteral("security.OCSP.timeoutMilliseconds.soft") ||
   1681        prefName.EqualsLiteral("security.OCSP.timeoutMilliseconds.hard") ||
   1682        prefName.EqualsLiteral("security.pki.crlite_mode")) {
   1683      MutexAutoLock lock(mMutex);
   1684      setValidationOptions(lock);
   1685 #ifdef DEBUG
   1686    } else if (prefName.EqualsLiteral("security.test.built_in_root_hash")) {
   1687      MutexAutoLock lock(mMutex);
   1688      mTestBuiltInRootHash.Truncate();
   1689      Preferences::GetCString("security.test.built_in_root_hash",
   1690                              mTestBuiltInRootHash);
   1691 #endif  // DEBUG
   1692    } else if (prefName.Equals("security.enterprise_roots.enabled")) {
   1693      UnloadEnterpriseRoots();
   1694      MaybeImportEnterpriseRoots();
   1695    } else if (prefName.Equals("security.osclientcerts.autoload")) {
   1696      bool loadOSClientCertsModule =
   1697          StaticPrefs::security_osclientcerts_autoload();
   1698      AsyncLoadOrUnloadOSClientCertsModule(loadOSClientCertsModule);
   1699    } else if (prefName.EqualsLiteral("security.pki.mitm_canary_issuer")) {
   1700      MutexAutoLock lock(mMutex);
   1701      mMitmCanaryIssuer.Truncate();
   1702      Preferences::GetString("security.pki.mitm_canary_issuer",
   1703                             mMitmCanaryIssuer);
   1704    } else if (prefName.EqualsLiteral(
   1705                   "security.pki.mitm_canary_issuer.enabled")) {
   1706      MutexAutoLock lock(mMutex);
   1707      mMitmDetecionEnabled =
   1708          Preferences::GetBool("security.pki.mitm_canary_issuer.enabled", true);
   1709    } else {
   1710      clearSessionCache = false;
   1711    }
   1712    if (clearSessionCache) {
   1713      ClearSSLExternalAndInternalSessionCache();
   1714    }
   1715  } else if (!nsCRT::strcmp(aTopic, "last-pb-context-exited")) {
   1716    nsNSSComponent::DoClearSSLExternalAndInternalSessionCache();
   1717  }
   1718 
   1719  return NS_OK;
   1720 }
   1721 
   1722 /*static*/
   1723 nsresult nsNSSComponent::GetNewPrompter(nsIPrompt** result) {
   1724  NS_ENSURE_ARG_POINTER(result);
   1725  *result = nullptr;
   1726 
   1727  if (!NS_IsMainThread()) {
   1728    NS_ERROR("nsSDRContext::GetNewPrompter called off the main thread");
   1729    return NS_ERROR_NOT_SAME_THREAD;
   1730  }
   1731 
   1732  nsresult rv;
   1733  nsCOMPtr<nsIWindowWatcher> wwatch(
   1734      do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
   1735  NS_ENSURE_SUCCESS(rv, rv);
   1736 
   1737  rv = wwatch->GetNewPrompter(0, result);
   1738  NS_ENSURE_SUCCESS(rv, rv);
   1739 
   1740  return rv;
   1741 }
   1742 
   1743 nsresult nsNSSComponent::LogoutAuthenticatedPK11() {
   1744  ClearSSLExternalAndInternalSessionCache();
   1745 
   1746  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   1747  if (os) {
   1748    os->NotifyObservers(nullptr, "net:cancel-all-connections", nullptr);
   1749  }
   1750 
   1751  return NS_OK;
   1752 }
   1753 
   1754 nsresult nsNSSComponent::RegisterObservers() {
   1755  nsCOMPtr<nsIObserverService> observerService(
   1756      do_GetService("@mozilla.org/observer-service;1"));
   1757  if (!observerService) {
   1758    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   1759            ("nsNSSComponent: couldn't get observer service\n"));
   1760    return NS_ERROR_FAILURE;
   1761  }
   1762 
   1763  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent: adding observers\n"));
   1764  // Using false for the ownsweak parameter means the observer service will
   1765  // keep a strong reference to this component. As a result, this will live at
   1766  // least as long as the observer service.
   1767  observerService->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
   1768  observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
   1769  observerService->AddObserver(this, "last-pb-context-exited", false);
   1770 
   1771  return NS_OK;
   1772 }
   1773 
   1774 nsresult DoesCertMatchFingerprint(const nsTArray<uint8_t>& cert,
   1775                                  const nsCString& fingerprint, bool& result) {
   1776  result = false;
   1777 
   1778  if (cert.Length() > std::numeric_limits<uint32_t>::max()) {
   1779    return NS_ERROR_INVALID_ARG;
   1780  }
   1781  nsTArray<uint8_t> digestArray;
   1782  nsresult rv = Digest::DigestBuf(SEC_OID_SHA256, cert.Elements(),
   1783                                  cert.Length(), digestArray);
   1784  if (NS_FAILED(rv)) {
   1785    return rv;
   1786  }
   1787  SECItem digestItem = {siBuffer, digestArray.Elements(),
   1788                        static_cast<unsigned int>(digestArray.Length())};
   1789  UniquePORTString certFingerprint(
   1790      CERT_Hexify(&digestItem, true /* use colon delimiters */));
   1791  if (!certFingerprint) {
   1792    return NS_ERROR_FAILURE;
   1793  }
   1794 
   1795  result = fingerprint.Equals(certFingerprint.get());
   1796  return NS_OK;
   1797 }
   1798 
   1799 NS_IMETHODIMP
   1800 nsNSSComponent::IsCertTestBuiltInRoot(const nsTArray<uint8_t>& cert,
   1801                                      bool* result) {
   1802  NS_ENSURE_ARG_POINTER(result);
   1803  *result = false;
   1804 
   1805 #ifdef DEBUG
   1806  MutexAutoLock lock(mMutex);
   1807  nsresult rv = DoesCertMatchFingerprint(cert, mTestBuiltInRootHash, *result);
   1808  if (NS_FAILED(rv)) {
   1809    return rv;
   1810  }
   1811 #endif  // DEBUG
   1812 
   1813  return NS_OK;
   1814 }
   1815 
   1816 NS_IMETHODIMP
   1817 nsNSSComponent::IssuerMatchesMitmCanary(const char* aCertIssuer) {
   1818  MutexAutoLock lock(mMutex);
   1819  if (mMitmDetecionEnabled && !mMitmCanaryIssuer.IsEmpty()) {
   1820    nsString certIssuer = NS_ConvertUTF8toUTF16(aCertIssuer);
   1821    if (mMitmCanaryIssuer.Equals(certIssuer)) {
   1822      return NS_OK;
   1823    }
   1824  }
   1825 
   1826  return NS_ERROR_FAILURE;
   1827 }
   1828 
   1829 SharedCertVerifier::~SharedCertVerifier() = default;
   1830 
   1831 NS_IMETHODIMP
   1832 nsNSSComponent::GetDefaultCertVerifier(SharedCertVerifier** result) {
   1833  MutexAutoLock lock(mMutex);
   1834  NS_ENSURE_ARG_POINTER(result);
   1835  RefPtr<SharedCertVerifier> certVerifier(mDefaultCertVerifier);
   1836  certVerifier.forget(result);
   1837  return NS_OK;
   1838 }
   1839 
   1840 // static
   1841 void nsNSSComponent::DoClearSSLExternalAndInternalSessionCache() {
   1842  SSL_ClearSessionCache();
   1843  mozilla::net::SSLTokensCache::Clear();
   1844 }
   1845 
   1846 NS_IMETHODIMP
   1847 nsNSSComponent::ClearSSLExternalAndInternalSessionCache() {
   1848  MOZ_ASSERT(XRE_IsParentProcess());
   1849  if (!XRE_IsParentProcess()) {
   1850    return NS_ERROR_NOT_AVAILABLE;
   1851  }
   1852 
   1853  if (mozilla::net::nsIOService::UseSocketProcess()) {
   1854    if (mozilla::net::gIOService) {
   1855      mozilla::net::gIOService->CallOrWaitForSocketProcess([]() {
   1856        RefPtr<mozilla::net::SocketProcessParent> socketParent =
   1857            mozilla::net::SocketProcessParent::GetSingleton();
   1858        (void)socketParent->SendClearSessionCache();
   1859      });
   1860    }
   1861  }
   1862  DoClearSSLExternalAndInternalSessionCache();
   1863  return NS_OK;
   1864 }
   1865 
   1866 NS_IMETHODIMP
   1867 nsNSSComponent::AsyncClearSSLExternalAndInternalSessionCache(
   1868    JSContext* aCx, ::mozilla::dom::Promise** aPromise) {
   1869  MOZ_ASSERT(XRE_IsParentProcess());
   1870  if (!XRE_IsParentProcess()) {
   1871    return NS_ERROR_NOT_AVAILABLE;
   1872  }
   1873 
   1874  nsIGlobalObject* globalObject = xpc::CurrentNativeGlobal(aCx);
   1875  if (NS_WARN_IF(!globalObject)) {
   1876    return NS_ERROR_FAILURE;
   1877  }
   1878 
   1879  ErrorResult result;
   1880  RefPtr<mozilla::dom::Promise> promise =
   1881      mozilla::dom::Promise::Create(globalObject, result);
   1882  if (NS_WARN_IF(result.Failed())) {
   1883    return result.StealNSResult();
   1884  }
   1885 
   1886  if (mozilla::net::nsIOService::UseSocketProcess() &&
   1887      mozilla::net::gIOService) {
   1888    mozilla::net::gIOService->CallOrWaitForSocketProcess([p = RefPtr{
   1889                                                              promise}]() {
   1890      RefPtr<mozilla::net::SocketProcessParent> socketParent =
   1891          mozilla::net::SocketProcessParent::GetSingleton();
   1892      (void)socketParent->SendClearSessionCache()->Then(
   1893          GetCurrentSerialEventTarget(), __func__,
   1894          [promise = RefPtr{p}] { promise->MaybeResolveWithUndefined(); },
   1895          [promise = RefPtr{p}] { promise->MaybeReject(NS_ERROR_UNEXPECTED); });
   1896    });
   1897  } else {
   1898    promise->MaybeResolveWithUndefined();
   1899  }
   1900  DoClearSSLExternalAndInternalSessionCache();
   1901  promise.forget(aPromise);
   1902  return NS_OK;
   1903 }
   1904 
   1905 Atomic<bool> sSearchingForClientAuthCertificates{false};
   1906 
   1907 extern "C" {
   1908 // Returns true once if gecko is searching for client authentication
   1909 // certificates (i.e., if some thread has an
   1910 // AutoSearchingForClientAuthCertificates on the stack).
   1911 // The idea is when gecko instantiates an
   1912 // AutoSearchingForClientAuthCertificates, sSearchingForClientAuthCertificates
   1913 // will get set to true. Some thread running some NSS code will result in a
   1914 // call to IsGeckoSearchingForClientAuthCertificates(), which will essentially
   1915 // claim the search by swapping the value for false. The search will happen,
   1916 // but for the rest of the lifetime of the
   1917 // AutoSearchingForClientAuthCertificates, this function will return false,
   1918 // meaning no other threads will also cause searches to happen.
   1919 bool IsGeckoSearchingForClientAuthCertificates() {
   1920  return sSearchingForClientAuthCertificates.exchange(false);
   1921 }
   1922 }
   1923 
   1924 AutoSearchingForClientAuthCertificates::
   1925    AutoSearchingForClientAuthCertificates() {
   1926  sSearchingForClientAuthCertificates = true;
   1927 }
   1928 
   1929 AutoSearchingForClientAuthCertificates::
   1930    ~AutoSearchingForClientAuthCertificates() {
   1931  sSearchingForClientAuthCertificates = false;
   1932 }
   1933 
   1934 namespace mozilla {
   1935 namespace psm {
   1936 
   1937 already_AddRefed<SharedCertVerifier> GetDefaultCertVerifier() {
   1938  static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
   1939 
   1940  nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID));
   1941  if (!nssComponent) {
   1942    return nullptr;
   1943  }
   1944  nsresult rv = nssComponent->BlockUntilLoadableCertsLoaded();
   1945  if (NS_FAILED(rv)) {
   1946    return nullptr;
   1947  }
   1948  RefPtr<SharedCertVerifier> result;
   1949  rv = nssComponent->GetDefaultCertVerifier(getter_AddRefs(result));
   1950  if (NS_FAILED(rv)) {
   1951    return nullptr;
   1952  }
   1953  return result.forget();
   1954 }
   1955 
   1956 // Helper for FindClientCertificatesWithPrivateKeys. Copies all
   1957 // CERTCertificates from `from` to `to`.
   1958 static inline void CopyCertificatesTo(UniqueCERTCertList& from,
   1959                                      UniqueCERTCertList& to) {
   1960  MOZ_ASSERT(from);
   1961  MOZ_ASSERT(to);
   1962  for (CERTCertListNode* n = CERT_LIST_HEAD(from.get());
   1963       !CERT_LIST_END(n, from.get()); n = CERT_LIST_NEXT(n)) {
   1964    UniqueCERTCertificate cert(CERT_DupCertificate(n->cert));
   1965    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   1966            ("      provisionally adding '%s'", n->cert->subjectName));
   1967    if (CERT_AddCertToListTail(to.get(), cert.get()) == SECSuccess) {
   1968      (void)cert.release();
   1969    }
   1970  }
   1971 }
   1972 
   1973 // Lists all private keys on all modules and returns a list of any corresponding
   1974 // client certificates. Returns an empty list if no such certificates can be
   1975 // found. Returns null if an error is encountered.
   1976 UniqueCERTCertList FindClientCertificatesWithPrivateKeys() {
   1977  MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   1978          ("FindClientCertificatesWithPrivateKeys"));
   1979  AutoSearchingForClientAuthCertificates _;
   1980 
   1981  (void)BlockUntilLoadableCertsLoaded();
   1982  (void)CheckForSmartCardChanges();
   1983 
   1984  UniqueCERTCertList certsWithPrivateKeys(CERT_NewCertList());
   1985  if (!certsWithPrivateKeys) {
   1986    return nullptr;
   1987  }
   1988 
   1989  UniquePK11SlotInfo internalSlot(PK11_GetInternalKeySlot());
   1990 
   1991  AutoSECMODListReadLock secmodLock;
   1992  SECMODModuleList* list = SECMOD_GetDefaultModuleList();
   1993  while (list) {
   1994    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   1995            ("  module '%s'", list->module->commonName));
   1996    for (int i = 0; i < list->module->slotCount; i++) {
   1997      PK11SlotInfo* slot = list->module->slots[i];
   1998      MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   1999              ("    slot '%s'", PK11_GetSlotName(slot)));
   2000      // If this is the internal certificate/key slot or the slot on the
   2001      // builtin roots module, there may be many more certificates than private
   2002      // keys, so search by private keys (PK11_HasRootCerts will be true if the
   2003      // slot contains an object with the vendor-specific CK_CLASS
   2004      // CKO_NSS_BUILTIN_ROOT_LIST, which should only be the case for the NSS
   2005      // builtin roots module).
   2006      if (internalSlot.get() == slot || PK11_HasRootCerts(slot)) {
   2007        MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   2008                ("    (looking at internal/builtin slot)"));
   2009        if (PK11_Authenticate(slot, true, nullptr) != SECSuccess) {
   2010          MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("    (couldn't authenticate)"));
   2011          continue;
   2012        }
   2013        UniqueSECKEYPrivateKeyList privateKeys(
   2014            PK11_ListPrivKeysInSlot(slot, nullptr, nullptr));
   2015        if (!privateKeys) {
   2016          MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("      (no private keys)"));
   2017          continue;
   2018        }
   2019        for (SECKEYPrivateKeyListNode* node = PRIVKEY_LIST_HEAD(privateKeys);
   2020             !PRIVKEY_LIST_END(node, privateKeys);
   2021             node = PRIVKEY_LIST_NEXT(node)) {
   2022          UniqueCERTCertList certs(PK11_GetCertsMatchingPrivateKey(node->key));
   2023          if (!certs) {
   2024            MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   2025                    ("      PK11_GetCertsMatchingPrivateKey encountered an "
   2026                     "error "));
   2027            continue;
   2028          }
   2029          if (CERT_LIST_EMPTY(certs)) {
   2030            MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("      (no certs for key)"));
   2031            continue;
   2032          }
   2033          CopyCertificatesTo(certs, certsWithPrivateKeys);
   2034        }
   2035      } else {
   2036        // ... otherwise, optimistically assume that searching by certificate
   2037        // won't take too much time. Since "friendly" slots expose certificates
   2038        // without needing to be authenticated to, this results in fewer PIN
   2039        // dialogs shown to the user.
   2040        MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   2041                ("    (looking at non-internal slot)"));
   2042 
   2043        if (!PK11_IsPresent(slot)) {
   2044          MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("    (not present)"));
   2045          continue;
   2046        }
   2047        // If this isn't a "friendly" slot, authenticate to expose certificates.
   2048        if (!PK11_IsFriendly(slot) &&
   2049            PK11_Authenticate(slot, true, nullptr) != SECSuccess) {
   2050          MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("    (couldn't authenticate)"));
   2051          continue;
   2052        }
   2053        UniqueCERTCertList certsInSlot(PK11_ListCertsInSlot(slot));
   2054        if (!certsInSlot) {
   2055          MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   2056                  ("      (couldn't list certs in slot)"));
   2057          continue;
   2058        }
   2059        // When NSS decodes a certificate, if that certificate has a
   2060        // corresponding private key (or public key, if the slot it's on hasn't
   2061        // been logged into), it notes it as a "user cert".
   2062        if (CERT_FilterCertListForUserCerts(certsInSlot.get()) != SECSuccess) {
   2063          MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   2064                  ("      (couldn't filter certs)"));
   2065          continue;
   2066        }
   2067        CopyCertificatesTo(certsInSlot, certsWithPrivateKeys);
   2068      }
   2069    }
   2070    list = list->next;
   2071  }
   2072 
   2073  if (CERT_FilterCertListByUsage(certsWithPrivateKeys.get(), certUsageSSLClient,
   2074                                 false) != SECSuccess) {
   2075    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
   2076            ("  CERT_FilterCertListByUsage encountered an error - returning"));
   2077    return nullptr;
   2078  }
   2079 
   2080  if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPIPNSSLog, LogLevel::Debug))) {
   2081    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("  returning:"));
   2082    for (CERTCertListNode* n = CERT_LIST_HEAD(certsWithPrivateKeys);
   2083         !CERT_LIST_END(n, certsWithPrivateKeys); n = CERT_LIST_NEXT(n)) {
   2084      MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("    %s", n->cert->subjectName));
   2085    }
   2086  }
   2087 
   2088  return certsWithPrivateKeys;
   2089 }
   2090 
   2091 CertVerifier::CertificateTransparencyMode GetCertificateTransparencyMode() {
   2092  const CertVerifier::CertificateTransparencyMode defaultCTMode =
   2093      CertVerifier::CertificateTransparencyMode::TelemetryOnly;
   2094  CertVerifier::CertificateTransparencyMode ctMode =
   2095      static_cast<CertVerifier::CertificateTransparencyMode>(
   2096          StaticPrefs::security_pki_certificate_transparency_mode());
   2097  switch (ctMode) {
   2098    case CertVerifier::CertificateTransparencyMode::Disabled:
   2099    case CertVerifier::CertificateTransparencyMode::TelemetryOnly:
   2100    case CertVerifier::CertificateTransparencyMode::Enforce:
   2101      break;
   2102    default:
   2103      ctMode = defaultCTMode;
   2104      break;
   2105  }
   2106  return ctMode;
   2107 }
   2108 
   2109 }  // namespace psm
   2110 }  // namespace mozilla
   2111 
   2112 NS_IMPL_ISUPPORTS(PipUIContext, nsIInterfaceRequestor)
   2113 
   2114 PipUIContext::PipUIContext() = default;
   2115 
   2116 PipUIContext::~PipUIContext() = default;
   2117 
   2118 NS_IMETHODIMP
   2119 PipUIContext::GetInterface(const nsIID& uuid, void** result) {
   2120  NS_ENSURE_ARG_POINTER(result);
   2121  *result = nullptr;
   2122 
   2123  if (!NS_IsMainThread()) {
   2124    NS_ERROR("PipUIContext::GetInterface called off the main thread");
   2125    return NS_ERROR_NOT_SAME_THREAD;
   2126  }
   2127 
   2128  if (!uuid.Equals(NS_GET_IID(nsIPrompt))) return NS_ERROR_NO_INTERFACE;
   2129 
   2130  nsIPrompt* prompt = nullptr;
   2131  nsresult rv = nsNSSComponent::GetNewPrompter(&prompt);
   2132  *result = prompt;
   2133  return rv;
   2134 }
   2135 
   2136 nsresult getNSSDialogs(void** _result, REFNSIID aIID, const char* contract) {
   2137  if (!NS_IsMainThread()) {
   2138    NS_ERROR("getNSSDialogs called off the main thread");
   2139    return NS_ERROR_NOT_SAME_THREAD;
   2140  }
   2141 
   2142  nsresult rv;
   2143 
   2144  nsCOMPtr<nsISupports> svc = do_GetService(contract, &rv);
   2145  if (NS_FAILED(rv)) {
   2146    return rv;
   2147  }
   2148 
   2149  rv = svc->QueryInterface(aIID, _result);
   2150 
   2151  return rv;
   2152 }
   2153 
   2154 nsresult setPassword(PK11SlotInfo* slot, nsIInterfaceRequestor* ctx) {
   2155  MOZ_ASSERT(slot);
   2156  MOZ_ASSERT(ctx);
   2157  NS_ENSURE_ARG_POINTER(slot);
   2158  NS_ENSURE_ARG_POINTER(ctx);
   2159 
   2160  if (PK11_NeedUserInit(slot)) {
   2161    nsCOMPtr<nsITokenPasswordDialogs> dialogs;
   2162    nsresult rv = getNSSDialogs(getter_AddRefs(dialogs),
   2163                                NS_GET_IID(nsITokenPasswordDialogs),
   2164                                NS_TOKENPASSWORDSDIALOG_CONTRACTID);
   2165    if (NS_FAILED(rv)) {
   2166      return rv;
   2167    }
   2168 
   2169    bool canceled;
   2170    nsCOMPtr<nsIPK11Token> token = new nsPK11Token(slot);
   2171    rv = dialogs->SetPassword(ctx, token, &canceled);
   2172    if (NS_FAILED(rv)) {
   2173      return rv;
   2174    }
   2175 
   2176    if (canceled) {
   2177      return NS_ERROR_NOT_AVAILABLE;
   2178    }
   2179  }
   2180 
   2181  return NS_OK;
   2182 }
   2183 
   2184 static PRBool ConvertBetweenUCS2andASCII(PRBool toUnicode, unsigned char* inBuf,
   2185                                         unsigned int inBufLen,
   2186                                         unsigned char* outBuf,
   2187                                         unsigned int maxOutBufLen,
   2188                                         unsigned int* outBufLen,
   2189                                         PRBool swapBytes) {
   2190  std::unique_ptr<unsigned char[]> inBufDup(new unsigned char[inBufLen]);
   2191  if (!inBufDup) {
   2192    return PR_FALSE;
   2193  }
   2194  std::memcpy(inBufDup.get(), inBuf, inBufLen * sizeof(unsigned char));
   2195 
   2196  // If converting Unicode to ASCII, swap bytes before conversion as neccessary.
   2197  if (!toUnicode && swapBytes) {
   2198    if (inBufLen % 2 != 0) {
   2199      return PR_FALSE;
   2200    }
   2201    mozilla::NativeEndian::swapFromLittleEndianInPlace(
   2202        reinterpret_cast<char16_t*>(inBufDup.get()), inBufLen / 2);
   2203  }
   2204  return PORT_UCS2_UTF8Conversion(toUnicode, inBufDup.get(), inBufLen, outBuf,
   2205                                  maxOutBufLen, outBufLen);
   2206 }
   2207 
   2208 namespace mozilla {
   2209 namespace psm {
   2210 
   2211 nsresult InitializeCipherSuite() {
   2212  MOZ_ASSERT(NS_IsMainThread(),
   2213             "InitializeCipherSuite() can only be accessed on the main thread");
   2214 
   2215  if (NSS_SetDomesticPolicy() != SECSuccess) {
   2216    return NS_ERROR_FAILURE;
   2217  }
   2218 
   2219  // Disable any ciphers that NSS might have enabled by default
   2220  for (uint16_t i = 0; i < SSL_NumImplementedCiphers; ++i) {
   2221    uint16_t cipher_id = SSL_ImplementedCiphers[i];
   2222    SSL_CipherPrefSetDefault(cipher_id, false);
   2223  }
   2224 
   2225  // Now only set SSL/TLS ciphers we knew about at compile time
   2226  for (const auto& cipherPref : sCipherPrefs) {
   2227    SSL_CipherPrefSetDefault(cipherPref.id, cipherPref.prefGetter());
   2228  }
   2229 
   2230  SetDeprecatedTLS1CipherPrefs();
   2231 
   2232  // Enable ciphers for PKCS#12
   2233  SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
   2234  SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
   2235  SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
   2236  SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
   2237  SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
   2238  SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
   2239  SEC_PKCS12EnableCipher(PKCS12_AES_CBC_128, 1);
   2240  SEC_PKCS12EnableCipher(PKCS12_AES_CBC_192, 1);
   2241  SEC_PKCS12EnableCipher(PKCS12_AES_CBC_256, 1);
   2242  SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
   2243  PORT_SetUCS2_ASCIIConversionFunction(ConvertBetweenUCS2andASCII);
   2244 
   2245  // PSM enforces a minimum RSA key size of 1024 bits, which is overridable.
   2246  // NSS has its own minimum, which is not overridable (the default is 1023
   2247  // bits). This sets the NSS minimum to 512 bits so users can still connect to
   2248  // devices like wifi routers with woefully small keys (they would have to add
   2249  // an override to do so, but they already do for such devices).
   2250  NSS_OptionSet(NSS_RSA_MIN_KEY_SIZE, 512);
   2251 
   2252  SetKyberPolicy();
   2253 
   2254  // Observe preference change around cipher suite setting.
   2255  return CipherSuiteChangeObserver::StartObserve();
   2256 }
   2257 
   2258 }  // namespace psm
   2259 }  // namespace mozilla