Backed out changeset f53842753805 (bug 1804872) for causing reftest failures on 15535...
[gecko.git] / security / manager / ssl / nsPKCS11Slot.cpp
blob130e79033d88d549bc8a0216d318ef803118eaff
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "nsPKCS11Slot.h"
7 #include <string.h>
9 #include "mozilla/Casting.h"
10 #include "mozilla/Logging.h"
11 #include "mozilla/Telemetry.h"
12 #include "mozilla/Unused.h"
13 #include "nsCOMPtr.h"
14 #include "nsIMutableArray.h"
15 #include "nsNSSCertHelper.h"
16 #include "nsNSSComponent.h"
17 #include "nsPK11TokenDB.h"
18 #include "nsPromiseFlatString.h"
19 #include "nsComponentManagerUtils.h"
20 #include "secmod.h"
22 using mozilla::LogLevel;
24 extern mozilla::LazyLogModule gPIPNSSLog;
26 NS_IMPL_ISUPPORTS(nsPKCS11Slot, nsIPKCS11Slot)
28 nsPKCS11Slot::nsPKCS11Slot(PK11SlotInfo* slot) {
29 MOZ_ASSERT(slot);
30 mSlot.reset(PK11_ReferenceSlot(slot));
31 mIsInternalCryptoSlot =
32 PK11_IsInternal(mSlot.get()) && !PK11_IsInternalKeySlot(mSlot.get());
33 mIsInternalKeySlot = PK11_IsInternalKeySlot(mSlot.get());
34 mSeries = PK11_GetSlotSeries(slot);
35 mozilla::Unused << refreshSlotInfo();
38 nsresult nsPKCS11Slot::refreshSlotInfo() {
39 CK_SLOT_INFO slotInfo;
40 nsresult rv = mozilla::MapSECStatus(PK11_GetSlotInfo(mSlot.get(), &slotInfo));
41 if (NS_FAILED(rv)) {
42 return rv;
45 // Set the Description field
46 if (mIsInternalCryptoSlot) {
47 nsresult rv;
48 if (PK11_IsFIPS()) {
49 rv = GetPIPNSSBundleString("Fips140SlotDescription", mSlotDesc);
50 } else {
51 rv = GetPIPNSSBundleString("SlotDescription", mSlotDesc);
53 if (NS_FAILED(rv)) {
54 return rv;
56 } else if (mIsInternalKeySlot) {
57 rv = GetPIPNSSBundleString("PrivateSlotDescription", mSlotDesc);
58 if (NS_FAILED(rv)) {
59 return rv;
61 } else {
62 const char* ccDesc =
63 mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(slotInfo.slotDescription);
64 mSlotDesc.Assign(ccDesc, strnlen(ccDesc, sizeof(slotInfo.slotDescription)));
65 mSlotDesc.Trim(" ", false, true);
68 // Set the Manufacturer field
69 if (mIsInternalCryptoSlot || mIsInternalKeySlot) {
70 rv = GetPIPNSSBundleString("ManufacturerID", mSlotManufacturerID);
71 if (NS_FAILED(rv)) {
72 return rv;
74 } else {
75 const char* ccManID =
76 mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(slotInfo.manufacturerID);
77 mSlotManufacturerID.Assign(
78 ccManID, strnlen(ccManID, sizeof(slotInfo.manufacturerID)));
79 mSlotManufacturerID.Trim(" ", false, true);
82 // Set the Hardware Version field
83 mSlotHWVersion.Truncate();
84 mSlotHWVersion.AppendInt(slotInfo.hardwareVersion.major);
85 mSlotHWVersion.Append('.');
86 mSlotHWVersion.AppendInt(slotInfo.hardwareVersion.minor);
88 // Set the Firmware Version field
89 mSlotFWVersion.Truncate();
90 mSlotFWVersion.AppendInt(slotInfo.firmwareVersion.major);
91 mSlotFWVersion.Append('.');
92 mSlotFWVersion.AppendInt(slotInfo.firmwareVersion.minor);
94 return NS_OK;
97 nsresult nsPKCS11Slot::GetAttributeHelper(const nsACString& attribute,
98 /*out*/ nsACString& xpcomOutParam) {
99 if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
100 nsresult rv = refreshSlotInfo();
101 if (NS_FAILED(rv)) {
102 return rv;
106 xpcomOutParam = attribute;
107 return NS_OK;
110 NS_IMETHODIMP
111 nsPKCS11Slot::GetName(/*out*/ nsACString& name) {
112 if (mIsInternalCryptoSlot) {
113 if (PK11_IsFIPS()) {
114 return GetPIPNSSBundleString("Fips140TokenDescription", name);
116 return GetPIPNSSBundleString("TokenDescription", name);
118 if (mIsInternalKeySlot) {
119 return GetPIPNSSBundleString("PrivateTokenDescription", name);
121 name.Assign(PK11_GetSlotName(mSlot.get()));
123 return NS_OK;
126 NS_IMETHODIMP
127 nsPKCS11Slot::GetDesc(/*out*/ nsACString& desc) {
128 return GetAttributeHelper(mSlotDesc, desc);
131 NS_IMETHODIMP
132 nsPKCS11Slot::GetManID(/*out*/ nsACString& manufacturerID) {
133 return GetAttributeHelper(mSlotManufacturerID, manufacturerID);
136 NS_IMETHODIMP
137 nsPKCS11Slot::GetHWVersion(/*out*/ nsACString& hwVersion) {
138 return GetAttributeHelper(mSlotHWVersion, hwVersion);
141 NS_IMETHODIMP
142 nsPKCS11Slot::GetFWVersion(/*out*/ nsACString& fwVersion) {
143 return GetAttributeHelper(mSlotFWVersion, fwVersion);
146 NS_IMETHODIMP
147 nsPKCS11Slot::GetToken(nsIPK11Token** _retval) {
148 NS_ENSURE_ARG_POINTER(_retval);
149 nsCOMPtr<nsIPK11Token> token = new nsPK11Token(mSlot.get());
150 token.forget(_retval);
151 return NS_OK;
154 NS_IMETHODIMP
155 nsPKCS11Slot::GetTokenName(/*out*/ nsACString& tokenName) {
156 if (!PK11_IsPresent(mSlot.get())) {
157 tokenName.SetIsVoid(true);
158 return NS_OK;
161 if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
162 nsresult rv = refreshSlotInfo();
163 if (NS_FAILED(rv)) {
164 return rv;
168 if (mIsInternalCryptoSlot) {
169 if (PK11_IsFIPS()) {
170 return GetPIPNSSBundleString("Fips140TokenDescription", tokenName);
172 return GetPIPNSSBundleString("TokenDescription", tokenName);
174 if (mIsInternalKeySlot) {
175 return GetPIPNSSBundleString("PrivateTokenDescription", tokenName);
178 tokenName.Assign(PK11_GetTokenName(mSlot.get()));
179 return NS_OK;
182 NS_IMETHODIMP
183 nsPKCS11Slot::GetStatus(uint32_t* _retval) {
184 NS_ENSURE_ARG_POINTER(_retval);
185 if (PK11_IsDisabled(mSlot.get())) {
186 *_retval = SLOT_DISABLED;
187 } else if (!PK11_IsPresent(mSlot.get())) {
188 *_retval = SLOT_NOT_PRESENT;
189 } else if (PK11_NeedLogin(mSlot.get()) && PK11_NeedUserInit(mSlot.get())) {
190 *_retval = SLOT_UNINITIALIZED;
191 } else if (PK11_NeedLogin(mSlot.get()) &&
192 !PK11_IsLoggedIn(mSlot.get(), nullptr)) {
193 *_retval = SLOT_NOT_LOGGED_IN;
194 } else if (PK11_NeedLogin(mSlot.get())) {
195 *_retval = SLOT_LOGGED_IN;
196 } else {
197 *_retval = SLOT_READY;
199 return NS_OK;
202 NS_IMPL_ISUPPORTS(nsPKCS11Module, nsIPKCS11Module)
204 nsPKCS11Module::nsPKCS11Module(SECMODModule* module) {
205 MOZ_ASSERT(module);
206 mModule.reset(SECMOD_ReferenceModule(module));
209 // Convert the UTF8 internal name of the module to how it should appear to the
210 // user. In most cases this involves simply passing back the module's name.
211 // However, the builtin roots module has a non-localized name internally that we
212 // must map to the localized version when we display it to the user.
213 static nsresult NormalizeModuleNameOut(const char* moduleNameIn,
214 nsACString& moduleNameOut) {
215 // Easy case: this isn't the builtin roots module.
216 if (strnlen(moduleNameIn, kRootModuleNameLen + 1) != kRootModuleNameLen ||
217 strncmp(kRootModuleName, moduleNameIn, kRootModuleNameLen) != 0) {
218 moduleNameOut.Assign(moduleNameIn);
219 return NS_OK;
222 nsAutoString localizedRootModuleName;
223 nsresult rv =
224 GetPIPNSSBundleString("RootCertModuleName", localizedRootModuleName);
225 if (NS_FAILED(rv)) {
226 return rv;
228 moduleNameOut.Assign(NS_ConvertUTF16toUTF8(localizedRootModuleName));
229 return NS_OK;
232 NS_IMETHODIMP
233 nsPKCS11Module::GetName(/*out*/ nsACString& name) {
234 return NormalizeModuleNameOut(mModule->commonName, name);
237 NS_IMETHODIMP
238 nsPKCS11Module::GetLibName(/*out*/ nsACString& libName) {
239 if (mModule->dllName) {
240 libName = mModule->dllName;
241 } else {
242 libName.SetIsVoid(true);
244 return NS_OK;
247 NS_IMETHODIMP
248 nsPKCS11Module::ListSlots(nsISimpleEnumerator** _retval) {
249 NS_ENSURE_ARG_POINTER(_retval);
251 nsresult rv = CheckForSmartCardChanges();
252 if (NS_FAILED(rv)) {
253 return rv;
256 nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
257 if (!array) {
258 return NS_ERROR_FAILURE;
261 /* applications which allow new slot creation (which Firefox now does
262 * since it uses the WaitForSlotEvent call) need to hold the
263 * ModuleList Read lock to prevent the slot array from changing out
264 * from under it. */
265 mozilla::AutoSECMODListReadLock lock;
266 for (int i = 0; i < mModule->slotCount; i++) {
267 if (mModule->slots[i]) {
268 nsCOMPtr<nsIPKCS11Slot> slot = new nsPKCS11Slot(mModule->slots[i]);
269 rv = array->AppendElement(slot);
270 if (NS_FAILED(rv)) {
271 return rv;
276 return array->Enumerate(_retval, NS_GET_IID(nsIPKCS11Slot));