1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 2000
19 * the Initial Developer. All Rights Reserved.
22 * Ian McGreer <mcgreer@netscape.com>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsPKCS11Slot.h"
39 #include "nsPK11TokenDB.h"
42 #include "nsISupportsArray.h"
44 #include "nsReadableUtils.h"
50 extern PRLogModuleInfo
* gPIPNSSLog
;
53 NS_IMPL_ISUPPORTS1(nsPKCS11Slot
, nsIPKCS11Slot
)
55 nsPKCS11Slot::nsPKCS11Slot(PK11SlotInfo
*slot
)
57 nsNSSShutDownPreventionLock locker
;
58 if (isAlreadyShutDown())
61 PK11_ReferenceSlot(slot
);
63 mSeries
= PK11_GetSlotSeries(slot
);
68 nsPKCS11Slot::refreshSlotInfo()
70 CK_SLOT_INFO slot_info
;
71 if (PK11_GetSlotInfo(mSlot
, &slot_info
) == SECSuccess
) {
72 // Set the Description field
73 const char *ccDesc
= (const char*)slot_info
.slotDescription
;
74 const nsACString
&cDesc
= Substring(
76 ccDesc
+PL_strnlen(ccDesc
, sizeof(slot_info
.slotDescription
)));
77 mSlotDesc
= NS_ConvertUTF8toUTF16(cDesc
);
78 mSlotDesc
.Trim(" ", PR_FALSE
, PR_TRUE
);
79 // Set the Manufacturer field
80 const char *ccManID
= (const char*)slot_info
.manufacturerID
;
81 const nsACString
&cManID
= Substring(
83 ccManID
+PL_strnlen(ccManID
, sizeof(slot_info
.manufacturerID
)));
84 mSlotManID
= NS_ConvertUTF8toUTF16(cManID
);
85 mSlotManID
.Trim(" ", PR_FALSE
, PR_TRUE
);
86 // Set the Hardware Version field
87 mSlotHWVersion
= EmptyString();
88 mSlotHWVersion
.AppendInt(slot_info
.hardwareVersion
.major
);
89 mSlotHWVersion
.AppendLiteral(".");
90 mSlotHWVersion
.AppendInt(slot_info
.hardwareVersion
.minor
);
91 // Set the Firmware Version field
92 mSlotFWVersion
= EmptyString();
93 mSlotFWVersion
.AppendInt(slot_info
.firmwareVersion
.major
);
94 mSlotFWVersion
.AppendLiteral(".");
95 mSlotFWVersion
.AppendInt(slot_info
.firmwareVersion
.minor
);
100 nsPKCS11Slot::~nsPKCS11Slot()
102 nsNSSShutDownPreventionLock locker
;
103 if (isAlreadyShutDown())
106 destructorSafeDestroyNSSReference();
107 shutdown(calledFromObject
);
110 void nsPKCS11Slot::virtualDestroyNSSReference()
112 destructorSafeDestroyNSSReference();
115 void nsPKCS11Slot::destructorSafeDestroyNSSReference()
117 if (isAlreadyShutDown())
121 PK11_FreeSlot(mSlot
);
126 /* readonly attribute wstring name; */
128 nsPKCS11Slot::GetName(PRUnichar
**aName
)
130 nsNSSShutDownPreventionLock locker
;
131 if (isAlreadyShutDown())
132 return NS_ERROR_NOT_AVAILABLE
;
134 char *csn
= PK11_GetSlotName(mSlot
);
136 *aName
= ToNewUnicode(NS_ConvertUTF8toUTF16(csn
));
137 } else if (PK11_HasRootCerts(mSlot
)) {
138 // This is a workaround to an Root Module bug - the root certs module has
139 // no slot name. Not bothering to localize, because this is a workaround
140 // and for now all the slot names returned by NSS are char * anyway.
141 *aName
= ToNewUnicode(NS_LITERAL_STRING("Root Certificates"));
143 // same as above, this is a catch-all
144 *aName
= ToNewUnicode(NS_LITERAL_STRING("Unnamed Slot"));
146 if (!*aName
) return NS_ERROR_OUT_OF_MEMORY
;
150 /* readonly attribute wstring desc; */
152 nsPKCS11Slot::GetDesc(PRUnichar
**aDesc
)
154 nsNSSShutDownPreventionLock locker
;
155 if (isAlreadyShutDown())
156 return NS_ERROR_NOT_AVAILABLE
;
158 if (mSeries
!= PK11_GetSlotSeries(mSlot
)) {
162 *aDesc
= ToNewUnicode(mSlotDesc
);
163 if (!*aDesc
) return NS_ERROR_OUT_OF_MEMORY
;
167 /* readonly attribute wstring manID; */
169 nsPKCS11Slot::GetManID(PRUnichar
**aManID
)
171 if (mSeries
!= PK11_GetSlotSeries(mSlot
)) {
174 *aManID
= ToNewUnicode(mSlotManID
);
175 if (!*aManID
) return NS_ERROR_OUT_OF_MEMORY
;
179 /* readonly attribute wstring HWVersion; */
181 nsPKCS11Slot::GetHWVersion(PRUnichar
**aHWVersion
)
183 if (mSeries
!= PK11_GetSlotSeries(mSlot
)) {
186 *aHWVersion
= ToNewUnicode(mSlotHWVersion
);
187 if (!*aHWVersion
) return NS_ERROR_OUT_OF_MEMORY
;
191 /* readonly attribute wstring FWVersion; */
193 nsPKCS11Slot::GetFWVersion(PRUnichar
**aFWVersion
)
195 if (mSeries
!= PK11_GetSlotSeries(mSlot
)) {
198 *aFWVersion
= ToNewUnicode(mSlotFWVersion
);
199 if (!*aFWVersion
) return NS_ERROR_OUT_OF_MEMORY
;
203 /* nsIPK11Token getToken (); */
205 nsPKCS11Slot::GetToken(nsIPK11Token
**_retval
)
207 nsNSSShutDownPreventionLock locker
;
208 if (isAlreadyShutDown())
209 return NS_ERROR_NOT_AVAILABLE
;
211 nsCOMPtr
<nsIPK11Token
> token
= new nsPK11Token(mSlot
);
213 return NS_ERROR_OUT_OF_MEMORY
;
219 /* readonly attribute wstring tokenName; */
221 nsPKCS11Slot::GetTokenName(PRUnichar
**aName
)
223 nsNSSShutDownPreventionLock locker
;
224 if (isAlreadyShutDown())
225 return NS_ERROR_NOT_AVAILABLE
;
227 if (!PK11_IsPresent(mSlot
)) {
232 if (mSeries
!= PK11_GetSlotSeries(mSlot
)) {
237 *aName
= ToNewUnicode(NS_ConvertUTF8toUTF16(PK11_GetTokenName(mSlot
)));
238 if (!*aName
) return NS_ERROR_OUT_OF_MEMORY
;
243 nsPKCS11Slot::GetStatus(PRUint32
*_retval
)
245 nsNSSShutDownPreventionLock locker
;
246 if (isAlreadyShutDown())
247 return NS_ERROR_NOT_AVAILABLE
;
249 if (PK11_IsDisabled(mSlot
))
250 *_retval
= SLOT_DISABLED
;
251 else if (!PK11_IsPresent(mSlot
))
252 *_retval
= SLOT_NOT_PRESENT
;
253 else if (PK11_NeedLogin(mSlot
) && PK11_NeedUserInit(mSlot
))
254 *_retval
= SLOT_UNINITIALIZED
;
255 else if (PK11_NeedLogin(mSlot
) && !PK11_IsLoggedIn(mSlot
, NULL
))
256 *_retval
= SLOT_NOT_LOGGED_IN
;
257 else if (PK11_NeedLogin(mSlot
))
258 *_retval
= SLOT_LOGGED_IN
;
260 *_retval
= SLOT_READY
;
264 NS_IMPL_ISUPPORTS1(nsPKCS11Module
, nsIPKCS11Module
)
266 nsPKCS11Module::nsPKCS11Module(SECMODModule
*module
)
268 nsNSSShutDownPreventionLock locker
;
269 if (isAlreadyShutDown())
272 SECMOD_ReferenceModule(module
);
276 nsPKCS11Module::~nsPKCS11Module()
278 nsNSSShutDownPreventionLock locker
;
279 if (isAlreadyShutDown())
282 destructorSafeDestroyNSSReference();
283 shutdown(calledFromObject
);
286 void nsPKCS11Module::virtualDestroyNSSReference()
288 destructorSafeDestroyNSSReference();
291 void nsPKCS11Module::destructorSafeDestroyNSSReference()
293 if (isAlreadyShutDown())
297 SECMOD_DestroyModule(mModule
);
302 /* readonly attribute wstring name; */
304 nsPKCS11Module::GetName(PRUnichar
**aName
)
306 nsNSSShutDownPreventionLock locker
;
307 if (isAlreadyShutDown())
308 return NS_ERROR_NOT_AVAILABLE
;
310 *aName
= ToNewUnicode(NS_ConvertUTF8toUTF16(mModule
->commonName
));
314 /* readonly attribute wstring libName; */
316 nsPKCS11Module::GetLibName(PRUnichar
**aName
)
318 nsNSSShutDownPreventionLock locker
;
319 if (isAlreadyShutDown())
320 return NS_ERROR_NOT_AVAILABLE
;
322 if ( mModule
->dllName
) {
323 *aName
= ToNewUnicode(NS_ConvertUTF8toUTF16(mModule
->dllName
));
330 /* nsIPKCS11Slot findSlotByName(in wstring name); */
332 nsPKCS11Module::FindSlotByName(const PRUnichar
*aName
,
333 nsIPKCS11Slot
**_retval
)
335 nsNSSShutDownPreventionLock locker
;
336 if (isAlreadyShutDown())
337 return NS_ERROR_NOT_AVAILABLE
;
339 char *asciiname
= ToNewUTF8String(nsDependentString(aName
));
340 PR_LOG(gPIPNSSLog
, PR_LOG_DEBUG
, ("Getting \"%s\"\n", asciiname
));
341 PK11SlotInfo
*slotinfo
= NULL
;
342 PK11SlotList
*slotList
= PK11_FindSlotsByNames(mModule
->dllName
,
343 asciiname
/* slotName */, NULL
/* token Name */, PR_FALSE
);
345 /* name must be the token name */
346 slotList
= PK11_FindSlotsByNames(mModule
->dllName
,
347 NULL
/*slot Name */, asciiname
/* token Name */, PR_FALSE
);
350 /* should only be one */
351 if (slotList
->head
&& slotList
->head
->slot
) {
352 slotinfo
= PK11_ReferenceSlot(slotList
->head
->slot
);
354 PK11_FreeSlotList(slotList
);
357 // workaround - the builtin module has no name
358 if (asciiname
== nsnull
) {
359 return NS_ERROR_FAILURE
;
360 } else if (nsCRT::strcmp(asciiname
, "Root Certificates") == 0) {
361 slotinfo
= PK11_ReferenceSlot(mModule
->slots
[0]);
364 nsMemory::Free(asciiname
);
365 return NS_ERROR_FAILURE
;
368 nsMemory::Free(asciiname
);
369 nsCOMPtr
<nsIPKCS11Slot
> slot
= new nsPKCS11Slot(slotinfo
);
370 PK11_FreeSlot(slotinfo
);
372 return NS_ERROR_OUT_OF_MEMORY
;
378 /* nsIEnumerator listSlots (); */
380 nsPKCS11Module::ListSlots(nsIEnumerator
**_retval
)
382 nsNSSShutDownPreventionLock locker
;
383 if (isAlreadyShutDown())
384 return NS_ERROR_NOT_AVAILABLE
;
388 /* get isupports array */
389 nsCOMPtr
<nsISupportsArray
> array
;
390 rv
= NS_NewISupportsArray(getter_AddRefs(array
));
391 if (NS_FAILED(rv
)) return rv
;
392 /* applications which allow new slot creation (which Firefox now does
393 * since it uses the WaitForSlotEvent call) need to hold the
394 * ModuleList Read lock to prevent the slot array from changing out
396 SECMODListLock
*lock
= SECMOD_GetDefaultModuleListLock();
397 SECMOD_GetReadLock(lock
);
398 for (i
=0; i
<mModule
->slotCount
; i
++) {
399 if (mModule
->slots
[i
]) {
400 nsCOMPtr
<nsIPKCS11Slot
> slot
= new nsPKCS11Slot(mModule
->slots
[i
]);
401 array
->AppendElement(slot
);
404 SECMOD_ReleaseReadLock(lock
);
405 rv
= array
->Enumerate(_retval
);
409 NS_IMPL_ISUPPORTS2(nsPKCS11ModuleDB
, nsIPKCS11ModuleDB
, nsICryptoFIPSInfo
)
411 nsPKCS11ModuleDB::nsPKCS11ModuleDB()
415 nsPKCS11ModuleDB::~nsPKCS11ModuleDB()
419 /* nsIPKCS11Module getInternal (); */
421 nsPKCS11ModuleDB::GetInternal(nsIPKCS11Module
**_retval
)
423 nsNSSShutDownPreventionLock locker
;
424 SECMODModule
*nssMod
=
425 SECMOD_CreateModule(NULL
,SECMOD_INT_NAME
, NULL
,SECMOD_INT_FLAGS
);
426 nsCOMPtr
<nsIPKCS11Module
> module
= new nsPKCS11Module(nssMod
);
427 SECMOD_DestroyModule(nssMod
);
429 return NS_ERROR_OUT_OF_MEMORY
;
435 /* nsIPKCS11Module getInternalFIPS (); */
437 nsPKCS11ModuleDB::GetInternalFIPS(nsIPKCS11Module
**_retval
)
439 nsNSSShutDownPreventionLock locker
;
440 SECMODModule
*nssMod
=
441 SECMOD_CreateModule(NULL
, SECMOD_FIPS_NAME
, NULL
, SECMOD_FIPS_FLAGS
);
442 nsCOMPtr
<nsIPKCS11Module
> module
= new nsPKCS11Module(nssMod
);
443 SECMOD_DestroyModule(nssMod
);
445 return NS_ERROR_OUT_OF_MEMORY
;
451 /* nsIPKCS11Module findModuleByName(in wstring name); */
453 nsPKCS11ModuleDB::FindModuleByName(const PRUnichar
*aName
,
454 nsIPKCS11Module
**_retval
)
456 nsNSSShutDownPreventionLock locker
;
457 NS_ConvertUTF16toUTF8
aUtf8Name(aName
);
459 SECMOD_FindModule(const_cast<char *>(aUtf8Name
.get()));
461 return NS_ERROR_FAILURE
;
462 nsCOMPtr
<nsIPKCS11Module
> module
= new nsPKCS11Module(mod
);
463 SECMOD_DestroyModule(mod
);
465 return NS_ERROR_OUT_OF_MEMORY
;
471 /* This is essentially the same as nsIPK11Token::findTokenByName, except
472 * that it returns an nsIPKCS11Slot, which may be desired.
474 /* nsIPKCS11Module findSlotByName(in wstring name); */
476 nsPKCS11ModuleDB::FindSlotByName(const PRUnichar
*aName
,
477 nsIPKCS11Slot
**_retval
)
479 nsNSSShutDownPreventionLock locker
;
480 NS_ConvertUTF16toUTF8
aUtf8Name(aName
);
481 PK11SlotInfo
*slotinfo
=
482 PK11_FindSlotByName(const_cast<char*>(aUtf8Name
.get()));
484 return NS_ERROR_FAILURE
;
485 nsCOMPtr
<nsIPKCS11Slot
> slot
= new nsPKCS11Slot(slotinfo
);
486 PK11_FreeSlot(slotinfo
);
488 return NS_ERROR_OUT_OF_MEMORY
;
494 /* nsIEnumerator listModules (); */
496 nsPKCS11ModuleDB::ListModules(nsIEnumerator
**_retval
)
498 nsNSSShutDownPreventionLock locker
;
500 /* get isupports array */
501 nsCOMPtr
<nsISupportsArray
> array
;
502 rv
= NS_NewISupportsArray(getter_AddRefs(array
));
503 if (NS_FAILED(rv
)) return rv
;
504 /* get the default list of modules */
505 SECMODModuleList
*list
= SECMOD_GetDefaultModuleList();
506 /* lock down the list for reading */
507 SECMODListLock
*lock
= SECMOD_GetDefaultModuleListLock();
508 SECMOD_GetReadLock(lock
);
510 nsCOMPtr
<nsIPKCS11Module
> module
= new nsPKCS11Module(list
->module
);
511 array
->AppendElement(module
);
514 /* Get the modules in the database that didn't load */
515 list
= SECMOD_GetDeadModuleList();
517 nsCOMPtr
<nsIPKCS11Module
> module
= new nsPKCS11Module(list
->module
);
518 array
->AppendElement(module
);
521 SECMOD_ReleaseReadLock(lock
);
522 rv
= array
->Enumerate(_retval
);
526 NS_IMETHODIMP
nsPKCS11ModuleDB::GetCanToggleFIPS(PRBool
*aCanToggleFIPS
)
528 nsNSSShutDownPreventionLock locker
;
529 *aCanToggleFIPS
= SECMOD_CanDeleteInternalModule();
534 /* void toggleFIPSMode (); */
535 NS_IMETHODIMP
nsPKCS11ModuleDB::ToggleFIPSMode()
537 nsNSSShutDownPreventionLock locker
;
538 // The way to toggle FIPS mode in NSS is extremely obscure.
539 // Basically, we delete the internal module, and voila it
540 // gets replaced with the opposite module, ie if it was
541 // FIPS before, then it becomes non-FIPS next.
542 SECMODModule
*internal
;
544 // This function returns us a pointer to a local copy of
545 // the internal module stashed in NSS. We don't want to
546 // delete it since it will cause much pain in NSS.
547 internal
= SECMOD_GetInternalModule();
549 return NS_ERROR_FAILURE
;
551 SECStatus srv
= SECMOD_DeleteInternalModule(internal
->commonName
);
552 if (srv
!= SECSuccess
)
553 return NS_ERROR_FAILURE
;
558 /* readonly attribute boolean isFIPSEnabled; */
559 NS_IMETHODIMP
nsPKCS11ModuleDB::GetIsFIPSEnabled(PRBool
*aIsFIPSEnabled
)
561 nsNSSShutDownPreventionLock locker
;
562 *aIsFIPSEnabled
= PK11_IsFIPS();
566 NS_IMETHODIMP
nsPKCS11ModuleDB::GetIsFIPSModeActive(PRBool
*aIsFIPSModeActive
)
568 return GetIsFIPSEnabled(aIsFIPSModeActive
);