1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */
7 #include "nsNSSComponent.h"
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"
18 #include "cert_storage/src/cert_storage.h"
20 #include "mozilla/AppShutdown.h"
21 #include "mozilla/ArrayUtils.h"
22 #include "mozilla/Assertions.h"
23 #include "mozilla/Base64.h"
24 #include "mozilla/Casting.h"
25 #include "mozilla/EndianUtils.h"
26 #include "mozilla/FilePreferences.h"
27 #include "mozilla/PodOperations.h"
28 #include "mozilla/Preferences.h"
29 #include "mozilla/ProfilerLabels.h"
30 #include "mozilla/ProfilerMarkers.h"
31 #include "mozilla/PublicSSL.h"
32 #include "mozilla/ScopeExit.h"
33 #include "mozilla/Services.h"
34 #include "mozilla/StaticMutex.h"
35 #include "mozilla/StaticPrefs_security.h"
36 #include "mozilla/StaticPtr.h"
37 #include "mozilla/SyncRunnable.h"
38 #include "mozilla/Telemetry.h"
39 #include "mozilla/TimeStamp.h"
40 #include "mozilla/Unused.h"
41 #include "mozilla/Vector.h"
42 #include "mozilla/dom/Promise.h"
43 #include "mozilla/net/SocketProcessParent.h"
44 #include "mozpkix/pkixnss.h"
45 #include "nsAppDirectoryServiceDefs.h"
47 #include "nsClientAuthRemember.h"
48 #include "nsComponentManagerUtils.h"
49 #include "nsDirectoryServiceDefs.h"
50 #include "nsICertOverrideService.h"
52 #include "nsIOService.h"
53 #include "nsIObserverService.h"
54 #include "nsIPrompt.h"
55 #include "nsIProperties.h"
56 #include "nsISerialEventTarget.h"
57 #include "nsISiteSecurityService.h"
59 #include "nsITokenPasswordDialogs.h"
60 #include "nsIWindowWatcher.h"
61 #include "nsIXULRuntime.h"
62 #include "nsLiteralString.h"
63 #include "nsNSSHelper.h"
64 #include "nsNSSIOLayer.h"
66 #include "nsPK11TokenDB.h"
67 #include "nsPrintfCString.h"
68 #include "nsServiceManagerUtils.h"
69 #include "nsThreadUtils.h"
70 #include "nsXULAppAPI.h"
81 #if defined(XP_LINUX) && !defined(ANDROID)
82 # include <linux/magic.h>
86 using namespace mozilla
;
87 using namespace mozilla::psm
;
89 LazyLogModule
gPIPNSSLog("pipnss");
91 int nsNSSComponent::mInstanceCount
= 0;
93 // Forward declaration.
94 nsresult
CommonInit();
96 template <const glean::impl::QuantityMetric
* metric
>
97 class MOZ_RAII AutoGleanTimer
{
99 explicit AutoGleanTimer(TimeStamp aStart
= TimeStamp::Now())
103 TimeStamp end
= TimeStamp::Now();
104 uint32_t delta
= static_cast<uint32_t>((end
- mStart
).ToMilliseconds());
109 const TimeStamp mStart
;
112 // Take an nsIFile and get a UTF-8-encoded c-string representation of the
113 // location of that file (encapsulated in an nsACString).
114 // This operation is generally to be avoided, except when interacting with
115 // third-party or legacy libraries that cannot handle `nsIFile`s (such as NSS).
116 // |result| is encoded in UTF-8.
117 nsresult
FileToCString(const nsCOMPtr
<nsIFile
>& file
, nsACString
& result
) {
120 nsresult rv
= file
->GetPath(path
);
121 if (NS_SUCCEEDED(rv
)) {
122 CopyUTF16toUTF8(path
, result
);
126 return file
->GetNativePath(result
);
130 void TruncateFromLastDirectorySeparator(nsCString
& path
) {
131 static const nsAutoCString
kSeparatorString(
132 mozilla::FilePreferences::kPathSeparator
);
133 int32_t index
= path
.RFind(kSeparatorString
);
134 if (index
== kNotFound
) {
137 path
.Truncate(index
);
140 bool LoadIPCClientCerts() {
141 // This returns the path to the binary currently running, which in most
142 // cases is "plugin-container".
143 UniqueFreePtr
<char> pluginContainerPath(BinaryPath::Get());
144 if (!pluginContainerPath
) {
145 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
146 ("failed to get get plugin-container path"));
149 nsAutoCString
ipcClientCertsDirString(pluginContainerPath
.get());
150 // On most platforms, ipcclientcerts is in the same directory as
151 // plugin-container. To obtain the path to that directory, truncate from
152 // the last directory separator.
153 // On macOS, plugin-container is in
154 // Firefox.app/Contents/MacOS/plugin-container.app/Contents/MacOS/,
155 // whereas ipcclientcerts is in Firefox.app/Contents/MacOS/. Consequently,
156 // this truncation from the last directory separator has to happen 4 times
157 // total. Normally this would be done using nsIFile APIs, but due to when
158 // this is initialized in the socket process, those aren't available.
159 TruncateFromLastDirectorySeparator(ipcClientCertsDirString
);
161 TruncateFromLastDirectorySeparator(ipcClientCertsDirString
);
162 TruncateFromLastDirectorySeparator(ipcClientCertsDirString
);
163 TruncateFromLastDirectorySeparator(ipcClientCertsDirString
);
165 if (!LoadIPCClientCertsModule(ipcClientCertsDirString
)) {
166 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
167 ("failed to load ipcclientcerts from '%s'",
168 ipcClientCertsDirString
.get()));
174 // This function can be called from chrome or content or socket processes
175 // to ensure that NSS is initialized.
176 bool EnsureNSSInitializedChromeOrContent() {
177 static Atomic
<bool> initialized(false);
183 // If this is not the main thread (i.e. probably a worker) then forward this
184 // call to the main thread.
185 if (!NS_IsMainThread()) {
186 nsCOMPtr
<nsIThread
> mainThread
;
187 nsresult rv
= NS_GetMainThread(getter_AddRefs(mainThread
));
192 // Forward to the main thread synchronously.
193 mozilla::SyncRunnable::DispatchToThread(
195 NS_NewRunnableFunction("EnsureNSSInitializedChromeOrContent", []() {
196 EnsureNSSInitializedChromeOrContent();
202 if (XRE_IsParentProcess()) {
203 nsCOMPtr
<nsISupports
> nss
= do_GetService(PSM_COMPONENT_CONTRACTID
);
211 if (NSS_IsInitialized()) {
216 if (NSS_NoDB_Init(nullptr) != SECSuccess
) {
220 if (XRE_IsSocketProcess()) {
221 if (NS_FAILED(CommonInit())) {
224 // If ipcclientcerts fails to load, client certificate authentication won't
225 // work (if networking is done on the socket process). This is preferable
226 // to stopping the program entirely, so treat this as best-effort.
227 Unused
<< NS_WARN_IF(!LoadIPCClientCerts());
232 if (NS_FAILED(mozilla::psm::InitializeCipherSuite())) {
236 mozilla::psm::DisableMD5();
237 mozilla::pkix::RegisterErrorTable();
242 static const uint32_t OCSP_TIMEOUT_MILLISECONDS_SOFT_MAX
= 5000;
243 static const uint32_t OCSP_TIMEOUT_MILLISECONDS_HARD_MAX
= 20000;
245 void nsNSSComponent::GetRevocationBehaviorFromPrefs(
246 /*out*/ CertVerifier::OcspDownloadConfig
* odc
,
247 /*out*/ CertVerifier::OcspStrictConfig
* osc
,
248 /*out*/ uint32_t* certShortLifetimeInDays
,
249 /*out*/ TimeDuration
& softTimeout
,
250 /*out*/ TimeDuration
& hardTimeout
) {
251 MOZ_ASSERT(NS_IsMainThread());
254 MOZ_ASSERT(certShortLifetimeInDays
);
257 // 1 = enabled for everything (default)
258 // 2 = enabled for EV certificates only
259 uint32_t ocspLevel
= StaticPrefs::security_OCSP_enabled();
262 *odc
= CertVerifier::ocspOff
;
265 *odc
= CertVerifier::ocspEVOnly
;
268 *odc
= CertVerifier::ocspOn
;
272 *osc
= StaticPrefs::security_OCSP_require() ? CertVerifier::ocspStrict
273 : CertVerifier::ocspRelaxed
;
275 *certShortLifetimeInDays
=
276 StaticPrefs::security_pki_cert_short_lifetime_in_days();
278 uint32_t softTimeoutMillis
=
279 StaticPrefs::security_OCSP_timeoutMilliseconds_soft();
281 std::min(softTimeoutMillis
, OCSP_TIMEOUT_MILLISECONDS_SOFT_MAX
);
282 softTimeout
= TimeDuration::FromMilliseconds(softTimeoutMillis
);
284 uint32_t hardTimeoutMillis
=
285 StaticPrefs::security_OCSP_timeoutMilliseconds_hard();
287 std::min(hardTimeoutMillis
, OCSP_TIMEOUT_MILLISECONDS_HARD_MAX
);
288 hardTimeout
= TimeDuration::FromMilliseconds(hardTimeoutMillis
);
291 nsNSSComponent::nsNSSComponent()
292 : mLoadableCertsLoadedMonitor("nsNSSComponent.mLoadableCertsLoadedMonitor"),
293 mLoadableCertsLoaded(false),
294 mLoadableCertsLoadedResult(NS_ERROR_FAILURE
),
295 mMutex("nsNSSComponent.mMutex"),
296 mMitmDetecionEnabled(false) {
297 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("nsNSSComponent::ctor\n"));
298 MOZ_RELEASE_ASSERT(NS_IsMainThread());
300 MOZ_ASSERT(mInstanceCount
== 0,
301 "nsNSSComponent is a singleton, but instantiated multiple times!");
305 nsNSSComponent::~nsNSSComponent() {
306 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("nsNSSComponent::dtor\n"));
307 MOZ_RELEASE_ASSERT(NS_IsMainThread());
309 // All cleanup code requiring services needs to happen in xpcom_shutdown
311 PrepareForShutdown();
312 nsSSLIOLayerHelpers::GlobalCleanup();
315 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("nsNSSComponent::dtor finished\n"));
318 void nsNSSComponent::UnloadEnterpriseRoots() {
319 MOZ_ASSERT(NS_IsMainThread());
320 if (!NS_IsMainThread()) {
323 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("UnloadEnterpriseRoots"));
324 MutexAutoLock
lock(mMutex
);
325 mEnterpriseCerts
.Clear();
326 setValidationOptions(false, lock
);
327 ClearSSLExternalAndInternalSessionCache();
330 class BackgroundImportEnterpriseCertsTask final
: public CryptoTask
{
332 explicit BackgroundImportEnterpriseCertsTask(nsNSSComponent
* nssComponent
)
333 : mNSSComponent(nssComponent
) {}
336 virtual nsresult
CalculateResult() override
{
337 mNSSComponent
->ImportEnterpriseRoots();
338 mNSSComponent
->UpdateCertVerifierWithEnterpriseRoots();
342 virtual void CallCallback(nsresult rv
) override
{
343 nsCOMPtr
<nsIObserverService
> observerService
=
344 mozilla::services::GetObserverService();
345 if (observerService
) {
346 observerService
->NotifyObservers(nullptr, "psm:enterprise-certs-imported",
351 RefPtr
<nsNSSComponent
> mNSSComponent
;
354 void nsNSSComponent::MaybeImportEnterpriseRoots() {
355 MOZ_ASSERT(NS_IsMainThread());
356 if (!NS_IsMainThread()) {
359 bool importEnterpriseRoots
= StaticPrefs::security_enterprise_roots_enabled();
360 if (importEnterpriseRoots
) {
361 RefPtr
<BackgroundImportEnterpriseCertsTask
> task
=
362 new BackgroundImportEnterpriseCertsTask(this);
363 Unused
<< task
->Dispatch();
367 void nsNSSComponent::ImportEnterpriseRoots() {
368 MOZ_ASSERT(!NS_IsMainThread());
369 if (NS_IsMainThread()) {
373 nsTArray
<EnterpriseCert
> enterpriseCerts
;
374 nsresult rv
= GatherEnterpriseCerts(enterpriseCerts
);
375 if (NS_SUCCEEDED(rv
)) {
376 MutexAutoLock
lock(mMutex
);
377 mEnterpriseCerts
= std::move(enterpriseCerts
);
379 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("failed gathering enterprise roots"));
383 nsresult
nsNSSComponent::CommonGetEnterpriseCerts(
384 nsTArray
<nsTArray
<uint8_t>>& enterpriseCerts
, bool getRoots
) {
385 nsresult rv
= BlockUntilLoadableCertsLoaded();
390 enterpriseCerts
.Clear();
391 MutexAutoLock
nsNSSComponentLock(mMutex
);
392 for (const auto& cert
: mEnterpriseCerts
) {
393 nsTArray
<uint8_t> certCopy
;
394 // mEnterpriseCerts includes both roots and intermediates.
395 if (cert
.GetIsRoot() == getRoots
) {
396 cert
.CopyBytes(certCopy
);
397 enterpriseCerts
.AppendElement(std::move(certCopy
));
404 nsNSSComponent::GetEnterpriseRoots(
405 nsTArray
<nsTArray
<uint8_t>>& enterpriseRoots
) {
406 return CommonGetEnterpriseCerts(enterpriseRoots
, true);
409 nsresult
BytesArrayToPEM(const nsTArray
<nsTArray
<uint8_t>>& bytesArray
,
410 nsACString
& pemArray
) {
411 for (const auto& bytes
: bytesArray
) {
412 nsAutoCString base64
;
413 nsresult rv
= Base64Encode(reinterpret_cast<const char*>(bytes
.Elements()),
414 bytes
.Length(), base64
);
418 if (!pemArray
.IsEmpty()) {
419 pemArray
.AppendLiteral("\n");
421 pemArray
.AppendLiteral("-----BEGIN CERTIFICATE-----\n");
422 for (size_t i
= 0; i
< base64
.Length() / 64; i
++) {
423 pemArray
.Append(Substring(base64
, i
* 64, 64));
424 pemArray
.AppendLiteral("\n");
426 if (base64
.Length() % 64 != 0) {
427 size_t chunks
= base64
.Length() / 64;
428 pemArray
.Append(Substring(base64
, chunks
* 64));
429 pemArray
.AppendLiteral("\n");
431 pemArray
.AppendLiteral("-----END CERTIFICATE-----");
437 nsNSSComponent::GetEnterpriseRootsPEM(nsACString
& enterpriseRootsPEM
) {
438 nsTArray
<nsTArray
<uint8_t>> enterpriseRoots
;
439 nsresult rv
= GetEnterpriseRoots(enterpriseRoots
);
443 return BytesArrayToPEM(enterpriseRoots
, enterpriseRootsPEM
);
447 nsNSSComponent::GetEnterpriseIntermediates(
448 nsTArray
<nsTArray
<uint8_t>>& enterpriseIntermediates
) {
449 return CommonGetEnterpriseCerts(enterpriseIntermediates
, false);
453 nsNSSComponent::GetEnterpriseIntermediatesPEM(
454 nsACString
& enterpriseIntermediatesPEM
) {
455 nsTArray
<nsTArray
<uint8_t>> enterpriseIntermediates
;
456 nsresult rv
= GetEnterpriseIntermediates(enterpriseIntermediates
);
460 return BytesArrayToPEM(enterpriseIntermediates
, enterpriseIntermediatesPEM
);
464 nsNSSComponent::AddEnterpriseIntermediate(
465 const nsTArray
<uint8_t>& intermediateBytes
) {
466 nsresult rv
= BlockUntilLoadableCertsLoaded();
470 EnterpriseCert
intermediate(intermediateBytes
.Elements(),
471 intermediateBytes
.Length(), false);
473 MutexAutoLock
nsNSSComponentLock(mMutex
);
474 mEnterpriseCerts
.AppendElement(std::move(intermediate
));
477 UpdateCertVerifierWithEnterpriseRoots();
481 class LoadLoadableCertsTask final
: public Runnable
{
483 LoadLoadableCertsTask(nsNSSComponent
* nssComponent
,
484 bool importEnterpriseRoots
,
485 Vector
<nsCString
>&& possibleLoadableRootsLocations
,
486 Maybe
<nsCString
>&& osClientCertsModuleLocation
)
487 : Runnable("LoadLoadableCertsTask"),
488 mNSSComponent(nssComponent
),
489 mImportEnterpriseRoots(importEnterpriseRoots
),
490 mPossibleLoadableRootsLocations(
491 std::move(possibleLoadableRootsLocations
)),
492 mOSClientCertsModuleLocation(std::move(osClientCertsModuleLocation
)) {
493 MOZ_ASSERT(nssComponent
);
496 ~LoadLoadableCertsTask() = default;
501 NS_IMETHOD
Run() override
;
502 nsresult
LoadLoadableRoots();
503 RefPtr
<nsNSSComponent
> mNSSComponent
;
504 bool mImportEnterpriseRoots
;
505 Vector
<nsCString
> mPossibleLoadableRootsLocations
; // encoded in UTF-8
506 Maybe
<nsCString
> mOSClientCertsModuleLocation
; // encoded in UTF-8
509 nsresult
LoadLoadableCertsTask::Dispatch() {
510 // The stream transport service (note: not the socket transport service) can
511 // be used to perform background tasks or I/O that would otherwise block the
513 nsCOMPtr
<nsIEventTarget
> target(
514 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID
));
516 return NS_ERROR_FAILURE
;
518 return target
->Dispatch(this, NS_DISPATCH_NORMAL
);
522 LoadLoadableCertsTask::Run() {
523 AutoGleanTimer
<&glean::networking::loading_certs_task
> timer
;
525 nsresult loadLoadableRootsResult
= LoadLoadableRoots();
526 if (NS_WARN_IF(NS_FAILED(loadLoadableRootsResult
))) {
527 MOZ_LOG(gPIPNSSLog
, LogLevel::Error
, ("LoadLoadableRoots failed"));
528 // We don't return loadLoadableRootsResult here because then
529 // BlockUntilLoadableCertsLoaded will just wait forever. Instead we'll save
530 // its value (below) so we can inform code that relies on the roots module
531 // being present that loading it failed.
534 // Loading EV information will only succeed if we've successfully loaded the
535 // loadable roots module.
536 if (NS_SUCCEEDED(loadLoadableRootsResult
)) {
537 if (NS_FAILED(LoadExtendedValidationInfo())) {
538 // This isn't a show-stopper in the same way that failing to load the
540 MOZ_LOG(gPIPNSSLog
, LogLevel::Error
, ("failed to load EV info"));
544 if (mImportEnterpriseRoots
) {
545 mNSSComponent
->ImportEnterpriseRoots();
546 mNSSComponent
->UpdateCertVerifierWithEnterpriseRoots();
548 if (mOSClientCertsModuleLocation
.isSome()) {
549 bool success
= LoadOSClientCertsModule(*mOSClientCertsModuleLocation
);
550 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
551 ("loading OS client certs module %s",
552 success
? "succeeded" : "failed"));
555 MonitorAutoLock
rootsLoadedLock(mNSSComponent
->mLoadableCertsLoadedMonitor
);
556 mNSSComponent
->mLoadableCertsLoaded
= true;
557 // Cache the result of LoadLoadableRoots so BlockUntilLoadableCertsLoaded
558 // can return it to all callers later (we use that particular result because
559 // if that operation fails, it's unlikely that any TLS connection will
560 // succeed whereas the browser may still be able to operate if the other
562 mNSSComponent
->mLoadableCertsLoadedResult
= loadLoadableRootsResult
;
563 mNSSComponent
->mLoadableCertsLoadedMonitor
.NotifyAll();
568 // Returns by reference the path to the desired directory, based on the current
569 // settings in the directory service.
570 // |result| is encoded in UTF-8.
571 static nsresult
GetDirectoryPath(const char* directoryKey
, nsCString
& result
) {
572 MOZ_ASSERT(NS_IsMainThread());
574 nsCOMPtr
<nsIProperties
> directoryService(
575 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
));
576 if (!directoryService
) {
577 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("could not get directory service"));
578 return NS_ERROR_FAILURE
;
580 nsCOMPtr
<nsIFile
> directory
;
581 nsresult rv
= directoryService
->Get(directoryKey
, NS_GET_IID(nsIFile
),
582 getter_AddRefs(directory
));
584 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
585 ("could not get '%s' from directory service", directoryKey
));
588 return FileToCString(directory
, result
);
591 class BackgroundLoadOSClientCertsModuleTask final
: public CryptoTask
{
593 explicit BackgroundLoadOSClientCertsModuleTask(const nsCString
&& libraryDir
)
594 : mLibraryDir(std::move(libraryDir
)) {}
597 virtual nsresult
CalculateResult() override
{
598 bool success
= LoadOSClientCertsModule(mLibraryDir
);
599 return success
? NS_OK
: NS_ERROR_FAILURE
;
602 virtual void CallCallback(nsresult rv
) override
{
603 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
604 ("loading OS client certs module %s",
605 NS_SUCCEEDED(rv
) ? "succeeded" : "failed"));
606 nsCOMPtr
<nsIObserverService
> observerService
=
607 mozilla::services::GetObserverService();
608 if (observerService
) {
609 observerService
->NotifyObservers(
610 nullptr, "psm:load-os-client-certs-module-task-ran", nullptr);
614 nsCString mLibraryDir
;
617 void AsyncLoadOrUnloadOSClientCertsModule(bool load
) {
619 nsCString libraryDir
;
620 nsresult rv
= GetDirectoryPath(NS_GRE_BIN_DIR
, libraryDir
);
624 RefPtr
<BackgroundLoadOSClientCertsModuleTask
> task
=
625 new BackgroundLoadOSClientCertsModuleTask(std::move(libraryDir
));
626 Unused
<< task
->Dispatch();
628 UniqueSECMODModule
osClientCertsModule(
629 SECMOD_FindModule(kOSClientCertsModuleName
.get()));
630 if (osClientCertsModule
) {
631 SECMOD_UnloadUserModule(osClientCertsModule
.get());
636 nsresult
nsNSSComponent::BlockUntilLoadableCertsLoaded() {
637 MonitorAutoLock
rootsLoadedLock(mLoadableCertsLoadedMonitor
);
638 while (!mLoadableCertsLoaded
) {
639 rootsLoadedLock
.Wait();
641 MOZ_ASSERT(mLoadableCertsLoaded
);
643 return mLoadableCertsLoadedResult
;
646 #ifndef MOZ_NO_SMART_CARDS
647 static StaticMutex sCheckForSmartCardChangesMutex MOZ_UNANNOTATED
;
648 MOZ_RUNINIT
static TimeStamp sLastCheckedForSmartCardChanges
= TimeStamp::Now();
651 nsresult
nsNSSComponent::CheckForSmartCardChanges() {
652 #ifndef MOZ_NO_SMART_CARDS
654 StaticMutexAutoLock
lock(sCheckForSmartCardChangesMutex
);
655 // Do this at most once every 3 seconds.
656 TimeStamp now
= TimeStamp::Now();
657 if (now
- sLastCheckedForSmartCardChanges
<
658 TimeDuration::FromSeconds(3.0)) {
661 sLastCheckedForSmartCardChanges
= now
;
664 // SECMOD_UpdateSlotList attempts to acquire the list lock as well, so we
665 // have to do this in three steps.
666 Vector
<UniqueSECMODModule
> modulesWithRemovableSlots
;
668 AutoSECMODListReadLock secmodLock
;
669 SECMODModuleList
* list
= SECMOD_GetDefaultModuleList();
671 if (SECMOD_LockedModuleHasRemovableSlots(list
->module
)) {
672 UniqueSECMODModule
module(SECMOD_ReferenceModule(list
->module
));
673 if (!modulesWithRemovableSlots
.append(std::move(module
))) {
674 return NS_ERROR_OUT_OF_MEMORY
;
680 for (auto& module
: modulesWithRemovableSlots
) {
682 Unused
<< SECMOD_UpdateSlotList(module
.get());
684 AutoSECMODListReadLock secmodLock
;
685 for (auto& module
: modulesWithRemovableSlots
) {
686 for (int i
= 0; i
< module
->slotCount
; i
++) {
687 // We actually don't care about the return value here - we just need to
688 // call this to get NSS to update its view of this slot.
689 Unused
<< PK11_IsPresent(module
->slots
[i
]);
697 // Returns by reference the path to the directory containing the file that has
698 // been loaded as MOZ_DLL_PREFIX nss3 MOZ_DLL_SUFFIX.
699 // |result| is encoded in UTF-8.
700 static nsresult
GetNSS3Directory(nsCString
& result
) {
701 MOZ_ASSERT(NS_IsMainThread());
703 UniquePRString
nss3Path(
704 PR_GetLibraryFilePathname(MOZ_DLL_PREFIX
"nss3" MOZ_DLL_SUFFIX
,
705 reinterpret_cast<PRFuncPtr
>(NSS_Initialize
)));
707 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("nss not loaded?"));
708 return NS_ERROR_FAILURE
;
710 nsCOMPtr
<nsIFile
> nss3File
;
711 nsresult rv
= NS_NewNativeLocalFile(nsDependentCString(nss3Path
.get()),
712 getter_AddRefs(nss3File
));
714 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
715 ("couldn't initialize file with path '%s'", nss3Path
.get()));
718 nsCOMPtr
<nsIFile
> nss3Directory
;
719 rv
= nss3File
->GetParent(getter_AddRefs(nss3Directory
));
721 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("couldn't get parent directory?"));
724 return FileToCString(nss3Directory
, result
);
727 // The loadable roots library is probably in the same directory we loaded the
728 // NSS shared library from, but in some cases it may be elsewhere. This function
729 // enumerates and returns the possible locations as nsCStrings.
730 // |possibleLoadableRootsLocations| is encoded in UTF-8.
731 static nsresult
ListPossibleLoadableRootsLocations(
732 Vector
<nsCString
>& possibleLoadableRootsLocations
) {
733 MOZ_ASSERT(NS_IsMainThread());
734 if (!NS_IsMainThread()) {
735 return NS_ERROR_NOT_SAME_THREAD
;
738 // First try in the directory where we've already loaded
739 // MOZ_DLL_PREFIX nss3 MOZ_DLL_SUFFIX, since that's likely to be correct.
740 nsAutoCString nss3Dir
;
741 nsresult rv
= GetNSS3Directory(nss3Dir
);
742 if (NS_SUCCEEDED(rv
)) {
743 if (!possibleLoadableRootsLocations
.append(std::move(nss3Dir
))) {
744 return NS_ERROR_OUT_OF_MEMORY
;
747 // For some reason this fails on android. In any case, we should try with
748 // the other potential locations we have.
749 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
750 ("could not determine where nss was loaded from"));
752 nsAutoCString currentProcessDir
;
753 rv
= GetDirectoryPath(NS_XPCOM_CURRENT_PROCESS_DIR
, currentProcessDir
);
754 if (NS_SUCCEEDED(rv
)) {
755 if (!possibleLoadableRootsLocations
.append(std::move(currentProcessDir
))) {
756 return NS_ERROR_OUT_OF_MEMORY
;
759 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
760 ("could not get current process directory"));
762 nsAutoCString greDir
;
763 rv
= GetDirectoryPath(NS_GRE_DIR
, greDir
);
764 if (NS_SUCCEEDED(rv
)) {
765 if (!possibleLoadableRootsLocations
.append(std::move(greDir
))) {
766 return NS_ERROR_OUT_OF_MEMORY
;
769 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("could not get gre directory"));
771 // As a last resort, this will cause the library loading code to use the OS'
772 // default library search path.
773 nsAutoCString emptyString
;
774 if (!possibleLoadableRootsLocations
.append(std::move(emptyString
))) {
775 return NS_ERROR_OUT_OF_MEMORY
;
781 nsresult
LoadLoadableCertsTask::LoadLoadableRoots() {
782 for (const auto& possibleLocation
: mPossibleLoadableRootsLocations
) {
783 if (mozilla::psm::LoadLoadableRoots(possibleLocation
)) {
784 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
785 ("loaded CKBI from %s", possibleLocation
.get()));
789 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("could not load loadable roots"));
790 return NS_ERROR_FAILURE
;
793 // Table of pref names and SSL cipher ID
797 bool (*prefGetter
)();
800 // Update the switch statement in AccumulateCipherSuite in nsNSSCallbacks.cpp
801 // when you add/remove cipher suites here.
802 static const CipherPref sCipherPrefs
[] = {
803 {"security.ssl3.ecdhe_rsa_aes_128_gcm_sha256",
804 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
,
805 StaticPrefs::security_ssl3_ecdhe_rsa_aes_128_gcm_sha256
},
806 {"security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256",
807 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
,
808 StaticPrefs::security_ssl3_ecdhe_ecdsa_aes_128_gcm_sha256
},
809 {"security.ssl3.ecdhe_ecdsa_chacha20_poly1305_sha256",
810 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
,
811 StaticPrefs::security_ssl3_ecdhe_ecdsa_chacha20_poly1305_sha256
},
812 {"security.ssl3.ecdhe_rsa_chacha20_poly1305_sha256",
813 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
,
814 StaticPrefs::security_ssl3_ecdhe_rsa_chacha20_poly1305_sha256
},
815 {"security.ssl3.ecdhe_ecdsa_aes_256_gcm_sha384",
816 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
,
817 StaticPrefs::security_ssl3_ecdhe_ecdsa_aes_256_gcm_sha384
},
818 {"security.ssl3.ecdhe_rsa_aes_256_gcm_sha384",
819 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
,
820 StaticPrefs::security_ssl3_ecdhe_rsa_aes_256_gcm_sha384
},
821 {"security.ssl3.ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
,
822 StaticPrefs::security_ssl3_ecdhe_rsa_aes_128_sha
},
823 {"security.ssl3.ecdhe_ecdsa_aes_128_sha",
824 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
,
825 StaticPrefs::security_ssl3_ecdhe_ecdsa_aes_128_sha
},
826 {"security.ssl3.ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
,
827 StaticPrefs::security_ssl3_ecdhe_rsa_aes_256_sha
},
828 {"security.ssl3.ecdhe_ecdsa_aes_256_sha",
829 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
,
830 StaticPrefs::security_ssl3_ecdhe_ecdsa_aes_256_sha
},
831 {"security.ssl3.dhe_rsa_aes_128_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
832 StaticPrefs::security_ssl3_dhe_rsa_aes_128_sha
},
833 {"security.ssl3.dhe_rsa_aes_256_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
834 StaticPrefs::security_ssl3_dhe_rsa_aes_256_sha
},
835 {"security.tls13.aes_128_gcm_sha256", TLS_AES_128_GCM_SHA256
,
836 StaticPrefs::security_tls13_aes_128_gcm_sha256
},
837 {"security.tls13.chacha20_poly1305_sha256", TLS_CHACHA20_POLY1305_SHA256
,
838 StaticPrefs::security_tls13_chacha20_poly1305_sha256
},
839 {"security.tls13.aes_256_gcm_sha384", TLS_AES_256_GCM_SHA384
,
840 StaticPrefs::security_tls13_aes_256_gcm_sha384
},
841 {"security.ssl3.rsa_aes_128_gcm_sha256", TLS_RSA_WITH_AES_128_GCM_SHA256
,
842 StaticPrefs::security_ssl3_rsa_aes_128_gcm_sha256
},
843 {"security.ssl3.rsa_aes_256_gcm_sha384", TLS_RSA_WITH_AES_256_GCM_SHA384
,
844 StaticPrefs::security_ssl3_rsa_aes_256_gcm_sha384
},
845 {"security.ssl3.rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA
,
846 StaticPrefs::security_ssl3_rsa_aes_128_sha
},
847 {"security.ssl3.rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA
,
848 StaticPrefs::security_ssl3_rsa_aes_256_sha
},
851 // These ciphersuites can only be enabled if deprecated versions of TLS are
852 // also enabled (via the preference "security.tls.version.enable-deprecated").
853 static const CipherPref sDeprecatedTLS1CipherPrefs
[] = {
854 {"security.ssl3.deprecated.rsa_des_ede3_sha", TLS_RSA_WITH_3DES_EDE_CBC_SHA
,
855 StaticPrefs::security_ssl3_deprecated_rsa_des_ede3_sha
},
858 // This function will convert from pref values like 1, 2, ...
859 // to the internal values of SSL_LIBRARY_VERSION_TLS_1_0,
860 // SSL_LIBRARY_VERSION_TLS_1_1, ...
862 void nsNSSComponent::FillTLSVersionRange(SSLVersionRange
& rangeOut
,
863 uint32_t minFromPrefs
,
864 uint32_t maxFromPrefs
,
865 SSLVersionRange defaults
) {
867 // determine what versions are supported
868 SSLVersionRange supported
;
869 if (SSL_VersionRangeGetSupported(ssl_variant_stream
, &supported
) !=
874 // Clip the defaults by what NSS actually supports to enable
875 // working with a system NSS with different ranges.
876 rangeOut
.min
= std::max(rangeOut
.min
, supported
.min
);
877 rangeOut
.max
= std::min(rangeOut
.max
, supported
.max
);
879 // convert min/maxFromPrefs to the internal representation
880 minFromPrefs
+= SSL_LIBRARY_VERSION_3_0
;
881 maxFromPrefs
+= SSL_LIBRARY_VERSION_3_0
;
882 // if min/maxFromPrefs are invalid, use defaults
883 if (minFromPrefs
> maxFromPrefs
|| minFromPrefs
< supported
.min
||
884 maxFromPrefs
> supported
.max
||
885 minFromPrefs
< SSL_LIBRARY_VERSION_TLS_1_0
) {
890 rangeOut
.min
= (uint16_t)minFromPrefs
;
891 rangeOut
.max
= (uint16_t)maxFromPrefs
;
894 static void ConfigureTLSSessionIdentifiers() {
895 bool disableSessionIdentifiers
=
896 StaticPrefs::security_ssl_disable_session_identifiers();
897 SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS
, !disableSessionIdentifiers
);
898 SSL_OptionSetDefault(SSL_NO_CACHE
, disableSessionIdentifiers
);
901 nsresult
CommonInit() {
902 SSL_OptionSetDefault(SSL_ENABLE_SSL2
, false);
903 SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO
, false);
905 nsresult rv
= nsNSSComponent::SetEnabledTLSVersions();
910 ConfigureTLSSessionIdentifiers();
912 SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION
,
913 StaticPrefs::security_ssl_require_safe_negotiation());
914 SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION
, SSL_RENEGOTIATE_REQUIRES_XTN
);
915 SSL_OptionSetDefault(SSL_ENABLE_EXTENDED_MASTER_SECRET
, true);
916 SSL_OptionSetDefault(SSL_ENABLE_HELLO_DOWNGRADE_CHECK
,
917 StaticPrefs::security_tls_hello_downgrade_check());
918 SSL_OptionSetDefault(SSL_ENABLE_FALSE_START
,
919 StaticPrefs::security_ssl_enable_false_start());
920 // SSL_ENABLE_ALPN also requires calling SSL_SetNextProtoNego in order for
921 // the extensions to be negotiated.
922 // WebRTC does not do that so it will not use ALPN even when this preference
924 SSL_OptionSetDefault(SSL_ENABLE_ALPN
,
925 StaticPrefs::security_ssl_enable_alpn());
926 SSL_OptionSetDefault(SSL_ENABLE_0RTT_DATA
,
927 StaticPrefs::security_tls_enable_0rtt_data());
928 SSL_OptionSetDefault(SSL_ENABLE_POST_HANDSHAKE_AUTH
,
929 StaticPrefs::security_tls_enable_post_handshake_auth());
930 SSL_OptionSetDefault(
931 SSL_ENABLE_DELEGATED_CREDENTIALS
,
932 StaticPrefs::security_tls_enable_delegated_credentials());
934 rv
= InitializeCipherSuite();
936 MOZ_LOG(gPIPNSSLog
, LogLevel::Error
,
937 ("Unable to initialize cipher suite settings\n"));
943 mozilla::pkix::RegisterErrorTable();
944 nsSSLIOLayerHelpers::GlobalInit();
949 void PrepareForShutdownInSocketProcess() {
950 MOZ_ASSERT(XRE_IsSocketProcess());
951 nsSSLIOLayerHelpers::GlobalCleanup();
954 bool HandleTLSPrefChange(const nsCString
& prefName
) {
955 // Note that the code in this function should be kept in sync with
956 // gCallbackSecurityPrefs in nsIOService.cpp.
957 bool prefFound
= true;
958 if (prefName
.EqualsLiteral("security.tls.version.min") ||
959 prefName
.EqualsLiteral("security.tls.version.max") ||
960 prefName
.EqualsLiteral("security.tls.version.enable-deprecated")) {
961 Unused
<< nsNSSComponent::SetEnabledTLSVersions();
962 } else if (prefName
.EqualsLiteral("security.tls.hello_downgrade_check")) {
963 SSL_OptionSetDefault(SSL_ENABLE_HELLO_DOWNGRADE_CHECK
,
964 StaticPrefs::security_tls_hello_downgrade_check());
965 } else if (prefName
.EqualsLiteral("security.ssl.require_safe_negotiation")) {
966 SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION
,
967 StaticPrefs::security_ssl_require_safe_negotiation());
968 } else if (prefName
.EqualsLiteral("security.ssl.enable_false_start")) {
969 SSL_OptionSetDefault(SSL_ENABLE_FALSE_START
,
970 StaticPrefs::security_ssl_enable_false_start());
971 } else if (prefName
.EqualsLiteral("security.ssl.enable_alpn")) {
972 SSL_OptionSetDefault(SSL_ENABLE_ALPN
,
973 StaticPrefs::security_ssl_enable_alpn());
974 } else if (prefName
.EqualsLiteral("security.tls.enable_0rtt_data")) {
975 SSL_OptionSetDefault(SSL_ENABLE_0RTT_DATA
,
976 StaticPrefs::security_tls_enable_0rtt_data());
977 } else if (prefName
.EqualsLiteral(
978 "security.tls.enable_post_handshake_auth")) {
979 SSL_OptionSetDefault(
980 SSL_ENABLE_POST_HANDSHAKE_AUTH
,
981 StaticPrefs::security_tls_enable_post_handshake_auth());
982 } else if (prefName
.EqualsLiteral(
983 "security.tls.enable_delegated_credentials")) {
984 SSL_OptionSetDefault(
985 SSL_ENABLE_DELEGATED_CREDENTIALS
,
986 StaticPrefs::security_tls_enable_delegated_credentials());
987 } else if (prefName
.EqualsLiteral(
988 "security.ssl.disable_session_identifiers")) {
989 ConfigureTLSSessionIdentifiers();
998 class CipherSuiteChangeObserver
: public nsIObserver
{
1003 static nsresult
StartObserve();
1006 virtual ~CipherSuiteChangeObserver() = default;
1009 static StaticRefPtr
<CipherSuiteChangeObserver
> sObserver
;
1010 CipherSuiteChangeObserver() = default;
1013 NS_IMPL_ISUPPORTS(CipherSuiteChangeObserver
, nsIObserver
)
1016 StaticRefPtr
<CipherSuiteChangeObserver
> CipherSuiteChangeObserver::sObserver
;
1019 nsresult
CipherSuiteChangeObserver::StartObserve() {
1020 MOZ_ASSERT(NS_IsMainThread(),
1021 "CipherSuiteChangeObserver::StartObserve() can only be accessed "
1022 "on the main thread");
1024 RefPtr
<CipherSuiteChangeObserver
> observer
=
1025 new CipherSuiteChangeObserver();
1026 nsresult rv
= Preferences::AddStrongObserver(observer
.get(), "security.");
1027 if (NS_FAILED(rv
)) {
1028 sObserver
= nullptr;
1032 nsCOMPtr
<nsIObserverService
> observerService
=
1033 mozilla::services::GetObserverService();
1034 observerService
->AddObserver(observer
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
,
1037 sObserver
= observer
;
1042 // Enables or disabled ciphersuites from deprecated versions of TLS as
1043 // appropriate. If security.tls.version.enable-deprecated is true, these
1044 // ciphersuites may be enabled, if the corresponding preference is true.
1045 // Otherwise, these ciphersuites will be disabled.
1046 void SetDeprecatedTLS1CipherPrefs() {
1047 if (StaticPrefs::security_tls_version_enable_deprecated()) {
1048 for (const auto& deprecatedTLS1CipherPref
: sDeprecatedTLS1CipherPrefs
) {
1049 SSL_CipherPrefSetDefault(deprecatedTLS1CipherPref
.id
,
1050 deprecatedTLS1CipherPref
.prefGetter());
1053 for (const auto& deprecatedTLS1CipherPref
: sDeprecatedTLS1CipherPrefs
) {
1054 SSL_CipherPrefSetDefault(deprecatedTLS1CipherPref
.id
, false);
1060 void SetKyberPolicy() {
1061 if (StaticPrefs::security_tls_enable_kyber()) {
1062 NSS_SetAlgorithmPolicy(SEC_OID_MLKEM768X25519
, NSS_USE_ALG_IN_SSL_KX
, 0);
1064 NSS_SetAlgorithmPolicy(SEC_OID_MLKEM768X25519
, 0, NSS_USE_ALG_IN_SSL_KX
);
1068 nsresult
CipherSuiteChangeObserver::Observe(nsISupports
* /*aSubject*/,
1070 const char16_t
* someData
) {
1071 MOZ_ASSERT(NS_IsMainThread(),
1072 "CipherSuiteChangeObserver::Observe can only be accessed on main "
1074 if (nsCRT::strcmp(aTopic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
) == 0) {
1075 NS_ConvertUTF16toUTF8
prefName(someData
);
1076 // Look through the cipher table and set according to pref setting
1077 for (const auto& cipherPref
: sCipherPrefs
) {
1078 if (prefName
.Equals(cipherPref
.pref
)) {
1079 SSL_CipherPrefSetDefault(cipherPref
.id
, cipherPref
.prefGetter());
1083 SetDeprecatedTLS1CipherPrefs();
1085 nsNSSComponent::DoClearSSLExternalAndInternalSessionCache();
1086 } else if (nsCRT::strcmp(aTopic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
) == 0) {
1087 Preferences::RemoveObserver(this, "security.");
1088 MOZ_ASSERT(sObserver
.get() == this);
1089 sObserver
= nullptr;
1090 nsCOMPtr
<nsIObserverService
> observerService
=
1091 mozilla::services::GetObserverService();
1092 observerService
->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
);
1099 void nsNSSComponent::setValidationOptions(
1100 bool isInitialSetting
, const mozilla::MutexAutoLock
& proofOfLock
) {
1101 // We access prefs so this must be done on the main thread.
1102 mMutex
.AssertCurrentThreadOwns();
1103 MOZ_ASSERT(NS_IsMainThread());
1104 if (NS_WARN_IF(!NS_IsMainThread())) {
1108 CertVerifier::CertificateTransparencyMode ctMode
=
1109 GetCertificateTransparencyMode();
1110 nsCString skipCTForHosts
;
1111 Preferences::GetCString(
1112 "security.pki.certificate_transparency.disable_for_hosts",
1114 nsAutoCString skipCTForSPKIHashesBase64
;
1115 Preferences::GetCString(
1116 "security.pki.certificate_transparency.disable_for_spki_hashes",
1117 skipCTForSPKIHashesBase64
);
1118 nsTArray
<CopyableTArray
<uint8_t>> skipCTForSPKIHashes
;
1119 for (const auto& spkiHashBase64
: skipCTForSPKIHashesBase64
.Split(',')) {
1120 nsAutoCString spkiHashString
;
1121 if (NS_SUCCEEDED(Base64Decode(spkiHashBase64
, spkiHashString
))) {
1122 nsTArray
<uint8_t> spkiHash(spkiHashString
.Data(),
1123 spkiHashString
.Length());
1124 skipCTForSPKIHashes
.AppendElement(std::move(spkiHash
));
1127 CertVerifier::CertificateTransparencyConfig
ctConfig(
1128 ctMode
, std::move(skipCTForHosts
), std::move(skipCTForSPKIHashes
));
1130 // This preference controls whether we do OCSP fetching and does not affect
1132 // 0 = disabled, 1 = enabled, 2 = only enabled for EV
1133 uint32_t ocspEnabled
= StaticPrefs::security_OCSP_enabled();
1135 bool ocspRequired
= ocspEnabled
> 0 && StaticPrefs::security_OCSP_require();
1137 // We measure the setting of the pref at startup only to minimize noise by
1138 // addons that may muck with the settings, though it probably doesn't matter.
1139 if (isInitialSetting
) {
1140 Telemetry::Accumulate(Telemetry::CERT_OCSP_ENABLED
, ocspEnabled
);
1141 Telemetry::Accumulate(Telemetry::CERT_OCSP_REQUIRED
, ocspRequired
);
1144 NetscapeStepUpPolicy netscapeStepUpPolicy
= static_cast<NetscapeStepUpPolicy
>(
1145 StaticPrefs::security_pki_netscape_step_up_policy());
1146 switch (netscapeStepUpPolicy
) {
1147 case NetscapeStepUpPolicy::AlwaysMatch
:
1148 case NetscapeStepUpPolicy::MatchBefore23August2016
:
1149 case NetscapeStepUpPolicy::MatchBefore23August2015
:
1150 case NetscapeStepUpPolicy::NeverMatch
:
1153 netscapeStepUpPolicy
= NetscapeStepUpPolicy::AlwaysMatch
;
1157 CRLiteMode defaultCRLiteMode
= CRLiteMode::Disabled
;
1158 CRLiteMode crliteMode
=
1159 static_cast<CRLiteMode
>(StaticPrefs::security_pki_crlite_mode());
1160 switch (crliteMode
) {
1161 case CRLiteMode::Disabled
:
1162 case CRLiteMode::TelemetryOnly
:
1163 case CRLiteMode::Enforce
:
1164 case CRLiteMode::ConfirmRevocations
:
1167 crliteMode
= defaultCRLiteMode
;
1171 CertVerifier::OcspDownloadConfig odc
;
1172 CertVerifier::OcspStrictConfig osc
;
1173 uint32_t certShortLifetimeInDays
;
1174 TimeDuration softTimeout
;
1175 TimeDuration hardTimeout
;
1177 GetRevocationBehaviorFromPrefs(&odc
, &osc
, &certShortLifetimeInDays
,
1178 softTimeout
, hardTimeout
);
1180 mDefaultCertVerifier
= new SharedCertVerifier(
1181 odc
, osc
, softTimeout
, hardTimeout
, certShortLifetimeInDays
,
1182 netscapeStepUpPolicy
, std::move(ctConfig
), crliteMode
, mEnterpriseCerts
);
1185 void nsNSSComponent::UpdateCertVerifierWithEnterpriseRoots() {
1186 MutexAutoLock
lock(mMutex
);
1187 if (!mDefaultCertVerifier
) {
1191 RefPtr
<SharedCertVerifier
> oldCertVerifier
= mDefaultCertVerifier
;
1192 nsCString
skipCTForHosts(oldCertVerifier
->mCTConfig
.mSkipForHosts
);
1193 CertVerifier::CertificateTransparencyConfig
ctConfig(
1194 oldCertVerifier
->mCTConfig
.mMode
, std::move(skipCTForHosts
),
1195 oldCertVerifier
->mCTConfig
.mSkipForSPKIHashes
.Clone());
1196 mDefaultCertVerifier
= new SharedCertVerifier(
1197 oldCertVerifier
->mOCSPDownloadConfig
,
1198 oldCertVerifier
->mOCSPStrict
? CertVerifier::ocspStrict
1199 : CertVerifier::ocspRelaxed
,
1200 oldCertVerifier
->mOCSPTimeoutSoft
, oldCertVerifier
->mOCSPTimeoutHard
,
1201 oldCertVerifier
->mCertShortLifetimeInDays
,
1202 oldCertVerifier
->mNetscapeStepUpPolicy
, std::move(ctConfig
),
1203 oldCertVerifier
->mCRLiteMode
, mEnterpriseCerts
);
1206 // Enable the TLS versions given in the prefs, defaulting to TLS 1.0 (min) and
1207 // TLS 1.2 (max) when the prefs aren't set or set to invalid values.
1208 nsresult
nsNSSComponent::SetEnabledTLSVersions() {
1209 // Keep these values in sync with all.js.
1210 // 1 means TLS 1.0, 2 means TLS 1.1, etc.
1211 static const uint32_t PSM_DEFAULT_MIN_TLS_VERSION
= 3;
1212 static const uint32_t PSM_DEFAULT_MAX_TLS_VERSION
= 4;
1213 static const uint32_t PSM_DEPRECATED_TLS_VERSION
= 1;
1215 uint32_t minFromPrefs
= StaticPrefs::security_tls_version_min();
1216 uint32_t maxFromPrefs
= StaticPrefs::security_tls_version_max();
1218 // This override should be removed some time after
1219 // PSM_DEFAULT_MIN_TLS_VERSION is increased to 3.
1220 bool enableDeprecated
= StaticPrefs::security_tls_version_enable_deprecated();
1221 if (enableDeprecated
) {
1222 minFromPrefs
= std::min(minFromPrefs
, PSM_DEPRECATED_TLS_VERSION
);
1225 SSLVersionRange defaults
= {
1226 SSL_LIBRARY_VERSION_3_0
+ PSM_DEFAULT_MIN_TLS_VERSION
,
1227 SSL_LIBRARY_VERSION_3_0
+ PSM_DEFAULT_MAX_TLS_VERSION
};
1228 SSLVersionRange filledInRange
;
1229 FillTLSVersionRange(filledInRange
, minFromPrefs
, maxFromPrefs
, defaults
);
1232 SSL_VersionRangeSetDefault(ssl_variant_stream
, &filledInRange
);
1233 if (srv
!= SECSuccess
) {
1234 return NS_ERROR_FAILURE
;
1240 #if defined(XP_WIN) || (defined(XP_LINUX) && !defined(ANDROID))
1241 // If the profile directory is on a networked drive, we want to set the
1242 // environment variable NSS_SDB_USE_CACHE to yes (as long as it hasn't been set
1244 static void SetNSSDatabaseCacheModeAsAppropriate() {
1245 MOZ_ASSERT(NS_IsMainThread());
1247 nsCOMPtr
<nsIFile
> profileFile
;
1248 nsresult rv
= NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR
,
1249 getter_AddRefs(profileFile
));
1250 if (NS_FAILED(rv
)) {
1251 // We're probably running without a profile directory, so this is
1256 static const char sNSS_SDB_USE_CACHE
[] = "NSS_SDB_USE_CACHE";
1257 static const char sNSS_SDB_USE_CACHE_WITH_VALUE
[] = "NSS_SDB_USE_CACHE=yes";
1258 auto profilePath
= profileFile
->NativePath();
1260 # if defined(XP_LINUX) && !defined(ANDROID)
1261 struct statfs statfs_s
;
1262 if (statfs(profilePath
.get(), &statfs_s
) == 0 &&
1263 statfs_s
.f_type
== NFS_SUPER_MAGIC
&& !PR_GetEnv(sNSS_SDB_USE_CACHE
)) {
1264 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
1265 ("profile is remote (and NSS_SDB_USE_CACHE wasn't set): "
1266 "setting NSS_SDB_USE_CACHE"));
1267 PR_SetEnv(sNSS_SDB_USE_CACHE_WITH_VALUE
);
1269 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("not setting NSS_SDB_USE_CACHE"));
1271 # endif // defined(XP_LINUX) && !defined(ANDROID)
1274 wchar_t volPath
[MAX_PATH
];
1275 if (::GetVolumePathNameW(profilePath
.get(), volPath
, MAX_PATH
) &&
1276 ::GetDriveTypeW(volPath
) == DRIVE_REMOTE
&&
1277 !PR_GetEnv(sNSS_SDB_USE_CACHE
)) {
1278 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
1279 ("profile is remote (and NSS_SDB_USE_CACHE wasn't set): "
1280 "setting NSS_SDB_USE_CACHE"));
1281 PR_SetEnv(sNSS_SDB_USE_CACHE_WITH_VALUE
);
1283 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("not setting NSS_SDB_USE_CACHE"));
1287 #endif // defined(XP_WIN) || (defined(XP_LINUX) && !defined(ANDROID))
1289 static nsresult
GetNSSProfilePath(nsAutoCString
& aProfilePath
) {
1290 aProfilePath
.Truncate();
1291 nsCOMPtr
<nsIFile
> profileFile
;
1292 nsresult rv
= NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR
,
1293 getter_AddRefs(profileFile
));
1294 if (NS_FAILED(rv
)) {
1296 "NSS will be initialized without a profile directory. "
1297 "Some things may not work as expected.");
1302 // SQLite always takes UTF-8 file paths regardless of the current system
1304 nsAutoString u16ProfilePath
;
1305 rv
= profileFile
->GetPath(u16ProfilePath
);
1306 CopyUTF16toUTF8(u16ProfilePath
, aProfilePath
);
1308 rv
= profileFile
->GetNativePath(aProfilePath
);
1310 if (NS_FAILED(rv
)) {
1311 MOZ_LOG(gPIPNSSLog
, LogLevel::Error
,
1312 ("Could not get native path for profile directory.\n"));
1316 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
1317 ("NSS profile at '%s'\n", aProfilePath
.get()));
1322 // Given a profile path, attempt to rename the PKCS#11 module DB to
1323 // "pkcs11.txt.fips". In the case of a catastrophic failure (e.g. out of
1324 // memory), returns a failing nsresult. If execution could conceivably proceed,
1325 // returns NS_OK even if renaming the file didn't work. This simplifies the
1326 // logic of the calling code.
1327 // |profilePath| is encoded in UTF-8.
1328 static nsresult
AttemptToRenamePKCS11ModuleDB(const nsACString
& profilePath
) {
1329 nsCOMPtr
<nsIFile
> profileDir
;
1330 // |profilePath| is encoded in UTF-8 because SQLite always takes UTF-8 file
1331 // paths regardless of the current system code page.
1332 MOZ_TRY(NS_NewUTF8LocalFile(profilePath
, getter_AddRefs(profileDir
)));
1333 const char* moduleDBFilename
= "pkcs11.txt";
1334 nsAutoCString
destModuleDBFilename(moduleDBFilename
);
1335 destModuleDBFilename
.Append(".fips");
1336 nsCOMPtr
<nsIFile
> dbFile
;
1337 nsresult rv
= profileDir
->Clone(getter_AddRefs(dbFile
));
1338 if (NS_FAILED(rv
) || !dbFile
) {
1339 return NS_ERROR_FAILURE
;
1341 rv
= dbFile
->AppendNative(nsAutoCString(moduleDBFilename
));
1342 if (NS_FAILED(rv
)) {
1345 // If the PKCS#11 module DB doesn't exist, renaming it won't help.
1347 rv
= dbFile
->Exists(&exists
);
1348 if (NS_FAILED(rv
)) {
1351 // This is strange, but not a catastrophic failure.
1353 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
1354 ("%s doesn't exist?", moduleDBFilename
));
1357 nsCOMPtr
<nsIFile
> destDBFile
;
1358 rv
= profileDir
->Clone(getter_AddRefs(destDBFile
));
1359 if (NS_FAILED(rv
) || !destDBFile
) {
1360 return NS_ERROR_FAILURE
;
1362 rv
= destDBFile
->AppendNative(destModuleDBFilename
);
1363 if (NS_FAILED(rv
)) {
1366 // If the destination exists, presumably we've already tried this. Doing it
1367 // again won't help.
1368 rv
= destDBFile
->Exists(&exists
);
1369 if (NS_FAILED(rv
)) {
1372 // Unfortunate, but not a catastrophic failure.
1375 gPIPNSSLog
, LogLevel::Debug
,
1376 ("%s already exists - not overwriting", destModuleDBFilename
.get()));
1379 // Now do the actual move.
1380 // This may fail on, e.g., a read-only file system. This would be unfortunate,
1381 // but again it isn't catastropic and we would want to fall back to
1382 // initializing NSS in no-DB mode.
1383 Unused
<< dbFile
->MoveToNative(profileDir
, destModuleDBFilename
);
1386 #endif // ifndef ANDROID
1388 // Given a profile directory, attempt to initialize NSS. If nocertdb is true,
1389 // (or if we don't have a profile directory) simply initialize NSS in no DB mode
1390 // and return. Otherwise, first attempt to initialize in read/write mode, and
1391 // then read-only mode if that fails. If both attempts fail, we may be failing
1392 // to initialize an NSS DB collection that has FIPS mode enabled. Attempt to
1393 // ascertain if this is the case, and if so, rename the offending PKCS#11 module
1394 // DB so we can (hopefully) initialize NSS in read-write mode. Again attempt
1395 // read-only mode if that fails. Finally, fall back to no DB mode. On Android
1396 // we can skip the FIPS workaround since it was never possible to enable FIPS
1398 // |profilePath| is encoded in UTF-8.
1399 static nsresult
InitializeNSSWithFallbacks(const nsACString
& profilePath
,
1400 bool nocertdb
, bool safeMode
) {
1401 if (nocertdb
|| profilePath
.IsEmpty()) {
1402 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
1403 ("nocertdb mode or empty profile path -> NSS_NoDB_Init"));
1404 SECStatus srv
= NSS_NoDB_Init(nullptr);
1405 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1406 if (srv
!= SECSuccess
) {
1407 MOZ_CRASH_UNSAFE_PRINTF("InitializeNSSWithFallbacks failed: %d",
1411 return srv
== SECSuccess
? NS_OK
: NS_ERROR_FAILURE
;
1414 // Try read/write mode. If we're in safeMode, we won't load PKCS#11 modules.
1416 PRErrorCode savedPRErrorCode1
;
1417 #endif // ifndef ANDROID
1418 PKCS11DBConfig safeModeDBConfig
=
1419 safeMode
? PKCS11DBConfig::DoNotLoadModules
: PKCS11DBConfig::LoadModules
;
1420 SECStatus srv
= ::mozilla::psm::InitializeNSS(
1421 profilePath
, NSSDBConfig::ReadWrite
, safeModeDBConfig
);
1422 if (srv
== SECSuccess
) {
1423 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("initialized NSS in r/w mode"));
1427 savedPRErrorCode1
= PR_GetError();
1428 PRErrorCode savedPRErrorCode2
;
1429 #endif // ifndef ANDROID
1430 // That failed. Try read-only mode.
1431 srv
= ::mozilla::psm::InitializeNSS(profilePath
, NSSDBConfig::ReadOnly
,
1433 if (srv
== SECSuccess
) {
1434 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("initialized NSS in r-o mode"));
1438 savedPRErrorCode2
= PR_GetError();
1440 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
1441 ("failed to initialize NSS with codes %d %d", savedPRErrorCode1
,
1442 savedPRErrorCode2
));
1443 #endif // ifndef ANDROID
1446 // That failed as well. Maybe we're trying to load a PKCS#11 module DB that is
1447 // in FIPS mode, but we don't support FIPS? Test load NSS without PKCS#11
1448 // modules. If that succeeds, that's probably what's going on.
1449 if (!safeMode
&& (savedPRErrorCode1
== SEC_ERROR_LEGACY_DATABASE
||
1450 savedPRErrorCode2
== SEC_ERROR_LEGACY_DATABASE
||
1451 savedPRErrorCode1
== SEC_ERROR_PKCS11_DEVICE_ERROR
||
1452 savedPRErrorCode2
== SEC_ERROR_PKCS11_DEVICE_ERROR
)) {
1453 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("attempting no-module db init"));
1454 // It would make sense to initialize NSS in read-only mode here since this
1455 // is just a test to see if the PKCS#11 module DB being in FIPS mode is the
1456 // problem, but for some reason the combination of read-only and no-moddb
1457 // flags causes NSS initialization to fail, so unfortunately we have to use
1459 srv
= ::mozilla::psm::InitializeNSS(profilePath
, NSSDBConfig::ReadWrite
,
1460 PKCS11DBConfig::DoNotLoadModules
);
1461 if (srv
== SECSuccess
) {
1462 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("FIPS may be the problem"));
1463 // Unload NSS so we can attempt to fix this situation for the user.
1464 srv
= NSS_Shutdown();
1465 if (srv
!= SECSuccess
) {
1466 # ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1467 MOZ_CRASH_UNSAFE_PRINTF("InitializeNSSWithFallbacks failed: %d",
1470 return NS_ERROR_FAILURE
;
1472 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("trying to rename module db"));
1473 // If this fails non-catastrophically, we'll attempt to initialize NSS
1474 // again in r/w then r-o mode (both of which will fail), and then we'll
1475 // fall back to NSS_NoDB_Init, which is the behavior we want.
1476 nsresult rv
= AttemptToRenamePKCS11ModuleDB(profilePath
);
1477 if (NS_FAILED(rv
)) {
1478 # ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1479 // An nsresult is a uint32_t, but at least one of our compilers doesn't
1480 // like this format string unless we include the cast. <shruggie emoji>
1481 MOZ_CRASH_UNSAFE_PRINTF("InitializeNSSWithFallbacks failed: %u",
1486 srv
= ::mozilla::psm::InitializeNSS(profilePath
, NSSDBConfig::ReadWrite
,
1487 PKCS11DBConfig::LoadModules
);
1488 if (srv
== SECSuccess
) {
1489 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("initialized in r/w mode"));
1492 srv
= ::mozilla::psm::InitializeNSS(profilePath
, NSSDBConfig::ReadOnly
,
1493 PKCS11DBConfig::LoadModules
);
1494 if (srv
== SECSuccess
) {
1495 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("initialized in r-o mode"));
1502 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("last-resort NSS_NoDB_Init"));
1503 srv
= NSS_NoDB_Init(nullptr);
1504 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1505 if (srv
!= SECSuccess
) {
1506 MOZ_CRASH_UNSAFE_PRINTF("InitializeNSSWithFallbacks failed: %d",
1510 return srv
== SECSuccess
? NS_OK
: NS_ERROR_FAILURE
;
1513 #if defined(NIGHTLY_BUILD) && !defined(ANDROID)
1514 // dbType is either "cert9.db" or "key4.db"
1515 void UnmigrateOneCertDB(const nsCOMPtr
<nsIFile
>& profileDirectory
,
1516 const nsACString
& dbType
) {
1517 nsCOMPtr
<nsIFile
> dbFile
;
1518 nsresult rv
= profileDirectory
->Clone(getter_AddRefs(dbFile
));
1519 if (NS_FAILED(rv
)) {
1522 rv
= dbFile
->AppendNative(dbType
);
1523 if (NS_FAILED(rv
)) {
1527 rv
= dbFile
->Exists(&exists
);
1528 if (NS_FAILED(rv
)) {
1531 // If the unprefixed DB already exists, don't overwrite it.
1535 nsCOMPtr
<nsIFile
> prefixedDBFile
;
1536 rv
= profileDirectory
->Clone(getter_AddRefs(prefixedDBFile
));
1537 if (NS_FAILED(rv
)) {
1540 nsAutoCString
prefixedDBName("gecko-no-share-");
1541 prefixedDBName
.Append(dbType
);
1542 rv
= prefixedDBFile
->AppendNative(prefixedDBName
);
1543 if (NS_FAILED(rv
)) {
1546 Unused
<< prefixedDBFile
->MoveToNative(nullptr, dbType
);
1549 void UnmigrateFromPrefixedCertDBs() {
1550 nsCOMPtr
<nsIFile
> profileDirectory
;
1551 nsresult rv
= NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR
,
1552 getter_AddRefs(profileDirectory
));
1553 if (NS_FAILED(rv
)) {
1556 UnmigrateOneCertDB(profileDirectory
, "cert9.db"_ns
);
1557 UnmigrateOneCertDB(profileDirectory
, "key4.db"_ns
);
1559 #endif // defined(NIGHTLY_BUILD) && !defined(ANDROID)
1561 nsresult
nsNSSComponent::InitializeNSS() {
1562 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("nsNSSComponent::InitializeNSS\n"));
1563 AUTO_PROFILER_LABEL("nsNSSComponent::InitializeNSS", OTHER
);
1564 AUTO_PROFILER_TRACING_MARKER("NSS", "nsNSSComponent::InitializeNSS", OTHER
);
1567 nsINSSErrorsService::NSS_SEC_ERROR_BASE
== SEC_ERROR_BASE
&&
1568 nsINSSErrorsService::NSS_SEC_ERROR_LIMIT
== SEC_ERROR_LIMIT
&&
1569 nsINSSErrorsService::NSS_SSL_ERROR_BASE
== SSL_ERROR_BASE
&&
1570 nsINSSErrorsService::NSS_SSL_ERROR_LIMIT
== SSL_ERROR_LIMIT
,
1571 "You must update the values in nsINSSErrorsService.idl");
1573 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("NSS Initialization beginning\n"));
1575 nsAutoCString profileStr
;
1576 nsresult rv
= GetNSSProfilePath(profileStr
);
1577 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv
));
1578 if (NS_FAILED(rv
)) {
1579 return NS_ERROR_NOT_AVAILABLE
;
1582 #if defined(NIGHTLY_BUILD) && !defined(ANDROID)
1583 if (!profileStr
.IsEmpty()) {
1584 UnmigrateFromPrefixedCertDBs();
1588 #if defined(XP_WIN) || (defined(XP_LINUX) && !defined(ANDROID))
1589 SetNSSDatabaseCacheModeAsAppropriate();
1592 bool nocertdb
= StaticPrefs::security_nocertdb_AtStartup();
1593 bool inSafeMode
= true;
1594 nsCOMPtr
<nsIXULRuntime
> runtime(do_GetService("@mozilla.org/xre/runtime;1"));
1595 // There might not be an nsIXULRuntime in embedded situations. This will
1596 // default to assuming we are in safe mode (as a result, no external PKCS11
1597 // modules will be loaded).
1599 rv
= runtime
->GetInSafeMode(&inSafeMode
);
1600 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv
));
1601 if (NS_FAILED(rv
)) {
1605 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("inSafeMode: %u\n", inSafeMode
));
1607 rv
= InitializeNSSWithFallbacks(profileStr
, nocertdb
, inSafeMode
);
1608 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv
));
1609 if (NS_FAILED(rv
)) {
1610 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("failed to initialize NSS"));
1614 PK11_SetPasswordFunc(PK11PasswordPrompt
);
1616 // Register an observer so we can inform NSS when these prefs change
1617 Preferences::AddStrongObserver(this, "security.");
1621 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv
));
1622 if (NS_FAILED(rv
)) {
1623 return NS_ERROR_UNEXPECTED
;
1626 nsCOMPtr
<nsICertOverrideService
> certOverrideService(
1627 do_GetService(NS_CERTOVERRIDE_CONTRACTID
));
1628 nsCOMPtr
<nsIClientAuthRememberService
> clientAuthRememberService(
1629 do_GetService(NS_CLIENTAUTHREMEMBERSERVICE_CONTRACTID
));
1630 nsCOMPtr
<nsISiteSecurityService
> siteSecurityService(
1631 do_GetService(NS_SSSERVICE_CONTRACTID
));
1632 nsCOMPtr
<nsICertStorage
> certStorage(do_GetService(NS_CERT_STORAGE_CID
));
1634 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("NSS Initialization done\n"));
1637 MutexAutoLock
lock(mMutex
);
1639 // ensure we have initial values for various root hashes
1641 mTestBuiltInRootHash
.Truncate();
1642 Preferences::GetCString("security.test.built_in_root_hash",
1643 mTestBuiltInRootHash
);
1645 mMitmCanaryIssuer
.Truncate();
1646 Preferences::GetString("security.pki.mitm_canary_issuer",
1648 mMitmDetecionEnabled
=
1649 Preferences::GetBool("security.pki.mitm_canary_issuer.enabled", true);
1651 // Set dynamic options from prefs.
1652 setValidationOptions(true, lock
);
1654 bool importEnterpriseRoots
=
1655 StaticPrefs::security_enterprise_roots_enabled();
1656 Vector
<nsCString
> possibleLoadableRootsLocations
;
1657 rv
= ListPossibleLoadableRootsLocations(possibleLoadableRootsLocations
);
1658 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv
));
1659 if (NS_FAILED(rv
)) {
1663 bool loadOSClientCertsModule
=
1664 StaticPrefs::security_osclientcerts_autoload();
1665 Maybe
<nsCString
> maybeOSClientCertsModuleLocation
;
1666 if (loadOSClientCertsModule
) {
1667 nsAutoCString libraryDir
;
1668 if (NS_SUCCEEDED(GetDirectoryPath(NS_GRE_BIN_DIR
, libraryDir
))) {
1669 maybeOSClientCertsModuleLocation
.emplace(libraryDir
);
1672 RefPtr
<LoadLoadableCertsTask
> loadLoadableCertsTask(
1673 new LoadLoadableCertsTask(this, importEnterpriseRoots
,
1674 std::move(possibleLoadableRootsLocations
),
1675 std::move(maybeOSClientCertsModuleLocation
)));
1676 rv
= loadLoadableCertsTask
->Dispatch();
1677 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv
));
1678 if (NS_FAILED(rv
)) {
1686 void nsNSSComponent::PrepareForShutdown() {
1687 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("nsNSSComponent::PrepareForShutdown"));
1688 MOZ_RELEASE_ASSERT(NS_IsMainThread());
1690 PK11_SetPasswordFunc((PK11PasswordFunc
) nullptr);
1692 Preferences::RemoveObserver(this, "security.");
1694 // Release the default CertVerifier. This will cause any held NSS resources
1696 MutexAutoLock
lock(mMutex
);
1697 mDefaultCertVerifier
= nullptr;
1698 // We don't actually shut down NSS - XPCOM does, after all threads have been
1699 // joined and the component manager has been shut down (and so there shouldn't
1700 // be any XPCOM objects holding NSS resources).
1703 nsresult
nsNSSComponent::Init() {
1704 MOZ_RELEASE_ASSERT(NS_IsMainThread());
1705 if (!NS_IsMainThread()) {
1706 return NS_ERROR_NOT_SAME_THREAD
;
1709 MOZ_ASSERT(XRE_IsParentProcess());
1710 if (!XRE_IsParentProcess()) {
1711 return NS_ERROR_NOT_AVAILABLE
;
1714 AutoGleanTimer
<&glean::networking::nss_initialization
> timer
;
1716 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("Beginning NSS initialization\n"));
1718 nsresult rv
= InitializeNSS();
1719 if (NS_FAILED(rv
)) {
1720 MOZ_LOG(gPIPNSSLog
, LogLevel::Error
,
1721 ("nsNSSComponent::InitializeNSS() failed\n"));
1725 rv
= RegisterObservers();
1726 if (NS_FAILED(rv
)) {
1733 // nsISupports Implementation for the class
1734 NS_IMPL_ISUPPORTS(nsNSSComponent
, nsINSSComponent
, nsIObserver
)
1736 static const char* const PROFILE_BEFORE_CHANGE_TOPIC
= "profile-before-change";
1739 nsNSSComponent::Observe(nsISupports
* aSubject
, const char* aTopic
,
1740 const char16_t
* someData
) {
1741 // In some tests, we don't receive a "profile-before-change" topic. However,
1742 // we still have to shut down before the storage service shuts down, because
1743 // closing the sql-backed softoken requires sqlite still be available. Thus,
1744 // we observe "xpcom-shutdown" just in case.
1745 if (nsCRT::strcmp(aTopic
, PROFILE_BEFORE_CHANGE_TOPIC
) == 0 ||
1746 nsCRT::strcmp(aTopic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
) == 0) {
1747 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
1748 ("receiving profile change or XPCOM shutdown notification"));
1749 PrepareForShutdown();
1750 } else if (nsCRT::strcmp(aTopic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
) == 0) {
1751 bool clearSessionCache
= true;
1752 NS_ConvertUTF16toUTF8
prefName(someData
);
1754 if (HandleTLSPrefChange(prefName
)) {
1755 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("HandleTLSPrefChange done"));
1757 prefName
.EqualsLiteral("security.OCSP.enabled") ||
1758 prefName
.EqualsLiteral("security.OCSP.require") ||
1759 prefName
.EqualsLiteral("security.pki.cert_short_lifetime_in_days") ||
1760 prefName
.EqualsLiteral("security.ssl.enable_ocsp_stapling") ||
1761 prefName
.EqualsLiteral("security.ssl.enable_ocsp_must_staple") ||
1762 prefName
.EqualsLiteral("security.pki.certificate_transparency.mode") ||
1763 prefName
.EqualsLiteral(
1764 "security.pki.certificate_transparency.disable_for_hosts") ||
1765 prefName
.EqualsLiteral(
1766 "security.pki.certificate_transparency.disable_for_spki_hashes") ||
1767 prefName
.EqualsLiteral("security.pki.netscape_step_up_policy") ||
1768 prefName
.EqualsLiteral("security.OCSP.timeoutMilliseconds.soft") ||
1769 prefName
.EqualsLiteral("security.OCSP.timeoutMilliseconds.hard") ||
1770 prefName
.EqualsLiteral("security.pki.crlite_mode")) {
1771 MutexAutoLock
lock(mMutex
);
1772 setValidationOptions(false, lock
);
1774 } else if (prefName
.EqualsLiteral("security.test.built_in_root_hash")) {
1775 MutexAutoLock
lock(mMutex
);
1776 mTestBuiltInRootHash
.Truncate();
1777 Preferences::GetCString("security.test.built_in_root_hash",
1778 mTestBuiltInRootHash
);
1780 } else if (prefName
.Equals("security.enterprise_roots.enabled")) {
1781 UnloadEnterpriseRoots();
1782 MaybeImportEnterpriseRoots();
1783 } else if (prefName
.Equals("security.osclientcerts.autoload")) {
1784 bool loadOSClientCertsModule
=
1785 StaticPrefs::security_osclientcerts_autoload();
1786 AsyncLoadOrUnloadOSClientCertsModule(loadOSClientCertsModule
);
1787 } else if (prefName
.EqualsLiteral("security.pki.mitm_canary_issuer")) {
1788 MutexAutoLock
lock(mMutex
);
1789 mMitmCanaryIssuer
.Truncate();
1790 Preferences::GetString("security.pki.mitm_canary_issuer",
1792 } else if (prefName
.EqualsLiteral(
1793 "security.pki.mitm_canary_issuer.enabled")) {
1794 MutexAutoLock
lock(mMutex
);
1795 mMitmDetecionEnabled
=
1796 Preferences::GetBool("security.pki.mitm_canary_issuer.enabled", true);
1798 clearSessionCache
= false;
1800 if (clearSessionCache
) {
1801 ClearSSLExternalAndInternalSessionCache();
1803 } else if (!nsCRT::strcmp(aTopic
, "last-pb-context-exited")) {
1804 nsNSSComponent::DoClearSSLExternalAndInternalSessionCache();
1811 nsresult
nsNSSComponent::GetNewPrompter(nsIPrompt
** result
) {
1812 NS_ENSURE_ARG_POINTER(result
);
1815 if (!NS_IsMainThread()) {
1816 NS_ERROR("nsSDRContext::GetNewPrompter called off the main thread");
1817 return NS_ERROR_NOT_SAME_THREAD
;
1821 nsCOMPtr
<nsIWindowWatcher
> wwatch(
1822 do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
));
1823 NS_ENSURE_SUCCESS(rv
, rv
);
1825 rv
= wwatch
->GetNewPrompter(0, result
);
1826 NS_ENSURE_SUCCESS(rv
, rv
);
1831 nsresult
nsNSSComponent::LogoutAuthenticatedPK11() {
1832 ClearSSLExternalAndInternalSessionCache();
1834 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
1836 os
->NotifyObservers(nullptr, "net:cancel-all-connections", nullptr);
1842 nsresult
nsNSSComponent::RegisterObservers() {
1843 nsCOMPtr
<nsIObserverService
> observerService(
1844 do_GetService("@mozilla.org/observer-service;1"));
1845 if (!observerService
) {
1846 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
1847 ("nsNSSComponent: couldn't get observer service\n"));
1848 return NS_ERROR_FAILURE
;
1851 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, ("nsNSSComponent: adding observers\n"));
1852 // Using false for the ownsweak parameter means the observer service will
1853 // keep a strong reference to this component. As a result, this will live at
1854 // least as long as the observer service.
1855 observerService
->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC
, false);
1856 observerService
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
, false);
1857 observerService
->AddObserver(this, "last-pb-context-exited", false);
1862 nsresult
DoesCertMatchFingerprint(const nsTArray
<uint8_t>& cert
,
1863 const nsCString
& fingerprint
, bool& result
) {
1866 if (cert
.Length() > std::numeric_limits
<uint32_t>::max()) {
1867 return NS_ERROR_INVALID_ARG
;
1869 nsTArray
<uint8_t> digestArray
;
1870 nsresult rv
= Digest::DigestBuf(SEC_OID_SHA256
, cert
.Elements(),
1871 cert
.Length(), digestArray
);
1872 if (NS_FAILED(rv
)) {
1875 SECItem digestItem
= {siBuffer
, digestArray
.Elements(),
1876 static_cast<unsigned int>(digestArray
.Length())};
1877 UniquePORTString
certFingerprint(
1878 CERT_Hexify(&digestItem
, true /* use colon delimiters */));
1879 if (!certFingerprint
) {
1880 return NS_ERROR_FAILURE
;
1883 result
= fingerprint
.Equals(certFingerprint
.get());
1888 nsNSSComponent::IsCertTestBuiltInRoot(const nsTArray
<uint8_t>& cert
,
1890 NS_ENSURE_ARG_POINTER(result
);
1894 MutexAutoLock
lock(mMutex
);
1895 nsresult rv
= DoesCertMatchFingerprint(cert
, mTestBuiltInRootHash
, *result
);
1896 if (NS_FAILED(rv
)) {
1905 nsNSSComponent::IssuerMatchesMitmCanary(const char* aCertIssuer
) {
1906 MutexAutoLock
lock(mMutex
);
1907 if (mMitmDetecionEnabled
&& !mMitmCanaryIssuer
.IsEmpty()) {
1908 nsString certIssuer
= NS_ConvertUTF8toUTF16(aCertIssuer
);
1909 if (mMitmCanaryIssuer
.Equals(certIssuer
)) {
1914 return NS_ERROR_FAILURE
;
1917 SharedCertVerifier::~SharedCertVerifier() = default;
1920 nsNSSComponent::GetDefaultCertVerifier(SharedCertVerifier
** result
) {
1921 MutexAutoLock
lock(mMutex
);
1922 NS_ENSURE_ARG_POINTER(result
);
1923 RefPtr
<SharedCertVerifier
> certVerifier(mDefaultCertVerifier
);
1924 certVerifier
.forget(result
);
1929 void nsNSSComponent::DoClearSSLExternalAndInternalSessionCache() {
1930 SSL_ClearSessionCache();
1931 mozilla::net::SSLTokensCache::Clear();
1935 nsNSSComponent::ClearSSLExternalAndInternalSessionCache() {
1936 MOZ_ASSERT(XRE_IsParentProcess());
1937 if (!XRE_IsParentProcess()) {
1938 return NS_ERROR_NOT_AVAILABLE
;
1941 if (mozilla::net::nsIOService::UseSocketProcess()) {
1942 if (mozilla::net::gIOService
) {
1943 mozilla::net::gIOService
->CallOrWaitForSocketProcess([]() {
1944 RefPtr
<mozilla::net::SocketProcessParent
> socketParent
=
1945 mozilla::net::SocketProcessParent::GetSingleton();
1946 Unused
<< socketParent
->SendClearSessionCache();
1950 DoClearSSLExternalAndInternalSessionCache();
1955 nsNSSComponent::AsyncClearSSLExternalAndInternalSessionCache(
1956 JSContext
* aCx
, ::mozilla::dom::Promise
** aPromise
) {
1957 MOZ_ASSERT(XRE_IsParentProcess());
1958 if (!XRE_IsParentProcess()) {
1959 return NS_ERROR_NOT_AVAILABLE
;
1962 nsIGlobalObject
* globalObject
= xpc::CurrentNativeGlobal(aCx
);
1963 if (NS_WARN_IF(!globalObject
)) {
1964 return NS_ERROR_FAILURE
;
1968 RefPtr
<mozilla::dom::Promise
> promise
=
1969 mozilla::dom::Promise::Create(globalObject
, result
);
1970 if (NS_WARN_IF(result
.Failed())) {
1971 return result
.StealNSResult();
1974 if (mozilla::net::nsIOService::UseSocketProcess() &&
1975 mozilla::net::gIOService
) {
1976 mozilla::net::gIOService
->CallOrWaitForSocketProcess([p
= RefPtr
{
1978 RefPtr
<mozilla::net::SocketProcessParent
> socketParent
=
1979 mozilla::net::SocketProcessParent::GetSingleton();
1980 Unused
<< socketParent
->SendClearSessionCache()->Then(
1981 GetCurrentSerialEventTarget(), __func__
,
1982 [promise
= RefPtr
{p
}] { promise
->MaybeResolveWithUndefined(); },
1983 [promise
= RefPtr
{p
}] { promise
->MaybeReject(NS_ERROR_UNEXPECTED
); });
1986 promise
->MaybeResolveWithUndefined();
1988 DoClearSSLExternalAndInternalSessionCache();
1989 promise
.forget(aPromise
);
1996 already_AddRefed
<SharedCertVerifier
> GetDefaultCertVerifier() {
1997 static NS_DEFINE_CID(kNSSComponentCID
, NS_NSSCOMPONENT_CID
);
1999 nsCOMPtr
<nsINSSComponent
> nssComponent(do_GetService(kNSSComponentCID
));
2000 if (!nssComponent
) {
2003 nsresult rv
= nssComponent
->BlockUntilLoadableCertsLoaded();
2004 if (NS_FAILED(rv
)) {
2007 RefPtr
<SharedCertVerifier
> result
;
2008 rv
= nssComponent
->GetDefaultCertVerifier(getter_AddRefs(result
));
2009 if (NS_FAILED(rv
)) {
2012 return result
.forget();
2015 // Helper for FindClientCertificatesWithPrivateKeys. Copies all
2016 // CERTCertificates from `from` to `to`.
2017 static inline void CopyCertificatesTo(UniqueCERTCertList
& from
,
2018 UniqueCERTCertList
& to
) {
2021 for (CERTCertListNode
* n
= CERT_LIST_HEAD(from
.get());
2022 !CERT_LIST_END(n
, from
.get()); n
= CERT_LIST_NEXT(n
)) {
2023 UniqueCERTCertificate
cert(CERT_DupCertificate(n
->cert
));
2024 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
2025 (" provisionally adding '%s'", n
->cert
->subjectName
));
2026 if (CERT_AddCertToListTail(to
.get(), cert
.get()) == SECSuccess
) {
2027 Unused
<< cert
.release();
2032 // Lists all private keys on all modules and returns a list of any corresponding
2033 // client certificates. Returns null if no such certificates can be found. Also
2034 // returns null if an error is encountered, because this is called as part of
2035 // the client auth data callback, and NSS ignores any errors returned by the
2037 UniqueCERTCertList
FindClientCertificatesWithPrivateKeys() {
2038 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
2039 ("FindClientCertificatesWithPrivateKeys"));
2041 (void)BlockUntilLoadableCertsLoaded();
2042 (void)CheckForSmartCardChanges();
2044 UniqueCERTCertList
certsWithPrivateKeys(CERT_NewCertList());
2045 if (!certsWithPrivateKeys
) {
2049 UniquePK11SlotInfo
internalSlot(PK11_GetInternalKeySlot());
2051 AutoSECMODListReadLock secmodLock
;
2052 SECMODModuleList
* list
= SECMOD_GetDefaultModuleList();
2054 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
2055 (" module '%s'", list
->module
->commonName
));
2056 for (int i
= 0; i
< list
->module
->slotCount
; i
++) {
2057 PK11SlotInfo
* slot
= list
->module
->slots
[i
];
2058 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
2059 (" slot '%s'", PK11_GetSlotName(slot
)));
2060 // If this is the internal certificate/key slot or the slot on the
2061 // builtin roots module, there may be many more certificates than private
2062 // keys, so search by private keys (PK11_HasRootCerts will be true if the
2063 // slot contains an object with the vendor-specific CK_CLASS
2064 // CKO_NSS_BUILTIN_ROOT_LIST, which should only be the case for the NSS
2065 // builtin roots module).
2066 if (internalSlot
.get() == slot
|| PK11_HasRootCerts(slot
)) {
2067 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
2068 (" (looking at internal/builtin slot)"));
2069 if (PK11_Authenticate(slot
, true, nullptr) != SECSuccess
) {
2070 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, (" (couldn't authenticate)"));
2073 UniqueSECKEYPrivateKeyList
privateKeys(
2074 PK11_ListPrivKeysInSlot(slot
, nullptr, nullptr));
2076 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, (" (no private keys)"));
2079 for (SECKEYPrivateKeyListNode
* node
= PRIVKEY_LIST_HEAD(privateKeys
);
2080 !PRIVKEY_LIST_END(node
, privateKeys
);
2081 node
= PRIVKEY_LIST_NEXT(node
)) {
2082 UniqueCERTCertList
certs(PK11_GetCertsMatchingPrivateKey(node
->key
));
2084 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
2085 (" PK11_GetCertsMatchingPrivateKey encountered an "
2089 if (CERT_LIST_EMPTY(certs
)) {
2090 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, (" (no certs for key)"));
2093 CopyCertificatesTo(certs
, certsWithPrivateKeys
);
2096 // ... otherwise, optimistically assume that searching by certificate
2097 // won't take too much time. Since "friendly" slots expose certificates
2098 // without needing to be authenticated to, this results in fewer PIN
2099 // dialogs shown to the user.
2100 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
2101 (" (looking at non-internal slot)"));
2103 if (!PK11_IsPresent(slot
)) {
2104 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, (" (not present)"));
2107 // If this isn't a "friendly" slot, authenticate to expose certificates.
2108 if (!PK11_IsFriendly(slot
) &&
2109 PK11_Authenticate(slot
, true, nullptr) != SECSuccess
) {
2110 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, (" (couldn't authenticate)"));
2113 UniqueCERTCertList
certsInSlot(PK11_ListCertsInSlot(slot
));
2115 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
2116 (" (couldn't list certs in slot)"));
2119 // When NSS decodes a certificate, if that certificate has a
2120 // corresponding private key (or public key, if the slot it's on hasn't
2121 // been logged into), it notes it as a "user cert".
2122 if (CERT_FilterCertListForUserCerts(certsInSlot
.get()) != SECSuccess
) {
2123 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
2124 (" (couldn't filter certs)"));
2127 CopyCertificatesTo(certsInSlot
, certsWithPrivateKeys
);
2133 if (CERT_FilterCertListByUsage(certsWithPrivateKeys
.get(), certUsageSSLClient
,
2134 false) != SECSuccess
) {
2135 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
,
2136 (" CERT_FilterCertListByUsage encountered an error - returning"));
2140 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPIPNSSLog
, LogLevel::Debug
))) {
2141 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, (" returning:"));
2142 for (CERTCertListNode
* n
= CERT_LIST_HEAD(certsWithPrivateKeys
);
2143 !CERT_LIST_END(n
, certsWithPrivateKeys
); n
= CERT_LIST_NEXT(n
)) {
2144 MOZ_LOG(gPIPNSSLog
, LogLevel::Debug
, (" %s", n
->cert
->subjectName
));
2148 if (CERT_LIST_EMPTY(certsWithPrivateKeys
)) {
2152 return certsWithPrivateKeys
;
2155 CertVerifier::CertificateTransparencyMode
GetCertificateTransparencyMode() {
2156 const CertVerifier::CertificateTransparencyMode defaultCTMode
=
2157 CertVerifier::CertificateTransparencyMode::TelemetryOnly
;
2158 CertVerifier::CertificateTransparencyMode ctMode
=
2159 static_cast<CertVerifier::CertificateTransparencyMode
>(
2160 StaticPrefs::security_pki_certificate_transparency_mode());
2162 case CertVerifier::CertificateTransparencyMode::Disabled
:
2163 case CertVerifier::CertificateTransparencyMode::TelemetryOnly
:
2164 case CertVerifier::CertificateTransparencyMode::Enforce
:
2167 ctMode
= defaultCTMode
;
2174 } // namespace mozilla
2176 NS_IMPL_ISUPPORTS(PipUIContext
, nsIInterfaceRequestor
)
2178 PipUIContext::PipUIContext() = default;
2180 PipUIContext::~PipUIContext() = default;
2183 PipUIContext::GetInterface(const nsIID
& uuid
, void** result
) {
2184 NS_ENSURE_ARG_POINTER(result
);
2187 if (!NS_IsMainThread()) {
2188 NS_ERROR("PipUIContext::GetInterface called off the main thread");
2189 return NS_ERROR_NOT_SAME_THREAD
;
2192 if (!uuid
.Equals(NS_GET_IID(nsIPrompt
))) return NS_ERROR_NO_INTERFACE
;
2194 nsIPrompt
* prompt
= nullptr;
2195 nsresult rv
= nsNSSComponent::GetNewPrompter(&prompt
);
2200 nsresult
getNSSDialogs(void** _result
, REFNSIID aIID
, const char* contract
) {
2201 if (!NS_IsMainThread()) {
2202 NS_ERROR("getNSSDialogs called off the main thread");
2203 return NS_ERROR_NOT_SAME_THREAD
;
2208 nsCOMPtr
<nsISupports
> svc
= do_GetService(contract
, &rv
);
2209 if (NS_FAILED(rv
)) {
2213 rv
= svc
->QueryInterface(aIID
, _result
);
2218 nsresult
setPassword(PK11SlotInfo
* slot
, nsIInterfaceRequestor
* ctx
) {
2221 NS_ENSURE_ARG_POINTER(slot
);
2222 NS_ENSURE_ARG_POINTER(ctx
);
2224 if (PK11_NeedUserInit(slot
)) {
2225 nsCOMPtr
<nsITokenPasswordDialogs
> dialogs
;
2226 nsresult rv
= getNSSDialogs(getter_AddRefs(dialogs
),
2227 NS_GET_IID(nsITokenPasswordDialogs
),
2228 NS_TOKENPASSWORDSDIALOG_CONTRACTID
);
2229 if (NS_FAILED(rv
)) {
2234 nsCOMPtr
<nsIPK11Token
> token
= new nsPK11Token(slot
);
2235 rv
= dialogs
->SetPassword(ctx
, token
, &canceled
);
2236 if (NS_FAILED(rv
)) {
2241 return NS_ERROR_NOT_AVAILABLE
;
2248 static PRBool
ConvertBetweenUCS2andASCII(PRBool toUnicode
, unsigned char* inBuf
,
2249 unsigned int inBufLen
,
2250 unsigned char* outBuf
,
2251 unsigned int maxOutBufLen
,
2252 unsigned int* outBufLen
,
2254 std::unique_ptr
<unsigned char[]> inBufDup(new unsigned char[inBufLen
]);
2258 std::memcpy(inBufDup
.get(), inBuf
, inBufLen
* sizeof(unsigned char));
2260 // If converting Unicode to ASCII, swap bytes before conversion as neccessary.
2261 if (!toUnicode
&& swapBytes
) {
2262 if (inBufLen
% 2 != 0) {
2265 mozilla::NativeEndian::swapFromLittleEndianInPlace(
2266 reinterpret_cast<char16_t
*>(inBufDup
.get()), inBufLen
/ 2);
2268 return PORT_UCS2_UTF8Conversion(toUnicode
, inBufDup
.get(), inBufLen
, outBuf
,
2269 maxOutBufLen
, outBufLen
);
2275 nsresult
InitializeCipherSuite() {
2276 MOZ_ASSERT(NS_IsMainThread(),
2277 "InitializeCipherSuite() can only be accessed on the main thread");
2279 if (NSS_SetDomesticPolicy() != SECSuccess
) {
2280 return NS_ERROR_FAILURE
;
2283 // Disable any ciphers that NSS might have enabled by default
2284 for (uint16_t i
= 0; i
< SSL_NumImplementedCiphers
; ++i
) {
2285 uint16_t cipher_id
= SSL_ImplementedCiphers
[i
];
2286 SSL_CipherPrefSetDefault(cipher_id
, false);
2289 // Now only set SSL/TLS ciphers we knew about at compile time
2290 for (const auto& cipherPref
: sCipherPrefs
) {
2291 SSL_CipherPrefSetDefault(cipherPref
.id
, cipherPref
.prefGetter());
2294 SetDeprecatedTLS1CipherPrefs();
2296 // Enable ciphers for PKCS#12
2297 SEC_PKCS12EnableCipher(PKCS12_RC4_40
, 1);
2298 SEC_PKCS12EnableCipher(PKCS12_RC4_128
, 1);
2299 SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40
, 1);
2300 SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128
, 1);
2301 SEC_PKCS12EnableCipher(PKCS12_DES_56
, 1);
2302 SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168
, 1);
2303 SEC_PKCS12EnableCipher(PKCS12_AES_CBC_128
, 1);
2304 SEC_PKCS12EnableCipher(PKCS12_AES_CBC_192
, 1);
2305 SEC_PKCS12EnableCipher(PKCS12_AES_CBC_256
, 1);
2306 SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168
, 1);
2307 PORT_SetUCS2_ASCIIConversionFunction(ConvertBetweenUCS2andASCII
);
2309 // PSM enforces a minimum RSA key size of 1024 bits, which is overridable.
2310 // NSS has its own minimum, which is not overridable (the default is 1023
2311 // bits). This sets the NSS minimum to 512 bits so users can still connect to
2312 // devices like wifi routers with woefully small keys (they would have to add
2313 // an override to do so, but they already do for such devices).
2314 NSS_OptionSet(NSS_RSA_MIN_KEY_SIZE
, 512);
2318 // Observe preference change around cipher suite setting.
2319 return CipherSuiteChangeObserver::StartObserve();
2323 } // namespace mozilla