Source code

Revision control

Other Tools

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
* Deal with PKCS #11 Slots.
6
*/
7
#include "seccomon.h"
8
#include "secmod.h"
9
#include "nssilock.h"
10
#include "secmodi.h"
11
#include "secmodti.h"
12
#include "pkcs11t.h"
13
#include "pk11func.h"
14
#include "secitem.h"
15
#include "secerr.h"
16
17
#include "dev.h"
18
#include "dev3hack.h"
19
#include "pkim.h"
20
#include "utilpars.h"
21
#include "pkcs11uri.h"
22
23
/*************************************************************
24
* local static and global data
25
*************************************************************/
26
27
/*
28
* This array helps parsing between names, mechanisms, and flags.
29
* to make the config files understand more entries, add them
30
* to this table.
31
*/
32
const PK11DefaultArrayEntry PK11_DefaultArray[] = {
33
{ "RSA", SECMOD_RSA_FLAG, CKM_RSA_PKCS },
34
{ "DSA", SECMOD_DSA_FLAG, CKM_DSA },
35
{ "ECC", SECMOD_ECC_FLAG, CKM_ECDSA },
36
{ "DH", SECMOD_DH_FLAG, CKM_DH_PKCS_DERIVE },
37
{ "RC2", SECMOD_RC2_FLAG, CKM_RC2_CBC },
38
{ "RC4", SECMOD_RC4_FLAG, CKM_RC4 },
39
{ "DES", SECMOD_DES_FLAG, CKM_DES_CBC },
40
{ "AES", SECMOD_AES_FLAG, CKM_AES_CBC },
41
{ "Camellia", SECMOD_CAMELLIA_FLAG, CKM_CAMELLIA_CBC },
42
{ "SEED", SECMOD_SEED_FLAG, CKM_SEED_CBC },
43
{ "RC5", SECMOD_RC5_FLAG, CKM_RC5_CBC },
44
{ "SHA-1", SECMOD_SHA1_FLAG, CKM_SHA_1 },
45
/* { "SHA224", SECMOD_SHA256_FLAG, CKM_SHA224 }, */
46
{ "SHA256", SECMOD_SHA256_FLAG, CKM_SHA256 },
47
/* { "SHA384", SECMOD_SHA512_FLAG, CKM_SHA384 }, */
48
{ "SHA512", SECMOD_SHA512_FLAG, CKM_SHA512 },
49
{ "MD5", SECMOD_MD5_FLAG, CKM_MD5 },
50
{ "MD2", SECMOD_MD2_FLAG, CKM_MD2 },
51
{ "SSL", SECMOD_SSL_FLAG, CKM_SSL3_PRE_MASTER_KEY_GEN },
52
{ "TLS", SECMOD_TLS_FLAG, CKM_TLS_MASTER_KEY_DERIVE },
53
{ "SKIPJACK", SECMOD_FORTEZZA_FLAG, CKM_SKIPJACK_CBC64 },
54
{ "Publicly-readable certs", SECMOD_FRIENDLY_FLAG, CKM_INVALID_MECHANISM },
55
{ "Random Num Generator", SECMOD_RANDOM_FLAG, CKM_FAKE_RANDOM },
56
};
57
const int num_pk11_default_mechanisms =
58
sizeof(PK11_DefaultArray) / sizeof(PK11_DefaultArray[0]);
59
60
const PK11DefaultArrayEntry *
61
PK11_GetDefaultArray(int *size)
62
{
63
if (size) {
64
*size = num_pk11_default_mechanisms;
65
}
66
return PK11_DefaultArray;
67
}
68
69
/*
70
* These slotlists are lists of modules which provide default support for
71
* a given algorithm or mechanism.
72
*/
73
static PK11SlotList
74
pk11_seedSlotList,
75
pk11_camelliaSlotList,
76
pk11_aesSlotList,
77
pk11_desSlotList,
78
pk11_rc4SlotList,
79
pk11_rc2SlotList,
80
pk11_rc5SlotList,
81
pk11_sha1SlotList,
82
pk11_md5SlotList,
83
pk11_md2SlotList,
84
pk11_rsaSlotList,
85
pk11_dsaSlotList,
86
pk11_dhSlotList,
87
pk11_ecSlotList,
88
pk11_ideaSlotList,
89
pk11_sslSlotList,
90
pk11_tlsSlotList,
91
pk11_randomSlotList,
92
pk11_sha256SlotList,
93
pk11_sha512SlotList; /* slots do SHA512 and SHA384 */
94
95
/************************************************************
96
* Generic Slot List and Slot List element manipulations
97
************************************************************/
98
99
/*
100
* allocate a new list
101
*/
102
PK11SlotList *
103
PK11_NewSlotList(void)
104
{
105
PK11SlotList *list;
106
107
list = (PK11SlotList *)PORT_Alloc(sizeof(PK11SlotList));
108
if (list == NULL)
109
return NULL;
110
list->head = NULL;
111
list->tail = NULL;
112
list->lock = PZ_NewLock(nssILockList);
113
if (list->lock == NULL) {
114
PORT_Free(list);
115
return NULL;
116
}
117
118
return list;
119
}
120
121
/*
122
* free a list element when all the references go away.
123
*/
124
SECStatus
125
PK11_FreeSlotListElement(PK11SlotList *list, PK11SlotListElement *le)
126
{
127
PRBool freeit = PR_FALSE;
128
129
if (list == NULL || le == NULL) {
130
PORT_SetError(SEC_ERROR_INVALID_ARGS);
131
return SECFailure;
132
}
133
134
PZ_Lock(list->lock);
135
if (le->refCount-- == 1) {
136
freeit = PR_TRUE;
137
}
138
PZ_Unlock(list->lock);
139
if (freeit) {
140
PK11_FreeSlot(le->slot);
141
PORT_Free(le);
142
}
143
return SECSuccess;
144
}
145
146
static void
147
pk11_FreeSlotListStatic(PK11SlotList *list)
148
{
149
PK11SlotListElement *le, *next;
150
if (list == NULL)
151
return;
152
153
for (le = list->head; le; le = next) {
154
next = le->next;
155
PK11_FreeSlotListElement(list, le);
156
}
157
if (list->lock) {
158
PZ_DestroyLock(list->lock);
159
}
160
list->lock = NULL;
161
list->head = NULL;
162
}
163
164
/*
165
* if we are freeing the list, we must be the only ones with a pointer
166
* to the list.
167
*/
168
void
169
PK11_FreeSlotList(PK11SlotList *list)
170
{
171
pk11_FreeSlotListStatic(list);
172
PORT_Free(list);
173
}
174
175
/*
176
* add a slot to a list
177
* "slot" is the slot to be added. Ownership is not transferred.
178
* "sorted" indicates whether or not the slot should be inserted according to
179
* cipherOrder of the associated module. PR_FALSE indicates that the slot
180
* should be inserted to the head of the list.
181
*/
182
SECStatus
183
PK11_AddSlotToList(PK11SlotList *list, PK11SlotInfo *slot, PRBool sorted)
184
{
185
PK11SlotListElement *le;
186
PK11SlotListElement *element;
187
188
le = (PK11SlotListElement *)PORT_Alloc(sizeof(PK11SlotListElement));
189
if (le == NULL)
190
return SECFailure;
191
192
le->slot = PK11_ReferenceSlot(slot);
193
le->prev = NULL;
194
le->refCount = 1;
195
PZ_Lock(list->lock);
196
element = list->head;
197
/* Insertion sort, with higher cipherOrders are sorted first in the list */
198
while (element && sorted && (element->slot->module->cipherOrder >
199
le->slot->module->cipherOrder)) {
200
element = element->next;
201
}
202
if (element) {
203
le->prev = element->prev;
204
element->prev = le;
205
le->next = element;
206
} else {
207
le->prev = list->tail;
208
le->next = NULL;
209
list->tail = le;
210
}
211
if (le->prev)
212
le->prev->next = le;
213
if (list->head == element)
214
list->head = le;
215
PZ_Unlock(list->lock);
216
217
return SECSuccess;
218
}
219
220
/*
221
* remove a slot entry from the list
222
*/
223
SECStatus
224
PK11_DeleteSlotFromList(PK11SlotList *list, PK11SlotListElement *le)
225
{
226
PZ_Lock(list->lock);
227
if (le->prev)
228
le->prev->next = le->next;
229
else
230
list->head = le->next;
231
if (le->next)
232
le->next->prev = le->prev;
233
else
234
list->tail = le->prev;
235
le->next = le->prev = NULL;
236
PZ_Unlock(list->lock);
237
PK11_FreeSlotListElement(list, le);
238
return SECSuccess;
239
}
240
241
/*
242
* Move a list to the end of the target list.
243
* NOTE: There is no locking here... This assumes BOTH lists are private copy
244
* lists. It also does not re-sort the target list.
245
*/
246
SECStatus
247
pk11_MoveListToList(PK11SlotList *target, PK11SlotList *src)
248
{
249
if (src->head == NULL)
250
return SECSuccess;
251
252
if (target->tail == NULL) {
253
target->head = src->head;
254
} else {
255
target->tail->next = src->head;
256
}
257
src->head->prev = target->tail;
258
target->tail = src->tail;
259
src->head = src->tail = NULL;
260
return SECSuccess;
261
}
262
263
/*
264
* get an element from the list with a reference. You must own the list.
265
*/
266
PK11SlotListElement *
267
PK11_GetFirstRef(PK11SlotList *list)
268
{
269
PK11SlotListElement *le;
270
271
le = list->head;
272
if (le != NULL)
273
(le)->refCount++;
274
return le;
275
}
276
277
/*
278
* get the next element from the list with a reference. You must own the list.
279
*/
280
PK11SlotListElement *
281
PK11_GetNextRef(PK11SlotList *list, PK11SlotListElement *le, PRBool restart)
282
{
283
PK11SlotListElement *new_le;
284
new_le = le->next;
285
if (new_le)
286
new_le->refCount++;
287
PK11_FreeSlotListElement(list, le);
288
return new_le;
289
}
290
291
/*
292
* get an element safely from the list. This just makes sure that if
293
* this element is not deleted while we deal with it.
294
*/
295
PK11SlotListElement *
296
PK11_GetFirstSafe(PK11SlotList *list)
297
{
298
PK11SlotListElement *le;
299
300
PZ_Lock(list->lock);
301
le = list->head;
302
if (le != NULL)
303
(le)->refCount++;
304
PZ_Unlock(list->lock);
305
return le;
306
}
307
308
/*
309
* NOTE: if this element gets deleted, we can no longer safely traverse using
310
* it's pointers. We can either terminate the loop, or restart from the
311
* beginning. This is controlled by the restart option.
312
*/
313
PK11SlotListElement *
314
PK11_GetNextSafe(PK11SlotList *list, PK11SlotListElement *le, PRBool restart)
315
{
316
PK11SlotListElement *new_le;
317
PZ_Lock(list->lock);
318
new_le = le->next;
319
if (le->next == NULL) {
320
/* if the prev and next fields are NULL then either this element
321
* has been removed and we need to walk the list again (if restart
322
* is true) or this was the only element on the list */
323
if ((le->prev == NULL) && restart && (list->head != le)) {
324
new_le = list->head;
325
}
326
}
327
if (new_le)
328
new_le->refCount++;
329
PZ_Unlock(list->lock);
330
PK11_FreeSlotListElement(list, le);
331
return new_le;
332
}
333
334
/*
335
* Find the element that holds this slot
336
*/
337
PK11SlotListElement *
338
PK11_FindSlotElement(PK11SlotList *list, PK11SlotInfo *slot)
339
{
340
PK11SlotListElement *le;
341
342
for (le = PK11_GetFirstSafe(list); le;
343
le = PK11_GetNextSafe(list, le, PR_TRUE)) {
344
if (le->slot == slot)
345
return le;
346
}
347
return NULL;
348
}
349
350
/************************************************************
351
* Generic Slot Utilities
352
************************************************************/
353
/*
354
* Create a new slot structure
355
*/
356
PK11SlotInfo *
357
PK11_NewSlotInfo(SECMODModule *mod)
358
{
359
PK11SlotInfo *slot;
360
361
slot = (PK11SlotInfo *)PORT_Alloc(sizeof(PK11SlotInfo));
362
if (slot == NULL)
363
return slot;
364
365
slot->sessionLock = mod->isThreadSafe ? PZ_NewLock(nssILockSession) : mod->refLock;
366
if (slot->sessionLock == NULL) {
367
PORT_Free(slot);
368
return NULL;
369
}
370
slot->freeListLock = PZ_NewLock(nssILockFreelist);
371
if (slot->freeListLock == NULL) {
372
if (mod->isThreadSafe) {
373
PZ_DestroyLock(slot->sessionLock);
374
}
375
PORT_Free(slot);
376
return NULL;
377
}
378
slot->freeSymKeysWithSessionHead = NULL;
379
slot->freeSymKeysHead = NULL;
380
slot->keyCount = 0;
381
slot->maxKeyCount = 0;
382
slot->functionList = NULL;
383
slot->needTest = PR_TRUE;
384
slot->isPerm = PR_FALSE;
385
slot->isHW = PR_FALSE;
386
slot->isInternal = PR_FALSE;
387
slot->isThreadSafe = PR_FALSE;
388
slot->disabled = PR_FALSE;
389
slot->series = 1;
390
slot->wrapKey = 0;
391
slot->wrapMechanism = CKM_INVALID_MECHANISM;
392
slot->refKeys[0] = CK_INVALID_HANDLE;
393
slot->reason = PK11_DIS_NONE;
394
slot->readOnly = PR_TRUE;
395
slot->needLogin = PR_FALSE;
396
slot->hasRandom = PR_FALSE;
397
slot->defRWSession = PR_FALSE;
398
slot->protectedAuthPath = PR_FALSE;
399
slot->flags = 0;
400
slot->session = CK_INVALID_SESSION;
401
slot->slotID = 0;
402
slot->defaultFlags = 0;
403
slot->refCount = 1;
404
slot->askpw = 0;
405
slot->timeout = 0;
406
slot->mechanismList = NULL;
407
slot->mechanismCount = 0;
408
slot->cert_array = NULL;
409
slot->cert_count = 0;
410
slot->slot_name[0] = 0;
411
slot->token_name[0] = 0;
412
PORT_Memset(slot->serial, ' ', sizeof(slot->serial));
413
PORT_Memset(&slot->tokenInfo, 0, sizeof(slot->tokenInfo));
414
slot->module = NULL;
415
slot->authTransact = 0;
416
slot->authTime = LL_ZERO;
417
slot->minPassword = 0;
418
slot->maxPassword = 0;
419
slot->hasRootCerts = PR_FALSE;
420
slot->hasRootTrust = PR_FALSE;
421
slot->nssToken = NULL;
422
slot->profileList = NULL;
423
slot->profileCount = 0;
424
return slot;
425
}
426
427
/* create a new reference to a slot so it doesn't go away */
428
PK11SlotInfo *
429
PK11_ReferenceSlot(PK11SlotInfo *slot)
430
{
431
PR_ATOMIC_INCREMENT(&slot->refCount);
432
return slot;
433
}
434
435
/* Destroy all info on a slot we have built up */
436
void
437
PK11_DestroySlot(PK11SlotInfo *slot)
438
{
439
/* free up the cached keys and sessions */
440
PK11_CleanKeyList(slot);
441
442
/* free up all the sessions on this slot */
443
if (slot->functionList) {
444
PK11_GETTAB(slot)
445
->C_CloseAllSessions(slot->slotID);
446
}
447
448
if (slot->mechanismList) {
449
PORT_Free(slot->mechanismList);
450
}
451
if (slot->profileList) {
452
PORT_Free(slot->profileList);
453
}
454
if (slot->isThreadSafe && slot->sessionLock) {
455
PZ_DestroyLock(slot->sessionLock);
456
}
457
slot->sessionLock = NULL;
458
if (slot->freeListLock) {
459
PZ_DestroyLock(slot->freeListLock);
460
slot->freeListLock = NULL;
461
}
462
463
/* finally Tell our parent module that we've gone away so it can unload */
464
if (slot->module) {
465
SECMOD_SlotDestroyModule(slot->module, PR_TRUE);
466
}
467
468
/* ok, well not quit finally... now we free the memory */
469
PORT_Free(slot);
470
}
471
472
/* We're all done with the slot, free it */
473
void
474
PK11_FreeSlot(PK11SlotInfo *slot)
475
{
476
if (PR_ATOMIC_DECREMENT(&slot->refCount) == 0) {
477
PK11_DestroySlot(slot);
478
}
479
}
480
481
void
482
PK11_EnterSlotMonitor(PK11SlotInfo *slot)
483
{
484
PZ_Lock(slot->sessionLock);
485
}
486
487
void
488
PK11_ExitSlotMonitor(PK11SlotInfo *slot)
489
{
490
PZ_Unlock(slot->sessionLock);
491
}
492
493
/***********************************************************
494
* Functions to find specific slots.
495
***********************************************************/
496
PRBool
497
SECMOD_HasRootCerts(void)
498
{
499
SECMODModuleList *mlp;
500
SECMODModuleList *modules;
501
SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
502
int i;
503
PRBool found = PR_FALSE;
504
505
if (!moduleLock) {
506
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
507
return found;
508
}
509
510
/* work through all the slots */
511
SECMOD_GetReadLock(moduleLock);
512
modules = SECMOD_GetDefaultModuleList();
513
for (mlp = modules; mlp != NULL; mlp = mlp->next) {
514
for (i = 0; i < mlp->module->slotCount; i++) {
515
PK11SlotInfo *tmpSlot = mlp->module->slots[i];
516
if (PK11_IsPresent(tmpSlot)) {
517
if (tmpSlot->hasRootCerts) {
518
found = PR_TRUE;
519
break;
520
}
521
}
522
}
523
if (found)
524
break;
525
}
526
SECMOD_ReleaseReadLock(moduleLock);
527
528
return found;
529
}
530
531
/***********************************************************
532
* Functions to find specific slots.
533
***********************************************************/
534
PK11SlotList *
535
PK11_FindSlotsByNames(const char *dllName, const char *slotName,
536
const char *tokenName, PRBool presentOnly)
537
{
538
SECMODModuleList *mlp;
539
SECMODModuleList *modules;
540
SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
541
int i;
542
PK11SlotList *slotList = NULL;
543
PRUint32 slotcount = 0;
544
SECStatus rv = SECSuccess;
545
546
if (!moduleLock) {
547
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
548
return slotList;
549
}
550
551
slotList = PK11_NewSlotList();
552
if (!slotList) {
553
PORT_SetError(SEC_ERROR_NO_MEMORY);
554
return slotList;
555
}
556
557
if (((NULL == dllName) || (0 == *dllName)) &&
558
((NULL == slotName) || (0 == *slotName)) &&
559
((NULL == tokenName) || (0 == *tokenName))) {
560
/* default to softoken */
561
/* PK11_GetInternalKeySlot increments the refcount on the internal slot,
562
* but so does PK11_AddSlotToList. To avoid erroneously increasing the
563
* refcount twice, we get our own reference to the internal slot and
564
* decrement its refcount when we're done with it. */
565
PK11SlotInfo *internalKeySlot = PK11_GetInternalKeySlot();
566
PK11_AddSlotToList(slotList, internalKeySlot, PR_TRUE);
567
PK11_FreeSlot(internalKeySlot);
568
return slotList;
569
}
570
571
/* work through all the slots */
572
SECMOD_GetReadLock(moduleLock);
573
modules = SECMOD_GetDefaultModuleList();
574
for (mlp = modules; mlp != NULL; mlp = mlp->next) {
575
PORT_Assert(mlp->module);
576
if (!mlp->module) {
577
rv = SECFailure;
578
break;
579
}
580
if ((!dllName) || (mlp->module->dllName &&
581
(0 == PORT_Strcmp(mlp->module->dllName, dllName)))) {
582
for (i = 0; i < mlp->module->slotCount; i++) {
583
PK11SlotInfo *tmpSlot = (mlp->module->slots ? mlp->module->slots[i] : NULL);
584
PORT_Assert(tmpSlot);
585
if (!tmpSlot) {
586
rv = SECFailure;
587
break;
588
}
589
if ((PR_FALSE == presentOnly || PK11_IsPresent(tmpSlot)) &&
590
((!tokenName) ||
591
(0 == PORT_Strcmp(tmpSlot->token_name, tokenName))) &&
592
((!slotName) ||
593
(0 == PORT_Strcmp(tmpSlot->slot_name, slotName)))) {
594
PK11_AddSlotToList(slotList, tmpSlot, PR_TRUE);
595
slotcount++;
596
}
597
}
598
}
599
}
600
SECMOD_ReleaseReadLock(moduleLock);
601
602
if ((0 == slotcount) || (SECFailure == rv)) {
603
PORT_SetError(SEC_ERROR_NO_TOKEN);
604
PK11_FreeSlotList(slotList);
605
slotList = NULL;
606
}
607
608
if (SECFailure == rv) {
609
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
610
}
611
612
return slotList;
613
}
614
615
typedef PRBool (*PK11SlotMatchFunc)(PK11SlotInfo *slot, const void *arg);
616
617
static PRBool
618
pk11_MatchSlotByTokenName(PK11SlotInfo *slot, const void *arg)
619
{
620
return PORT_Strcmp(slot->token_name, arg) == 0;
621
}
622
623
static PRBool
624
pk11_MatchSlotBySerial(PK11SlotInfo *slot, const void *arg)
625
{
626
return PORT_Memcmp(slot->serial, arg, sizeof(slot->serial)) == 0;
627
}
628
629
static PRBool
630
pk11_MatchSlotByTokenURI(PK11SlotInfo *slot, const void *arg)
631
{
632
return pk11_MatchUriTokenInfo(slot, (PK11URI *)arg);
633
}
634
635
static PK11SlotInfo *
636
pk11_FindSlot(const void *arg, PK11SlotMatchFunc func)
637
{
638
SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
639
SECMODModuleList *mlp;
640
SECMODModuleList *modules;
641
int i;
642
PK11SlotInfo *slot = NULL;
643
644
if (!moduleLock) {
645
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
646
return slot;
647
}
648
/* work through all the slots */
649
SECMOD_GetReadLock(moduleLock);
650
modules = SECMOD_GetDefaultModuleList();
651
for (mlp = modules; mlp != NULL; mlp = mlp->next) {
652
for (i = 0; i < mlp->module->slotCount; i++) {
653
PK11SlotInfo *tmpSlot = mlp->module->slots[i];
654
if (PK11_IsPresent(tmpSlot)) {
655
if (func(tmpSlot, arg)) {
656
slot = PK11_ReferenceSlot(tmpSlot);
657
break;
658
}
659
}
660
}
661
if (slot != NULL)
662
break;
663
}
664
SECMOD_ReleaseReadLock(moduleLock);
665
666
if (slot == NULL) {
667
PORT_SetError(SEC_ERROR_NO_TOKEN);
668
}
669
670
return slot;
671
}
672
673
static PK11SlotInfo *
674
pk11_FindSlotByTokenURI(const char *uriString)
675
{
676
PK11SlotInfo *slot = NULL;
677
PK11URI *uri;
678
679
uri = PK11URI_ParseURI(uriString);
680
if (!uri) {
681
PORT_SetError(SEC_ERROR_INVALID_ARGS);
682
return slot;
683
}
684
685
slot = pk11_FindSlot(uri, pk11_MatchSlotByTokenURI);
686
PK11URI_DestroyURI(uri);
687
return slot;
688
}
689
690
PK11SlotInfo *
691
PK11_FindSlotByName(const char *name)
692
{
693
if ((name == NULL) || (*name == 0)) {
694
return PK11_GetInternalKeySlot();
695
}
696
697
if (!PORT_Strncasecmp(name, "pkcs11:", strlen("pkcs11:"))) {
698
return pk11_FindSlotByTokenURI(name);
699
}
700
701
return pk11_FindSlot(name, pk11_MatchSlotByTokenName);
702
}
703
704
PK11SlotInfo *
705
PK11_FindSlotBySerial(char *serial)
706
{
707
return pk11_FindSlot(serial, pk11_MatchSlotBySerial);
708
}
709
710
/*
711
* notification stub. If we ever get interested in any events that
712
* the pkcs11 functions may pass back to use, we can catch them here...
713
* currently pdata is a slotinfo structure.
714
*/
715
CK_RV
716
pk11_notify(CK_SESSION_HANDLE session, CK_NOTIFICATION event,
717
CK_VOID_PTR pdata)
718
{
719
return CKR_OK;
720
}
721
722
/*
723
* grab a new RW session
724
* !!! has a side effect of grabbing the Monitor if either the slot's default
725
* session is RW or the slot is not thread safe. Monitor is release in function
726
* below
727
*/
728
CK_SESSION_HANDLE
729
PK11_GetRWSession(PK11SlotInfo *slot)
730
{
731
CK_SESSION_HANDLE rwsession;
732
CK_RV crv;
733
PRBool haveMonitor = PR_FALSE;
734
735
if (!slot->isThreadSafe || slot->defRWSession) {
736
PK11_EnterSlotMonitor(slot);
737
haveMonitor = PR_TRUE;
738
}
739
if (slot->defRWSession) {
740
PORT_Assert(slot->session != CK_INVALID_SESSION);
741
if (slot->session != CK_INVALID_SESSION)
742
return slot->session;
743
}
744
745
crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,
746
CKF_RW_SESSION | CKF_SERIAL_SESSION,
747
slot, pk11_notify, &rwsession);
748
PORT_Assert(rwsession != CK_INVALID_SESSION || crv != CKR_OK);
749
if (crv != CKR_OK || rwsession == CK_INVALID_SESSION) {
750
if (crv == CKR_OK)
751
crv = CKR_DEVICE_ERROR;
752
if (haveMonitor)
753
PK11_ExitSlotMonitor(slot);
754
PORT_SetError(PK11_MapError(crv));
755
return CK_INVALID_SESSION;
756
}
757
if (slot->defRWSession) { /* we have the monitor */
758
slot->session = rwsession;
759
}
760
return rwsession;
761
}
762
763
PRBool
764
PK11_RWSessionHasLock(PK11SlotInfo *slot, CK_SESSION_HANDLE session_handle)
765
{
766
PRBool hasLock;
767
hasLock = (PRBool)(!slot->isThreadSafe ||
768
(slot->defRWSession && slot->session != CK_INVALID_SESSION));
769
return hasLock;
770
}
771
772
static PRBool
773
pk11_RWSessionIsDefault(PK11SlotInfo *slot, CK_SESSION_HANDLE rwsession)
774
{
775
PRBool isDefault;
776
isDefault = (PRBool)(slot->session == rwsession &&
777
slot->defRWSession &&
778
slot->session != CK_INVALID_SESSION);
779
return isDefault;
780
}
781
782
/*
783
* close the rwsession and restore our readonly session
784
* !!! has a side effect of releasing the Monitor if either the slot's default
785
* session is RW or the slot is not thread safe.
786
*/
787
void
788
PK11_RestoreROSession(PK11SlotInfo *slot, CK_SESSION_HANDLE rwsession)
789
{
790
PORT_Assert(rwsession != CK_INVALID_SESSION);
791
if (rwsession != CK_INVALID_SESSION) {
792
PRBool doExit = PK11_RWSessionHasLock(slot, rwsession);
793
if (!pk11_RWSessionIsDefault(slot, rwsession))
794
PK11_GETTAB(slot)
795
->C_CloseSession(rwsession);
796
if (doExit)
797
PK11_ExitSlotMonitor(slot);
798
}
799
}
800
801
/************************************************************
802
* Manage the built-In Slot Lists
803
************************************************************/
804
805
/* Init the static built int slot list (should actually integrate
806
* with PK11_NewSlotList */
807
static void
808
pk11_InitSlotListStatic(PK11SlotList *list)
809
{
810
list->lock = PZ_NewLock(nssILockList);
811
list->head = NULL;
812
}
813
814
/* initialize the system slotlists */
815
SECStatus
816
PK11_InitSlotLists(void)
817
{
818
pk11_InitSlotListStatic(&pk11_seedSlotList);
819
pk11_InitSlotListStatic(&pk11_camelliaSlotList);
820
pk11_InitSlotListStatic(&pk11_aesSlotList);
821
pk11_InitSlotListStatic(&pk11_desSlotList);
822
pk11_InitSlotListStatic(&pk11_rc4SlotList);
823
pk11_InitSlotListStatic(&pk11_rc2SlotList);
824
pk11_InitSlotListStatic(&pk11_rc5SlotList);
825
pk11_InitSlotListStatic(&pk11_md5SlotList);
826
pk11_InitSlotListStatic(&pk11_md2SlotList);
827
pk11_InitSlotListStatic(&pk11_sha1SlotList);
828
pk11_InitSlotListStatic(&pk11_rsaSlotList);
829
pk11_InitSlotListStatic(&pk11_dsaSlotList);
830
pk11_InitSlotListStatic(&pk11_dhSlotList);
831
pk11_InitSlotListStatic(&pk11_ecSlotList);
832
pk11_InitSlotListStatic(&pk11_ideaSlotList);
833
pk11_InitSlotListStatic(&pk11_sslSlotList);
834
pk11_InitSlotListStatic(&pk11_tlsSlotList);
835
pk11_InitSlotListStatic(&pk11_randomSlotList);
836
pk11_InitSlotListStatic(&pk11_sha256SlotList);
837
pk11_InitSlotListStatic(&pk11_sha512SlotList);
838
return SECSuccess;
839
}
840
841
void
842
PK11_DestroySlotLists(void)
843
{
844
pk11_FreeSlotListStatic(&pk11_seedSlotList);
845
pk11_FreeSlotListStatic(&pk11_camelliaSlotList);
846
pk11_FreeSlotListStatic(&pk11_aesSlotList);
847
pk11_FreeSlotListStatic(&pk11_desSlotList);
848
pk11_FreeSlotListStatic(&pk11_rc4SlotList);
849
pk11_FreeSlotListStatic(&pk11_rc2SlotList);
850
pk11_FreeSlotListStatic(&pk11_rc5SlotList);
851
pk11_FreeSlotListStatic(&pk11_md5SlotList);
852
pk11_FreeSlotListStatic(&pk11_md2SlotList);
853
pk11_FreeSlotListStatic(&pk11_sha1SlotList);
854
pk11_FreeSlotListStatic(&pk11_rsaSlotList);
855
pk11_FreeSlotListStatic(&pk11_dsaSlotList);
856
pk11_FreeSlotListStatic(&pk11_dhSlotList);
857
pk11_FreeSlotListStatic(&pk11_ecSlotList);
858
pk11_FreeSlotListStatic(&pk11_ideaSlotList);
859
pk11_FreeSlotListStatic(&pk11_sslSlotList);
860
pk11_FreeSlotListStatic(&pk11_tlsSlotList);
861
pk11_FreeSlotListStatic(&pk11_randomSlotList);
862
pk11_FreeSlotListStatic(&pk11_sha256SlotList);
863
pk11_FreeSlotListStatic(&pk11_sha512SlotList);
864
return;
865
}
866
867
/* return a system slot list based on mechanism */
868
PK11SlotList *
869
PK11_GetSlotList(CK_MECHANISM_TYPE type)
870
{
871
/* XXX a workaround for Bugzilla bug #55267 */
872
#if defined(HPUX) && defined(__LP64__)
873
if (CKM_INVALID_MECHANISM == type)
874
return NULL;
875
#endif
876
switch (type) {
877
case CKM_SEED_CBC:
878
case CKM_SEED_ECB:
879
return &pk11_seedSlotList;
880
case CKM_CAMELLIA_CBC:
881
case CKM_CAMELLIA_ECB:
882
return &pk11_camelliaSlotList;
883
case CKM_AES_CBC:
884
case CKM_AES_CCM:
885
case CKM_AES_CTR:
886
case CKM_AES_CTS:
887
case CKM_AES_GCM:
888
case CKM_AES_ECB:
889
return &pk11_aesSlotList;
890
case CKM_DES_CBC:
891
case CKM_DES_ECB:
892
case CKM_DES3_ECB:
893
case CKM_DES3_CBC:
894
return &pk11_desSlotList;
895
case CKM_RC4:
896
return &pk11_rc4SlotList;
897
case CKM_RC5_CBC:
898
return &pk11_rc5SlotList;
899
case CKM_SHA_1:
900
return &pk11_sha1SlotList;
901
case CKM_SHA224:
902
case CKM_SHA256:
903
return &pk11_sha256SlotList;
904
case CKM_SHA384:
905
case CKM_SHA512:
906
return &pk11_sha512SlotList;
907
case CKM_MD5:
908
return &pk11_md5SlotList;
909
case CKM_MD2:
910
return &pk11_md2SlotList;
911
case CKM_RC2_ECB:
912
case CKM_RC2_CBC:
913
return &pk11_rc2SlotList;
914
case CKM_RSA_PKCS:
915
case CKM_RSA_PKCS_KEY_PAIR_GEN:
916
case CKM_RSA_X_509:
917
return &pk11_rsaSlotList;
918
case CKM_DSA:
919
return &pk11_dsaSlotList;
920
case CKM_DH_PKCS_KEY_PAIR_GEN:
921
case CKM_DH_PKCS_DERIVE:
922
return &pk11_dhSlotList;
923
case CKM_ECDSA:
924
case CKM_ECDSA_SHA1:
925
case CKM_EC_KEY_PAIR_GEN: /* aka CKM_ECDSA_KEY_PAIR_GEN */
926
case CKM_ECDH1_DERIVE:
927
return &pk11_ecSlotList;
928
case CKM_SSL3_PRE_MASTER_KEY_GEN:
929
case CKM_SSL3_MASTER_KEY_DERIVE:
930
case CKM_SSL3_SHA1_MAC:
931
case CKM_SSL3_MD5_MAC:
932
return &pk11_sslSlotList;
933
case CKM_TLS_MASTER_KEY_DERIVE:
934
case CKM_TLS_KEY_AND_MAC_DERIVE:
935
case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256:
936
return &pk11_tlsSlotList;
937
case CKM_IDEA_CBC:
938
case CKM_IDEA_ECB:
939
return &pk11_ideaSlotList;
940
case CKM_FAKE_RANDOM:
941
return &pk11_randomSlotList;
942
}
943
return NULL;
944
}
945
946
/*
947
* load the static SlotInfo structures used to select a PKCS11 slot.
948
* preSlotInfo has a list of all the default flags for the slots on this
949
* module.
950
*/
951
void
952
PK11_LoadSlotList(PK11SlotInfo *slot, PK11PreSlotInfo *psi, int count)
953
{
954
int i;
955
956
for (i = 0; i < count; i++) {
957
if (psi[i].slotID == slot->slotID)
958
break;
959
}
960
961
if (i == count)
962
return;
963
964
slot->defaultFlags = psi[i].defaultFlags;
965
slot->askpw = psi[i].askpw;
966
slot->timeout = psi[i].timeout;
967
slot->hasRootCerts = psi[i].hasRootCerts;
968
969
/* if the slot is already disabled, don't load them into the
970
* default slot lists. We get here so we can save the default
971
* list value. */
972
if (slot->disabled)
973
return;
974
975
/* if the user has disabled us, don't load us in */
976
if (slot->defaultFlags & PK11_DISABLE_FLAG) {
977
slot->disabled = PR_TRUE;
978
slot->reason = PK11_DIS_USER_SELECTED;
979
/* free up sessions and things?? */
980
return;
981
}
982
983
for (i = 0; i < num_pk11_default_mechanisms; i++) {
984
if (slot->defaultFlags & PK11_DefaultArray[i].flag) {
985
CK_MECHANISM_TYPE mechanism = PK11_DefaultArray[i].mechanism;
986
PK11SlotList *slotList = PK11_GetSlotList(mechanism);
987
988
if (slotList)
989
PK11_AddSlotToList(slotList, slot, PR_FALSE);
990
}
991
}
992
993
return;
994
}
995
996
/*
997
* update a slot to its new attribute according to the slot list
998
* returns: SECSuccess if nothing to do or add/delete is successful
999
*/
1000
SECStatus
1001
PK11_UpdateSlotAttribute(PK11SlotInfo *slot,
1002
const PK11DefaultArrayEntry *entry,
1003
PRBool add)
1004
/* add: PR_TRUE if want to turn on */
1005
{
1006
SECStatus result = SECSuccess;
1007
PK11SlotList *slotList = PK11_GetSlotList(entry->mechanism);
1008
1009
if (add) { /* trying to turn on a mechanism */
1010
1011
/* turn on the default flag in the slot */
1012
slot->defaultFlags |= entry->flag;
1013
1014
/* add this slot to the list */
1015
if (slotList != NULL)
1016
result = PK11_AddSlotToList(slotList, slot, PR_FALSE);
1017
1018
} else { /* trying to turn off */
1019
1020
/* turn OFF the flag in the slot */
1021
slot->defaultFlags &= ~entry->flag;
1022
1023
if (slotList) {
1024
/* find the element in the list & delete it */
1025
PK11SlotListElement *le = PK11_FindSlotElement(slotList, slot);
1026
1027
/* remove the slot from the list */
1028
if (le)
1029
result = PK11_DeleteSlotFromList(slotList, le);
1030
}
1031
}
1032
return result;
1033
}
1034
1035
/*
1036
* clear a slot off of all of it's default list
1037
*/
1038
void
1039
PK11_ClearSlotList(PK11SlotInfo *slot)
1040
{
1041
int i;
1042
1043
if (slot->disabled)
1044
return;
1045
if (slot->defaultFlags == 0)
1046
return;
1047
1048
for (i = 0; i < num_pk11_default_mechanisms; i++) {
1049
if (slot->defaultFlags & PK11_DefaultArray[i].flag) {
1050
CK_MECHANISM_TYPE mechanism = PK11_DefaultArray[i].mechanism;
1051
PK11SlotList *slotList = PK11_GetSlotList(mechanism);
1052
PK11SlotListElement *le = NULL;
1053
1054
if (slotList)
1055
le = PK11_FindSlotElement(slotList, slot);
1056
1057
if (le) {
1058
PK11_DeleteSlotFromList(slotList, le);
1059
PK11_FreeSlotListElement(slotList, le);
1060
}
1061
}
1062
}
1063
}
1064
1065
/******************************************************************
1066
* Slot initialization
1067
******************************************************************/
1068
/*
1069
* turn a PKCS11 Static Label into a string
1070
*/
1071
char *
1072
PK11_MakeString(PLArenaPool *arena, char *space,
1073
char *staticString, int stringLen)
1074
{
1075
int i;
1076
char *newString;
1077
for (i = (stringLen - 1); i >= 0; i--) {
1078
if (staticString[i] != ' ')
1079
break;
1080
}
1081
/* move i to point to the last space */
1082
i++;
1083
if (arena) {
1084
newString = (char *)PORT_ArenaAlloc(arena, i + 1 /* space for NULL */);
1085
} else if (space) {
1086
newString = space;
1087
} else {
1088
newString = (char *)PORT_Alloc(i + 1 /* space for NULL */);
1089
}
1090
if (newString == NULL)
1091
return NULL;
1092
1093
if (i)
1094
PORT_Memcpy(newString, staticString, i);
1095
newString[i] = 0;
1096
1097
return newString;
1098
}
1099
1100
/*
1101
* check if a null-terminated string matches with a PKCS11 Static Label
1102
*/
1103
PRBool
1104
pk11_MatchString(const char *string,
1105
const char *staticString, int staticStringLen)
1106
{
1107
int i;
1108
1109
for (i = (staticStringLen - 1); i >= 0; i--) {
1110
if (staticString[i] != ' ')
1111
break;
1112
}
1113
/* move i to point to the last space */
1114
i++;
1115
1116
if (strlen(string) == i && memcmp(string, staticString, i) == 0) {
1117
return PR_TRUE;
1118
}
1119
1120
return PR_FALSE;
1121
}
1122
1123
/*
1124
* Reads in the slots mechanism list for later use
1125
*/
1126
SECStatus
1127
PK11_ReadMechanismList(PK11SlotInfo *slot)
1128
{
1129
CK_ULONG count;
1130
CK_RV crv;
1131
PRUint32 i;
1132
1133
if (slot->mechanismList) {
1134
PORT_Free(slot->mechanismList);
1135
slot->mechanismList = NULL;
1136
}
1137
slot->mechanismCount = 0;
1138
1139
if (!slot->isThreadSafe)
1140
PK11_EnterSlotMonitor(slot);
1141
crv = PK11_GETTAB(slot)->C_GetMechanismList(slot->slotID, NULL, &count);
1142
if (crv != CKR_OK) {
1143
if (!slot->isThreadSafe)
1144
PK11_ExitSlotMonitor(slot);
1145
PORT_SetError(PK11_MapError(crv));
1146
return SECFailure;
1147
}
1148
1149
slot->mechanismList = (CK_MECHANISM_TYPE *)
1150
PORT_Alloc(count * sizeof(CK_MECHANISM_TYPE));
1151
if (slot->mechanismList == NULL) {
1152
if (!slot->isThreadSafe)
1153
PK11_ExitSlotMonitor(slot);
1154
return SECFailure;
1155
}
1156
crv = PK11_GETTAB(slot)->C_GetMechanismList(slot->slotID,
1157
slot->mechanismList, &count);
1158
if (!slot->isThreadSafe)
1159
PK11_ExitSlotMonitor(slot);
1160
if (crv != CKR_OK) {
1161
PORT_Free(slot->mechanismList);
1162
slot->mechanismList = NULL;
1163
PORT_SetError(PK11_MapError(crv));
1164
return SECSuccess;
1165
}
1166
slot->mechanismCount = count;
1167
PORT_Memset(slot->mechanismBits, 0, sizeof(slot->mechanismBits));
1168
1169
for (i = 0; i < count; i++) {
1170
CK_MECHANISM_TYPE mech = slot->mechanismList[i];
1171
if (mech < 0x7ff) {
1172
slot->mechanismBits[mech & 0xff] |= 1 << (mech >> 8);
1173
}
1174
}
1175
return SECSuccess;
1176
}
1177
1178
static SECStatus
1179
pk11_ReadProfileList(PK11SlotInfo *slot)
1180
{
1181
CK_ATTRIBUTE findTemp[2];
1182
CK_ATTRIBUTE *attrs;
1183
CK_BBOOL cktrue = CK_TRUE;
1184
CK_OBJECT_CLASS oclass = CKO_PROFILE;
1185
int tsize;
1186
int objCount;
1187
CK_OBJECT_HANDLE *handles = NULL;
1188
int i;
1189
1190
attrs = findTemp;
1191
PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue));
1192
attrs++;
1193
PK11_SETATTRS(attrs, CKA_CLASS, &oclass, sizeof(oclass));
1194
attrs++;
1195
tsize = attrs - findTemp;
1196
PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE));
1197
1198
if (slot->profileList) {
1199
PORT_Free(slot->profileList);
1200
slot->profileList = NULL;
1201
}
1202
slot->profileCount = 0;
1203
1204
objCount = 0;
1205
handles = pk11_FindObjectsByTemplate(slot, findTemp, tsize, &objCount);
1206
if (handles == NULL) {
1207
if (objCount < 0) {
1208
return SECFailure; /* error code is set */
1209
}
1210
PORT_Assert(objCount == 0);
1211
return SECSuccess;
1212
}
1213
1214
slot->profileList = (CK_PROFILE_ID *)
1215
PORT_Alloc(objCount * sizeof(CK_PROFILE_ID));
1216
if (slot->profileList == NULL) {
1217
PORT_Free(handles);
1218
return SECFailure; /* error code is set */
1219
}
1220
1221
for (i = 0; i < objCount; i++) {
1222
CK_ULONG value;
1223
1224
value = PK11_ReadULongAttribute(slot, handles[i], CKA_PROFILE_ID);
1225
if (value == CK_UNAVAILABLE_INFORMATION) {
1226
continue;
1227
}
1228
slot->profileList[slot->profileCount++] = value;
1229
}
1230
1231
PORT_Free(handles);
1232
return SECSuccess;
1233
}
1234
1235
static PRBool
1236
pk11_HasProfile(PK11SlotInfo *slot, CK_PROFILE_ID id)
1237
{
1238
int i;
1239
1240
for (i = 0; i < slot->profileCount; i++) {
1241
if (slot->profileList[i] == id) {
1242
return PR_TRUE;
1243
}
1244
}
1245
return PR_FALSE;
1246
}
1247
1248
/*
1249
* initialize a new token
1250
* unlike initialize slot, this can be called multiple times in the lifetime
1251
* of NSS. It reads the information associated with a card or token,
1252
* that is not going to change unless the card or token changes.
1253
*/
1254
SECStatus
1255
PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts)
1256
{
1257
CK_RV crv;
1258
SECStatus rv;
1259
PRStatus status;
1260
1261
/* set the slot flags to the current token values */
1262
if (!slot->isThreadSafe)
1263
PK11_EnterSlotMonitor(slot);
1264
crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID, &slot->tokenInfo);
1265
if (!slot->isThreadSafe)
1266
PK11_ExitSlotMonitor(slot);
1267
if (crv != CKR_OK) {
1268
PORT_SetError(PK11_MapError(crv));
1269
return SECFailure;
1270
}
1271
1272
/* set the slot flags to the current token values */
1273
slot->series++; /* allow other objects to detect that the
1274
* slot is different */
1275
slot->flags = slot->tokenInfo.flags;
1276
slot->needLogin = ((slot->tokenInfo.flags & CKF_LOGIN_REQUIRED) ? PR_TRUE : PR_FALSE);
1277
slot->readOnly = ((slot->tokenInfo.flags & CKF_WRITE_PROTECTED) ? PR_TRUE : PR_FALSE);
1278
1279
slot->hasRandom = ((slot->tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE);
1280
slot->protectedAuthPath =
1281
((slot->tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
1282
? PR_TRUE
1283
: PR_FALSE);
1284
slot->lastLoginCheck = 0;
1285
slot->lastState = 0;
1286
/* on some platforms Active Card incorrectly sets the
1287
* CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */
1288
if (slot->isActiveCard) {
1289
slot->protectedAuthPath = PR_FALSE;
1290
}
1291
(void)PK11_MakeString(NULL, slot->token_name,
1292
(char *)slot->tokenInfo.label, sizeof(slot->tokenInfo.label));
1293
slot->minPassword = slot->tokenInfo.ulMinPinLen;
1294
slot->maxPassword = slot->tokenInfo.ulMaxPinLen;
1295
PORT_Memcpy(slot->serial, slot->tokenInfo.serialNumber, sizeof(slot->serial));
1296
1297
nssToken_UpdateName(slot->nssToken);
1298
1299
slot->defRWSession = (PRBool)((!slot->readOnly) &&
1300
(slot->tokenInfo.ulMaxSessionCount == 1));
1301
rv = PK11_ReadMechanismList(slot);
1302
if (rv != SECSuccess)
1303
return rv;
1304
1305
slot->hasRSAInfo = PR_FALSE;
1306
slot->RSAInfoFlags = 0;
1307
1308
/* initialize the maxKeyCount value */
1309
if (slot->tokenInfo.ulMaxSessionCount == 0) {
1310
slot->maxKeyCount = 800; /* should be #define or a config param */
1311
} else if (slot->tokenInfo.ulMaxSessionCount < 20) {
1312
/* don't have enough sessions to keep that many keys around */
1313
slot->maxKeyCount = 0;
1314
} else {
1315
slot->maxKeyCount = slot->tokenInfo.ulMaxSessionCount / 2;
1316
}
1317
1318
/* Make sure our session handle is valid */
1319
if (slot->session == CK_INVALID_SESSION) {
1320
/* we know we don't have a valid session, go get one */
1321
CK_SESSION_HANDLE session;
1322
1323
/* session should be Readonly, serial */
1324
if (!slot->isThreadSafe)
1325
PK11_EnterSlotMonitor(slot);
1326
crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,
1327
(slot->defRWSession ? CKF_RW_SESSION : 0) | CKF_SERIAL_SESSION,
1328
slot, pk11_notify, &session);
1329
if (!slot->isThreadSafe)
1330
PK11_ExitSlotMonitor(slot);
1331
if (crv != CKR_OK) {
1332
PORT_SetError(PK11_MapError(crv));
1333
return SECFailure;
1334
}
1335
slot->session = session;
1336
} else {
1337
/* The session we have may be defunct (the token associated with it)
1338
* has been removed */
1339
CK_SESSION_INFO sessionInfo;
1340
1341
if (!slot->isThreadSafe)
1342
PK11_EnterSlotMonitor(slot);
1343
crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session, &sessionInfo);
1344
if (crv == CKR_DEVICE_ERROR) {
1345
PK11_GETTAB(slot)
1346
->C_CloseSession(slot->session);
1347
crv = CKR_SESSION_CLOSED;
1348
}
1349
if ((crv == CKR_SESSION_CLOSED) || (crv == CKR_SESSION_HANDLE_INVALID)) {
1350
crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,
1351
(slot->defRWSession ? CKF_RW_SESSION : 0) | CKF_SERIAL_SESSION,
1352
slot, pk11_notify, &slot->session);
1353
if (crv != CKR_OK) {
1354
PORT_SetError(PK11_MapError(crv));
1355
slot->session = CK_INVALID_SESSION;
1356
if (!slot->isThreadSafe)
1357
PK11_ExitSlotMonitor(slot);
1358
return SECFailure;
1359
}
1360
}
1361
if (!slot->isThreadSafe)
1362
PK11_ExitSlotMonitor(slot);
1363
}
1364
1365
status = nssToken_Refresh(slot->nssToken);
1366
if (status != PR_SUCCESS)
1367
return SECFailure;
1368
1369
rv = pk11_ReadProfileList(slot);
1370
if (rv != SECSuccess) {
1371
return SECFailure;
1372
}
1373
1374
if (!(slot->isInternal) && (slot->hasRandom)) {
1375
/* if this slot has a random number generater, use it to add entropy
1376
* to the internal slot. */
1377
PK11SlotInfo *int_slot = PK11_GetInternalSlot();
1378
1379
if (int_slot) {
1380
unsigned char random_bytes[32];
1381
1382
/* if this slot can issue random numbers, get some entropy from
1383
* that random number generater and give it to our internal token.
1384
*/
1385
PK11_EnterSlotMonitor(slot);
1386
crv = PK11_GETTAB(slot)->C_GenerateRandom(slot->session, random_bytes, sizeof(random_bytes));
1387
PK11_ExitSlotMonitor(slot);
1388
if (crv == CKR_OK) {
1389
PK11_EnterSlotMonitor(int_slot);
1390
PK11_GETTAB(int_slot)
1391
->C_SeedRandom(int_slot->session,
1392
random_bytes, sizeof(random_bytes));
1393
PK11_ExitSlotMonitor(int_slot);
1394
}
1395
1396
/* Now return the favor and send entropy to the token's random
1397
* number generater */
1398
PK11_EnterSlotMonitor(int_slot);
1399
crv = PK11_GETTAB(int_slot)->C_GenerateRandom(int_slot->session,
1400
random_bytes, sizeof(random_bytes));
1401
PK11_ExitSlotMonitor(int_slot);
1402
if (crv == CKR_OK) {
1403
PK11_EnterSlotMonitor(slot);
1404
crv = PK11_GETTAB(slot)->C_SeedRandom(slot->session,
1405
random_bytes, sizeof(random_bytes));
1406
PK11_ExitSlotMonitor(slot);
1407
}
1408
PK11_FreeSlot(int_slot);
1409
}
1410
}
1411
/* work around a problem in softoken where it incorrectly
1412
* reports databases opened read only as read/write. */
1413
if (slot->isInternal && !slot->readOnly) {
1414
CK_SESSION_HANDLE session = CK_INVALID_SESSION;
1415
1416
/* try to open a R/W session */
1417
crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,
1418
CKF_RW_SESSION | CKF_SERIAL_SESSION, slot, pk11_notify, &session);
1419
/* what a well behaved token should return if you open
1420
* a RW session on a read only token */
1421
if (crv == CKR_TOKEN_WRITE_PROTECTED) {
1422
slot->readOnly = PR_TRUE;
1423
} else if (crv == CKR_OK) {
1424
CK_SESSION_INFO sessionInfo;
1425
1426
/* Because of a second bug in softoken, which silently returns
1427
* a RO session, we need to check what type of session we got. */
1428
crv = PK11_GETTAB(slot)->C_GetSessionInfo(session, &sessionInfo);
1429
if (crv == CKR_OK) {
1430
if ((sessionInfo.flags & CKF_RW_SESSION) == 0) {
1431
/* session was readonly, so this softoken slot must be readonly */
1432
slot->readOnly = PR_TRUE;
1433
}
1434
}
1435
PK11_GETTAB(slot)
1436
->C_CloseSession(session);
1437
}
1438
}
1439
1440
return SECSuccess;
1441
}
1442
1443
/*
1444
* initialize a new token
1445
* unlike initialize slot, this can be called multiple times in the lifetime
1446
* of NSS. It reads the information associated with a card or token,
1447
* that is not going to change unless the card or token changes.
1448
*/
1449
SECStatus
1450
PK11_TokenRefresh(PK11SlotInfo *slot)
1451
{
1452
CK_RV crv;
1453
1454
/* set the slot flags to the current token values */
1455
if (!slot->isThreadSafe)
1456
PK11_EnterSlotMonitor(slot);
1457
crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID, &slot->tokenInfo);
1458
if (!slot->isThreadSafe)
1459
PK11_ExitSlotMonitor(slot);
1460
if (crv != CKR_OK) {
1461
PORT_SetError(PK11_MapError(crv));
1462
return SECFailure;
1463
}
1464
1465
slot->flags = slot->tokenInfo.flags;
1466
slot->needLogin = ((slot->tokenInfo.flags & CKF_LOGIN_REQUIRED) ? PR_TRUE : PR_FALSE);
1467
slot->readOnly = ((slot->tokenInfo.flags & CKF_WRITE_PROTECTED) ? PR_TRUE : PR_FALSE);
1468
slot->hasRandom = ((slot->tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE);
1469
slot->protectedAuthPath =
1470
((slot->tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
1471
? PR_TRUE
1472
: PR_FALSE);
1473
/* on some platforms Active Card incorrectly sets the
1474
* CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */
1475
if (slot->isActiveCard) {
1476
slot->protectedAuthPath = PR_FALSE;
1477
}
1478
return SECSuccess;
1479
}
1480
1481
static PRBool
1482
pk11_isRootSlot(PK11SlotInfo *slot)
1483
{
1484
CK_ATTRIBUTE findTemp[1];
1485
CK_ATTRIBUTE *attrs;
1486
CK_OBJECT_CLASS oclass = CKO_NETSCAPE_BUILTIN_ROOT_LIST;
1487
int tsize;
1488
CK_OBJECT_HANDLE handle;
1489
1490
attrs = findTemp;
1491
PK11_SETATTRS(attrs, CKA_CLASS, &oclass, sizeof(oclass));
1492
attrs++;
1493
tsize = attrs - findTemp;
1494
PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE));
1495
1496
handle = pk11_FindObjectByTemplate(slot, findTemp, tsize);
1497
if (handle == CK_INVALID_HANDLE) {
1498
return PR_FALSE;
1499
}
1500
return PR_TRUE;
1501
}
1502
1503
/*
1504
* Initialize the slot :
1505
* This initialization code is called on each slot a module supports when
1506
* it is loaded. It does the bringup initialization. The difference between
1507
* this and InitToken is Init slot does those one time initialization stuff,
1508
* usually associated with the reader, while InitToken may get called multiple
1509
* times as tokens are removed and re-inserted.
1510
*/
1511
void
1512
PK11_InitSlot(SECMODModule *mod, CK_SLOT_ID slotID, PK11SlotInfo *slot)
1513
{
1514
SECStatus rv;
1515
CK_SLOT_INFO slotInfo;
1516
1517
slot->functionList = mod->functionList;
1518
slot->isInternal = mod->internal;
1519
slot->slotID = slotID;
1520
slot->isThreadSafe = mod->isThreadSafe;
1521
slot->hasRSAInfo = PR_FALSE;
1522
slot->module = mod; /* NOTE: we don't make a reference here because
1523
* modules have references to their slots. This
1524
* works because modules keep implicit references
1525
* from their slots, and won't unload and disappear
1526
* until all their slots have been freed */
1527
1528
if (PK11_GETTAB(slot)->C_GetSlotInfo(slotID, &slotInfo) != CKR_OK) {
1529
slot->disabled = PR_TRUE;
1530
slot->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1531
return;
1532
}
1533
1534
/* test to make sure claimed mechanism work */
1535
slot->needTest = mod->internal ? PR_FALSE : PR_TRUE;
1536
(void)PK11_MakeString(NULL, slot->slot_name,
1537
(char *)slotInfo.slotDescription, sizeof(slotInfo.slotDescription));
1538
slot->isHW = (PRBool)((slotInfo.flags & CKF_HW_SLOT) == CKF_HW_SLOT);
1539
#define ACTIVE_CARD "ActivCard SA"
1540
slot->isActiveCard = (PRBool)(PORT_Strncmp((char *)slotInfo.manufacturerID,
1541
ACTIVE_CARD, sizeof(ACTIVE_CARD) - 1) == 0);
1542
if ((slotInfo.flags & CKF_REMOVABLE_DEVICE) == 0) {
1543
slot->isPerm = PR_TRUE;
1544
/* permanment slots must have the token present always */
1545
if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {
1546
slot->disabled = PR_TRUE;
1547
slot->reason = PK11_DIS_TOKEN_NOT_PRESENT;
1548
return; /* nothing else to do */
1549
}
1550
}
1551
/* if the token is present, initialize it */
1552
if ((slotInfo.flags & CKF_TOKEN_PRESENT) != 0) {
1553
rv = PK11_InitToken(slot, PR_TRUE);
1554
/* the only hard failures are on permanent devices, or function
1555
* verify failures... function verify failures are already handled
1556
* by tokenInit */
1557
if ((rv != SECSuccess) && (slot->isPerm) && (!slot->disabled)) {
1558
slot->disabled = PR_TRUE;
1559
slot->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1560
}
1561
if (rv == SECSuccess && pk11_isRootSlot(slot)) {
1562
if (!slot->hasRootCerts) {
1563
slot->module->trustOrder = 100;
1564
}
1565
slot->hasRootCerts = PR_TRUE;
1566
}
1567
}
1568
if ((slotInfo.flags & CKF_USER_PIN_INITIALIZED) != 0) {
1569
slot->flags |= CKF_USER_PIN_INITIALIZED;
1570
}
1571
}
1572
1573
/*********************************************************************
1574
* Slot mapping utility functions.
1575
*********************************************************************/
1576
1577
/*
1578
* determine if the token is present. If the token is present, make sure
1579
* we have a valid session handle. Also set the value of needLogin
1580
* appropriately.
1581
*/
1582
static PRBool
1583
pk11_IsPresentCertLoad(PK11SlotInfo *slot, PRBool loadCerts)
1584
{
1585
CK_SLOT_INFO slotInfo;
1586
CK_SESSION_INFO sessionInfo;
1587
CK_RV crv;
1588
1589
/* disabled slots are never present */
1590
if (slot->disabled) {
1591
return PR_FALSE;
1592
}
1593
1594
/* permanent slots are always present */
1595
if (slot->isPerm && (slot->session != CK_INVALID_SESSION)) {
1596
return PR_TRUE;
1597
}
1598
1599
if (slot->nssToken) {
1600
return nssToken_IsPresent(slot->nssToken);
1601
}
1602
1603
/* removable slots have a flag that says they are present */
1604
if (!slot->isThreadSafe)
1605
PK11_EnterSlotMonitor(slot);
1606
if (PK11_GETTAB(slot)->C_GetSlotInfo(slot->slotID, &slotInfo) != CKR_OK) {
1607
if (!slot->isThreadSafe)
1608
PK11_ExitSlotMonitor(slot);
1609
return PR_FALSE;
1610
}
1611
if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {
1612
/* if the slot is no longer present, close the session */
1613
if (slot->session != CK_INVALID_SESSION) {
1614
PK11_GETTAB(slot)
1615
->C_CloseSession(slot->session);
1616
slot->session = CK_INVALID_SESSION;
1617
}
1618
if (!slot->isThreadSafe)
1619
PK11_ExitSlotMonitor(slot);
1620
return PR_FALSE;
1621
}
1622
1623
/* use the session Info to determine if the card has been removed and then
1624
* re-inserted */
1625
if (slot->session != CK_INVALID_SESSION) {
1626
if (slot->isThreadSafe)
1627
PK11_EnterSlotMonitor(slot);
1628
crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session, &sessionInfo);
1629
if (crv != CKR_OK) {
1630
PK11_GETTAB(slot)
1631
->C_CloseSession(slot->session);
1632
slot->session = CK_INVALID_SESSION;
1633
}
1634
if (slot->isThreadSafe)
1635
PK11_ExitSlotMonitor(slot);
1636
}
1637
if (!slot->isThreadSafe)
1638
PK11_ExitSlotMonitor(slot);
1639
1640
/* card has not been removed, current token info is correct */
1641
if (slot->session != CK_INVALID_SESSION)
1642
return PR_TRUE;
1643
1644
/* initialize the token info state */
1645
if (PK11_InitToken(slot, loadCerts) != SECSuccess) {
1646
return PR_FALSE;
1647
}
1648
1649
return PR_TRUE;
1650
}
1651
1652
/*
1653
* old version of the routine
1654
*/
1655
PRBool
1656
PK11_IsPresent(PK11SlotInfo *slot)
1657
{
1658
return pk11_IsPresentCertLoad(slot, PR_TRUE);
1659
}
1660
1661
/* is the slot disabled? */
1662
PRBool
1663
PK11_IsDisabled(PK11SlotInfo *slot)
1664
{
1665
return slot->disabled;
1666
}
1667
1668
/* and why? */
1669
PK11DisableReasons
1670
PK11_GetDisabledReason(PK11SlotInfo *slot)
1671
{
1672
return slot->reason;
1673
}
1674
1675
/* returns PR_TRUE if successfully disable the slot */
1676
/* returns PR_FALSE otherwise */
1677
PRBool
1678
PK11_UserDisableSlot(PK11SlotInfo *slot)
1679
{
1680
1681
/* Prevent users from disabling the internal module. */
1682
if (slot->isInternal) {
1683
PORT_SetError(SEC_ERROR_INVALID_ARGS);
1684
return PR_FALSE;
1685
}
1686
1687
slot->defaultFlags |= PK11_DISABLE_FLAG;
1688
slot->disabled = PR_TRUE;
1689
slot->reason = PK11_DIS_USER_SELECTED;
1690
1691
return PR_TRUE;
1692
}
1693
1694
PRBool
1695
PK11_UserEnableSlot(PK11SlotInfo *slot)
1696
{
1697
1698
slot->defaultFlags &= ~PK11_DISABLE_FLAG;
1699
slot->disabled = PR_FALSE;
1700
slot->reason = PK11_DIS_NONE;
1701
return PR_TRUE;
1702
}
1703
1704
PRBool
1705
PK11_HasRootCerts(PK11SlotInfo *slot)
1706
{
1707
return slot->hasRootCerts;
1708
}
1709
1710
/* Get the module this slot is attached to */
1711
SECMODModule *
1712
PK11_GetModule(PK11SlotInfo *slot)
1713
{
1714
return slot->module;
1715
}
1716
1717
/* return the default flags of a slot */
1718
unsigned long
1719
PK11_GetDefaultFlags(PK11SlotInfo *slot)
1720
{
1721
return slot->defaultFlags;
1722
}
1723
1724
/*
1725
* The following wrapper functions allow us to export an opaque slot
1726
* function to the rest of libsec and the world... */
1727
PRBool
1728
PK11_IsReadOnly(PK11SlotInfo *slot)
1729
{
1730
return slot->readOnly;
1731
}
1732
1733
PRBool
1734
PK11_IsHW(PK11SlotInfo *slot)
1735
{
1736
return slot->isHW;
1737
}
1738
1739
PRBool
1740
PK11_IsRemovable(PK11SlotInfo *slot)
1741
{
1742
return !slot->isPerm;
1743
}
1744
1745
PRBool
1746
PK11_IsInternal(PK11SlotInfo *slot)
1747
{
1748
return slot->isInternal;
1749
}
1750
1751
PRBool
1752
PK11_IsInternalKeySlot(PK11SlotInfo *slot)
1753
{
1754
PK11SlotInfo *int_slot;
1755
PRBool result;
1756
1757
if (!slot->isInternal) {
1758
return PR_FALSE;
1759
}
1760
1761
int_slot = PK11_GetInternalKeySlot();
1762
result = (int_slot == slot) ? PR_TRUE : PR_FALSE;
1763
PK11_FreeSlot(int_slot);
1764
return result;
1765
}
1766
1767
PRBool
1768
PK11_NeedLogin(PK11SlotInfo *slot)
1769
{
1770
return slot->needLogin;
1771
}
1772
1773
PRBool
1774
PK11_IsFriendly(PK11SlotInfo *slot)
1775
{
1776
/* internal slot always has public readable certs */
1777
return (PRBool)(slot->isInternal ||
1778
pk11_HasProfile(slot, CKP_PUBLIC_CERTIFICATES_TOKEN) ||
1779
((slot->defaultFlags & SECMOD_FRIENDLY_FLAG) ==
1780
SECMOD_FRIENDLY_FLAG));
1781
}
1782
1783
char *
1784
PK11_GetTokenName(PK11SlotInfo *slot)
1785
{
1786
return slot->token_name;
1787
}
1788
1789
char *
1790
PK11_GetTokenURI(PK11SlotInfo *slot)
1791
{
1792
PK11URI *uri;
1793
char *ret = NULL;
1794
char label[32 + 1], manufacturer[32 + 1], serial[16 + 1], model[16 + 1];
1795
PK11URIAttribute attrs[4];
1796
size_t nattrs = 0;
1797
1798
PK11_MakeString(NULL, label, (char *)slot->tokenInfo.label,
1799
sizeof(slot->tokenInfo.label));
1800
if (*label != '\0') {
1801
attrs[nattrs].name = PK11URI_PATTR_TOKEN;
1802
attrs[nattrs].value = label;
1803
nattrs++;
1804
}
1805
1806
PK11_MakeString(NULL, manufacturer, (char *)slot->tokenInfo.manufacturerID,
1807
sizeof(slot->tokenInfo.manufacturerID));
1808
if (*manufacturer != '\0') {
1809
attrs[nattrs].name = PK11URI_PATTR_MANUFACTURER;
1810
attrs[nattrs].value = manufacturer;
1811
nattrs++;
1812
}
1813
1814
PK11_MakeString(NULL, serial, (char *)slot->tokenInfo.serialNumber,
1815
sizeof(slot->tokenInfo.serialNumber));
1816
if (*serial != '\0') {
1817
attrs[nattrs].name = PK11URI_PATTR_SERIAL;
1818
attrs[nattrs].value = serial;
1819
nattrs++;
1820
}
1821
1822
PK11_MakeString(NULL, model, (char *)slot->tokenInfo.model,
1823
sizeof(slot->tokenInfo.model));
1824
if (*model != '\0') {
1825
attrs[nattrs].name = PK11URI_PATTR_MODEL;
1826
attrs[nattrs].value = model;
1827
nattrs++;
1828
}
1829
1830
uri = PK11URI_CreateURI(attrs, nattrs, NULL, 0);
1831
if (uri == NULL) {
1832
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1833
return NULL;
1834
}
1835
1836
ret = PK11URI_FormatURI(NULL, uri);
1837
PK11URI_DestroyURI(uri);
1838
1839
if (ret == NULL) {
1840
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1841
}
1842
1843
return ret;
1844
}
1845
1846
char *
1847
PK11_GetSlotName(PK11SlotInfo *slot)
1848
{
1849
return slot->slot_name;
1850
}
1851
1852
int
1853
PK11_GetSlotSeries(PK11SlotInfo *slot)
1854
{
1855
return slot->series;
1856
}
1857
1858
int
1859
PK11_GetCurrentWrapIndex(PK11SlotInfo *slot)
1860
{
1861
return slot->wrapKey;
1862
}
1863
1864
CK_SLOT_ID
1865
PK11_GetSlotID(PK11SlotInfo *slot)
1866
{
1867
return slot->slotID;
1868
}
1869
1870
SECMODModuleID
1871
PK11_GetModuleID(PK11SlotInfo *slot)
1872
{
1873
return slot->module->moduleID;
1874
}
1875
1876
static void
1877
pk11_zeroTerminatedToBlankPadded(CK_CHAR *buffer, size_t buffer_size)
1878
{
1879
CK_CHAR *walk = buffer;
1880
CK_CHAR *end = buffer + buffer_size;
1881
1882
/* find the NULL */
1883
while (walk < end && *walk != '\0') {
1884
walk++;
1885
}
1886
1887
/* clear out the buffer */
1888
while (walk < end) {
1889
*walk++ = ' ';
1890
}
1891
}
1892
1893
/* return the slot info structure */
1894
SECStatus
1895
PK11_GetSlotInfo(PK11SlotInfo *slot, CK_SLOT_INFO *info)
1896
{
1897
CK_RV crv;
1898
1899
if (!slot->isThreadSafe)
1900
PK11_EnterSlotMonitor(slot);
1901
/*
1902
* some buggy drivers do not fill the buffer completely,
1903
* erase the buffer first
1904
*/
1905
PORT_Memset(info->slotDescription, ' ', sizeof(info->slotDescription));
1906
PORT_Memset(info->manufacturerID, ' ', sizeof(info->manufacturerID));
1907
crv = PK11_GETTAB(slot)->C_GetSlotInfo(slot->slotID, info);
1908
pk11_zeroTerminatedToBlankPadded(info->slotDescription,
1909
sizeof(info->slotDescription));
1910
pk11_zeroTerminatedToBlankPadded(info->manufacturerID,
1911
sizeof(info->manufacturerID));
1912
if (!slot->isThreadSafe)
1913
PK11_ExitSlotMonitor(slot);
1914
if (crv != CKR_OK) {
1915
PORT_SetError(PK11_MapError(crv));
1916
return SECFailure;
1917
}
1918
return SECSuccess;
1919
}
1920
1921
/* return the token info structure */
1922
SECStatus
1923
PK11_GetTokenInfo(PK11SlotInfo *slot, CK_TOKEN_INFO *info)
1924
{
1925
CK_RV crv;
1926
if (!slot->isThreadSafe)
1927
PK11_EnterSlotMonitor(slot);
1928
/*
1929
* some buggy drivers do not fill the buffer completely,
1930
* erase the buffer first
1931
*/
1932
PORT_Memset(info->label, ' ', sizeof(info->label));
1933
PORT_Memset(info->manufacturerID, ' ', sizeof(info->manufacturerID));
1934
PORT_Memset(info->model, ' ', sizeof(info->model));
1935
PORT_Memset(info->serialNumber, ' ', sizeof(info->serialNumber));
1936
crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID, info);
1937
pk11_zeroTerminatedToBlankPadded(info->label, sizeof(info->label));
1938
pk11_zeroTerminatedToBlankPadded(info->manufacturerID,
1939
sizeof(info->manufacturerID));
1940
pk11_zeroTerminatedToBlankPadded(info->model, sizeof(info->model));
1941
pk11_zeroTerminatedToBlankPadded(info->serialNumber,
1942
sizeof(info->serialNumber));
1943
if (!slot->isThreadSafe)
1944
PK11_ExitSlotMonitor(slot);
1945
if (crv != CKR_OK) {
1946
PORT_SetError(PK11_MapError(crv));
1947