Merge autoland to mozilla-central. a=merge
[gecko.git] / security / manager / ssl / nsPKCS11Slot.cpp
blob88ac9bb0d708a0d934b7a3bc160823aae9941dd5
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 "PKCS11ModuleDB.h"
10 #include "mozilla/Casting.h"
11 #include "mozilla/Logging.h"
12 #include "mozilla/Telemetry.h"
13 #include "mozilla/Unused.h"
14 #include "nsCOMPtr.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"
21 #include "secmod.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) {
31 MOZ_ASSERT(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));
43 if (NS_FAILED(rv)) {
44 return rv;
47 // Set the Description field
48 if (mIsInternalCryptoSlot) {
49 nsresult rv;
50 if (PK11_IsFIPS()) {
51 rv = GetPIPNSSBundleString("Fips140SlotDescription", mSlotDesc);
52 } else {
53 rv = GetPIPNSSBundleString("SlotDescription", mSlotDesc);
55 if (NS_FAILED(rv)) {
56 return rv;
58 } else if (mIsInternalKeySlot) {
59 rv = GetPIPNSSBundleString("PrivateSlotDescription", mSlotDesc);
60 if (NS_FAILED(rv)) {
61 return rv;
63 } else {
64 const char* ccDesc =
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);
73 if (NS_FAILED(rv)) {
74 return rv;
76 } else {
77 const char* ccManID =
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);
96 return NS_OK;
99 nsresult nsPKCS11Slot::GetAttributeHelper(const nsACString& attribute,
100 /*out*/ nsACString& xpcomOutParam) {
101 if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
102 nsresult rv = refreshSlotInfo();
103 if (NS_FAILED(rv)) {
104 return rv;
108 xpcomOutParam = attribute;
109 return NS_OK;
112 NS_IMETHODIMP
113 nsPKCS11Slot::GetName(/*out*/ nsACString& name) {
114 if (mIsInternalCryptoSlot) {
115 if (PK11_IsFIPS()) {
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()));
125 return NS_OK;
128 NS_IMETHODIMP
129 nsPKCS11Slot::GetDesc(/*out*/ nsACString& desc) {
130 return GetAttributeHelper(mSlotDesc, desc);
133 NS_IMETHODIMP
134 nsPKCS11Slot::GetManID(/*out*/ nsACString& manufacturerID) {
135 return GetAttributeHelper(mSlotManufacturerID, manufacturerID);
138 NS_IMETHODIMP
139 nsPKCS11Slot::GetHWVersion(/*out*/ nsACString& hwVersion) {
140 return GetAttributeHelper(mSlotHWVersion, hwVersion);
143 NS_IMETHODIMP
144 nsPKCS11Slot::GetFWVersion(/*out*/ nsACString& fwVersion) {
145 return GetAttributeHelper(mSlotFWVersion, fwVersion);
148 NS_IMETHODIMP
149 nsPKCS11Slot::GetToken(nsIPK11Token** _retval) {
150 NS_ENSURE_ARG_POINTER(_retval);
151 nsCOMPtr<nsIPK11Token> token = new nsPK11Token(mSlot.get());
152 token.forget(_retval);
153 return NS_OK;
156 NS_IMETHODIMP
157 nsPKCS11Slot::GetTokenName(/*out*/ nsACString& tokenName) {
158 if (!PK11_IsPresent(mSlot.get())) {
159 tokenName.SetIsVoid(true);
160 return NS_OK;
163 if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
164 nsresult rv = refreshSlotInfo();
165 if (NS_FAILED(rv)) {
166 return rv;
170 if (mIsInternalCryptoSlot) {
171 if (PK11_IsFIPS()) {
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()));
181 return NS_OK;
184 NS_IMETHODIMP
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;
198 } else {
199 *_retval = SLOT_READY;
201 return NS_OK;
204 NS_IMPL_ISUPPORTS(nsPKCS11Module, nsIPKCS11Module)
206 nsPKCS11Module::nsPKCS11Module(SECMODModule* module) {
207 MOZ_ASSERT(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()) !=
221 0) {
222 moduleNameOut.Assign(moduleNameIn);
223 return NS_OK;
226 nsAutoString localizedRootModuleName;
227 nsresult rv =
228 GetPIPNSSBundleString("RootCertModuleName", localizedRootModuleName);
229 if (NS_FAILED(rv)) {
230 return rv;
232 moduleNameOut.Assign(NS_ConvertUTF16toUTF8(localizedRootModuleName));
233 return NS_OK;
236 NS_IMETHODIMP
237 nsPKCS11Module::GetName(/*out*/ nsACString& name) {
238 return NormalizeModuleNameOut(mModule->commonName, name);
241 NS_IMETHODIMP
242 nsPKCS11Module::GetLibName(/*out*/ nsACString& libName) {
243 if (mModule->dllName) {
244 libName = mModule->dllName;
245 } else {
246 libName.SetIsVoid(true);
248 return NS_OK;
251 NS_IMETHODIMP
252 nsPKCS11Module::ListSlots(nsISimpleEnumerator** _retval) {
253 NS_ENSURE_ARG_POINTER(_retval);
255 nsresult rv = CheckForSmartCardChanges();
256 if (NS_FAILED(rv)) {
257 return rv;
260 nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
261 if (!array) {
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
268 * from under it. */
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);
274 if (NS_FAILED(rv)) {
275 return rv;
280 return array->Enumerate(_retval, NS_GET_IID(nsIPKCS11Slot));