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/. */
6
static const char CVS_ID[] = "@(#) $RCSfile: devtoken.c,v $ $Revision: 1.57 $ $Date: 2012/04/25 14:49:42 $";
17
#endif /* CKHELPER_H */
23
extern const NSSError NSS_ERROR_NOT_FOUND;
24
extern const NSSError NSS_ERROR_INVALID_ARGUMENT;
25
extern const NSSError NSS_ERROR_PKCS11;
27
/* The number of object handles to grab during each call to C_FindObjects */
28
#define OBJECT_STACK_SIZE 16
30
NSS_IMPLEMENT PRStatus
36
if (PR_ATOMIC_DECREMENT(&tok->base.refCount) == 0) {
37
PZ_DestroyLock(tok->base.lock);
38
nssTokenObjectCache_Destroy(tok->cache);
39
/* The token holds the first/last reference to the slot.
40
* When the token is actually destroyed, that ref must go too.
42
(void)nssSlot_Destroy(tok->slot);
43
return nssArena_Destroy(tok->base.arena);
54
nssTokenObjectCache_Clear(tok->cache);
62
(void)nssToken_Destroy(tok);
65
NSS_IMPLEMENT NSSToken *
70
PR_ATOMIC_INCREMENT(&tok->base.refCount);
74
NSS_IMPLEMENT NSSSlot *
79
return nssSlot_AddRef(tok->slot);
83
nssToken_GetCryptokiEPV (
87
return nssSlot_GetCryptokiEPV(token->slot);
90
NSS_IMPLEMENT nssSession *
91
nssToken_GetDefaultSession (
95
return token->defaultSession;
98
NSS_IMPLEMENT NSSUTF8 *
106
if (tok->base.name[0] == 0) {
107
(void) nssSlot_IsTokenPresent(tok->slot);
109
return tok->base.name;
112
NSS_IMPLEMENT NSSUTF8 *
117
return nssToken_GetName(token);
121
nssToken_IsLoginRequired (
125
return (token->ckFlags & CKF_LOGIN_REQUIRED);
129
nssToken_NeedsPINInitialization (
133
return (!(token->ckFlags & CKF_USER_PIN_INITIALIZED));
136
NSS_IMPLEMENT PRStatus
137
nssToken_DeleteStoredObject (
138
nssCryptokiObject *instance
143
PRBool createdSession = PR_FALSE;
144
NSSToken *token = instance->token;
145
nssSession *session = NULL;
146
void *epv = nssToken_GetCryptokiEPV(instance->token);
148
nssTokenObjectCache_RemoveObject(token->cache, instance);
150
if (instance->isTokenObject) {
151
if (token->defaultSession &&
152
nssSession_IsReadWrite(token->defaultSession)) {
153
session = token->defaultSession;
155
session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE);
156
createdSession = PR_TRUE;
159
if (session == NULL) {
162
nssSession_EnterMonitor(session);
163
ckrv = CKAPI(epv)->C_DestroyObject(session->handle, instance->handle);
164
nssSession_ExitMonitor(session);
165
if (createdSession) {
166
nssSession_Destroy(session);
169
if (ckrv != CKR_OK) {
171
/* use the error stack to pass the PKCS #11 error out */
173
nss_SetError(NSS_ERROR_PKCS11);
178
static nssCryptokiObject *
181
nssSession *sessionOpt,
182
CK_ATTRIBUTE_PTR objectTemplate,
186
nssSession *session = NULL;
187
PRBool createdSession = PR_FALSE;
188
nssCryptokiObject *object = NULL;
189
CK_OBJECT_HANDLE handle;
191
void *epv = nssToken_GetCryptokiEPV(tok);
192
if (nssCKObject_IsTokenObjectTemplate(objectTemplate, otsize)) {
194
if (!nssSession_IsReadWrite(sessionOpt)) {
195
nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
198
session = sessionOpt;
199
} else if (tok->defaultSession &&
200
nssSession_IsReadWrite(tok->defaultSession)) {
201
session = tok->defaultSession;
203
session = nssSlot_CreateSession(tok->slot, NULL, PR_TRUE);
204
createdSession = PR_TRUE;
207
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
209
if (session == NULL) {
210
nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
213
nssSession_EnterMonitor(session);
214
ckrv = CKAPI(epv)->C_CreateObject(session->handle,
215
objectTemplate, otsize,
217
nssSession_ExitMonitor(session);
218
if (ckrv == CKR_OK) {
219
object = nssCryptokiObject_Create(tok, session, handle);
222
nss_SetError(NSS_ERROR_PKCS11);
224
if (createdSession) {
225
nssSession_Destroy(session);
230
static nssCryptokiObject **
231
create_objects_from_handles (
234
CK_OBJECT_HANDLE *handles,
238
nssCryptokiObject **objects;
239
objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numH + 1);
242
for (i=0; i<(PRInt32)numH; i++) {
243
objects[i] = nssCryptokiObject_Create(tok, session, handles[i]);
245
for (--i; i>0; --i) {
246
nssCryptokiObject_Destroy(objects[i]);
248
nss_ZFreeIf(objects);
257
static nssCryptokiObject **
260
nssSession *sessionOpt,
261
CK_ATTRIBUTE_PTR obj_template,
269
CK_OBJECT_HANDLE *objectHandles = NULL;
270
CK_OBJECT_HANDLE staticObjects[OBJECT_STACK_SIZE];
271
PRUint32 arraySize, numHandles;
272
void *epv = nssToken_GetCryptokiEPV(tok);
273
nssCryptokiObject **objects;
274
nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
276
/* Don't ask the module to use an invalid session handle. */
277
if (!session || session->handle == CK_INVALID_SESSION) {
278
ckrv = CKR_SESSION_HANDLE_INVALID;
282
/* the arena is only for the array of object handles */
283
if (maximumOpt > 0) {
284
arraySize = maximumOpt;
286
arraySize = OBJECT_STACK_SIZE;
289
if (arraySize <= OBJECT_STACK_SIZE) {
290
objectHandles = staticObjects;
292
objectHandles = nss_ZNEWARRAY(NULL, CK_OBJECT_HANDLE, arraySize);
294
if (!objectHandles) {
295
ckrv = CKR_HOST_MEMORY;
298
nssSession_EnterMonitor(session); /* ==== session lock === */
299
/* Initialize the find with the template */
300
ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle,
301
obj_template, otsize);
302
if (ckrv != CKR_OK) {
303
nssSession_ExitMonitor(session);
307
/* Issue the find for up to arraySize - numHandles objects */
308
ckrv = CKAPI(epv)->C_FindObjects(session->handle,
309
objectHandles + numHandles,
310
arraySize - numHandles,
312
if (ckrv != CKR_OK) {
313
nssSession_ExitMonitor(session);
316
/* bump the number of found objects */
318
if (maximumOpt > 0 || numHandles < arraySize) {
319
/* When a maximum is provided, the search is done all at once,
320
* so the search is finished. If the number returned was less
321
* than the number sought, the search is finished.
325
/* the array is filled, double it and continue */
327
if (objectHandles == staticObjects) {
328
objectHandles = nss_ZNEWARRAY(NULL,CK_OBJECT_HANDLE, arraySize);
330
PORT_Memcpy(objectHandles, staticObjects,
331
OBJECT_STACK_SIZE * sizeof(objectHandles[1]));
334
objectHandles = nss_ZREALLOCARRAY(objectHandles,
338
if (!objectHandles) {
339
nssSession_ExitMonitor(session);
340
ckrv = CKR_HOST_MEMORY;
344
ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle);
345
nssSession_ExitMonitor(session); /* ==== end session lock === */
346
if (ckrv != CKR_OK) {
349
if (numHandles > 0) {
350
objects = create_objects_from_handles(tok, session,
351
objectHandles, numHandles);
353
nss_SetError(NSS_ERROR_NOT_FOUND);
356
if (objectHandles && objectHandles != staticObjects) {
357
nss_ZFreeIf(objectHandles);
359
if (statusOpt) *statusOpt = PR_SUCCESS;
362
if (objectHandles && objectHandles != staticObjects) {
363
nss_ZFreeIf(objectHandles);
366
* These errors should be treated the same as if the objects just weren't
369
if ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) ||
370
(ckrv == CKR_ATTRIBUTE_VALUE_INVALID) ||
371
(ckrv == CKR_DATA_INVALID) ||
372
(ckrv == CKR_DATA_LEN_RANGE) ||
373
(ckrv == CKR_FUNCTION_NOT_SUPPORTED) ||
374
(ckrv == CKR_TEMPLATE_INCOMPLETE) ||
375
(ckrv == CKR_TEMPLATE_INCONSISTENT)) {
377
nss_SetError(NSS_ERROR_NOT_FOUND);
378
if (statusOpt) *statusOpt = PR_SUCCESS;
381
nss_SetError(NSS_ERROR_PKCS11);
382
if (statusOpt) *statusOpt = PR_FAILURE;
384
return (nssCryptokiObject **)NULL;
387
static nssCryptokiObject **
388
find_objects_by_template (
390
nssSession *sessionOpt,
391
CK_ATTRIBUTE_PTR obj_template,
397
CK_OBJECT_CLASS objclass = (CK_OBJECT_CLASS)-1;
398
nssCryptokiObject **objects = NULL;
402
PORT_SetError(SEC_ERROR_NO_TOKEN);
404
*statusOpt = PR_FAILURE;
407
for (i=0; i<otsize; i++) {
408
if (obj_template[i].type == CKA_CLASS) {
409
objclass = *(CK_OBJECT_CLASS *)obj_template[i].pValue;
413
PR_ASSERT(i < otsize);
415
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
416
if (statusOpt) *statusOpt = PR_FAILURE;
419
/* If these objects are being cached, try looking there first */
421
nssTokenObjectCache_HaveObjectClass(token->cache, objclass))
424
objects = nssTokenObjectCache_FindObjectsByTemplate(token->cache,
430
if (status == PR_SUCCESS) {
431
if (statusOpt) *statusOpt = status;
435
/* Either they are not cached, or cache failed; look on token. */
436
objects = find_objects(token, sessionOpt,
437
obj_template, otsize,
438
maximumOpt, statusOpt);
442
extern const NSSError NSS_ERROR_INVALID_CERTIFICATE;
444
NSS_IMPLEMENT nssCryptokiObject *
445
nssToken_ImportCertificate (
447
nssSession *sessionOpt,
448
NSSCertificateType certType,
450
const NSSUTF8 *nickname,
460
CK_CERTIFICATE_TYPE cert_type;
461
CK_ATTRIBUTE_PTR attr;
462
CK_ATTRIBUTE cert_tmpl[10];
464
nssTokenSearchType searchType;
465
nssCryptokiObject *rvObject = NULL;
468
PORT_SetError(SEC_ERROR_NO_TOKEN);
471
if (certType == NSSCertificateType_PKIX) {
472
cert_type = CKC_X_509;
474
return (nssCryptokiObject *)NULL;
476
NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize);
478
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
479
searchType = nssTokenSearchType_TokenOnly;
481
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
482
searchType = nssTokenSearchType_SessionOnly;
484
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
485
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CERTIFICATE_TYPE, cert_type);
486
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
487
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
488
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding);
489
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer);
490
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
491
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial);
493
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_EMAIL, email);
495
NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize);
496
/* see if the cert is already there */
497
rvObject = nssToken_FindCertificateByIssuerAndSerialNumber(tok,
505
NSSSlot *slot = nssToken_GetSlot(tok);
506
nssSession *session = nssSlot_CreateSession(slot, NULL, PR_TRUE);
508
nssCryptokiObject_Destroy(rvObject);
509
nssSlot_Destroy(slot);
510
return (nssCryptokiObject *)NULL;
512
/* Reject any attempt to import a new cert that has the same
513
* issuer/serial as an existing cert, but does not have the
516
NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize);
517
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
518
NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize);
519
status = nssCKObject_GetAttributes(rvObject->handle,
520
cert_tmpl, ctsize, NULL,
522
NSS_CK_ATTRIBUTE_TO_ITEM(cert_tmpl, &existingDER);
523
if (status == PR_SUCCESS) {
524
if (!nssItem_Equal(encoding, &existingDER, NULL)) {
525
nss_SetError(NSS_ERROR_INVALID_CERTIFICATE);
528
nss_ZFreeIf(existingDER.data);
530
if (status == PR_FAILURE) {
531
nssCryptokiObject_Destroy(rvObject);
532
nssSession_Destroy(session);
533
nssSlot_Destroy(slot);
534
return (nssCryptokiObject *)NULL;
536
/* according to PKCS#11, label, ID, issuer, and serial number
537
* may change after the object has been created. For PKIX, the
538
* last two attributes can't change, so for now we'll only worry
539
* about the first two.
541
NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize);
542
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
543
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
544
NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize);
545
/* reset the mutable attributes on the token */
546
nssCKObject_SetAttributes(rvObject->handle,
549
if (!rvObject->label && nickname) {
550
rvObject->label = nssUTF8_Duplicate(nickname, NULL);
552
nssSession_Destroy(session);
553
nssSlot_Destroy(slot);
555
/* Import the certificate onto the token */
556
rvObject = import_object(tok, sessionOpt, cert_tmpl, ctsize);
558
if (rvObject && tok->cache) {
559
/* The cache will overwrite the attributes if the object already
562
nssTokenObjectCache_ImportObject(tok->cache, rvObject,
569
/* traverse all objects of the given class - this should only happen
570
* if the token has been marked as "traversable"
572
NSS_IMPLEMENT nssCryptokiObject **
573
nssToken_FindObjects (
575
nssSession *sessionOpt,
576
CK_OBJECT_CLASS objclass,
577
nssTokenSearchType searchType,
582
CK_ATTRIBUTE_PTR attr;
583
CK_ATTRIBUTE obj_template[2];
585
nssCryptokiObject **objects;
586
NSS_CK_TEMPLATE_START(obj_template, attr, obj_size);
587
/* Set the search to token/session only if provided */
588
if (searchType == nssTokenSearchType_SessionOnly) {
589
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
590
} else if (searchType == nssTokenSearchType_TokenOnly ||
591
searchType == nssTokenSearchType_TokenForced) {
592
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
594
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, objclass);
595
NSS_CK_TEMPLATE_FINISH(obj_template, attr, obj_size);
597
if (searchType == nssTokenSearchType_TokenForced) {
598
objects = find_objects(token, sessionOpt,
599
obj_template, obj_size,
600
maximumOpt, statusOpt);
602
objects = find_objects_by_template(token, sessionOpt,
603
obj_template, obj_size,
604
maximumOpt, statusOpt);
609
NSS_IMPLEMENT nssCryptokiObject **
610
nssToken_FindCertificatesBySubject (
612
nssSession *sessionOpt,
614
nssTokenSearchType searchType,
619
CK_ATTRIBUTE_PTR attr;
620
CK_ATTRIBUTE subj_template[3];
622
nssCryptokiObject **objects;
623
NSS_CK_TEMPLATE_START(subj_template, attr, stsize);
624
/* Set the search to token/session only if provided */
625
if (searchType == nssTokenSearchType_SessionOnly) {
626
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
627
} else if (searchType == nssTokenSearchType_TokenOnly) {
628
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
630
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
631
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
632
NSS_CK_TEMPLATE_FINISH(subj_template, attr, stsize);
633
/* now locate the token certs matching this template */
634
objects = find_objects_by_template(token, sessionOpt,
635
subj_template, stsize,
636
maximumOpt, statusOpt);
640
NSS_IMPLEMENT nssCryptokiObject **
641
nssToken_FindCertificatesByNickname (
643
nssSession *sessionOpt,
645
nssTokenSearchType searchType,
650
CK_ATTRIBUTE_PTR attr;
651
CK_ATTRIBUTE nick_template[3];
653
nssCryptokiObject **objects;
654
NSS_CK_TEMPLATE_START(nick_template, attr, ntsize);
655
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, name);
656
/* Set the search to token/session only if provided */
657
if (searchType == nssTokenSearchType_SessionOnly) {
658
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
659
} else if (searchType == nssTokenSearchType_TokenOnly) {
660
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
662
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
663
NSS_CK_TEMPLATE_FINISH(nick_template, attr, ntsize);
664
/* now locate the token certs matching this template */
665
objects = find_objects_by_template(token, sessionOpt,
666
nick_template, ntsize,
667
maximumOpt, statusOpt);
669
/* This is to workaround the fact that PKCS#11 doesn't specify
670
* whether the '\0' should be included. XXX Is that still true?
671
* im - this is not needed by the current softoken. However, I'm
672
* leaving it in until I have surveyed more tokens to see if it needed.
673
* well, its needed by the builtin token...
675
nick_template[0].ulValueLen++;
676
objects = find_objects_by_template(token, sessionOpt,
677
nick_template, ntsize,
678
maximumOpt, statusOpt);
684
* This function *does not* use the token object cache, because not even
685
* the softoken will return a value for CKA_NSS_EMAIL from a call
686
* to GetAttributes. The softoken does allow searches with that attribute,
687
* it just won't return a value for it.
689
NSS_IMPLEMENT nssCryptokiObject **
690
nssToken_FindCertificatesByEmail (
692
nssSession *sessionOpt,
694
nssTokenSearchType searchType,
699
CK_ATTRIBUTE_PTR attr;
700
CK_ATTRIBUTE email_template[3];
702
nssCryptokiObject **objects;
703
NSS_CK_TEMPLATE_START(email_template, attr, etsize);
704
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_EMAIL, email);
705
/* Set the search to token/session only if provided */
706
if (searchType == nssTokenSearchType_SessionOnly) {
707
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
708
} else if (searchType == nssTokenSearchType_TokenOnly) {
709
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
711
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
712
NSS_CK_TEMPLATE_FINISH(email_template, attr, etsize);
713
/* now locate the token certs matching this template */
714
objects = find_objects(token, sessionOpt,
715
email_template, etsize,
716
maximumOpt, statusOpt);
718
/* This is to workaround the fact that PKCS#11 doesn't specify
719
* whether the '\0' should be included. XXX Is that still true?
720
* im - this is not needed by the current softoken. However, I'm
721
* leaving it in until I have surveyed more tokens to see if it needed.
722
* well, its needed by the builtin token...
724
email_template[0].ulValueLen++;
725
objects = find_objects(token, sessionOpt,
726
email_template, etsize,
727
maximumOpt, statusOpt);
732
NSS_IMPLEMENT nssCryptokiObject **
733
nssToken_FindCertificatesByID (
735
nssSession *sessionOpt,
737
nssTokenSearchType searchType,
742
CK_ATTRIBUTE_PTR attr;
743
CK_ATTRIBUTE id_template[3];
745
nssCryptokiObject **objects;
746
NSS_CK_TEMPLATE_START(id_template, attr, idtsize);
747
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
748
/* Set the search to token/session only if provided */
749
if (searchType == nssTokenSearchType_SessionOnly) {
750
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
751
} else if (searchType == nssTokenSearchType_TokenOnly) {
752
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
754
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
755
NSS_CK_TEMPLATE_FINISH(id_template, attr, idtsize);
756
/* now locate the token certs matching this template */
757
objects = find_objects_by_template(token, sessionOpt,
758
id_template, idtsize,
759
maximumOpt, statusOpt);
764
* decode the serial item and return our result.
765
* NOTE serialDecode's data is really stored in serial. Don't free it.
768
nssToken_decodeSerialItem(NSSItem *serial, NSSItem *serialDecode)
770
unsigned char *data = (unsigned char *)serial->data;
771
int data_left, data_len, index;
773
if ((serial->size >= 3) && (data[0] == 0x2)) {
774
/* remove the der encoding of the serial number before generating the
776
data_left = serial->size-2;
780
/* extended length ? (not very likely for a serial number) */
781
if (data_len & 0x80) {
782
int len_count = data_len & 0x7f;
785
data_left -= len_count;
787
while (len_count --) {
788
data_len = (data_len << 8) | data[index++];
792
/* XXX leaving any leading zeros on the serial number for backwards
795
/* not a valid der, must be just an unlucky serial number value */
796
if (data_len == data_left) {
797
serialDecode->size = data_len;
798
serialDecode->data = &data[index];
805
NSS_IMPLEMENT nssCryptokiObject *
806
nssToken_FindCertificateByIssuerAndSerialNumber (
808
nssSession *sessionOpt,
811
nssTokenSearchType searchType,
815
CK_ATTRIBUTE_PTR attr;
816
CK_ATTRIBUTE_PTR serialAttr;
817
CK_ATTRIBUTE cert_template[4];
819
nssCryptokiObject **objects;
820
nssCryptokiObject *rvObject = NULL;
821
NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
824
PORT_SetError(SEC_ERROR_NO_TOKEN);
826
*statusOpt = PR_FAILURE;
829
/* Set the search to token/session only if provided */
830
if (searchType == nssTokenSearchType_SessionOnly) {
831
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
832
} else if ((searchType == nssTokenSearchType_TokenOnly) ||
833
(searchType == nssTokenSearchType_TokenForced)) {
834
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
836
/* Set the unique id */
837
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
838
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer);
840
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial);
841
NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);
842
/* get the object handle */
843
if (searchType == nssTokenSearchType_TokenForced) {
844
objects = find_objects(token, sessionOpt,
845
cert_template, ctsize,
848
objects = find_objects_by_template(token, sessionOpt,
849
cert_template, ctsize,
853
rvObject = objects[0];
854
nss_ZFreeIf(objects);
858
* NSS used to incorrectly store serial numbers in their decoded form.
859
* because of this old tokens have decoded serial numbers.
862
NSSItem serialDecode;
865
status = nssToken_decodeSerialItem(serial, &serialDecode);
866
if (status != PR_SUCCESS) {
869
NSS_CK_SET_ATTRIBUTE_ITEM(serialAttr,CKA_SERIAL_NUMBER,&serialDecode);
870
if (searchType == nssTokenSearchType_TokenForced) {
871
objects = find_objects(token, sessionOpt,
872
cert_template, ctsize,
875
objects = find_objects_by_template(token, sessionOpt,
876
cert_template, ctsize,
880
rvObject = objects[0];
881
nss_ZFreeIf(objects);
887
NSS_IMPLEMENT nssCryptokiObject *
888
nssToken_FindCertificateByEncodedCertificate (
890
nssSession *sessionOpt,
891
NSSBER *encodedCertificate,
892
nssTokenSearchType searchType,
896
CK_ATTRIBUTE_PTR attr;
897
CK_ATTRIBUTE cert_template[3];
899
nssCryptokiObject **objects;
900
nssCryptokiObject *rvObject = NULL;
901
NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
902
/* Set the search to token/session only if provided */
903
if (searchType == nssTokenSearchType_SessionOnly) {
904
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
905
} else if (searchType == nssTokenSearchType_TokenOnly) {
906
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
908
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
909
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encodedCertificate);
910
NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);
911
/* get the object handle */
912
objects = find_objects_by_template(token, sessionOpt,
913
cert_template, ctsize,
916
rvObject = objects[0];
917
nss_ZFreeIf(objects);
922
NSS_IMPLEMENT nssCryptokiObject **
923
nssToken_FindPrivateKeys (
925
nssSession *sessionOpt,
926
nssTokenSearchType searchType,
931
CK_ATTRIBUTE_PTR attr;
932
CK_ATTRIBUTE key_template[2];
934
nssCryptokiObject **objects;
936
NSS_CK_TEMPLATE_START(key_template, attr, ktsize);
937
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey);
938
if (searchType == nssTokenSearchType_SessionOnly) {
939
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
940
} else if (searchType == nssTokenSearchType_TokenOnly) {
941
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
943
NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize);
945
objects = find_objects_by_template(token, sessionOpt,
946
key_template, ktsize,
947
maximumOpt, statusOpt);
951
/* XXX ?there are no session cert objects, so only search token objects */
952
NSS_IMPLEMENT nssCryptokiObject *
953
nssToken_FindPrivateKeyByID (
955
nssSession *sessionOpt,
959
CK_ATTRIBUTE_PTR attr;
960
CK_ATTRIBUTE key_template[3];
962
nssCryptokiObject **objects;
963
nssCryptokiObject *rvKey = NULL;
965
NSS_CK_TEMPLATE_START(key_template, attr, ktsize);
966
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey);
967
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
968
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID);
969
NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize);
971
objects = find_objects_by_template(token, sessionOpt,
972
key_template, ktsize,
976
nss_ZFreeIf(objects);
981
/* XXX ?there are no session cert objects, so only search token objects */
982
NSS_IMPLEMENT nssCryptokiObject *
983
nssToken_FindPublicKeyByID (
985
nssSession *sessionOpt,
989
CK_ATTRIBUTE_PTR attr;
990
CK_ATTRIBUTE key_template[3];
992
nssCryptokiObject **objects;
993
nssCryptokiObject *rvKey = NULL;
995
NSS_CK_TEMPLATE_START(key_template, attr, ktsize);
996
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_pubkey);
997
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
998
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID);
999
NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize);
1001
objects = find_objects_by_template(token, sessionOpt,
1002
key_template, ktsize,
1006
nss_ZFreeIf(objects);
1012
sha1_hash(NSSItem *input, NSSItem *output)
1014
NSSAlgorithmAndParameters *ap;
1015
PK11SlotInfo *internal = PK11_GetInternalSlot();
1016
NSSToken *token = PK11Slot_GetNSSToken(internal);
1017
ap = NSSAlgorithmAndParameters_CreateSHA1Digest(NULL);
1018
(void)nssToken_Digest(token, NULL, ap, input, output, NULL);
1019
PK11_FreeSlot(token->pk11slot);
1024
md5_hash(NSSItem *input, NSSItem *output)
1026
NSSAlgorithmAndParameters *ap;
1027
PK11SlotInfo *internal = PK11_GetInternalSlot();
1028
NSSToken *token = PK11Slot_GetNSSToken(internal);
1029
ap = NSSAlgorithmAndParameters_CreateMD5Digest(NULL);
1030
(void)nssToken_Digest(token, NULL, ap, input, output, NULL);
1031
PK11_FreeSlot(token->pk11slot);
1037
nssTrustLevel nssTrust
1042
case nssTrustLevel_NotTrusted: t = CKT_NSS_NOT_TRUSTED; break;
1043
case nssTrustLevel_TrustedDelegator: t = CKT_NSS_TRUSTED_DELEGATOR;
1045
case nssTrustLevel_ValidDelegator: t = CKT_NSS_VALID_DELEGATOR; break;
1046
case nssTrustLevel_Trusted: t = CKT_NSS_TRUSTED; break;
1047
case nssTrustLevel_MustVerify: t = CKT_NSS_MUST_VERIFY_TRUST; break;
1048
case nssTrustLevel_Unknown:
1049
default: t = CKT_NSS_TRUST_UNKNOWN; break;
1054
NSS_IMPLEMENT nssCryptokiObject *
1055
nssToken_ImportTrust (
1057
nssSession *sessionOpt,
1058
NSSDER *certEncoding,
1061
nssTrustLevel serverAuth,
1062
nssTrustLevel clientAuth,
1063
nssTrustLevel codeSigning,
1064
nssTrustLevel emailProtection,
1065
PRBool stepUpApproved,
1066
PRBool asTokenObject
1069
nssCryptokiObject *object;
1070
CK_OBJECT_CLASS tobjc = CKO_NSS_TRUST;
1071
CK_TRUST ckSA, ckCA, ckCS, ckEP;
1072
CK_ATTRIBUTE_PTR attr;
1073
CK_ATTRIBUTE trust_tmpl[11];
1075
PRUint8 sha1[20]; /* this is cheating... */
1077
NSSItem sha1_result, md5_result;
1078
sha1_result.data = sha1; sha1_result.size = sizeof sha1;
1079
md5_result.data = md5; md5_result.size = sizeof md5;
1080
sha1_hash(certEncoding, &sha1_result);
1081
md5_hash(certEncoding, &md5_result);
1082
ckSA = get_ck_trust(serverAuth);
1083
ckCA = get_ck_trust(clientAuth);
1084
ckCS = get_ck_trust(codeSigning);
1085
ckEP = get_ck_trust(emailProtection);
1086
NSS_CK_TEMPLATE_START(trust_tmpl, attr, tsize);
1087
if (asTokenObject) {
1088
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1090
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1092
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc);
1093
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer);
1094
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, certSerial);
1095
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result);
1096
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_MD5_HASH, &md5_result);
1097
/* now set the trust values */
1098
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, ckSA);
1099
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, ckCA);
1100
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, ckCS);
1101
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, ckEP);
1102
if (stepUpApproved) {
1103
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TRUST_STEP_UP_APPROVED,
1106
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TRUST_STEP_UP_APPROVED,
1109
NSS_CK_TEMPLATE_FINISH(trust_tmpl, attr, tsize);
1110
/* import the trust object onto the token */
1111
object = import_object(tok, sessionOpt, trust_tmpl, tsize);
1112
if (object && tok->cache) {
1113
nssTokenObjectCache_ImportObject(tok->cache, object, tobjc,
1119
NSS_IMPLEMENT nssCryptokiObject *
1120
nssToken_FindTrustForCertificate (
1122
nssSession *sessionOpt,
1123
NSSDER *certEncoding,
1126
nssTokenSearchType searchType
1129
CK_OBJECT_CLASS tobjc = CKO_NSS_TRUST;
1130
CK_ATTRIBUTE_PTR attr;
1131
CK_ATTRIBUTE tobj_template[5];
1133
nssSession *session = sessionOpt ? sessionOpt : token->defaultSession;
1134
nssCryptokiObject *object = NULL, **objects;
1136
/* Don't ask the module to use an invalid session handle. */
1137
if (!session || session->handle == CK_INVALID_SESSION) {
1138
PORT_SetError(SEC_ERROR_NO_TOKEN);
1142
NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size);
1143
if (searchType == nssTokenSearchType_TokenOnly) {
1144
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1146
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc);
1147
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer);
1148
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER , certSerial);
1149
NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size);
1150
objects = find_objects_by_template(token, session,
1151
tobj_template, tobj_size,
1154
object = objects[0];
1155
nss_ZFreeIf(objects);
1160
NSS_IMPLEMENT nssCryptokiObject *
1161
nssToken_ImportCRL (
1163
nssSession *sessionOpt,
1168
PRBool asTokenObject
1171
nssCryptokiObject *object;
1172
CK_OBJECT_CLASS crlobjc = CKO_NSS_CRL;
1173
CK_ATTRIBUTE_PTR attr;
1174
CK_ATTRIBUTE crl_tmpl[6];
1177
NSS_CK_TEMPLATE_START(crl_tmpl, attr, crlsize);
1178
if (asTokenObject) {
1179
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1181
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1183
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc);
1184
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
1185
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding);
1186
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_URL, url);
1188
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NSS_KRL, &g_ck_true);
1190
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NSS_KRL, &g_ck_false);
1192
NSS_CK_TEMPLATE_FINISH(crl_tmpl, attr, crlsize);
1194
/* import the crl object onto the token */
1195
object = import_object(token, sessionOpt, crl_tmpl, crlsize);
1196
if (object && token->cache) {
1197
nssTokenObjectCache_ImportObject(token->cache, object, crlobjc,
1203
NSS_IMPLEMENT nssCryptokiObject **
1204
nssToken_FindCRLsBySubject (
1206
nssSession *sessionOpt,
1208
nssTokenSearchType searchType,
1209
PRUint32 maximumOpt,
1213
CK_OBJECT_CLASS crlobjc = CKO_NSS_CRL;
1214
CK_ATTRIBUTE_PTR attr;
1215
CK_ATTRIBUTE crlobj_template[3];
1216
CK_ULONG crlobj_size;
1217
nssCryptokiObject **objects = NULL;
1218
nssSession *session = sessionOpt ? sessionOpt : token->defaultSession;
1220
/* Don't ask the module to use an invalid session handle. */
1221
if (!session || session->handle == CK_INVALID_SESSION) {
1222
PORT_SetError(SEC_ERROR_NO_TOKEN);
1226
NSS_CK_TEMPLATE_START(crlobj_template, attr, crlobj_size);
1227
if (searchType == nssTokenSearchType_SessionOnly) {
1228
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1229
} else if (searchType == nssTokenSearchType_TokenOnly ||
1230
searchType == nssTokenSearchType_TokenForced) {
1231
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1233
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc);
1234
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
1235
NSS_CK_TEMPLATE_FINISH(crlobj_template, attr, crlobj_size);
1237
objects = find_objects_by_template(token, session,
1238
crlobj_template, crlobj_size,
1239
maximumOpt, statusOpt);
1243
NSS_IMPLEMENT PRStatus
1244
nssToken_GetCachedObjectAttributes (
1247
nssCryptokiObject *object,
1248
CK_OBJECT_CLASS objclass,
1249
CK_ATTRIBUTE_PTR atemplate,
1253
if (!token->cache) {
1256
return nssTokenObjectCache_GetObjectAttributes(token->cache, arenaOpt,
1261
NSS_IMPLEMENT NSSItem *
1264
nssSession *sessionOpt,
1265
NSSAlgorithmAndParameters *ap,
1274
NSSItem *rvItem = NULL;
1275
void *epv = nssToken_GetCryptokiEPV(tok);
1276
nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
1278
/* Don't ask the module to use an invalid session handle. */
1279
if (!session || session->handle == CK_INVALID_SESSION) {
1280
PORT_SetError(SEC_ERROR_NO_TOKEN);
1284
nssSession_EnterMonitor(session);
1285
ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism);
1286
if (ckrv != CKR_OK) {
1287
nssSession_ExitMonitor(session);
1291
/* XXX the standard says this should work, but it doesn't */
1292
ckrv = CKAPI(epv)->C_Digest(session->handle, NULL, 0, NULL, &digestLen);
1293
if (ckrv != CKR_OK) {
1294
nssSession_ExitMonitor(session);
1298
digestLen = 0; /* XXX for now */
1301
if (rvOpt->size > 0 && rvOpt->size < digestLen) {
1302
nssSession_ExitMonitor(session);
1303
/* the error should be bad args */
1307
digest = rvOpt->data;
1309
digestLen = rvOpt->size;
1312
digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen);
1314
nssSession_ExitMonitor(session);
1318
ckrv = CKAPI(epv)->C_Digest(session->handle,
1319
(CK_BYTE_PTR)data->data,
1320
(CK_ULONG)data->size,
1321
(CK_BYTE_PTR)digest,
1323
nssSession_ExitMonitor(session);
1324
if (ckrv != CKR_OK) {
1325
nss_ZFreeIf(digest);
1329
rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
1334
NSS_IMPLEMENT PRStatus
1335
nssToken_BeginDigest (
1337
nssSession *sessionOpt,
1338
NSSAlgorithmAndParameters *ap
1342
void *epv = nssToken_GetCryptokiEPV(tok);
1343
nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
1345
/* Don't ask the module to use an invalid session handle. */
1346
if (!session || session->handle == CK_INVALID_SESSION) {
1347
PORT_SetError(SEC_ERROR_NO_TOKEN);
1351
nssSession_EnterMonitor(session);
1352
ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism);
1353
nssSession_ExitMonitor(session);
1354
return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
1357
NSS_IMPLEMENT PRStatus
1358
nssToken_ContinueDigest (
1360
nssSession *sessionOpt,
1365
void *epv = nssToken_GetCryptokiEPV(tok);
1366
nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
1368
/* Don't ask the module to use an invalid session handle. */
1369
if (!session || session->handle == CK_INVALID_SESSION) {
1370
PORT_SetError(SEC_ERROR_NO_TOKEN);
1374
nssSession_EnterMonitor(session);
1375
ckrv = CKAPI(epv)->C_DigestUpdate(session->handle,
1376
(CK_BYTE_PTR)item->data,
1377
(CK_ULONG)item->size);
1378
nssSession_ExitMonitor(session);
1379
return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
1382
NSS_IMPLEMENT NSSItem *
1383
nssToken_FinishDigest (
1385
nssSession *sessionOpt,
1393
NSSItem *rvItem = NULL;
1394
void *epv = nssToken_GetCryptokiEPV(tok);
1395
nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
1397
/* Don't ask the module to use an invalid session handle. */
1398
if (!session || session->handle == CK_INVALID_SESSION) {
1399
PORT_SetError(SEC_ERROR_NO_TOKEN);
1403
nssSession_EnterMonitor(session);
1404
ckrv = CKAPI(epv)->C_DigestFinal(session->handle, NULL, &digestLen);
1405
if (ckrv != CKR_OK || digestLen == 0) {
1406
nssSession_ExitMonitor(session);
1411
if (rvOpt->size > 0 && rvOpt->size < digestLen) {
1412
nssSession_ExitMonitor(session);
1413
/* the error should be bad args */
1417
digest = rvOpt->data;
1419
digestLen = rvOpt->size;
1422
digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen);
1424
nssSession_ExitMonitor(session);
1428
ckrv = CKAPI(epv)->C_DigestFinal(session->handle, digest, &digestLen);
1429
nssSession_ExitMonitor(session);
1430
if (ckrv != CKR_OK) {
1431
nss_ZFreeIf(digest);
1435
rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
1440
NSS_IMPLEMENT PRBool
1441
nssToken_IsPresent (
1445
return nssSlot_IsTokenPresent(token->slot);
1448
/* Sigh. The methods to find objects declared above cause problems with
1449
* the low-level object cache in the softoken -- the objects are found in
1450
* toto, then one wave of GetAttributes is done, then another. Having a
1451
* large number of objects causes the cache to be thrashed, as the objects
1452
* are gone before there's any chance to ask for their attributes.
1453
* So, for now, bringing back traversal methods for certs. This way all of
1454
* the cert's attributes can be grabbed immediately after finding it,
1455
* increasing the likelihood that the cache takes care of it.
1457
NSS_IMPLEMENT PRStatus
1458
nssToken_TraverseCertificates (
1460
nssSession *sessionOpt,
1461
nssTokenSearchType searchType,
1462
PRStatus (* callback)(nssCryptokiObject *instance, void *arg),
1468
CK_OBJECT_HANDLE *objectHandles;
1469
CK_ATTRIBUTE_PTR attr;
1470
CK_ATTRIBUTE cert_template[2];
1474
PRUint32 arraySize, numHandles;
1475
nssCryptokiObject **objects;
1476
void *epv = nssToken_GetCryptokiEPV(token);
1477
nssSession *session = (sessionOpt) ? sessionOpt : token->defaultSession;
1479
/* Don't ask the module to use an invalid session handle. */
1480
if (!session || session->handle == CK_INVALID_SESSION) {
1481
PORT_SetError(SEC_ERROR_NO_TOKEN);
1485
/* template for all certs */
1486
NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
1487
if (searchType == nssTokenSearchType_SessionOnly) {
1488
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1489
} else if (searchType == nssTokenSearchType_TokenOnly ||
1490
searchType == nssTokenSearchType_TokenForced) {
1491
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1493
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
1494
NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);
1496
/* the arena is only for the array of object handles */
1497
arena = nssArena_Create();
1501
arraySize = OBJECT_STACK_SIZE;
1503
objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize);
1504
if (!objectHandles) {
1507
nssSession_EnterMonitor(session); /* ==== session lock === */
1508
/* Initialize the find with the template */
1509
ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle,
1510
cert_template, ctsize);
1511
if (ckrv != CKR_OK) {
1512
nssSession_ExitMonitor(session);
1516
/* Issue the find for up to arraySize - numHandles objects */
1517
ckrv = CKAPI(epv)->C_FindObjects(session->handle,
1518
objectHandles + numHandles,
1519
arraySize - numHandles,
1521
if (ckrv != CKR_OK) {
1522
nssSession_ExitMonitor(session);
1525
/* bump the number of found objects */
1526
numHandles += count;
1527
if (numHandles < arraySize) {
1530
/* the array is filled, double it and continue */
1532
objectHandles = nss_ZREALLOCARRAY(objectHandles,
1535
if (!objectHandles) {
1536
nssSession_ExitMonitor(session);
1540
ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle);
1541
nssSession_ExitMonitor(session); /* ==== end session lock === */
1542
if (ckrv != CKR_OK) {
1545
if (numHandles > 0) {
1546
objects = create_objects_from_handles(token, session,
1547
objectHandles, numHandles);
1549
nssCryptokiObject **op;
1550
for (op = objects; *op; op++) {
1551
status = (*callback)(*op, arg);
1553
nss_ZFreeIf(objects);
1556
nssArena_Destroy(arena);
1559
nssArena_Destroy(arena);
1563
NSS_IMPLEMENT PRBool
1564
nssToken_IsPrivateKeyAvailable (
1567
nssCryptokiObject *instance
1570
CK_OBJECT_CLASS theClass;
1572
if (token == NULL) return PR_FALSE;
1573
if (c == NULL) return PR_FALSE;
1575
theClass = CKO_PRIVATE_KEY;
1576
if (!nssSlot_IsLoggedIn(token->slot)) {
1577
theClass = CKO_PUBLIC_KEY;
1579
if (PK11_MatchItem(token->pk11slot, instance->handle, theClass)
1580
!= CK_INVALID_HANDLE) {