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 "mozilla/Casting.h"
10 #include "mozilla/Logging.h"
11 #include "mozilla/Telemetry.h"
12 #include "mozilla/Unused.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"
22 using mozilla::LogLevel
;
24 extern mozilla::LazyLogModule gPIPNSSLog
;
26 NS_IMPL_ISUPPORTS(nsPKCS11Slot
, nsIPKCS11Slot
)
28 nsPKCS11Slot::nsPKCS11Slot(PK11SlotInfo
* 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
));
45 // Set the Description field
46 if (mIsInternalCryptoSlot
) {
49 rv
= GetPIPNSSBundleString("Fips140SlotDescription", mSlotDesc
);
51 rv
= GetPIPNSSBundleString("SlotDescription", mSlotDesc
);
56 } else if (mIsInternalKeySlot
) {
57 rv
= GetPIPNSSBundleString("PrivateSlotDescription", mSlotDesc
);
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
);
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
);
97 nsresult
nsPKCS11Slot::GetAttributeHelper(const nsACString
& attribute
,
98 /*out*/ nsACString
& xpcomOutParam
) {
99 if (PK11_GetSlotSeries(mSlot
.get()) != mSeries
) {
100 nsresult rv
= refreshSlotInfo();
106 xpcomOutParam
= attribute
;
111 nsPKCS11Slot::GetName(/*out*/ nsACString
& name
) {
112 if (mIsInternalCryptoSlot
) {
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()));
127 nsPKCS11Slot::GetDesc(/*out*/ nsACString
& desc
) {
128 return GetAttributeHelper(mSlotDesc
, desc
);
132 nsPKCS11Slot::GetManID(/*out*/ nsACString
& manufacturerID
) {
133 return GetAttributeHelper(mSlotManufacturerID
, manufacturerID
);
137 nsPKCS11Slot::GetHWVersion(/*out*/ nsACString
& hwVersion
) {
138 return GetAttributeHelper(mSlotHWVersion
, hwVersion
);
142 nsPKCS11Slot::GetFWVersion(/*out*/ nsACString
& fwVersion
) {
143 return GetAttributeHelper(mSlotFWVersion
, fwVersion
);
147 nsPKCS11Slot::GetToken(nsIPK11Token
** _retval
) {
148 NS_ENSURE_ARG_POINTER(_retval
);
149 nsCOMPtr
<nsIPK11Token
> token
= new nsPK11Token(mSlot
.get());
150 token
.forget(_retval
);
155 nsPKCS11Slot::GetTokenName(/*out*/ nsACString
& tokenName
) {
156 if (!PK11_IsPresent(mSlot
.get())) {
157 tokenName
.SetIsVoid(true);
161 if (PK11_GetSlotSeries(mSlot
.get()) != mSeries
) {
162 nsresult rv
= refreshSlotInfo();
168 if (mIsInternalCryptoSlot
) {
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()));
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
;
197 *_retval
= SLOT_READY
;
202 NS_IMPL_ISUPPORTS(nsPKCS11Module
, nsIPKCS11Module
)
204 nsPKCS11Module::nsPKCS11Module(SECMODModule
* 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
);
222 nsAutoString localizedRootModuleName
;
224 GetPIPNSSBundleString("RootCertModuleName", localizedRootModuleName
);
228 moduleNameOut
.Assign(NS_ConvertUTF16toUTF8(localizedRootModuleName
));
233 nsPKCS11Module::GetName(/*out*/ nsACString
& name
) {
234 return NormalizeModuleNameOut(mModule
->commonName
, name
);
238 nsPKCS11Module::GetLibName(/*out*/ nsACString
& libName
) {
239 if (mModule
->dllName
) {
240 libName
= mModule
->dllName
;
242 libName
.SetIsVoid(true);
248 nsPKCS11Module::ListSlots(nsISimpleEnumerator
** _retval
) {
249 NS_ENSURE_ARG_POINTER(_retval
);
251 nsresult rv
= CheckForSmartCardChanges();
256 nsCOMPtr
<nsIMutableArray
> array
= do_CreateInstance(NS_ARRAY_CONTRACTID
);
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
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
);
276 return array
->Enumerate(_retval
, NS_GET_IID(nsIPKCS11Slot
));