nsPKCS11Slot.cpp (8090B)
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/. */ 4 5 #include "nsPKCS11Slot.h" 6 7 #include <string.h> 8 9 #include "PKCS11ModuleDB.h" 10 #include "mozilla/Casting.h" 11 #include "mozilla/Logging.h" 12 #include "nsCOMPtr.h" 13 #include "nsIMutableArray.h" 14 #include "nsNSSCertHelper.h" 15 #include "nsNSSComponent.h" 16 #include "nsPK11TokenDB.h" 17 #include "nsPromiseFlatString.h" 18 #include "nsComponentManagerUtils.h" 19 #include "secmod.h" 20 21 using mozilla::LogLevel; 22 using namespace mozilla::psm; 23 24 extern mozilla::LazyLogModule gPIPNSSLog; 25 26 NS_IMPL_ISUPPORTS(nsPKCS11Slot, nsIPKCS11Slot) 27 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 (void)refreshSlotInfo(); 36 } 37 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; 43 } 44 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); 52 } 53 if (NS_FAILED(rv)) { 54 return rv; 55 } 56 } else if (mIsInternalKeySlot) { 57 rv = GetPIPNSSBundleString("PrivateSlotDescription", mSlotDesc); 58 if (NS_FAILED(rv)) { 59 return rv; 60 } 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); 66 } 67 68 // Set the Manufacturer field 69 if (mIsInternalCryptoSlot || mIsInternalKeySlot) { 70 rv = GetPIPNSSBundleString("ManufacturerID", mSlotManufacturerID); 71 if (NS_FAILED(rv)) { 72 return rv; 73 } 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); 80 } 81 82 // Set the Hardware Version field 83 mSlotHWVersion.Truncate(); 84 mSlotHWVersion.AppendInt(slotInfo.hardwareVersion.major); 85 mSlotHWVersion.Append('.'); 86 mSlotHWVersion.AppendInt(slotInfo.hardwareVersion.minor); 87 88 // Set the Firmware Version field 89 mSlotFWVersion.Truncate(); 90 mSlotFWVersion.AppendInt(slotInfo.firmwareVersion.major); 91 mSlotFWVersion.Append('.'); 92 mSlotFWVersion.AppendInt(slotInfo.firmwareVersion.minor); 93 94 return NS_OK; 95 } 96 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; 103 } 104 } 105 106 xpcomOutParam = attribute; 107 return NS_OK; 108 } 109 110 NS_IMETHODIMP 111 nsPKCS11Slot::GetName(/*out*/ nsACString& name) { 112 if (mIsInternalCryptoSlot) { 113 if (PK11_IsFIPS()) { 114 return GetPIPNSSBundleString("Fips140TokenDescription", name); 115 } 116 return GetPIPNSSBundleString("TokenDescription", name); 117 } 118 if (mIsInternalKeySlot) { 119 return GetPIPNSSBundleString("PrivateTokenDescription", name); 120 } 121 name.Assign(PK11_GetSlotName(mSlot.get())); 122 123 return NS_OK; 124 } 125 126 NS_IMETHODIMP 127 nsPKCS11Slot::GetDesc(/*out*/ nsACString& desc) { 128 return GetAttributeHelper(mSlotDesc, desc); 129 } 130 131 NS_IMETHODIMP 132 nsPKCS11Slot::GetManID(/*out*/ nsACString& manufacturerID) { 133 return GetAttributeHelper(mSlotManufacturerID, manufacturerID); 134 } 135 136 NS_IMETHODIMP 137 nsPKCS11Slot::GetHWVersion(/*out*/ nsACString& hwVersion) { 138 return GetAttributeHelper(mSlotHWVersion, hwVersion); 139 } 140 141 NS_IMETHODIMP 142 nsPKCS11Slot::GetFWVersion(/*out*/ nsACString& fwVersion) { 143 return GetAttributeHelper(mSlotFWVersion, fwVersion); 144 } 145 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; 152 } 153 154 NS_IMETHODIMP 155 nsPKCS11Slot::GetTokenName(/*out*/ nsACString& tokenName) { 156 if (!PK11_IsPresent(mSlot.get())) { 157 tokenName.SetIsVoid(true); 158 return NS_OK; 159 } 160 161 if (PK11_GetSlotSeries(mSlot.get()) != mSeries) { 162 nsresult rv = refreshSlotInfo(); 163 if (NS_FAILED(rv)) { 164 return rv; 165 } 166 } 167 168 if (mIsInternalCryptoSlot) { 169 if (PK11_IsFIPS()) { 170 return GetPIPNSSBundleString("Fips140TokenDescription", tokenName); 171 } 172 return GetPIPNSSBundleString("TokenDescription", tokenName); 173 } 174 if (mIsInternalKeySlot) { 175 return GetPIPNSSBundleString("PrivateTokenDescription", tokenName); 176 } 177 178 tokenName.Assign(PK11_GetTokenName(mSlot.get())); 179 return NS_OK; 180 } 181 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; 198 } 199 return NS_OK; 200 } 201 202 NS_IMPL_ISUPPORTS(nsPKCS11Module, nsIPKCS11Module) 203 204 nsPKCS11Module::nsPKCS11Module(SECMODModule* module) { 205 MOZ_ASSERT(module); 206 mModule.reset(SECMOD_ReferenceModule(module)); 207 } 208 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, kRootModuleName.Length() + 1) != 217 kRootModuleName.Length() || 218 strncmp(kRootModuleName.get(), moduleNameIn, kRootModuleName.Length()) != 219 0) { 220 moduleNameOut.Assign(moduleNameIn); 221 return NS_OK; 222 } 223 224 nsAutoString localizedRootModuleName; 225 nsresult rv = 226 GetPIPNSSBundleString("RootCertModuleName", localizedRootModuleName); 227 if (NS_FAILED(rv)) { 228 return rv; 229 } 230 moduleNameOut.Assign(NS_ConvertUTF16toUTF8(localizedRootModuleName)); 231 return NS_OK; 232 } 233 234 NS_IMETHODIMP 235 nsPKCS11Module::GetName(/*out*/ nsACString& name) { 236 return NormalizeModuleNameOut(mModule->commonName, name); 237 } 238 239 NS_IMETHODIMP 240 nsPKCS11Module::GetLibName(/*out*/ nsACString& libName) { 241 if (mModule->dllName) { 242 libName = mModule->dllName; 243 } else { 244 libName.SetIsVoid(true); 245 } 246 return NS_OK; 247 } 248 249 NS_IMETHODIMP 250 nsPKCS11Module::ListSlots(nsISimpleEnumerator** _retval) { 251 NS_ENSURE_ARG_POINTER(_retval); 252 253 nsresult rv = CheckForSmartCardChanges(); 254 if (NS_FAILED(rv)) { 255 return rv; 256 } 257 258 nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID); 259 if (!array) { 260 return NS_ERROR_FAILURE; 261 } 262 263 /* applications which allow new slot creation (which Firefox now does 264 * since it uses the WaitForSlotEvent call) need to hold the 265 * ModuleList Read lock to prevent the slot array from changing out 266 * from under it. */ 267 mozilla::AutoSECMODListReadLock lock; 268 for (int i = 0; i < mModule->slotCount; i++) { 269 if (mModule->slots[i]) { 270 nsCOMPtr<nsIPKCS11Slot> slot = new nsPKCS11Slot(mModule->slots[i]); 271 rv = array->AppendElement(slot); 272 if (NS_FAILED(rv)) { 273 return rv; 274 } 275 } 276 } 277 278 return array->Enumerate(_retval, NS_GET_IID(nsIPKCS11Slot)); 279 }