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"
9 #include "PKCS11ModuleDB.h"
10 #include "mozilla/Casting.h"
11 #include "mozilla/Logging.h"
12 #include "mozilla/Telemetry.h"
13 #include "mozilla/Unused.h"
15 #include "nsIMutableArray.h"
16 #include "nsNSSCertHelper.h"
17 #include "nsNSSComponent.h"
18 #include "nsPK11TokenDB.h"
19 #include "nsPromiseFlatString.h"
20 #include "nsComponentManagerUtils.h"
23 using mozilla::LogLevel
;
24 using namespace mozilla::psm
;
26 extern mozilla::LazyLogModule gPIPNSSLog
;
28 NS_IMPL_ISUPPORTS(nsPKCS11Slot
, nsIPKCS11Slot
)
30 nsPKCS11Slot::nsPKCS11Slot(PK11SlotInfo
* slot
) {
32 mSlot
.reset(PK11_ReferenceSlot(slot
));
33 mIsInternalCryptoSlot
=
34 PK11_IsInternal(mSlot
.get()) && !PK11_IsInternalKeySlot(mSlot
.get());
35 mIsInternalKeySlot
= PK11_IsInternalKeySlot(mSlot
.get());
36 mSeries
= PK11_GetSlotSeries(slot
);
37 mozilla::Unused
<< refreshSlotInfo();
40 nsresult
nsPKCS11Slot::refreshSlotInfo() {
41 CK_SLOT_INFO slotInfo
;
42 nsresult rv
= mozilla::MapSECStatus(PK11_GetSlotInfo(mSlot
.get(), &slotInfo
));
47 // Set the Description field
48 if (mIsInternalCryptoSlot
) {
51 rv
= GetPIPNSSBundleString("Fips140SlotDescription", mSlotDesc
);
53 rv
= GetPIPNSSBundleString("SlotDescription", mSlotDesc
);
58 } else if (mIsInternalKeySlot
) {
59 rv
= GetPIPNSSBundleString("PrivateSlotDescription", mSlotDesc
);
65 mozilla::BitwiseCast
<char*, CK_UTF8CHAR
*>(slotInfo
.slotDescription
);
66 mSlotDesc
.Assign(ccDesc
, strnlen(ccDesc
, sizeof(slotInfo
.slotDescription
)));
67 mSlotDesc
.Trim(" ", false, true);
70 // Set the Manufacturer field
71 if (mIsInternalCryptoSlot
|| mIsInternalKeySlot
) {
72 rv
= GetPIPNSSBundleString("ManufacturerID", mSlotManufacturerID
);
78 mozilla::BitwiseCast
<char*, CK_UTF8CHAR
*>(slotInfo
.manufacturerID
);
79 mSlotManufacturerID
.Assign(
80 ccManID
, strnlen(ccManID
, sizeof(slotInfo
.manufacturerID
)));
81 mSlotManufacturerID
.Trim(" ", false, true);
84 // Set the Hardware Version field
85 mSlotHWVersion
.Truncate();
86 mSlotHWVersion
.AppendInt(slotInfo
.hardwareVersion
.major
);
87 mSlotHWVersion
.Append('.');
88 mSlotHWVersion
.AppendInt(slotInfo
.hardwareVersion
.minor
);
90 // Set the Firmware Version field
91 mSlotFWVersion
.Truncate();
92 mSlotFWVersion
.AppendInt(slotInfo
.firmwareVersion
.major
);
93 mSlotFWVersion
.Append('.');
94 mSlotFWVersion
.AppendInt(slotInfo
.firmwareVersion
.minor
);
99 nsresult
nsPKCS11Slot::GetAttributeHelper(const nsACString
& attribute
,
100 /*out*/ nsACString
& xpcomOutParam
) {
101 if (PK11_GetSlotSeries(mSlot
.get()) != mSeries
) {
102 nsresult rv
= refreshSlotInfo();
108 xpcomOutParam
= attribute
;
113 nsPKCS11Slot::GetName(/*out*/ nsACString
& name
) {
114 if (mIsInternalCryptoSlot
) {
116 return GetPIPNSSBundleString("Fips140TokenDescription", name
);
118 return GetPIPNSSBundleString("TokenDescription", name
);
120 if (mIsInternalKeySlot
) {
121 return GetPIPNSSBundleString("PrivateTokenDescription", name
);
123 name
.Assign(PK11_GetSlotName(mSlot
.get()));
129 nsPKCS11Slot::GetDesc(/*out*/ nsACString
& desc
) {
130 return GetAttributeHelper(mSlotDesc
, desc
);
134 nsPKCS11Slot::GetManID(/*out*/ nsACString
& manufacturerID
) {
135 return GetAttributeHelper(mSlotManufacturerID
, manufacturerID
);
139 nsPKCS11Slot::GetHWVersion(/*out*/ nsACString
& hwVersion
) {
140 return GetAttributeHelper(mSlotHWVersion
, hwVersion
);
144 nsPKCS11Slot::GetFWVersion(/*out*/ nsACString
& fwVersion
) {
145 return GetAttributeHelper(mSlotFWVersion
, fwVersion
);
149 nsPKCS11Slot::GetToken(nsIPK11Token
** _retval
) {
150 NS_ENSURE_ARG_POINTER(_retval
);
151 nsCOMPtr
<nsIPK11Token
> token
= new nsPK11Token(mSlot
.get());
152 token
.forget(_retval
);
157 nsPKCS11Slot::GetTokenName(/*out*/ nsACString
& tokenName
) {
158 if (!PK11_IsPresent(mSlot
.get())) {
159 tokenName
.SetIsVoid(true);
163 if (PK11_GetSlotSeries(mSlot
.get()) != mSeries
) {
164 nsresult rv
= refreshSlotInfo();
170 if (mIsInternalCryptoSlot
) {
172 return GetPIPNSSBundleString("Fips140TokenDescription", tokenName
);
174 return GetPIPNSSBundleString("TokenDescription", tokenName
);
176 if (mIsInternalKeySlot
) {
177 return GetPIPNSSBundleString("PrivateTokenDescription", tokenName
);
180 tokenName
.Assign(PK11_GetTokenName(mSlot
.get()));
185 nsPKCS11Slot::GetStatus(uint32_t* _retval
) {
186 NS_ENSURE_ARG_POINTER(_retval
);
187 if (PK11_IsDisabled(mSlot
.get())) {
188 *_retval
= SLOT_DISABLED
;
189 } else if (!PK11_IsPresent(mSlot
.get())) {
190 *_retval
= SLOT_NOT_PRESENT
;
191 } else if (PK11_NeedLogin(mSlot
.get()) && PK11_NeedUserInit(mSlot
.get())) {
192 *_retval
= SLOT_UNINITIALIZED
;
193 } else if (PK11_NeedLogin(mSlot
.get()) &&
194 !PK11_IsLoggedIn(mSlot
.get(), nullptr)) {
195 *_retval
= SLOT_NOT_LOGGED_IN
;
196 } else if (PK11_NeedLogin(mSlot
.get())) {
197 *_retval
= SLOT_LOGGED_IN
;
199 *_retval
= SLOT_READY
;
204 NS_IMPL_ISUPPORTS(nsPKCS11Module
, nsIPKCS11Module
)
206 nsPKCS11Module::nsPKCS11Module(SECMODModule
* module
) {
208 mModule
.reset(SECMOD_ReferenceModule(module
));
211 // Convert the UTF8 internal name of the module to how it should appear to the
212 // user. In most cases this involves simply passing back the module's name.
213 // However, the builtin roots module has a non-localized name internally that we
214 // must map to the localized version when we display it to the user.
215 static nsresult
NormalizeModuleNameOut(const char* moduleNameIn
,
216 nsACString
& moduleNameOut
) {
217 // Easy case: this isn't the builtin roots module.
218 if (strnlen(moduleNameIn
, kRootModuleName
.Length() + 1) !=
219 kRootModuleName
.Length() ||
220 strncmp(kRootModuleName
.get(), moduleNameIn
, kRootModuleName
.Length()) !=
222 moduleNameOut
.Assign(moduleNameIn
);
226 nsAutoString localizedRootModuleName
;
228 GetPIPNSSBundleString("RootCertModuleName", localizedRootModuleName
);
232 moduleNameOut
.Assign(NS_ConvertUTF16toUTF8(localizedRootModuleName
));
237 nsPKCS11Module::GetName(/*out*/ nsACString
& name
) {
238 return NormalizeModuleNameOut(mModule
->commonName
, name
);
242 nsPKCS11Module::GetLibName(/*out*/ nsACString
& libName
) {
243 if (mModule
->dllName
) {
244 libName
= mModule
->dllName
;
246 libName
.SetIsVoid(true);
252 nsPKCS11Module::ListSlots(nsISimpleEnumerator
** _retval
) {
253 NS_ENSURE_ARG_POINTER(_retval
);
255 nsresult rv
= CheckForSmartCardChanges();
260 nsCOMPtr
<nsIMutableArray
> array
= do_CreateInstance(NS_ARRAY_CONTRACTID
);
262 return NS_ERROR_FAILURE
;
265 /* applications which allow new slot creation (which Firefox now does
266 * since it uses the WaitForSlotEvent call) need to hold the
267 * ModuleList Read lock to prevent the slot array from changing out
269 mozilla::AutoSECMODListReadLock lock
;
270 for (int i
= 0; i
< mModule
->slotCount
; i
++) {
271 if (mModule
->slots
[i
]) {
272 nsCOMPtr
<nsIPKCS11Slot
> slot
= new nsPKCS11Slot(mModule
->slots
[i
]);
273 rv
= array
->AppendElement(slot
);
280 return array
->Enumerate(_retval
, NS_GET_IID(nsIPKCS11Slot
));