Bug 1935611 - Fix libyuv/libpng link failed for loongarch64. r=glandium,tnikkel,ng
[gecko.git] / security / manager / ssl / PKCS11ModuleDB.cpp
blob281dea67f4b2b5260531d20d6f090beb5bdb6a04
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 "PKCS11ModuleDB.h"
9 #include "CertVerifier.h"
10 #include "ScopedNSSTypes.h"
11 #include "mozilla/glean/GleanMetrics.h"
12 #include "nsComponentManagerUtils.h"
13 #include "nsIMutableArray.h"
14 #include "nsNSSCertHelper.h"
15 #include "nsNSSComponent.h"
16 #include "nsNativeCharsetUtils.h"
17 #include "nsPKCS11Slot.h"
18 #include "nsServiceManagerUtils.h"
20 namespace mozilla {
21 namespace psm {
23 NS_IMPL_ISUPPORTS(PKCS11ModuleDB, nsIPKCS11ModuleDB)
25 // Convert the UTF16 name of the module as it appears to the user to the
26 // internal representation. For most modules this just involves converting from
27 // UTF16 to UTF8. For the builtin root module, it also involves mapping from the
28 // localized name to the internal, non-localized name.
29 static nsresult NormalizeModuleNameIn(const nsAString& moduleNameIn,
30 nsCString& moduleNameOut) {
31 nsAutoString localizedRootModuleName;
32 nsresult rv =
33 GetPIPNSSBundleString("RootCertModuleName", localizedRootModuleName);
34 if (NS_FAILED(rv)) {
35 return rv;
37 if (moduleNameIn.Equals(localizedRootModuleName)) {
38 moduleNameOut.Assign(kRootModuleName.get());
39 return NS_OK;
41 moduleNameOut.Assign(NS_ConvertUTF16toUTF8(moduleNameIn));
42 return NS_OK;
45 // Delete a PKCS11 module from the user's profile.
46 NS_IMETHODIMP
47 PKCS11ModuleDB::DeleteModule(const nsAString& aModuleName) {
48 if (aModuleName.IsEmpty()) {
49 return NS_ERROR_INVALID_ARG;
52 nsAutoCString moduleNameNormalized;
53 nsresult rv = NormalizeModuleNameIn(aModuleName, moduleNameNormalized);
54 if (NS_FAILED(rv)) {
55 return rv;
57 // modType is an output variable. We ignore it.
58 int32_t modType;
59 SECStatus srv = SECMOD_DeleteModule(moduleNameNormalized.get(), &modType);
60 if (srv != SECSuccess) {
61 return NS_ERROR_FAILURE;
64 RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
65 if (!certVerifier) {
66 return NS_ERROR_FAILURE;
68 certVerifier->ClearTrustCache();
70 CollectThirdPartyPKCS11ModuleTelemetry();
72 return NS_OK;
75 // Add a new PKCS11 module to the user's profile.
76 NS_IMETHODIMP
77 PKCS11ModuleDB::AddModule(const nsAString& aModuleName,
78 const nsAString& aLibraryFullPath,
79 int32_t aCryptoMechanismFlags, int32_t aCipherFlags) {
80 if (aModuleName.IsEmpty()) {
81 return NS_ERROR_INVALID_ARG;
84 // "Root Certs" is the name some NSS command-line utilities will give the
85 // roots module if they decide to load it when there happens to be a
86 // `MOZ_DLL_PREFIX "nssckbi" MOZ_DLL_SUFFIX` file in the directory being
87 // operated on. This causes failures, so as a workaround, the PSM
88 // initialization code will unconditionally remove any module named "Root
89 // Certs". We should prevent the user from adding an unrelated module named
90 // "Root Certs" in the first place so PSM doesn't delete it. See bug 1406396.
91 if (aModuleName.EqualsLiteral("Root Certs")) {
92 return NS_ERROR_ILLEGAL_VALUE;
95 // There appears to be a deadlock if we try to load modules concurrently, so
96 // just wait until the loadable roots module has been loaded.
97 nsresult rv = BlockUntilLoadableCertsLoaded();
98 if (NS_FAILED(rv)) {
99 return rv;
102 nsAutoCString moduleNameNormalized;
103 rv = NormalizeModuleNameIn(aModuleName, moduleNameNormalized);
104 if (NS_FAILED(rv)) {
105 return rv;
107 nsCString fullPath;
108 CopyUTF16toUTF8(aLibraryFullPath, fullPath);
109 uint32_t mechFlags = SECMOD_PubMechFlagstoInternal(aCryptoMechanismFlags);
110 uint32_t cipherFlags = SECMOD_PubCipherFlagstoInternal(aCipherFlags);
111 SECStatus srv = SECMOD_AddNewModule(moduleNameNormalized.get(),
112 fullPath.get(), mechFlags, cipherFlags);
113 if (srv != SECSuccess) {
114 return NS_ERROR_FAILURE;
117 RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
118 if (!certVerifier) {
119 return NS_ERROR_FAILURE;
121 certVerifier->ClearTrustCache();
123 CollectThirdPartyPKCS11ModuleTelemetry();
125 return NS_OK;
128 NS_IMETHODIMP
129 PKCS11ModuleDB::ListModules(nsISimpleEnumerator** _retval) {
130 NS_ENSURE_ARG_POINTER(_retval);
132 nsresult rv = BlockUntilLoadableCertsLoaded();
133 if (NS_FAILED(rv)) {
134 return rv;
137 nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
138 if (!array) {
139 return NS_ERROR_FAILURE;
142 /* lock down the list for reading */
143 AutoSECMODListReadLock lock;
144 for (SECMODModuleList* list = SECMOD_GetDefaultModuleList(); list;
145 list = list->next) {
146 nsCOMPtr<nsIPKCS11Module> module = new nsPKCS11Module(list->module);
147 nsresult rv = array->AppendElement(module);
148 if (NS_FAILED(rv)) {
149 return rv;
153 /* Get the modules in the database that didn't load */
154 for (SECMODModuleList* list = SECMOD_GetDeadModuleList(); list;
155 list = list->next) {
156 nsCOMPtr<nsIPKCS11Module> module = new nsPKCS11Module(list->module);
157 nsresult rv = array->AppendElement(module);
158 if (NS_FAILED(rv)) {
159 return rv;
163 return array->Enumerate(_retval, NS_GET_IID(nsIPKCS11Module));
166 NS_IMETHODIMP
167 PKCS11ModuleDB::GetCanToggleFIPS(bool* aCanToggleFIPS) {
168 NS_ENSURE_ARG_POINTER(aCanToggleFIPS);
170 *aCanToggleFIPS = SECMOD_CanDeleteInternalModule();
171 return NS_OK;
174 NS_IMETHODIMP
175 PKCS11ModuleDB::ToggleFIPSMode() {
176 // The way to toggle FIPS mode in NSS is extremely obscure. Basically, we
177 // delete the internal module, and it gets replaced with the opposite module
178 // (i.e. if it was FIPS before, then it becomes non-FIPS next).
179 // SECMOD_GetInternalModule() returns a pointer to a local copy of the
180 // internal module stashed in NSS. We don't want to delete it since it will
181 // cause much pain in NSS.
182 SECMODModule* internal = SECMOD_GetInternalModule();
183 if (!internal) {
184 return NS_ERROR_FAILURE;
187 if (SECMOD_DeleteInternalModule(internal->commonName) != SECSuccess) {
188 return NS_ERROR_FAILURE;
191 return NS_OK;
194 NS_IMETHODIMP
195 PKCS11ModuleDB::GetIsFIPSEnabled(bool* aIsFIPSEnabled) {
196 NS_ENSURE_ARG_POINTER(aIsFIPSEnabled);
198 *aIsFIPSEnabled = PK11_IsFIPS();
199 return NS_OK;
202 const nsLiteralCString kBuiltInModuleNames[] = {
203 kNSSInternalModuleName,
204 kRootModuleName,
205 kOSClientCertsModuleName,
206 kIPCClientCertsModuleName,
209 void CollectThirdPartyPKCS11ModuleTelemetry() {
210 size_t thirdPartyModulesLoaded = 0;
211 AutoSECMODListReadLock lock;
212 for (SECMODModuleList* list = SECMOD_GetDefaultModuleList(); list;
213 list = list->next) {
214 bool isThirdParty = true;
215 for (const auto& builtInModuleName : kBuiltInModuleNames) {
216 if (builtInModuleName.Equals(list->module->commonName)) {
217 isThirdParty = false;
218 break;
221 if (isThirdParty) {
222 thirdPartyModulesLoaded++;
225 mozilla::glean::pkcs11::third_party_modules_loaded.Set(
226 thirdPartyModulesLoaded);
229 } // namespace psm
230 } // namespace mozilla