tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }