security/manager/ssl/src/nsPKCS11Slot.cpp

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     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"
     6 #include "nsPK11TokenDB.h"
     8 #include "nsCOMPtr.h"
     9 #include "nsISupportsArray.h"
    10 #include "nsString.h"
    11 #include "nsReadableUtils.h"
    12 #include "nsCRT.h"
    14 #include "secmod.h"
    16 #ifdef PR_LOGGING
    17 extern PRLogModuleInfo* gPIPNSSLog;
    18 #endif
    20 NS_IMPL_ISUPPORTS(nsPKCS11Slot, nsIPKCS11Slot)
    22 nsPKCS11Slot::nsPKCS11Slot(PK11SlotInfo *slot)
    23 {
    24   nsNSSShutDownPreventionLock locker;
    25   if (isAlreadyShutDown())
    26     return;
    28   PK11_ReferenceSlot(slot);
    29   mSlot = slot;
    30   mSeries = PK11_GetSlotSeries(slot);
    31   refreshSlotInfo();
    32 }
    34 void
    35 nsPKCS11Slot::refreshSlotInfo()
    36 {
    37   CK_SLOT_INFO slot_info;
    38   if (PK11_GetSlotInfo(mSlot, &slot_info) == SECSuccess) {
    39     // Set the Description field
    40     const char *ccDesc = (const char*)slot_info.slotDescription;
    41     const nsACString &cDesc = Substring(
    42       ccDesc, 
    43       ccDesc+PL_strnlen(ccDesc, sizeof(slot_info.slotDescription)));
    44     mSlotDesc = NS_ConvertUTF8toUTF16(cDesc);
    45     mSlotDesc.Trim(" ", false, true);
    46     // Set the Manufacturer field
    47     const char *ccManID = (const char*)slot_info.manufacturerID;
    48     const nsACString &cManID = Substring(
    49       ccManID, 
    50       ccManID+PL_strnlen(ccManID, sizeof(slot_info.manufacturerID)));
    51     mSlotManID = NS_ConvertUTF8toUTF16(cManID);
    52     mSlotManID.Trim(" ", false, true);
    53     // Set the Hardware Version field
    54     mSlotHWVersion = EmptyString();
    55     mSlotHWVersion.AppendInt(slot_info.hardwareVersion.major);
    56     mSlotHWVersion.AppendLiteral(".");
    57     mSlotHWVersion.AppendInt(slot_info.hardwareVersion.minor);
    58     // Set the Firmware Version field
    59     mSlotFWVersion = EmptyString();
    60     mSlotFWVersion.AppendInt(slot_info.firmwareVersion.major);
    61     mSlotFWVersion.AppendLiteral(".");
    62     mSlotFWVersion.AppendInt(slot_info.firmwareVersion.minor);
    63   }
    65 }
    67 nsPKCS11Slot::~nsPKCS11Slot()
    68 {
    69   nsNSSShutDownPreventionLock locker;
    70   if (isAlreadyShutDown()) {
    71     return;
    72   }
    73   destructorSafeDestroyNSSReference();
    74   shutdown(calledFromObject);
    75 }
    77 void nsPKCS11Slot::virtualDestroyNSSReference()
    78 {
    79   destructorSafeDestroyNSSReference();
    80 }
    82 void nsPKCS11Slot::destructorSafeDestroyNSSReference()
    83 {
    84   if (mSlot) {
    85     PK11_FreeSlot(mSlot);
    86     mSlot = nullptr;
    87   }
    88 }
    90 /* readonly attribute wstring name; */
    91 NS_IMETHODIMP 
    92 nsPKCS11Slot::GetName(char16_t **aName)
    93 {
    94   nsNSSShutDownPreventionLock locker;
    95   if (isAlreadyShutDown())
    96     return NS_ERROR_NOT_AVAILABLE;
    98   char *csn = PK11_GetSlotName(mSlot);
    99   if (*csn) {
   100     *aName = ToNewUnicode(NS_ConvertUTF8toUTF16(csn));
   101   } else if (PK11_HasRootCerts(mSlot)) {
   102     // This is a workaround to an Root Module bug - the root certs module has
   103     // no slot name.  Not bothering to localize, because this is a workaround
   104     // and for now all the slot names returned by NSS are char * anyway.
   105     *aName = ToNewUnicode(NS_LITERAL_STRING("Root Certificates"));
   106   } else {
   107     // same as above, this is a catch-all
   108     *aName = ToNewUnicode(NS_LITERAL_STRING("Unnamed Slot"));
   109   }
   110   if (!*aName) return NS_ERROR_OUT_OF_MEMORY;
   111   return NS_OK;
   112 }
   114 /* readonly attribute wstring desc; */
   115 NS_IMETHODIMP 
   116 nsPKCS11Slot::GetDesc(char16_t **aDesc)
   117 {
   118   nsNSSShutDownPreventionLock locker;
   119   if (isAlreadyShutDown())
   120     return NS_ERROR_NOT_AVAILABLE;
   122   if (mSeries != PK11_GetSlotSeries(mSlot)) {
   123     refreshSlotInfo();
   124   }
   126   *aDesc = ToNewUnicode(mSlotDesc);
   127   if (!*aDesc) return NS_ERROR_OUT_OF_MEMORY;
   128   return NS_OK;
   129 }
   131 /* readonly attribute wstring manID; */
   132 NS_IMETHODIMP 
   133 nsPKCS11Slot::GetManID(char16_t **aManID)
   134 {
   135   if (mSeries != PK11_GetSlotSeries(mSlot)) {
   136     refreshSlotInfo();
   137   }
   138   *aManID = ToNewUnicode(mSlotManID);
   139   if (!*aManID) return NS_ERROR_OUT_OF_MEMORY;
   140   return NS_OK;
   141 }
   143 /* readonly attribute wstring HWVersion; */
   144 NS_IMETHODIMP 
   145 nsPKCS11Slot::GetHWVersion(char16_t **aHWVersion)
   146 {
   147   if (mSeries != PK11_GetSlotSeries(mSlot)) {
   148     refreshSlotInfo();
   149   }
   150   *aHWVersion = ToNewUnicode(mSlotHWVersion);
   151   if (!*aHWVersion) return NS_ERROR_OUT_OF_MEMORY;
   152   return NS_OK;
   153 }
   155 /* readonly attribute wstring FWVersion; */
   156 NS_IMETHODIMP 
   157 nsPKCS11Slot::GetFWVersion(char16_t **aFWVersion)
   158 {
   159   if (mSeries != PK11_GetSlotSeries(mSlot)) {
   160     refreshSlotInfo();
   161   }
   162   *aFWVersion = ToNewUnicode(mSlotFWVersion);
   163   if (!*aFWVersion) return NS_ERROR_OUT_OF_MEMORY;
   164   return NS_OK;
   165 }
   167 /* nsIPK11Token getToken (); */
   168 NS_IMETHODIMP 
   169 nsPKCS11Slot::GetToken(nsIPK11Token **_retval)
   170 {
   171   nsNSSShutDownPreventionLock locker;
   172   if (isAlreadyShutDown())
   173     return NS_ERROR_NOT_AVAILABLE;
   175   nsCOMPtr<nsIPK11Token> token = new nsPK11Token(mSlot);
   176   *_retval = token;
   177   NS_ADDREF(*_retval);
   178   return NS_OK;
   179 }
   181 /* readonly attribute wstring tokenName; */
   182 NS_IMETHODIMP 
   183 nsPKCS11Slot::GetTokenName(char16_t **aName)
   184 {
   185   nsNSSShutDownPreventionLock locker;
   186   if (isAlreadyShutDown())
   187     return NS_ERROR_NOT_AVAILABLE;
   189   if (!PK11_IsPresent(mSlot)) {
   190     *aName = nullptr;
   191     return NS_OK;
   192   }
   194   if (mSeries != PK11_GetSlotSeries(mSlot)) {
   195     refreshSlotInfo();
   196   }
   199   *aName = ToNewUnicode(NS_ConvertUTF8toUTF16(PK11_GetTokenName(mSlot)));
   200   if (!*aName) return NS_ERROR_OUT_OF_MEMORY;
   201   return NS_OK;
   202 }
   204 NS_IMETHODIMP
   205 nsPKCS11Slot::GetStatus(uint32_t *_retval)
   206 {
   207   nsNSSShutDownPreventionLock locker;
   208   if (isAlreadyShutDown())
   209     return NS_ERROR_NOT_AVAILABLE;
   211   if (PK11_IsDisabled(mSlot))
   212     *_retval = SLOT_DISABLED;
   213   else if (!PK11_IsPresent(mSlot))
   214     *_retval = SLOT_NOT_PRESENT;
   215   else if (PK11_NeedLogin(mSlot) && PK11_NeedUserInit(mSlot))
   216     *_retval = SLOT_UNINITIALIZED;
   217   else if (PK11_NeedLogin(mSlot) && !PK11_IsLoggedIn(mSlot, nullptr))
   218     *_retval = SLOT_NOT_LOGGED_IN;
   219   else if (PK11_NeedLogin(mSlot))
   220     *_retval = SLOT_LOGGED_IN;
   221   else
   222     *_retval = SLOT_READY;
   223   return NS_OK;
   224 }
   226 NS_IMPL_ISUPPORTS(nsPKCS11Module, nsIPKCS11Module)
   228 nsPKCS11Module::nsPKCS11Module(SECMODModule *module)
   229 {
   230   nsNSSShutDownPreventionLock locker;
   231   if (isAlreadyShutDown())
   232     return;
   234   SECMOD_ReferenceModule(module);
   235   mModule = module;
   236 }
   238 nsPKCS11Module::~nsPKCS11Module()
   239 {
   240   nsNSSShutDownPreventionLock locker;
   241   if (isAlreadyShutDown()) {
   242     return;
   243   }
   244   destructorSafeDestroyNSSReference();
   245   shutdown(calledFromObject);
   246 }
   248 void nsPKCS11Module::virtualDestroyNSSReference()
   249 {
   250   destructorSafeDestroyNSSReference();
   251 }
   253 void nsPKCS11Module::destructorSafeDestroyNSSReference()
   254 {
   255   if (mModule) {
   256     SECMOD_DestroyModule(mModule);
   257     mModule = nullptr;
   258   }
   259 }
   261 /* readonly attribute wstring name; */
   262 NS_IMETHODIMP 
   263 nsPKCS11Module::GetName(char16_t **aName)
   264 {
   265   nsNSSShutDownPreventionLock locker;
   266   if (isAlreadyShutDown())
   267     return NS_ERROR_NOT_AVAILABLE;
   269   *aName = ToNewUnicode(NS_ConvertUTF8toUTF16(mModule->commonName));
   270   return NS_OK;
   271 }
   273 /* readonly attribute wstring libName; */
   274 NS_IMETHODIMP 
   275 nsPKCS11Module::GetLibName(char16_t **aName)
   276 {
   277   nsNSSShutDownPreventionLock locker;
   278   if (isAlreadyShutDown())
   279     return NS_ERROR_NOT_AVAILABLE;
   281   if ( mModule->dllName ) {
   282     *aName = ToNewUnicode(NS_ConvertUTF8toUTF16(mModule->dllName));
   283   } else {
   284     *aName = nullptr;
   285   }
   286   return NS_OK;
   287 }
   289 /*  nsIPKCS11Slot findSlotByName(in wstring name); */
   290 NS_IMETHODIMP 
   291 nsPKCS11Module::FindSlotByName(const char16_t *aName,
   292                                nsIPKCS11Slot **_retval)
   293 {
   294   nsNSSShutDownPreventionLock locker;
   295   if (isAlreadyShutDown())
   296     return NS_ERROR_NOT_AVAILABLE;
   298   char *asciiname = ToNewUTF8String(nsDependentString(aName));
   299   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting \"%s\"\n", asciiname));
   300   PK11SlotInfo *slotinfo = nullptr;
   301   PK11SlotList *slotList = PK11_FindSlotsByNames(mModule->dllName, 
   302         asciiname /* slotName */, nullptr /* token Name */, false);
   303   if (!slotList) {
   304     /* name must be the token name */
   305     slotList = PK11_FindSlotsByNames(mModule->dllName, 
   306         nullptr /*slot Name */, asciiname /* token Name */, false);
   307   }
   308   if (slotList) {
   309     /* should only be one */
   310     if (slotList->head && slotList->head->slot) {
   311       slotinfo =  PK11_ReferenceSlot(slotList->head->slot);
   312     }
   313     PK11_FreeSlotList(slotList);
   314   }
   315   if (!slotinfo) {
   316     // workaround - the builtin module has no name
   317     if (!asciiname) {
   318       return NS_ERROR_FAILURE;
   319     } else if (nsCRT::strcmp(asciiname, "Root Certificates") == 0) {
   320       slotinfo = PK11_ReferenceSlot(mModule->slots[0]);
   321     } else {
   322       // give up
   323       nsMemory::Free(asciiname);
   324       return NS_ERROR_FAILURE;
   325     }
   326   } 
   327   nsMemory::Free(asciiname);
   328   nsCOMPtr<nsIPKCS11Slot> slot = new nsPKCS11Slot(slotinfo);
   329   PK11_FreeSlot(slotinfo);
   330   *_retval = slot;
   331   NS_ADDREF(*_retval);
   332   return NS_OK;
   333 }
   335 /* nsIEnumerator listSlots (); */
   336 NS_IMETHODIMP 
   337 nsPKCS11Module::ListSlots(nsIEnumerator **_retval)
   338 {
   339   nsNSSShutDownPreventionLock locker;
   340   if (isAlreadyShutDown())
   341     return NS_ERROR_NOT_AVAILABLE;
   343   nsresult rv = NS_OK;
   344   int i;
   345   /* get isupports array */
   346   nsCOMPtr<nsISupportsArray> array;
   347   rv = NS_NewISupportsArray(getter_AddRefs(array));
   348   if (NS_FAILED(rv)) return rv;
   349   /* applications which allow new slot creation (which Firefox now does
   350    * since it uses the WaitForSlotEvent call) need to hold the
   351    * ModuleList Read lock to prevent the slot array from changing out
   352    * from under it. */
   353   SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
   354   SECMOD_GetReadLock(lock);
   355   for (i=0; i<mModule->slotCount; i++) {
   356     if (mModule->slots[i]) {
   357       nsCOMPtr<nsIPKCS11Slot> slot = new nsPKCS11Slot(mModule->slots[i]);
   358       array->AppendElement(slot);
   359     }
   360   }
   361   SECMOD_ReleaseReadLock(lock);
   362   rv = array->Enumerate(_retval);
   363   return rv;
   364 }
   366 NS_IMPL_ISUPPORTS(nsPKCS11ModuleDB, nsIPKCS11ModuleDB, nsICryptoFIPSInfo)
   368 nsPKCS11ModuleDB::nsPKCS11ModuleDB()
   369 {
   370 }
   372 nsPKCS11ModuleDB::~nsPKCS11ModuleDB()
   373 {
   374 }
   376 /* nsIPKCS11Module getInternal (); */
   377 NS_IMETHODIMP 
   378 nsPKCS11ModuleDB::GetInternal(nsIPKCS11Module **_retval)
   379 {
   380   nsNSSShutDownPreventionLock locker;
   381   SECMODModule *nssMod = 
   382     SECMOD_CreateModule(nullptr, SECMOD_INT_NAME, nullptr, SECMOD_INT_FLAGS);
   383   nsCOMPtr<nsIPKCS11Module> module = new nsPKCS11Module(nssMod);
   384   SECMOD_DestroyModule(nssMod);
   385   *_retval = module;
   386   NS_ADDREF(*_retval);
   387   return NS_OK;
   388 }
   390 /* nsIPKCS11Module getInternalFIPS (); */
   391 NS_IMETHODIMP 
   392 nsPKCS11ModuleDB::GetInternalFIPS(nsIPKCS11Module **_retval)
   393 {
   394   nsNSSShutDownPreventionLock locker;
   395   SECMODModule *nssMod = 
   396     SECMOD_CreateModule(nullptr, SECMOD_FIPS_NAME, nullptr, SECMOD_FIPS_FLAGS);
   397   nsCOMPtr<nsIPKCS11Module> module = new nsPKCS11Module(nssMod);
   398   SECMOD_DestroyModule(nssMod);
   399   *_retval = module;
   400   NS_ADDREF(*_retval);
   401   return NS_OK;
   402 }
   404 /* nsIPKCS11Module findModuleByName(in wstring name); */
   405 NS_IMETHODIMP 
   406 nsPKCS11ModuleDB::FindModuleByName(const char16_t *aName,
   407                                    nsIPKCS11Module **_retval)
   408 {
   409   nsNSSShutDownPreventionLock locker;
   410   NS_ConvertUTF16toUTF8 aUtf8Name(aName);
   411   SECMODModule *mod =
   412     SECMOD_FindModule(const_cast<char *>(aUtf8Name.get()));
   413   if (!mod)
   414     return NS_ERROR_FAILURE;
   415   nsCOMPtr<nsIPKCS11Module> module = new nsPKCS11Module(mod);
   416   SECMOD_DestroyModule(mod);
   417   *_retval = module;
   418   NS_ADDREF(*_retval);
   419   return NS_OK;
   420 }
   422 /* This is essentially the same as nsIPK11Token::findTokenByName, except
   423  * that it returns an nsIPKCS11Slot, which may be desired.
   424  */
   425 /* nsIPKCS11Module findSlotByName(in wstring name); */
   426 NS_IMETHODIMP 
   427 nsPKCS11ModuleDB::FindSlotByName(const char16_t *aName,
   428                                  nsIPKCS11Slot **_retval)
   429 {
   430   nsNSSShutDownPreventionLock locker;
   431   NS_ConvertUTF16toUTF8 aUtf8Name(aName);
   432   PK11SlotInfo *slotinfo =
   433    PK11_FindSlotByName(const_cast<char*>(aUtf8Name.get()));
   434   if (!slotinfo)
   435     return NS_ERROR_FAILURE;
   436   nsCOMPtr<nsIPKCS11Slot> slot = new nsPKCS11Slot(slotinfo);
   437   PK11_FreeSlot(slotinfo);
   438   *_retval = slot;
   439   NS_ADDREF(*_retval);
   440   return NS_OK;
   441 }
   443 /* nsIEnumerator listModules (); */
   444 NS_IMETHODIMP 
   445 nsPKCS11ModuleDB::ListModules(nsIEnumerator **_retval)
   446 {
   447   nsNSSShutDownPreventionLock locker;
   448   nsresult rv = NS_OK;
   449   /* get isupports array */
   450   nsCOMPtr<nsISupportsArray> array;
   451   rv = NS_NewISupportsArray(getter_AddRefs(array));
   452   if (NS_FAILED(rv)) return rv;
   453   /* get the default list of modules */
   454   SECMODModuleList *list = SECMOD_GetDefaultModuleList();
   455   /* lock down the list for reading */
   456   SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
   457   SECMOD_GetReadLock(lock);
   458   while (list) {
   459     nsCOMPtr<nsIPKCS11Module> module = new nsPKCS11Module(list->module);
   460     array->AppendElement(module);
   461     list = list->next;
   462   }
   463   /* Get the modules in the database that didn't load */
   464   list = SECMOD_GetDeadModuleList();
   465   while (list) {
   466     nsCOMPtr<nsIPKCS11Module> module = new nsPKCS11Module(list->module);
   467     array->AppendElement(module);
   468     list = list->next;
   469   }
   470   SECMOD_ReleaseReadLock(lock);
   471   rv = array->Enumerate(_retval);
   472   return rv;
   473 }
   475 NS_IMETHODIMP nsPKCS11ModuleDB::GetCanToggleFIPS(bool *aCanToggleFIPS)
   476 {
   477   nsNSSShutDownPreventionLock locker;
   478   *aCanToggleFIPS = SECMOD_CanDeleteInternalModule();
   479   return NS_OK;
   480 }
   483 /* void toggleFIPSMode (); */
   484 NS_IMETHODIMP nsPKCS11ModuleDB::ToggleFIPSMode()
   485 {
   486   nsNSSShutDownPreventionLock locker;
   487   // The way to toggle FIPS mode in NSS is extremely obscure.
   488   // Basically, we delete the internal module, and voila it
   489   // gets replaced with the opposite module, ie if it was 
   490   // FIPS before, then it becomes non-FIPS next.
   491   SECMODModule *internal;
   493   // This function returns us a pointer to a local copy of 
   494   // the internal module stashed in NSS.  We don't want to
   495   // delete it since it will cause much pain in NSS.
   496   internal = SECMOD_GetInternalModule();
   497   if (!internal)
   498     return NS_ERROR_FAILURE;
   500   SECStatus srv = SECMOD_DeleteInternalModule(internal->commonName);
   501   if (srv != SECSuccess)
   502     return NS_ERROR_FAILURE;
   504   return NS_OK;
   505 }
   507 /* readonly attribute boolean isFIPSEnabled; */
   508 NS_IMETHODIMP nsPKCS11ModuleDB::GetIsFIPSEnabled(bool *aIsFIPSEnabled)
   509 {
   510   nsNSSShutDownPreventionLock locker;
   511   *aIsFIPSEnabled = PK11_IsFIPS();
   512   return NS_OK;
   513 }
   515 NS_IMETHODIMP nsPKCS11ModuleDB::GetIsFIPSModeActive(bool *aIsFIPSModeActive)
   516 {
   517   return GetIsFIPSEnabled(aIsFIPSModeActive);
   518 }

mercurial