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
return slot;
423
}
424
425
/* create a new reference to a slot so it doesn't go away */
426
PK11SlotInfo *
427
PK11_ReferenceSlot(PK11SlotInfo *slot)
428
{
429
PR_ATOMIC_INCREMENT(&slot->refCount);
430
return slot;
431
}
432
433
/* Destroy all info on a slot we have built up */
434
void
435
PK11_DestroySlot(PK11SlotInfo *slot)
436
{
437
/* free up the cached keys and sessions */
438
PK11_CleanKeyList(slot);
439
440
/* free up all the sessions on this slot */
441
if (slot->functionList) {
442
PK11_GETTAB(slot)
443
->C_CloseAllSessions(slot->slotID);
444
}
445
446
if (slot->mechanismList) {
447
PORT_Free(slot->mechanismList);
448
}
449
if (slot->isThreadSafe && slot->sessionLock) {
450
PZ_DestroyLock(slot->sessionLock);
451
}
452
slot->sessionLock = NULL;
453
if (slot->freeListLock) {
454
PZ_DestroyLock(slot->freeListLock);
455
slot->freeListLock = NULL;
456
}
457
458
/* finally Tell our parent module that we've gone away so it can unload */
459
if (slot->module) {
460
SECMOD_SlotDestroyModule(slot->module, PR_TRUE);
461
}
462
463
/* ok, well not quit finally... now we free the memory */
464
PORT_Free(slot);
465
}
466
467
/* We're all done with the slot, free it */
468
void
469
PK11_FreeSlot(PK11SlotInfo *slot)
470
{
471
if (PR_ATOMIC_DECREMENT(&slot->refCount) == 0) {
472
PK11_DestroySlot(slot);
473
}
474
}
475
476
void
477
PK11_EnterSlotMonitor(PK11SlotInfo *slot)
478
{
479
PZ_Lock(slot->sessionLock);
480
}
481
482
void
483
PK11_ExitSlotMonitor(PK11SlotInfo *slot)
484
{
485
PZ_Unlock(slot->sessionLock);
486
}
487
488
/***********************************************************
489
* Functions to find specific slots.
490
***********************************************************/
491
PRBool
492
SECMOD_HasRootCerts(void)
493
{
494
SECMODModuleList *mlp;
495
SECMODModuleList *modules;
496
SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
497
int i;
498
PRBool found = PR_FALSE;
499
500
if (!moduleLock) {
501
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
502
return found;
503
}
504
505
/* work through all the slots */
506
SECMOD_GetReadLock(moduleLock);
507
modules = SECMOD_GetDefaultModuleList();
508
for (mlp = modules; mlp != NULL; mlp = mlp->next) {
509
for (i = 0; i < mlp->module->slotCount; i++) {
510
PK11SlotInfo *tmpSlot = mlp->module->slots[i];
511
if (PK11_IsPresent(tmpSlot)) {
512
if (tmpSlot->hasRootCerts) {
513
found = PR_TRUE;
514
break;
515
}
516
}
517
}
518
if (found)
519
break;
520
}
521
SECMOD_ReleaseReadLock(moduleLock);
522
523
return found;
524
}
525
526
/***********************************************************
527
* Functions to find specific slots.
528
***********************************************************/
529
PK11SlotList *
530
PK11_FindSlotsByNames(const char *dllName, const char *slotName,
531
const char *tokenName, PRBool presentOnly)
532
{
533
SECMODModuleList *mlp;
534
SECMODModuleList *modules;
535
SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
536
int i;
537
PK11SlotList *slotList = NULL;
538
PRUint32 slotcount = 0;
539
SECStatus rv = SECSuccess;
540
541
if (!moduleLock) {
542
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
543
return slotList;
544
}
545
546
slotList = PK11_NewSlotList();
547
if (!slotList) {
548
PORT_SetError(SEC_ERROR_NO_MEMORY);
549
return slotList;
550
}
551
552
if (((NULL == dllName) || (0 == *dllName)) &&
553
((NULL == slotName) || (0 == *slotName)) &&
554
((NULL == tokenName) || (0 == *tokenName))) {
555
/* default to softoken */
556
/* PK11_GetInternalKeySlot increments the refcount on the internal slot,
557
* but so does PK11_AddSlotToList. To avoid erroneously increasing the
558
* refcount twice, we get our own reference to the internal slot and
559
* decrement its refcount when we're done with it. */
560
PK11SlotInfo *internalKeySlot = PK11_GetInternalKeySlot();
561
PK11_AddSlotToList(slotList, internalKeySlot, PR_TRUE);
562
PK11_FreeSlot(internalKeySlot);
563
return slotList;
564
}
565
566
/* work through all the slots */
567
SECMOD_GetReadLock(moduleLock);
568
modules = SECMOD_GetDefaultModuleList();
569
for (mlp = modules; mlp != NULL; mlp = mlp->next) {
570
PORT_Assert(mlp->module);
571
if (!mlp->module) {
572
rv = SECFailure;
573
break;
574
}
575
if ((!dllName) || (mlp->module->dllName &&
576
(0 == PORT_Strcmp(mlp->module->dllName, dllName)))) {
577
for (i = 0; i < mlp->module->slotCount; i++) {
578
PK11SlotInfo *tmpSlot = (mlp->module->slots ? mlp->module->slots[i] : NULL);
579
PORT_Assert(tmpSlot);
580
if (!tmpSlot) {
581
rv = SECFailure;
582
break;
583
}
584
if ((PR_FALSE == presentOnly || PK11_IsPresent(tmpSlot)) &&
585
((!tokenName) ||
586
(0 == PORT_Strcmp(tmpSlot->token_name, tokenName))) &&
587
((!slotName) ||
588
(0 == PORT_Strcmp(tmpSlot->slot_name, slotName)))) {
589
PK11_AddSlotToList(slotList, tmpSlot, PR_TRUE);
590
slotcount++;
591
}
592
}
593
}
594
}
595
SECMOD_ReleaseReadLock(moduleLock);
596
597
if ((0 == slotcount) || (SECFailure == rv)) {
598
PORT_SetError(SEC_ERROR_NO_TOKEN);
599
PK11_FreeSlotList(slotList);
600
slotList = NULL;
601
}
602
603
if (SECFailure == rv) {
604
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
605
}
606
607
return slotList;
608
}
609
610
typedef PRBool (*PK11SlotMatchFunc)(PK11SlotInfo *slot, const void *arg);
611
612
static PRBool
613
pk11_MatchSlotByTokenName(PK11SlotInfo *slot, const void *arg)
614
{
615
return PORT_Strcmp(slot->token_name, arg) == 0;
616
}
617
618
static PRBool
619
pk11_MatchSlotBySerial(PK11SlotInfo *slot, const void *arg)
620
{
621
return PORT_Memcmp(slot->serial, arg, sizeof(slot->serial)) == 0;
622
}
623
624
static PRBool
625
pk11_MatchSlotByTokenURI(PK11SlotInfo *slot, const void *arg)
626
{
627
return pk11_MatchUriTokenInfo(slot, (PK11URI *)arg);
628
}
629
630
static PK11SlotInfo *
631
pk11_FindSlot(const void *arg, PK11SlotMatchFunc func)
632
{
633
SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
634
SECMODModuleList *mlp;
635
SECMODModuleList *modules;
636
int i;
637
PK11SlotInfo *slot = NULL;
638
639
if (!moduleLock) {
640
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
641
return slot;
642
}
643
/* work through all the slots */
644
SECMOD_GetReadLock(moduleLock);
645
modules = SECMOD_GetDefaultModuleList();
646
for (mlp = modules; mlp != NULL; mlp = mlp->next) {
647
for (i = 0; i < mlp->module->slotCount; i++) {
648
PK11SlotInfo *tmpSlot = mlp->module->slots[i];
649
if (PK11_IsPresent(tmpSlot)) {
650
if (func(tmpSlot, arg)) {
651
slot = PK11_ReferenceSlot(tmpSlot);
652
break;
653
}
654
}
655
}
656
if (slot != NULL)
657
break;
658
}
659
SECMOD_ReleaseReadLock(moduleLock);
660
661
if (slot == NULL) {
662
PORT_SetError(SEC_ERROR_NO_TOKEN);
663
}
664
665
return slot;
666
}
667
668
static PK11SlotInfo *
669
pk11_FindSlotByTokenURI(const char *uriString)
670
{
671
PK11SlotInfo *slot = NULL;
672
PK11URI *uri;
673
674
uri = PK11URI_ParseURI(uriString);
675
if (!uri) {
676
PORT_SetError(SEC_ERROR_INVALID_ARGS);
677
return slot;
678
}
679
680
slot = pk11_FindSlot(uri, pk11_MatchSlotByTokenURI);
681
PK11URI_DestroyURI(uri);
682
return slot;
683
}
684
685
PK11SlotInfo *
686
PK11_FindSlotByName(const char *name)
687
{
688
if ((name == NULL) || (*name == 0)) {
689
return PK11_GetInternalKeySlot();
690
}
691
692
if (!PORT_Strncasecmp(name, "pkcs11:", strlen("pkcs11:"))) {
693
return pk11_FindSlotByTokenURI(name);
694
}
695
696
return pk11_FindSlot(name, pk11_MatchSlotByTokenName);
697
}
698
699
PK11SlotInfo *
700
PK11_FindSlotBySerial(char *serial)
701
{
702
return pk11_FindSlot(serial, pk11_MatchSlotBySerial);
703
}
704
705
/*
706
* notification stub. If we ever get interested in any events that
707
* the pkcs11 functions may pass back to use, we can catch them here...
708
* currently pdata is a slotinfo structure.
709
*/
710
CK_RV
711
pk11_notify(CK_SESSION_HANDLE session, CK_NOTIFICATION event,
712
CK_VOID_PTR pdata)
713
{
714
return CKR_OK;
715
}
716
717
/*
718
* grab a new RW session
719
* !!! has a side effect of grabbing the Monitor if either the slot's default
720
* session is RW or the slot is not thread safe. Monitor is release in function
721
* below
722
*/
723
CK_SESSION_HANDLE
724
PK11_GetRWSession(PK11SlotInfo *slot)
725
{
726
CK_SESSION_HANDLE rwsession;
727
CK_RV crv;
728
PRBool haveMonitor = PR_FALSE;
729
730
if (!slot->isThreadSafe || slot->defRWSession) {
731
PK11_EnterSlotMonitor(slot);
732
haveMonitor = PR_TRUE;
733
}
734
if (slot->defRWSession) {
735
PORT_Assert(slot->session != CK_INVALID_SESSION);
736
if (slot->session != CK_INVALID_SESSION)
737
return slot->session;
738
}
739
740
crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,
741
CKF_RW_SESSION | CKF_SERIAL_SESSION,
742
slot, pk11_notify, &rwsession);
743
PORT_Assert(rwsession != CK_INVALID_SESSION || crv != CKR_OK);
744
if (crv != CKR_OK || rwsession == CK_INVALID_SESSION) {
745
if (crv == CKR_OK)
746
crv = CKR_DEVICE_ERROR;
747
if (haveMonitor)
748
PK11_ExitSlotMonitor(slot);
749
PORT_SetError(PK11_MapError(crv));
750
return CK_INVALID_SESSION;
751
}
752
if (slot->defRWSession) { /* we have the monitor */
753
slot->session = rwsession;
754
}
755
return rwsession;
756
}
757
758
PRBool
759
PK11_RWSessionHasLock(PK11SlotInfo *slot, CK_SESSION_HANDLE session_handle)
760
{
761
PRBool hasLock;
762
hasLock = (PRBool)(!slot->isThreadSafe ||
763
(slot->defRWSession && slot->session != CK_INVALID_SESSION));
764
return hasLock;
765
}
766
767
static PRBool
768
pk11_RWSessionIsDefault(PK11SlotInfo *slot, CK_SESSION_HANDLE rwsession)
769
{
770
PRBool isDefault;
771
isDefault = (PRBool)(slot->session == rwsession &&
772
slot->defRWSession &&
773
slot->session != CK_INVALID_SESSION);
774
return isDefault;
775
}
776
777
/*
778
* close the rwsession and restore our readonly session
779
* !!! has a side effect of releasing the Monitor if either the slot's default
780
* session is RW or the slot is not thread safe.
781
*/
782
void
783
PK11_RestoreROSession(PK11SlotInfo *slot, CK_SESSION_HANDLE rwsession)
784
{
785
PORT_Assert(rwsession != CK_INVALID_SESSION);
786
if (rwsession != CK_INVALID_SESSION) {
787
PRBool doExit = PK11_RWSessionHasLock(slot, rwsession);
788
if (!pk11_RWSessionIsDefault(slot, rwsession))
789
PK11_GETTAB(slot)
790
->C_CloseSession(rwsession);
791
if (doExit)
792
PK11_ExitSlotMonitor(slot);
793
}
794
}
795
796
/************************************************************
797
* Manage the built-In Slot Lists
798
************************************************************/
799
800
/* Init the static built int slot list (should actually integrate
801
* with PK11_NewSlotList */
802
static void
803
pk11_InitSlotListStatic(PK11SlotList *list)
804
{
805
list->lock = PZ_NewLock(nssILockList);
806
list->head = NULL;
807
}
808
809
/* initialize the system slotlists */
810
SECStatus
811
PK11_InitSlotLists(void)
812
{
813
pk11_InitSlotListStatic(&pk11_seedSlotList);
814
pk11_InitSlotListStatic(&pk11_camelliaSlotList);
815
pk11_InitSlotListStatic(&pk11_aesSlotList);
816
pk11_InitSlotListStatic(&pk11_desSlotList);
817
pk11_InitSlotListStatic(&pk11_rc4SlotList);
818
pk11_InitSlotListStatic(&pk11_rc2SlotList);
819
pk11_InitSlotListStatic(&pk11_rc5SlotList);
820
pk11_InitSlotListStatic(&pk11_md5SlotList);
821
pk11_InitSlotListStatic(&pk11_md2SlotList);
822
pk11_InitSlotListStatic(&pk11_sha1SlotList);
823
pk11_InitSlotListStatic(&pk11_rsaSlotList);
824
pk11_InitSlotListStatic(&pk11_dsaSlotList);
825
pk11_InitSlotListStatic(&pk11_dhSlotList);
826
pk11_InitSlotListStatic(&pk11_ecSlotList);
827
pk11_InitSlotListStatic(&pk11_ideaSlotList);
828
pk11_InitSlotListStatic(&pk11_sslSlotList);
829
pk11_InitSlotListStatic(&pk11_tlsSlotList);
830
pk11_InitSlotListStatic(&pk11_randomSlotList);
831
pk11_InitSlotListStatic(&pk11_sha256SlotList);
832
pk11_InitSlotListStatic(&pk11_sha512SlotList);
833
return SECSuccess;
834
}
835
836
void
837
PK11_DestroySlotLists(void)
838
{
839
pk11_FreeSlotListStatic(&pk11_seedSlotList);
840
pk11_FreeSlotListStatic(&pk11_camelliaSlotList);
841
pk11_FreeSlotListStatic(&pk11_aesSlotList);
842
pk11_FreeSlotListStatic(&pk11_desSlotList);
843
pk11_FreeSlotListStatic(&pk11_rc4SlotList);
844
pk11_FreeSlotListStatic(&pk11_rc2SlotList);
845
pk11_FreeSlotListStatic(&pk11_rc5SlotList);
846
pk11_FreeSlotListStatic(&pk11_md5SlotList);
847
pk11_FreeSlotListStatic(&pk11_md2SlotList);
848
pk11_FreeSlotListStatic(&pk11_sha1SlotList);
849
pk11_FreeSlotListStatic(&pk11_rsaSlotList);
850
pk11_FreeSlotListStatic(&pk11_dsaSlotList);
851
pk11_FreeSlotListStatic(&pk11_dhSlotList);
852
pk11_FreeSlotListStatic(&pk11_ecSlotList);
853
pk11_FreeSlotListStatic(&pk11_ideaSlotList);
854
pk11_FreeSlotListStatic(&pk11_sslSlotList);
855
pk11_FreeSlotListStatic(&pk11_tlsSlotList);
856
pk11_FreeSlotListStatic(&pk11_randomSlotList);
857
pk11_FreeSlotListStatic(&pk11_sha256SlotList);
858
pk11_FreeSlotListStatic(&pk11_sha512SlotList);
859
return;
860
}
861
862
/* return a system slot list based on mechanism */
863
PK11SlotList *
864
PK11_GetSlotList(CK_MECHANISM_TYPE type)
865
{
866
/* XXX a workaround for Bugzilla bug #55267 */
867
#if defined(HPUX) && defined(__LP64__)
868
if (CKM_INVALID_MECHANISM == type)
869
return NULL;
870
#endif
871
switch (type) {
872
case CKM_SEED_CBC:
873
case CKM_SEED_ECB:
874
return &pk11_seedSlotList;
875
case CKM_CAMELLIA_CBC:
876
case CKM_CAMELLIA_ECB:
877
return &pk11_camelliaSlotList;
878
case CKM_AES_CBC:
879
case CKM_AES_CCM:
880
case CKM_AES_CTR:
881
case CKM_AES_CTS:
882
case CKM_AES_GCM:
883
case CKM_AES_ECB:
884
return &pk11_aesSlotList;
885
case CKM_DES_CBC:
886
case CKM_DES_ECB:
887
case CKM_DES3_ECB:
888
case CKM_DES3_CBC:
889
return &pk11_desSlotList;
890
case CKM_RC4:
891
return &pk11_rc4SlotList;
892
case CKM_RC5_CBC:
893
return &pk11_rc5SlotList;
894
case CKM_SHA_1:
895
return &pk11_sha1SlotList;
896
case CKM_SHA224:
897
case CKM_SHA256:
898
return &pk11_sha256SlotList;
899
case CKM_SHA384:
900
case CKM_SHA512:
901
return &pk11_sha512SlotList;
902
case CKM_MD5:
903
return &pk11_md5SlotList;
904
case CKM_MD2:
905
return &pk11_md2SlotList;
906
case CKM_RC2_ECB:
907
case CKM_RC2_CBC:
908
return &pk11_rc2SlotList;
909
case CKM_RSA_PKCS:
910
case CKM_RSA_PKCS_KEY_PAIR_GEN:
911
case CKM_RSA_X_509:
912
return &pk11_rsaSlotList;
913
case CKM_DSA:
914
return &pk11_dsaSlotList;
915
case CKM_DH_PKCS_KEY_PAIR_GEN:
916
case CKM_DH_PKCS_DERIVE:
917
return &pk11_dhSlotList;
918
case CKM_ECDSA:
919
case CKM_ECDSA_SHA1:
920
case CKM_EC_KEY_PAIR_GEN: /* aka CKM_ECDSA_KEY_PAIR_GEN */
921
case CKM_ECDH1_DERIVE:
922
return &pk11_ecSlotList;
923
case CKM_SSL3_PRE_MASTER_KEY_GEN:
924
case CKM_SSL3_MASTER_KEY_DERIVE:
925
case CKM_SSL3_SHA1_MAC:
926
case CKM_SSL3_MD5_MAC:
927
return &pk11_sslSlotList;
928
case CKM_TLS_MASTER_KEY_DERIVE:
929
case CKM_TLS_KEY_AND_MAC_DERIVE:
930
case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256:
931
return &pk11_tlsSlotList;
932
case CKM_IDEA_CBC:
933
case CKM_IDEA_ECB:
934
return &pk11_ideaSlotList;
935
case CKM_FAKE_RANDOM:
936
return &pk11_randomSlotList;
937
}
938
return NULL;
939
}
940
941
/*
942
* load the static SlotInfo structures used to select a PKCS11 slot.
943
* preSlotInfo has a list of all the default flags for the slots on this
944
* module.
945
*/
946
void
947
PK11_LoadSlotList(PK11SlotInfo *slot, PK11PreSlotInfo *psi, int count)
948
{
949
int i;
950
951
for (i = 0; i < count; i++) {
952
if (psi[i].slotID == slot->slotID)
953
break;
954
}
955
956
if (i == count)
957
return;
958
959
slot->defaultFlags = psi[i].defaultFlags;
960
slot->askpw = psi[i].askpw;
961
slot->timeout = psi[i].timeout;
962
slot->hasRootCerts = psi[i].hasRootCerts;
963
964
/* if the slot is already disabled, don't load them into the
965
* default slot lists. We get here so we can save the default
966
* list value. */
967
if (slot->disabled)
968
return;
969
970
/* if the user has disabled us, don't load us in */
971
if (slot->defaultFlags & PK11_DISABLE_FLAG) {
972
slot->disabled = PR_TRUE;
973
slot->reason = PK11_DIS_USER_SELECTED;
974
/* free up sessions and things?? */
975
return;
976
}
977
978
for (i = 0; i < num_pk11_default_mechanisms; i++) {
979
if (slot->defaultFlags & PK11_DefaultArray[i].flag) {
980
CK_MECHANISM_TYPE mechanism = PK11_DefaultArray[i].mechanism;
981
PK11SlotList *slotList = PK11_GetSlotList(mechanism);
982
983
if (slotList)
984
PK11_AddSlotToList(slotList, slot, PR_FALSE);
985
}
986
}
987
988
return;
989
}
990
991
/*
992
* update a slot to its new attribute according to the slot list
993
* returns: SECSuccess if nothing to do or add/delete is successful
994
*/
995
SECStatus
996
PK11_UpdateSlotAttribute(PK11SlotInfo *slot,
997
const PK11DefaultArrayEntry *entry,
998
PRBool add)
999
/* add: PR_TRUE if want to turn on */
1000
{
1001
SECStatus result = SECSuccess;
1002
PK11SlotList *slotList = PK11_GetSlotList(entry->mechanism);
1003
1004
if (add) { /* trying to turn on a mechanism */
1005
1006
/* turn on the default flag in the slot */
1007
slot->defaultFlags |= entry->flag;
1008
1009
/* add this slot to the list */
1010
if (slotList != NULL)
1011
result = PK11_AddSlotToList(slotList, slot, PR_FALSE);
1012
1013
} else { /* trying to turn off */
1014
1015
/* turn OFF the flag in the slot */
1016
slot->defaultFlags &= ~entry->flag;
1017
1018
if (slotList) {
1019
/* find the element in the list & delete it */
1020
PK11SlotListElement *le = PK11_FindSlotElement(slotList, slot);
1021
1022
/* remove the slot from the list */
1023
if (le)
1024
result = PK11_DeleteSlotFromList(slotList, le);
1025
}
1026
}
1027
return result;
1028
}
1029
1030
/*
1031
* clear a slot off of all of it's default list
1032
*/
1033
void
1034
PK11_ClearSlotList(PK11SlotInfo *slot)
1035
{
1036
int i;
1037
1038
if (slot->disabled)
1039
return;
1040
if (slot->defaultFlags == 0)
1041
return;
1042
1043
for (i = 0; i < num_pk11_default_mechanisms; i++) {
1044
if (slot->defaultFlags & PK11_DefaultArray[i].flag) {
1045
CK_MECHANISM_TYPE mechanism = PK11_DefaultArray[i].mechanism;
1046
PK11SlotList *slotList = PK11_GetSlotList(mechanism);
1047
PK11SlotListElement *le = NULL;
1048
1049
if (slotList)
1050
le = PK11_FindSlotElement(slotList, slot);
1051
1052
if (le) {
1053
PK11_DeleteSlotFromList(slotList, le);
1054
PK11_FreeSlotListElement(slotList, le);
1055
}
1056
}
1057
}
1058
}
1059
1060
/******************************************************************
1061
* Slot initialization
1062
******************************************************************/
1063
/*
1064
* turn a PKCS11 Static Label into a string
1065
*/
1066
char *
1067
PK11_MakeString(PLArenaPool *arena, char *space,
1068
char *staticString, int stringLen)
1069
{
1070
int i;
1071
char *newString;
1072
for (i = (stringLen - 1); i >= 0; i--) {
1073
if (staticString[i] != ' ')
1074
break;
1075
}
1076
/* move i to point to the last space */
1077
i++;
1078
if (arena) {
1079
newString = (char *)PORT_ArenaAlloc(arena, i + 1 /* space for NULL */);
1080
} else if (space) {
1081
newString = space;
1082
} else {
1083
newString = (char *)PORT_Alloc(i + 1 /* space for NULL */);
1084
}
1085
if (newString == NULL)
1086
return NULL;
1087
1088
if (i)
1089
PORT_Memcpy(newString, staticString, i);
1090
newString[i] = 0;
1091
1092
return newString;
1093
}
1094
1095
/*
1096
* check if a null-terminated string matches with a PKCS11 Static Label
1097
*/
1098
PRBool
1099
pk11_MatchString(const char *string,
1100
const char *staticString, int staticStringLen)
1101
{
1102
int i;
1103
1104
for (i = (staticStringLen - 1); i >= 0; i--) {
1105
if (staticString[i] != ' ')
1106
break;
1107
}
1108
/* move i to point to the last space */
1109
i++;
1110
1111
if (strlen(string) == i && memcmp(string, staticString, i) == 0) {
1112
return PR_TRUE;
1113
}
1114
1115
return PR_FALSE;
1116
}
1117
1118
/*
1119
* Reads in the slots mechanism list for later use
1120
*/
1121
SECStatus
1122
PK11_ReadMechanismList(PK11SlotInfo *slot)
1123
{
1124
CK_ULONG count;
1125
CK_RV crv;
1126
PRUint32 i;
1127
1128
if (slot->mechanismList) {
1129
PORT_Free(slot->mechanismList);
1130
slot->mechanismList = NULL;
1131
}
1132
slot->mechanismCount = 0;
1133
1134
if (!slot->isThreadSafe)
1135
PK11_EnterSlotMonitor(slot);
1136
crv = PK11_GETTAB(slot)->C_GetMechanismList(slot->slotID, NULL, &count);
1137
if (crv != CKR_OK) {
1138
if (!slot->isThreadSafe)
1139
PK11_ExitSlotMonitor(slot);
1140
PORT_SetError(PK11_MapError(crv));
1141
return SECFailure;
1142
}
1143
1144
slot->mechanismList = (CK_MECHANISM_TYPE *)
1145
PORT_Alloc(count * sizeof(CK_MECHANISM_TYPE));
1146
if (slot->mechanismList == NULL) {
1147
if (!slot->isThreadSafe)
1148
PK11_ExitSlotMonitor(slot);
1149
return SECFailure;
1150
}
1151
crv = PK11_GETTAB(slot)->C_GetMechanismList(slot->slotID,
1152
slot->mechanismList, &count);
1153
if (!slot->isThreadSafe)
1154
PK11_ExitSlotMonitor(slot);
1155
if (crv != CKR_OK) {
1156
PORT_Free(slot->mechanismList);
1157
slot->mechanismList = NULL;
1158
PORT_SetError(PK11_MapError(crv));
1159
return SECSuccess;
1160
}
1161
slot->mechanismCount = count;
1162
PORT_Memset(slot->mechanismBits, 0, sizeof(slot->mechanismBits));
1163
1164
for (i = 0; i < count; i++) {
1165
CK_MECHANISM_TYPE mech = slot->mechanismList[i];
1166
if (mech < 0x7ff) {
1167
slot->mechanismBits[mech & 0xff] |= 1 << (mech >> 8);
1168
}
1169
}
1170
return SECSuccess;
1171
}
1172
1173
/*
1174
* initialize a new token
1175
* unlike initialize slot, this can be called multiple times in the lifetime
1176
* of NSS. It reads the information associated with a card or token,
1177
* that is not going to change unless the card or token changes.
1178
*/
1179
SECStatus
1180
PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts)
1181
{
1182
CK_RV crv;
1183
SECStatus rv;
1184
PRStatus status;
1185
1186
/* set the slot flags to the current token values */
1187
if (!slot->isThreadSafe)
1188
PK11_EnterSlotMonitor(slot);
1189
crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID, &slot->tokenInfo);
1190
if (!slot->isThreadSafe)
1191
PK11_ExitSlotMonitor(slot);
1192
if (crv != CKR_OK) {
1193
PORT_SetError(PK11_MapError(crv));
1194
return SECFailure;
1195
}
1196
1197
/* set the slot flags to the current token values */
1198
slot->series++; /* allow other objects to detect that the
1199
* slot is different */
1200
slot->flags = slot->tokenInfo.flags;
1201
slot->needLogin = ((slot->tokenInfo.flags & CKF_LOGIN_REQUIRED) ? PR_TRUE : PR_FALSE);
1202
slot->readOnly = ((slot->tokenInfo.flags & CKF_WRITE_PROTECTED) ? PR_TRUE : PR_FALSE);
1203
1204
slot->hasRandom = ((slot->tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE);
1205
slot->protectedAuthPath =
1206
((slot->tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
1207
? PR_TRUE
1208
: PR_FALSE);
1209
slot->lastLoginCheck = 0;
1210
slot->lastState = 0;
1211
/* on some platforms Active Card incorrectly sets the
1212
* CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */
1213
if (slot->isActiveCard) {
1214
slot->protectedAuthPath = PR_FALSE;
1215
}
1216
(void)PK11_MakeString(NULL, slot->token_name,
1217
(char *)slot->tokenInfo.label, sizeof(slot->tokenInfo.label));
1218
slot->minPassword = slot->tokenInfo.ulMinPinLen;
1219
slot->maxPassword = slot->tokenInfo.ulMaxPinLen;
1220
PORT_Memcpy(slot->serial, slot->tokenInfo.serialNumber, sizeof(slot->serial));
1221
1222
nssToken_UpdateName(slot->nssToken);
1223
1224
slot->defRWSession = (PRBool)((!slot->readOnly) &&
1225
(slot->tokenInfo.ulMaxSessionCount == 1));
1226
rv = PK11_ReadMechanismList(slot);
1227
if (rv != SECSuccess)
1228
return rv;
1229
1230
slot->hasRSAInfo = PR_FALSE;
1231
slot->RSAInfoFlags = 0;
1232
1233
/* initialize the maxKeyCount value */
1234
if (slot->tokenInfo.ulMaxSessionCount == 0) {
1235
slot->maxKeyCount = 800; /* should be #define or a config param */
1236
} else if (slot->tokenInfo.ulMaxSessionCount < 20) {
1237
/* don't have enough sessions to keep that many keys around */
1238
slot->maxKeyCount = 0;
1239
} else {
1240
slot->maxKeyCount = slot->tokenInfo.ulMaxSessionCount / 2;
1241
}
1242
1243
/* Make sure our session handle is valid */
1244
if (slot->session == CK_INVALID_SESSION) {
1245
/* we know we don't have a valid session, go get one */
1246
CK_SESSION_HANDLE session;
1247
1248
/* session should be Readonly, serial */
1249
if (!slot->isThreadSafe)
1250
PK11_EnterSlotMonitor(slot);
1251
crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,
1252
(slot->defRWSession ? CKF_RW_SESSION : 0) | CKF_SERIAL_SESSION,
1253
slot, pk11_notify, &session);
1254
if (!slot->isThreadSafe)
1255
PK11_ExitSlotMonitor(slot);
1256
if (crv != CKR_OK) {
1257
PORT_SetError(PK11_MapError(crv));
1258
return SECFailure;
1259
}
1260
slot->session = session;
1261
} else {
1262
/* The session we have may be defunct (the token associated with it)
1263
* has been removed */
1264
CK_SESSION_INFO sessionInfo;
1265
1266
if (!slot->isThreadSafe)
1267
PK11_EnterSlotMonitor(slot);
1268
crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session, &sessionInfo);
1269
if (crv == CKR_DEVICE_ERROR) {
1270
PK11_GETTAB(slot)
1271
->C_CloseSession(slot->session);
1272
crv = CKR_SESSION_CLOSED;
1273
}
1274
if ((crv == CKR_SESSION_CLOSED) || (crv == CKR_SESSION_HANDLE_INVALID)) {
1275
crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,
1276
(slot->defRWSession ? CKF_RW_SESSION : 0) | CKF_SERIAL_SESSION,
1277
slot, pk11_notify, &slot->session);
1278
if (crv != CKR_OK) {
1279
PORT_SetError(PK11_MapError(crv));
1280
slot->session = CK_INVALID_SESSION;
1281
if (!slot->isThreadSafe)
1282
PK11_ExitSlotMonitor(slot);
1283
return SECFailure;
1284
}
1285
}
1286
if (!slot->isThreadSafe)
1287
PK11_ExitSlotMonitor(slot);
1288
}
1289
1290
status = nssToken_Refresh(slot->nssToken);
1291
if (status != PR_SUCCESS)
1292
return SECFailure;
1293
1294
if (!(slot->isInternal) && (slot->hasRandom)) {
1295
/* if this slot has a random number generater, use it to add entropy
1296
* to the internal slot. */
1297
PK11SlotInfo *int_slot = PK11_GetInternalSlot();
1298
1299
if (int_slot) {
1300
unsigned char random_bytes[32];
1301
1302
/* if this slot can issue random numbers, get some entropy from
1303
* that random number generater and give it to our internal token.
1304
*/
1305
PK11_EnterSlotMonitor(slot);
1306
crv = PK11_GETTAB(slot)->C_GenerateRandom(slot->session, random_bytes, sizeof(random_bytes));
1307
PK11_ExitSlotMonitor(slot);
1308
if (crv == CKR_OK) {
1309
PK11_EnterSlotMonitor(int_slot);
1310
PK11_GETTAB(int_slot)
1311
->C_SeedRandom(int_slot->session,
1312
random_bytes, sizeof(random_bytes));
1313
PK11_ExitSlotMonitor(int_slot);
1314
}
1315
1316
/* Now return the favor and send entropy to the token's random
1317
* number generater */
1318
PK11_EnterSlotMonitor(int_slot);
1319
crv = PK11_GETTAB(int_slot)->C_GenerateRandom(int_slot->session,
1320
random_bytes, sizeof(random_bytes));
1321
PK11_ExitSlotMonitor(int_slot);
1322
if (crv == CKR_OK) {
1323
PK11_EnterSlotMonitor(slot);
1324
crv = PK11_GETTAB(slot)->C_SeedRandom(slot->session,
1325
random_bytes, sizeof(random_bytes));
1326
PK11_ExitSlotMonitor(slot);
1327
}
1328
PK11_FreeSlot(int_slot);
1329
}
1330
}
1331
/* work around a problem in softoken where it incorrectly
1332
* reports databases opened read only as read/write. */
1333
if (slot->isInternal && !slot->readOnly) {
1334
CK_SESSION_HANDLE session = CK_INVALID_SESSION;
1335
1336
/* try to open a R/W session */
1337
crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,
1338
CKF_RW_SESSION | CKF_SERIAL_SESSION, slot, pk11_notify, &session);
1339
/* what a well behaved token should return if you open
1340
* a RW session on a read only token */
1341
if (crv == CKR_TOKEN_WRITE_PROTECTED) {
1342
slot->readOnly = PR_TRUE;
1343
} else if (crv == CKR_OK) {
1344
CK_SESSION_INFO sessionInfo;
1345
1346
/* Because of a second bug in softoken, which silently returns
1347
* a RO session, we need to check what type of session we got. */
1348
crv = PK11_GETTAB(slot)->C_GetSessionInfo(session, &sessionInfo);
1349
if (crv == CKR_OK) {
1350
if ((sessionInfo.flags & CKF_RW_SESSION) == 0) {
1351
/* session was readonly, so this softoken slot must be readonly */
1352
slot->readOnly = PR_TRUE;
1353
}
1354
}
1355
PK11_GETTAB(slot)
1356
->C_CloseSession(session);
1357
}
1358
}
1359
1360
return SECSuccess;
1361
}
1362
1363
/*
1364
* initialize a new token
1365
* unlike initialize slot, this can be called multiple times in the lifetime
1366
* of NSS. It reads the information associated with a card or token,
1367
* that is not going to change unless the card or token changes.
1368
*/
1369
SECStatus
1370
PK11_TokenRefresh(PK11SlotInfo *slot)
1371
{
1372
CK_RV crv;
1373
1374
/* set the slot flags to the current token values */
1375
if (!slot->isThreadSafe)
1376
PK11_EnterSlotMonitor(slot);
1377
crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID, &slot->tokenInfo);
1378
if (!slot->isThreadSafe)
1379
PK11_ExitSlotMonitor(slot);
1380
if (crv != CKR_OK) {
1381
PORT_SetError(PK11_MapError(crv));
1382
return SECFailure;
1383
}
1384
1385
slot->flags = slot->tokenInfo.flags;
1386
slot->needLogin = ((slot->tokenInfo.flags & CKF_LOGIN_REQUIRED) ? PR_TRUE : PR_FALSE);
1387
slot->readOnly = ((slot->tokenInfo.flags & CKF_WRITE_PROTECTED) ? PR_TRUE : PR_FALSE);
1388
slot->hasRandom = ((slot->tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE);
1389
slot->protectedAuthPath =
1390
((slot->tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
1391
? PR_TRUE
1392
: PR_FALSE);
1393
/* on some platforms Active Card incorrectly sets the
1394
* CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */
1395
if (slot->isActiveCard) {
1396
slot->protectedAuthPath = PR_FALSE;
1397
}
1398
return SECSuccess;
1399
}
1400
1401
static PRBool
1402
pk11_isRootSlot(PK11SlotInfo *slot)
1403
{
1404
CK_ATTRIBUTE findTemp[1];
1405
CK_ATTRIBUTE *attrs;
1406
CK_OBJECT_CLASS oclass = CKO_NETSCAPE_BUILTIN_ROOT_LIST;
1407
int tsize;
1408
CK_OBJECT_HANDLE handle;
1409
1410
attrs = findTemp;
1411
PK11_SETATTRS(attrs, CKA_CLASS, &oclass, sizeof(oclass));
1412
attrs++;
1413
tsize = attrs - findTemp;
1414
PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE));
1415
1416
handle = pk11_FindObjectByTemplate(slot, findTemp, tsize);
1417
if (handle == CK_INVALID_HANDLE) {
1418
return PR_FALSE;
1419
}
1420
return PR_TRUE;
1421
}
1422
1423
/*
1424
* Initialize the slot :
1425
* This initialization code is called on each slot a module supports when
1426
* it is loaded. It does the bringup initialization. The difference between
1427
* this and InitToken is Init slot does those one time initialization stuff,
1428
* usually associated with the reader, while InitToken may get called multiple
1429
* times as tokens are removed and re-inserted.
1430
*/
1431
void
1432
PK11_InitSlot(SECMODModule *mod, CK_SLOT_ID slotID, PK11SlotInfo *slot)
1433
{
1434
SECStatus rv;
1435
CK_SLOT_INFO slotInfo;
1436
1437
slot->functionList = mod->functionList;
1438
slot->isInternal = mod->internal;
1439
slot->slotID = slotID;
1440
slot->isThreadSafe = mod->isThreadSafe;
1441
slot->hasRSAInfo = PR_FALSE;
1442
slot->module = mod; /* NOTE: we don't make a reference here because
1443
* modules have references to their slots. This
1444
* works because modules keep implicit references
1445
* from their slots, and won't unload and disappear
1446
* until all their slots have been freed */
1447
1448
if (PK11_GETTAB(slot)->C_GetSlotInfo(slotID, &slotInfo) != CKR_OK) {
1449
slot->disabled = PR_TRUE;
1450
slot->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1451
return;
1452
}
1453
1454
/* test to make sure claimed mechanism work */
1455
slot->needTest = mod->internal ? PR_FALSE : PR_TRUE;
1456
(void)PK11_MakeString(NULL, slot->slot_name,
1457
(char *)slotInfo.slotDescription, sizeof(slotInfo.slotDescription));
1458
slot->isHW = (PRBool)((slotInfo.flags & CKF_HW_SLOT) == CKF_HW_SLOT);
1459
#define ACTIVE_CARD "ActivCard SA"
1460
slot->isActiveCard = (PRBool)(PORT_Strncmp((char *)slotInfo.manufacturerID,
1461
ACTIVE_CARD, sizeof(ACTIVE_CARD) - 1) == 0);
1462
if ((slotInfo.flags & CKF_REMOVABLE_DEVICE) == 0) {
1463
slot->isPerm = PR_TRUE;
1464
/* permanment slots must have the token present always */
1465
if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {
1466
slot->disabled = PR_TRUE;
1467
slot->reason = PK11_DIS_TOKEN_NOT_PRESENT;
1468
return; /* nothing else to do */
1469
}
1470
}
1471
/* if the token is present, initialize it */
1472
if ((slotInfo.flags & CKF_TOKEN_PRESENT) != 0) {
1473
rv = PK11_InitToken(slot, PR_TRUE);
1474
/* the only hard failures are on permanent devices, or function
1475
* verify failures... function verify failures are already handled
1476
* by tokenInit */
1477
if ((rv != SECSuccess) && (slot->isPerm) && (!slot->disabled)) {
1478
slot->disabled = PR_TRUE;
1479
slot->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1480
}
1481
if (rv == SECSuccess && pk11_isRootSlot(slot)) {
1482
if (!slot->hasRootCerts) {
1483
slot->module->trustOrder = 100;
1484
}
1485
slot->hasRootCerts = PR_TRUE;
1486
}
1487
}
1488
if ((slotInfo.flags & CKF_USER_PIN_INITIALIZED) != 0) {
1489
slot->flags |= CKF_USER_PIN_INITIALIZED;
1490
}
1491
}
1492
1493
/*********************************************************************
1494
* Slot mapping utility functions.
1495
*********************************************************************/
1496
1497
/*
1498
* determine if the token is present. If the token is present, make sure
1499
* we have a valid session handle. Also set the value of needLogin
1500
* appropriately.
1501
*/
1502
static PRBool
1503
pk11_IsPresentCertLoad(PK11SlotInfo *slot, PRBool loadCerts)
1504
{
1505
CK_SLOT_INFO slotInfo;
1506
CK_SESSION_INFO sessionInfo;
1507
CK_RV crv;
1508
1509
/* disabled slots are never present */
1510
if (slot->disabled) {
1511
return PR_FALSE;
1512
}
1513
1514
/* permanent slots are always present */
1515
if (slot->isPerm && (slot->session != CK_INVALID_SESSION)) {
1516
return PR_TRUE;
1517
}
1518
1519
if (slot->nssToken) {
1520
return nssToken_IsPresent(slot->nssToken);
1521
}
1522
1523
/* removable slots have a flag that says they are present */
1524
if (!slot->isThreadSafe)
1525
PK11_EnterSlotMonitor(slot);
1526
if (PK11_GETTAB(slot)->C_GetSlotInfo(slot->slotID, &slotInfo) != CKR_OK) {
1527
if (!slot->isThreadSafe)
1528
PK11_ExitSlotMonitor(slot);
1529
return PR_FALSE;
1530
}
1531
if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {
1532
/* if the slot is no longer present, close the session */
1533
if (slot->session != CK_INVALID_SESSION) {
1534
PK11_GETTAB(slot)
1535
->C_CloseSession(slot->session);
1536
slot->session = CK_INVALID_SESSION;
1537
}
1538
if (!slot->isThreadSafe)
1539
PK11_ExitSlotMonitor(slot);
1540
return PR_FALSE;
1541
}
1542
1543
/* use the session Info to determine if the card has been removed and then
1544
* re-inserted */
1545
if (slot->session != CK_INVALID_SESSION) {
1546
if (slot->isThreadSafe)
1547
PK11_EnterSlotMonitor(slot);
1548
crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session, &sessionInfo);
1549
if (crv != CKR_OK) {
1550
PK11_GETTAB(slot)
1551
->C_CloseSession(slot->session);
1552
slot->session = CK_INVALID_SESSION;
1553
}
1554
if (slot->isThreadSafe)
1555
PK11_ExitSlotMonitor(slot);
1556
}
1557
if (!slot->isThreadSafe)
1558
PK11_ExitSlotMonitor(slot);
1559
1560
/* card has not been removed, current token info is correct */
1561
if (slot->session != CK_INVALID_SESSION)
1562
return PR_TRUE;
1563
1564
/* initialize the token info state */
1565
if (PK11_InitToken(slot, loadCerts) != SECSuccess) {
1566
return PR_FALSE;
1567
}
1568
1569
return PR_TRUE;
1570
}
1571
1572
/*
1573
* old version of the routine
1574
*/
1575
PRBool
1576
PK11_IsPresent(PK11SlotInfo *slot)
1577
{
1578
return pk11_IsPresentCertLoad(slot, PR_TRUE);
1579
}
1580
1581
/* is the slot disabled? */
1582
PRBool
1583
PK11_IsDisabled(PK11SlotInfo *slot)
1584
{
1585
return slot->disabled;
1586
}
1587
1588
/* and why? */
1589
PK11DisableReasons
1590
PK11_GetDisabledReason(PK11SlotInfo *slot)
1591
{
1592
return slot->reason;
1593
}
1594
1595
/* returns PR_TRUE if successfully disable the slot */
1596
/* returns PR_FALSE otherwise */
1597
PRBool
1598
PK11_UserDisableSlot(PK11SlotInfo *slot)
1599
{
1600
1601
/* Prevent users from disabling the internal module. */
1602
if (slot->isInternal) {
1603
PORT_SetError(SEC_ERROR_INVALID_ARGS);
1604
return PR_FALSE;
1605
}
1606
1607
slot->defaultFlags |= PK11_DISABLE_FLAG;
1608
slot->disabled = PR_TRUE;
1609
slot->reason = PK11_DIS_USER_SELECTED;
1610
1611
return PR_TRUE;
1612
}
1613
1614
PRBool
1615
PK11_UserEnableSlot(PK11SlotInfo *slot)
1616
{
1617
1618
slot->defaultFlags &= ~PK11_DISABLE_FLAG;
1619
slot->disabled = PR_FALSE;
1620
slot->reason = PK11_DIS_NONE;
1621
return PR_TRUE;
1622
}
1623
1624
PRBool
1625
PK11_HasRootCerts(PK11SlotInfo *slot)
1626
{
1627
return slot->hasRootCerts;
1628
}
1629
1630
/* Get the module this slot is attached to */
1631
SECMODModule *
1632
PK11_GetModule(PK11SlotInfo *slot)
1633
{
1634
return slot->module;
1635
}
1636
1637
/* return the default flags of a slot */
1638
unsigned long
1639
PK11_GetDefaultFlags(PK11SlotInfo *slot)
1640
{
1641
return slot->defaultFlags;
1642
}
1643
1644
/*
1645
* The following wrapper functions allow us to export an opaque slot
1646
* function to the rest of libsec and the world... */
1647
PRBool
1648
PK11_IsReadOnly(PK11SlotInfo *slot)
1649
{
1650
return slot->readOnly;
1651
}
1652
1653
PRBool
1654
PK11_IsHW(PK11SlotInfo *slot)
1655
{
1656
return slot->isHW;
1657
}
1658
1659
PRBool
1660
PK11_IsRemovable(PK11SlotInfo *slot)
1661
{
1662
return !slot->isPerm;
1663
}
1664
1665
PRBool
1666
PK11_IsInternal(PK11SlotInfo *slot)
1667
{
1668
return slot->isInternal;
1669
}
1670
1671
PRBool
1672
PK11_IsInternalKeySlot(PK11SlotInfo *slot)
1673
{
1674
PK11SlotInfo *int_slot;
1675
PRBool result;
1676
1677
if (!slot->isInternal) {
1678
return PR_FALSE;
1679
}
1680
1681
int_slot = PK11_GetInternalKeySlot();
1682
result = (int_slot == slot) ? PR_TRUE : PR_FALSE;
1683
PK11_FreeSlot(int_slot);
1684
return result;
1685
}
1686
1687
PRBool
1688
PK11_NeedLogin(PK11SlotInfo *slot)
1689
{
1690
return slot->needLogin;
1691
}
1692
1693
PRBool
1694
PK11_IsFriendly(PK11SlotInfo *slot)
1695
{
1696
/* internal slot always has public readable certs */
1697
return (PRBool)(slot->isInternal ||
1698
((slot->defaultFlags & SECMOD_FRIENDLY_FLAG) ==
1699
SECMOD_FRIENDLY_FLAG));
1700
}
1701
1702
char *
1703
PK11_GetTokenName(PK11SlotInfo *slot)
1704
{
1705
return slot->token_name;
1706
}
1707
1708
char *
1709
PK11_GetTokenURI(PK11SlotInfo *slot)
1710
{
1711
PK11URI *uri;
1712
char *ret = NULL;
1713
char label[32 + 1], manufacturer[32 + 1], serial[16 + 1], model[16 + 1];
1714
PK11URIAttribute attrs[4];
1715
size_t nattrs = 0;
1716
1717
PK11_MakeString(NULL, label, (char *)slot->tokenInfo.label,
1718
sizeof(slot->tokenInfo.label));
1719
if (*label != '\0') {
1720
attrs[nattrs].name = PK11URI_PATTR_TOKEN;
1721
attrs[nattrs].value = label;
1722
nattrs++;
1723
}
1724
1725
PK11_MakeString(NULL, manufacturer, (char *)slot->tokenInfo.manufacturerID,
1726
sizeof(slot->tokenInfo.manufacturerID));
1727
if (*manufacturer != '\0') {
1728
attrs[nattrs].name = PK11URI_PATTR_MANUFACTURER;
1729
attrs[nattrs].value = manufacturer;
1730
nattrs++;
1731
}
1732
1733
PK11_MakeString(NULL, serial, (char *)slot->tokenInfo.serialNumber,
1734
sizeof(slot->tokenInfo.serialNumber));
1735
if (*serial != '\0') {
1736
attrs[nattrs].name = PK11URI_PATTR_SERIAL;
1737
attrs[nattrs].value = serial;
1738
nattrs++;
1739
}
1740
1741
PK11_MakeString(NULL, model, (char *)slot->tokenInfo.model,
1742
sizeof(slot->tokenInfo.model));
1743
if (*model != '\0') {
1744
attrs[nattrs].name = PK11URI_PATTR_MODEL;
1745
attrs[nattrs].value = model;
1746
nattrs++;
1747
}
1748
1749
uri = PK11URI_CreateURI(attrs, nattrs, NULL, 0);
1750
if (uri == NULL) {
1751
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1752
return NULL;
1753
}
1754
1755
ret = PK11URI_FormatURI(NULL, uri);
1756
PK11URI_DestroyURI(uri);
1757
1758
if (ret == NULL) {
1759
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1760
}
1761
1762
return ret;
1763
}
1764
1765
char *
1766
PK11_GetSlotName(PK11SlotInfo *slot)
1767
{
1768
return slot->slot_name;
1769
}
1770
1771
int
1772
PK11_GetSlotSeries(PK11SlotInfo *slot)
1773
{
1774
return slot->series;
1775
}
1776
1777
int
1778
PK11_GetCurrentWrapIndex(PK11SlotInfo *slot)
1779
{
1780
return slot->wrapKey;
1781
}
1782
1783
CK_SLOT_ID
1784
PK11_GetSlotID(PK11SlotInfo *slot)
1785
{
1786
return slot->slotID;
1787
}
1788
1789
SECMODModuleID
1790
PK11_GetModuleID(PK11SlotInfo *slot)
1791
{
1792
return slot->module->moduleID;
1793
}
1794
1795
static void
1796
pk11_zeroTerminatedToBlankPadded(CK_CHAR *buffer, size_t buffer_size)
1797
{
1798
CK_CHAR *walk = buffer;
1799
CK_CHAR *end = buffer + buffer_size;
1800
1801
/* find the NULL */
1802
while (walk < end && *walk != '\0') {
1803
walk++;
1804
}
1805
1806
/* clear out the buffer */
1807
while (walk < end) {
1808
*walk++ = ' ';
1809
}
1810
}
1811
1812
/* return the slot info structure */
1813
SECStatus
1814
PK11_GetSlotInfo(PK11SlotInfo *slot, CK_SLOT_INFO *info)
1815
{
1816
CK_RV crv;
1817
1818
if (!slot->isThreadSafe)
1819
PK11_EnterSlotMonitor(slot);
1820
/*
1821
* some buggy drivers do not fill the buffer completely,
1822
* erase the buffer first
1823
*/
1824
PORT_Memset(info->slotDescription, ' ', sizeof(info->slotDescription));
1825
PORT_Memset(info->manufacturerID, ' ', sizeof(info->manufacturerID));
1826
crv = PK11_GETTAB(slot)->C_GetSlotInfo(slot->slotID, info);
1827
pk11_zeroTerminatedToBlankPadded(info->slotDescription,
1828
sizeof(info->slotDescription));
1829
pk11_zeroTerminatedToBlankPadded(info->manufacturerID,
1830
sizeof(info->manufacturerID));
1831
if (!slot->isThreadSafe)
1832
PK11_ExitSlotMonitor(slot);
1833
if (crv != CKR_OK) {
1834
PORT_SetError(PK11_MapError(crv));
1835
return SECFailure;
1836
}
1837
return SECSuccess;
1838
}
1839
1840
/* return the token info structure */
1841
SECStatus
1842
PK11_GetTokenInfo(PK11SlotInfo *slot, CK_TOKEN_INFO *info)
1843
{
1844
CK_RV crv;
1845
if (!slot->isThreadSafe)
1846
PK11_EnterSlotMonitor(slot);
1847
/*
1848
* some buggy drivers do not fill the buffer completely,
1849
* erase the buffer first
1850
*/
1851
PORT_Memset(info->label, ' ', sizeof(info->label));
1852
PORT_Memset(info->manufacturerID, ' ', sizeof(info->manufacturerID));
1853
PORT_Memset(info->model, ' ', sizeof(info->model));
1854
PORT_Memset(info->serialNumber, ' ', sizeof(info->serialNumber));
1855
crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID, info);
1856
pk11_zeroTerminatedToBlankPadded(info->label, sizeof(info->label));
1857
pk11_zeroTerminatedToBlankPadded(info->manufacturerID,
1858
sizeof(info->manufacturerID));
1859
pk11_zeroTerminatedToBlankPadded(info->model, sizeof(info->model));
1860
pk11_zeroTerminatedToBlankPadded(info->serialNumber,
1861
sizeof(info->serialNumber));
1862
if (!slot->isThreadSafe)
1863
PK11_ExitSlotMonitor(slot);
1864
if (crv != CKR_OK) {
1865
PORT_SetError(PK11_MapError(crv));
1866
return SECFailure;
1867
}
1868
return SECSuccess;
1869
}
1870
1871
PRBool
1872
pk11_MatchUriTokenInfo(PK11SlotInfo *slot, PK11URI *uri)
1873
{
1874
const char *value;
1875
1876
value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_TOKEN);
1877
if (value) {
1878
if (!pk11_MatchString(value, (char *)slot->tokenInfo.label,
1879
sizeof(slot->tokenInfo.label))) {
1880
return PR_FALSE;
1881
}
1882
}
1883
1884
value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_MANUFACTURER);
1885
if (value) {
1886
if (!pk11_MatchString(value, (char *)slot->tokenInfo.manufacturerID,
1887
sizeof(slot->tokenInfo.manufacturerID))) {
1888
return PR_FALSE;
1889
}
1890
}
1891
1892
value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_SERIAL);
1893
if (value) {
1894
if (!pk11_MatchString(value, (char *)slot->tokenInfo.serialNumber,
1895
sizeof(slot->tokenInfo.serialNumber))) {
1896
return PR_FALSE;
1897
}
1898
}
1899
1900
value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_MODEL);
1901
if (value) {
1902
if (!pk11_MatchString(value, (char *)slot->tokenInfo.model,
1903
sizeof(slot->tokenInfo.model))) {
1904
return PR_FALSE;
1905
}
1906
}
1907
1908
return PR_TRUE;
1909
}
1910
1911
/* Find out if we need to initialize the user's pin */
1912
PRBool
1913
PK11_NeedUserInit(PK11SlotInfo *slot)
1914
{
1915
PRBool needUserInit = (PRBool)((slot->flags & CKF_USER_PIN_INITIALIZED) == 0);
1916
1917
if (needUserInit) {
1918
CK_TOKEN_INFO info;
1919
SECStatus rv;
1920
1921
/* see if token has been initialized off line */
1922
rv = PK11_GetTokenInfo(slot, &info);
1923
if (rv == SECSuccess) {
1924
slot->flags = info.flags;
1925
}
1926
}
1927
return (PRBool)((slot->flags & CKF_USER_PIN_INITIALIZED) == 0);
1928
}
1929
1930
static PK11SlotInfo *pk11InternalKeySlot = NULL;
1931
1932
/*
1933
* Set a new default internal keyslot. If one has already been set, clear it.
1934
* Passing NULL falls back to the NSS normally selected default internal key
1935
* slot.
1936
*/
1937
void
1938
pk11_SetInternalKeySlot(PK11SlotInfo *slot)
1939
{
1940
if (pk11InternalKeySlot) {
1941
PK11_FreeSlot(pk11InternalKeySlot);
1942
}
1943
pk11InternalKeySlot = slot ? PK11_ReferenceSlot(slot) : NULL;
1944
}
1945
1946
/*
1947
* Set a new default internal keyslot if the normal key slot has not already
1948
* been overridden. Subsequent calls to this function will be ignored unless
1949
* pk11_SetInternalKeySlot is used to clear the current default.
1950
*/
1951
void