1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1994-2000
19
* the Initial Developer. All Rights Reserved.
23
* Alternatively, the contents of this file may be used under the terms of
24
* either the GNU General Public License Version 2 or later (the "GPL"), or
25
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26
* in which case the provisions of the GPL or the LGPL are applicable instead
27
* of those above. If you wish to allow use of your version of this file only
28
* under the terms of either the GPL or the LGPL, and not to allow others to
29
* use your version of this file under the terms of the MPL, indicate your
30
* decision by deleting the provisions above and replace them with the notice
31
* and other provisions required by the GPL or the LGPL. If you do not delete
32
* the provisions above, a recipient may use your version of this file under
33
* the terms of any one of the MPL, the GPL or the LGPL.
35
* ***** END LICENSE BLOCK ***** */
38
static const char CVS_ID[] = "@(#) $RCSfile: devtoken.c,v $ $Revision: 1.39 $ $Date: 2005/01/20 02:25:47 $";
43
#endif /* NSSCKEPV_H */
51
#endif /* CKHELPER_H */
59
extern const NSSError NSS_ERROR_NOT_FOUND;
61
/* The number of object handles to grab during each call to C_FindObjects */
62
#define OBJECT_STACK_SIZE 16
64
#ifdef PURE_STAN_BUILD
67
struct nssDeviceBaseStr base;
68
NSSSlot *slot; /* Peer */
69
CK_FLAGS ckFlags; /* from CK_TOKEN_INFO.flags */
70
nssSession *defaultSession;
71
nssTokenObjectCache *cache;
74
NSS_IMPLEMENT NSSToken *
82
nssSession *session = NULL;
83
NSSUTF8 *tokenName = NULL;
86
CK_TOKEN_INFO tokenInfo;
88
void *epv = nssSlot_GetCryptokiEPV(peer);
89
arena = NSSArena_Create();
91
return (NSSToken *)NULL;
93
rvToken = nss_ZNEW(arena, NSSToken);
97
/* Get token information */
98
ckrv = CKAPI(epv)->C_GetTokenInfo(slotID, &tokenInfo);
100
/* set an error here, eh? */
103
/* Grab the slot description from the PKCS#11 fixed-length buffer */
104
length = nssPKCS11String_Length(tokenInfo.label, sizeof(tokenInfo.label));
106
tokenName = nssUTF8_Create(arena, nssStringType_UTF8String,
107
(void *)tokenInfo.label, length);
112
/* Open a default session handle for the token. */
113
if (tokenInfo.ulMaxSessionCount == 1) {
114
/* if the token can only handle one session, it must be RW. */
117
readWrite = PR_FALSE;
119
session = nssSlot_CreateSession(peer, arena, readWrite);
120
if (session == NULL) {
123
/* TODO: seed the RNG here */
124
rvToken->base.arena = arena;
125
rvToken->base.refCount = 1;
126
rvToken->base.name = tokenName;
127
rvToken->base.lock = PZ_NewLock(nssNSSILockOther); /* XXX */
128
if (!rvToken->base.lock) {
131
rvToken->slot = peer; /* slot owns ref to token */
132
rvToken->ckFlags = tokenInfo.flags;
133
rvToken->defaultSession = session;
134
if (nssSlot_IsHardware(peer)) {
135
rvToken->cache = nssTokenObjectCache_Create(rvToken,
136
PR_TRUE, PR_TRUE, PR_TRUE);
137
if (!rvToken->cache) {
138
nssSlot_Destroy(peer);
145
nssSession_Destroy(session);
147
nssArena_Destroy(arena);
148
return (NSSToken *)NULL;
150
#endif /* PURE_STAN_BUILD */
152
NSS_IMPLEMENT PRStatus
158
if (PR_AtomicDecrement(&tok->base.refCount) == 0) {
159
PZ_DestroyLock(tok->base.lock);
160
nssTokenObjectCache_Destroy(tok->cache);
161
return nssArena_Destroy(tok->base.arena);
172
nssTokenObjectCache_Clear(tok->cache);
180
(void)nssToken_Destroy(tok);
183
NSS_IMPLEMENT NSSToken *
188
PR_AtomicIncrement(&tok->base.refCount);
192
NSS_IMPLEMENT NSSSlot *
197
return nssSlot_AddRef(tok->slot);
200
#ifdef PURE_STAN_BUILD
201
NSS_IMPLEMENT NSSModule *
206
return nssSlot_GetModule(token->slot);
211
nssToken_GetCryptokiEPV (
215
return nssSlot_GetCryptokiEPV(token->slot);
218
NSS_IMPLEMENT nssSession *
219
nssToken_GetDefaultSession (
223
return token->defaultSession;
226
NSS_IMPLEMENT NSSUTF8 *
234
if (tok->base.name[0] == 0) {
235
(void) nssSlot_IsTokenPresent(tok->slot);
237
return tok->base.name;
240
NSS_IMPLEMENT NSSUTF8 *
245
return nssToken_GetName(token);
249
nssToken_IsLoginRequired (
253
return (token->ckFlags & CKF_LOGIN_REQUIRED);
257
nssToken_NeedsPINInitialization (
261
return (!(token->ckFlags & CKF_USER_PIN_INITIALIZED));
264
NSS_IMPLEMENT PRStatus
265
nssToken_DeleteStoredObject (
266
nssCryptokiObject *instance
271
PRBool createdSession = PR_FALSE;
272
NSSToken *token = instance->token;
273
nssSession *session = NULL;
274
void *epv = nssToken_GetCryptokiEPV(instance->token);
276
nssTokenObjectCache_RemoveObject(token->cache, instance);
278
if (instance->isTokenObject) {
279
if (nssSession_IsReadWrite(token->defaultSession)) {
280
session = token->defaultSession;
282
session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE);
283
createdSession = PR_TRUE;
286
if (session == NULL) {
289
nssSession_EnterMonitor(session);
290
ckrv = CKAPI(epv)->C_DestroyObject(session->handle, instance->handle);
291
nssSession_ExitMonitor(session);
292
if (createdSession) {
293
nssSession_Destroy(session);
295
status = (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
299
static nssCryptokiObject *
302
nssSession *sessionOpt,
303
CK_ATTRIBUTE_PTR objectTemplate,
307
nssSession *session = NULL;
308
PRBool createdSession = PR_FALSE;
309
nssCryptokiObject *object = NULL;
310
CK_OBJECT_HANDLE handle;
312
void *epv = nssToken_GetCryptokiEPV(tok);
313
if (nssCKObject_IsTokenObjectTemplate(objectTemplate, otsize)) {
315
if (!nssSession_IsReadWrite(sessionOpt)) {
316
return CK_INVALID_HANDLE;
318
session = sessionOpt;
320
} else if (nssSession_IsReadWrite(tok->defaultSession)) {
321
session = tok->defaultSession;
323
session = nssSlot_CreateSession(tok->slot, NULL, PR_TRUE);
324
createdSession = PR_TRUE;
327
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
329
if (session == NULL) {
330
return CK_INVALID_HANDLE;
332
nssSession_EnterMonitor(session);
333
ckrv = CKAPI(epv)->C_CreateObject(session->handle,
334
objectTemplate, otsize,
336
nssSession_ExitMonitor(session);
337
if (ckrv == CKR_OK) {
338
object = nssCryptokiObject_Create(tok, session, handle);
340
if (createdSession) {
341
nssSession_Destroy(session);
346
static nssCryptokiObject **
347
create_objects_from_handles (
350
CK_OBJECT_HANDLE *handles,
354
nssCryptokiObject **objects;
355
objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numH + 1);
358
for (i=0; i<(PRInt32)numH; i++) {
359
objects[i] = nssCryptokiObject_Create(tok, session, handles[i]);
361
for (--i; i>0; --i) {
362
nssCryptokiObject_Destroy(objects[i]);
364
return (nssCryptokiObject **)NULL;
371
static nssCryptokiObject **
374
nssSession *sessionOpt,
375
CK_ATTRIBUTE_PTR obj_template,
383
CK_OBJECT_HANDLE *objectHandles;
384
CK_OBJECT_HANDLE staticObjects[OBJECT_STACK_SIZE];
385
PRUint32 arraySize, numHandles;
386
void *epv = nssToken_GetCryptokiEPV(tok);
387
nssCryptokiObject **objects;
388
nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
390
/* the arena is only for the array of object handles */
391
if (maximumOpt > 0) {
392
arraySize = maximumOpt;
394
arraySize = OBJECT_STACK_SIZE;
397
if (arraySize <= OBJECT_STACK_SIZE) {
398
objectHandles = staticObjects;
400
objectHandles = nss_ZNEWARRAY(NULL, CK_OBJECT_HANDLE, arraySize);
402
if (!objectHandles) {
403
ckrv = CKR_HOST_MEMORY;
406
nssSession_EnterMonitor(session); /* ==== session lock === */
407
/* Initialize the find with the template */
408
ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle,
409
obj_template, otsize);
410
if (ckrv != CKR_OK) {
411
nssSession_ExitMonitor(session);
415
/* Issue the find for up to arraySize - numHandles objects */
416
ckrv = CKAPI(epv)->C_FindObjects(session->handle,
417
objectHandles + numHandles,
418
arraySize - numHandles,
420
if (ckrv != CKR_OK) {
421
nssSession_ExitMonitor(session);
424
/* bump the number of found objects */
426
if (maximumOpt > 0 || numHandles < arraySize) {
427
/* When a maximum is provided, the search is done all at once,
428
* so the search is finished. If the number returned was less
429
* than the number sought, the search is finished.
433
/* the array is filled, double it and continue */
435
if (objectHandles == staticObjects) {
436
objectHandles = nss_ZNEWARRAY(NULL,CK_OBJECT_HANDLE, arraySize);
438
PORT_Memcpy(objectHandles, staticObjects,
439
OBJECT_STACK_SIZE * sizeof(objectHandles[1]));
442
objectHandles = nss_ZREALLOCARRAY(objectHandles,
446
if (!objectHandles) {
447
nssSession_ExitMonitor(session);
448
ckrv = CKR_HOST_MEMORY;
452
ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle);
453
nssSession_ExitMonitor(session); /* ==== end session lock === */
454
if (ckrv != CKR_OK) {
457
if (numHandles > 0) {
458
objects = create_objects_from_handles(tok, session,
459
objectHandles, numHandles);
461
nss_SetError(NSS_ERROR_NOT_FOUND);
464
if (objectHandles && objectHandles != staticObjects) {
465
nss_ZFreeIf(objectHandles);
467
if (statusOpt) *statusOpt = PR_SUCCESS;
470
if (objectHandles && objectHandles != staticObjects) {
471
nss_ZFreeIf(objectHandles);
474
* These errors should be treated the same as if the objects just weren't
477
if ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) ||
478
(ckrv == CKR_ATTRIBUTE_VALUE_INVALID) ||
479
(ckrv == CKR_DATA_INVALID) ||
480
(ckrv == CKR_DATA_LEN_RANGE) ||
481
(ckrv == CKR_FUNCTION_NOT_SUPPORTED) ||
482
(ckrv == CKR_TEMPLATE_INCOMPLETE) ||
483
(ckrv == CKR_TEMPLATE_INCONSISTENT)) {
485
nss_SetError(NSS_ERROR_NOT_FOUND);
486
if (statusOpt) *statusOpt = PR_SUCCESS;
488
if (statusOpt) *statusOpt = PR_FAILURE;
490
return (nssCryptokiObject **)NULL;
493
static nssCryptokiObject **
494
find_objects_by_template (
496
nssSession *sessionOpt,
497
CK_ATTRIBUTE_PTR obj_template,
503
CK_OBJECT_CLASS objclass = (CK_OBJECT_CLASS)-1;
504
nssCryptokiObject **objects = NULL;
506
for (i=0; i<otsize; i++) {
507
if (obj_template[i].type == CKA_CLASS) {
508
objclass = *(CK_OBJECT_CLASS *)obj_template[i].pValue;
512
PR_ASSERT(i < otsize);
515
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
517
if (statusOpt) *statusOpt = PR_FAILURE;
520
/* If these objects are being cached, try looking there first */
522
nssTokenObjectCache_HaveObjectClass(token->cache, objclass))
525
objects = nssTokenObjectCache_FindObjectsByTemplate(token->cache,
531
if (status == PR_SUCCESS) {
532
if (statusOpt) *statusOpt = status;
536
/* Either they are not cached, or cache failed; look on token. */
537
objects = find_objects(token, sessionOpt,
538
obj_template, otsize,
539
maximumOpt, statusOpt);
543
extern const NSSError NSS_ERROR_INVALID_CERTIFICATE;
545
NSS_IMPLEMENT nssCryptokiObject *
546
nssToken_ImportCertificate (
548
nssSession *sessionOpt,
549
NSSCertificateType certType,
561
CK_CERTIFICATE_TYPE cert_type;
562
CK_ATTRIBUTE_PTR attr;
563
CK_ATTRIBUTE cert_tmpl[10];
565
nssTokenSearchType searchType;
566
nssCryptokiObject *rvObject = NULL;
568
if (certType == NSSCertificateType_PKIX) {
569
cert_type = CKC_X_509;
571
return (nssCryptokiObject *)NULL;
573
NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize);
575
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
576
searchType = nssTokenSearchType_TokenOnly;
578
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
579
searchType = nssTokenSearchType_SessionOnly;
581
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
582
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CERTIFICATE_TYPE, cert_type);
583
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
584
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
585
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding);
586
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer);
587
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
588
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial);
590
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NETSCAPE_EMAIL, email);
592
NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize);
593
/* see if the cert is already there */
594
rvObject = nssToken_FindCertificateByIssuerAndSerialNumber(tok,
602
NSSSlot *slot = nssToken_GetSlot(tok);
603
nssSession *session = nssSlot_CreateSession(slot, NULL, PR_TRUE);
605
nssCryptokiObject_Destroy(rvObject);
606
nssSlot_Destroy(slot);
607
return (nssCryptokiObject *)NULL;
609
/* Reject any attempt to import a new cert that has the same
610
* issuer/serial as an existing cert, but does not have the
613
NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize);
614
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
615
NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize);
616
status = nssCKObject_GetAttributes(rvObject->handle,
617
cert_tmpl, ctsize, NULL,
619
NSS_CK_ATTRIBUTE_TO_ITEM(cert_tmpl, &existingDER);
620
if (status == PR_SUCCESS) {
621
if (!nssItem_Equal(encoding, &existingDER, NULL)) {
622
nss_SetError(NSS_ERROR_INVALID_CERTIFICATE);
625
nss_ZFreeIf(existingDER.data);
627
if (status == PR_FAILURE) {
628
nssCryptokiObject_Destroy(rvObject);
629
nssSession_Destroy(session);
630
nssSlot_Destroy(slot);
631
return (nssCryptokiObject *)NULL;
633
/* according to PKCS#11, label, ID, issuer, and serial number
634
* may change after the object has been created. For PKIX, the
635
* last two attributes can't change, so for now we'll only worry
636
* about the first two.
638
NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize);
639
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
640
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
641
NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize);
642
/* reset the mutable attributes on the token */
643
nssCKObject_SetAttributes(rvObject->handle,
646
if (!rvObject->label && nickname) {
647
rvObject->label = nssUTF8_Duplicate(nickname, NULL);
649
nssSession_Destroy(session);
650
nssSlot_Destroy(slot);
652
/* Import the certificate onto the token */
653
rvObject = import_object(tok, sessionOpt, cert_tmpl, ctsize);
655
if (rvObject && tok->cache) {
656
/* The cache will overwrite the attributes if the object already
659
nssTokenObjectCache_ImportObject(tok->cache, rvObject,
666
/* traverse all certificates - this should only happen if the token
667
* has been marked as "traversable"
669
NSS_IMPLEMENT nssCryptokiObject **
670
nssToken_FindCertificates (
672
nssSession *sessionOpt,
673
nssTokenSearchType searchType,
678
CK_ATTRIBUTE_PTR attr;
679
CK_ATTRIBUTE cert_template[2];
681
nssCryptokiObject **objects;
682
NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
683
/* Set the search to token/session only if provided */
684
if (searchType == nssTokenSearchType_SessionOnly) {
685
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
686
} else if (searchType == nssTokenSearchType_TokenOnly ||
687
searchType == nssTokenSearchType_TokenForced) {
688
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
690
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
691
NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);
693
if (searchType == nssTokenSearchType_TokenForced) {
694
objects = find_objects(token, sessionOpt,
695
cert_template, ctsize,
696
maximumOpt, statusOpt);
698
objects = find_objects_by_template(token, sessionOpt,
699
cert_template, ctsize,
700
maximumOpt, statusOpt);
705
NSS_IMPLEMENT nssCryptokiObject **
706
nssToken_FindCertificatesBySubject (
708
nssSession *sessionOpt,
710
nssTokenSearchType searchType,
715
CK_ATTRIBUTE_PTR attr;
716
CK_ATTRIBUTE subj_template[3];
718
nssCryptokiObject **objects;
719
NSS_CK_TEMPLATE_START(subj_template, attr, stsize);
720
/* Set the search to token/session only if provided */
721
if (searchType == nssTokenSearchType_SessionOnly) {
722
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
723
} else if (searchType == nssTokenSearchType_TokenOnly) {
724
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
726
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
727
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
728
NSS_CK_TEMPLATE_FINISH(subj_template, attr, stsize);
729
/* now locate the token certs matching this template */
730
objects = find_objects_by_template(token, sessionOpt,
731
subj_template, stsize,
732
maximumOpt, statusOpt);
736
NSS_IMPLEMENT nssCryptokiObject **
737
nssToken_FindCertificatesByNickname (
739
nssSession *sessionOpt,
741
nssTokenSearchType searchType,
746
CK_ATTRIBUTE_PTR attr;
747
CK_ATTRIBUTE nick_template[3];
749
nssCryptokiObject **objects;
750
NSS_CK_TEMPLATE_START(nick_template, attr, ntsize);
751
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, name);
752
/* Set the search to token/session only if provided */
753
if (searchType == nssTokenSearchType_SessionOnly) {
754
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
755
} else if (searchType == nssTokenSearchType_TokenOnly) {
756
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
758
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
759
NSS_CK_TEMPLATE_FINISH(nick_template, attr, ntsize);
760
/* now locate the token certs matching this template */
761
objects = find_objects_by_template(token, sessionOpt,
762
nick_template, ntsize,
763
maximumOpt, statusOpt);
765
/* This is to workaround the fact that PKCS#11 doesn't specify
766
* whether the '\0' should be included. XXX Is that still true?
767
* im - this is not needed by the current softoken. However, I'm
768
* leaving it in until I have surveyed more tokens to see if it needed.
769
* well, its needed by the builtin token...
771
nick_template[0].ulValueLen++;
772
objects = find_objects_by_template(token, sessionOpt,
773
nick_template, ntsize,
774
maximumOpt, statusOpt);
780
* This function *does not* use the token object cache, because not even
781
* the softoken will return a value for CKA_NETSCAPE_EMAIL from a call
782
* to GetAttributes. The softoken does allow searches with that attribute,
783
* it just won't return a value for it.
785
NSS_IMPLEMENT nssCryptokiObject **
786
nssToken_FindCertificatesByEmail (
788
nssSession *sessionOpt,
790
nssTokenSearchType searchType,
795
CK_ATTRIBUTE_PTR attr;
796
CK_ATTRIBUTE email_template[3];
798
nssCryptokiObject **objects;
799
NSS_CK_TEMPLATE_START(email_template, attr, etsize);
800
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NETSCAPE_EMAIL, email);
801
/* Set the search to token/session only if provided */
802
if (searchType == nssTokenSearchType_SessionOnly) {
803
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
804
} else if (searchType == nssTokenSearchType_TokenOnly) {
805
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
807
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
808
NSS_CK_TEMPLATE_FINISH(email_template, attr, etsize);
809
/* now locate the token certs matching this template */
810
objects = find_objects(token, sessionOpt,
811
email_template, etsize,
812
maximumOpt, statusOpt);
814
/* This is to workaround the fact that PKCS#11 doesn't specify
815
* whether the '\0' should be included. XXX Is that still true?
816
* im - this is not needed by the current softoken. However, I'm
817
* leaving it in until I have surveyed more tokens to see if it needed.
818
* well, its needed by the builtin token...
820
email_template[0].ulValueLen++;
821
objects = find_objects(token, sessionOpt,
822
email_template, etsize,
823
maximumOpt, statusOpt);
828
NSS_IMPLEMENT nssCryptokiObject **
829
nssToken_FindCertificatesByID (
831
nssSession *sessionOpt,
833
nssTokenSearchType searchType,
838
CK_ATTRIBUTE_PTR attr;
839
CK_ATTRIBUTE id_template[3];
841
nssCryptokiObject **objects;
842
NSS_CK_TEMPLATE_START(id_template, attr, idtsize);
843
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
844
/* Set the search to token/session only if provided */
845
if (searchType == nssTokenSearchType_SessionOnly) {
846
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
847
} else if (searchType == nssTokenSearchType_TokenOnly) {
848
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
850
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
851
NSS_CK_TEMPLATE_FINISH(id_template, attr, idtsize);
852
/* now locate the token certs matching this template */
853
objects = find_objects_by_template(token, sessionOpt,
854
id_template, idtsize,
855
maximumOpt, statusOpt);
860
* decode the serial item and return our result.
861
* NOTE serialDecode's data is really stored in serial. Don't free it.
864
nssToken_decodeSerialItem(NSSItem *serial, NSSItem *serialDecode)
866
unsigned char *data = (unsigned char *)serial->data;
867
int data_left, data_len, index;
869
if ((serial->size >= 3) && (data[0] == 0x2)) {
870
/* remove the der encoding of the serial number before generating the
872
data_left = serial->size-2;
876
/* extended length ? (not very likely for a serial number) */
877
if (data_len & 0x80) {
878
int len_count = data_len & 0x7f;
881
data_left -= len_count;
883
while (len_count --) {
884
data_len = (data_len << 8) | data[index++];
888
/* XXX leaving any leading zeros on the serial number for backwards
891
/* not a valid der, must be just an unlucky serial number value */
892
if (data_len == data_left) {
893
serialDecode->size = data_len;
894
serialDecode->data = &data[index];
901
NSS_IMPLEMENT nssCryptokiObject *
902
nssToken_FindCertificateByIssuerAndSerialNumber (
904
nssSession *sessionOpt,
907
nssTokenSearchType searchType,
911
CK_ATTRIBUTE_PTR attr;
912
CK_ATTRIBUTE_PTR serialAttr;
913
CK_ATTRIBUTE cert_template[4];
915
nssCryptokiObject **objects;
916
nssCryptokiObject *rvObject = NULL;
917
NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
918
/* Set the search to token/session only if provided */
919
if (searchType == nssTokenSearchType_SessionOnly) {
920
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
921
} else if ((searchType == nssTokenSearchType_TokenOnly) ||
922
(searchType == nssTokenSearchType_TokenForced)) {
923
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
925
/* Set the unique id */
926
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
927
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer);
929
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial);
930
NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);
931
/* get the object handle */
932
if (searchType == nssTokenSearchType_TokenForced) {
933
objects = find_objects(token, sessionOpt,
934
cert_template, ctsize,
937
objects = find_objects_by_template(token, sessionOpt,
938
cert_template, ctsize,
942
rvObject = objects[0];
943
nss_ZFreeIf(objects);
947
* NSS used to incorrectly store serial numbers in their decoded form.
948
* because of this old tokens have decoded serial numbers.
951
NSSItem serialDecode;
954
status = nssToken_decodeSerialItem(serial, &serialDecode);
955
if (status != PR_SUCCESS) {
958
NSS_CK_SET_ATTRIBUTE_ITEM(serialAttr,CKA_SERIAL_NUMBER,&serialDecode);
959
if (searchType == nssTokenSearchType_TokenForced) {
960
objects = find_objects(token, sessionOpt,
961
cert_template, ctsize,
964
objects = find_objects_by_template(token, sessionOpt,
965
cert_template, ctsize,
969
rvObject = objects[0];
970
nss_ZFreeIf(objects);
976
NSS_IMPLEMENT nssCryptokiObject *
977
nssToken_FindCertificateByEncodedCertificate (
979
nssSession *sessionOpt,
980
NSSBER *encodedCertificate,
981
nssTokenSearchType searchType,
985
CK_ATTRIBUTE_PTR attr;
986
CK_ATTRIBUTE cert_template[3];
988
nssCryptokiObject **objects;
989
nssCryptokiObject *rvObject = NULL;
990
NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
991
/* Set the search to token/session only if provided */
992
if (searchType == nssTokenSearchType_SessionOnly) {
993
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
994
} else if (searchType == nssTokenSearchType_TokenOnly) {
995
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
997
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
998
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encodedCertificate);
999
NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);
1000
/* get the object handle */
1001
objects = find_objects_by_template(token, sessionOpt,
1002
cert_template, ctsize,
1005
rvObject = objects[0];
1006
nss_ZFreeIf(objects);
1011
NSS_IMPLEMENT nssCryptokiObject **
1012
nssToken_FindPrivateKeys (
1014
nssSession *sessionOpt,
1015
nssTokenSearchType searchType,
1016
PRUint32 maximumOpt,
1020
CK_ATTRIBUTE_PTR attr;
1021
CK_ATTRIBUTE key_template[2];
1023
nssCryptokiObject **objects;
1025
NSS_CK_TEMPLATE_START(key_template, attr, ktsize);
1026
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey);
1027
if (searchType == nssTokenSearchType_SessionOnly) {
1028
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1029
} else if (searchType == nssTokenSearchType_TokenOnly) {
1030
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1032
NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize);
1034
objects = find_objects_by_template(token, sessionOpt,
1035
key_template, ktsize,
1036
maximumOpt, statusOpt);
1040
/* XXX ?there are no session cert objects, so only search token objects */
1041
NSS_IMPLEMENT nssCryptokiObject *
1042
nssToken_FindPrivateKeyByID (
1044
nssSession *sessionOpt,
1048
CK_ATTRIBUTE_PTR attr;
1049
CK_ATTRIBUTE key_template[3];
1051
nssCryptokiObject **objects;
1052
nssCryptokiObject *rvKey = NULL;
1054
NSS_CK_TEMPLATE_START(key_template, attr, ktsize);
1055
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey);
1056
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1057
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID);
1058
NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize);
1060
objects = find_objects_by_template(token, sessionOpt,
1061
key_template, ktsize,
1065
nss_ZFreeIf(objects);
1070
/* XXX ?there are no session cert objects, so only search token objects */
1071
NSS_IMPLEMENT nssCryptokiObject *
1072
nssToken_FindPublicKeyByID (
1074
nssSession *sessionOpt,
1078
CK_ATTRIBUTE_PTR attr;
1079
CK_ATTRIBUTE key_template[3];
1081
nssCryptokiObject **objects;
1082
nssCryptokiObject *rvKey = NULL;
1084
NSS_CK_TEMPLATE_START(key_template, attr, ktsize);
1085
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_pubkey);
1086
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1087
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID);
1088
NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize);
1090
objects = find_objects_by_template(token, sessionOpt,
1091
key_template, ktsize,
1095
nss_ZFreeIf(objects);
1101
sha1_hash(NSSItem *input, NSSItem *output)
1103
NSSAlgorithmAndParameters *ap;
1105
PK11SlotInfo *internal = PK11_GetInternalSlot();
1106
NSSToken *token = PK11Slot_GetNSSToken(internal);
1108
NSSToken *token = nss_GetDefaultCryptoToken();
1110
ap = NSSAlgorithmAndParameters_CreateSHA1Digest(NULL);
1111
(void)nssToken_Digest(token, NULL, ap, input, output, NULL);
1113
PK11_FreeSlot(token->pk11slot);
1119
md5_hash(NSSItem *input, NSSItem *output)
1121
NSSAlgorithmAndParameters *ap;
1123
PK11SlotInfo *internal = PK11_GetInternalSlot();
1124
NSSToken *token = PK11Slot_GetNSSToken(internal);
1126
NSSToken *token = nss_GetDefaultCryptoToken();
1128
ap = NSSAlgorithmAndParameters_CreateMD5Digest(NULL);
1129
(void)nssToken_Digest(token, NULL, ap, input, output, NULL);
1131
PK11_FreeSlot(token->pk11slot);
1138
nssTrustLevel nssTrust
1143
case nssTrustLevel_NotTrusted: t = CKT_NETSCAPE_UNTRUSTED; break;
1144
case nssTrustLevel_TrustedDelegator: t = CKT_NETSCAPE_TRUSTED_DELEGATOR;
1146
case nssTrustLevel_ValidDelegator: t = CKT_NETSCAPE_VALID_DELEGATOR; break;
1147
case nssTrustLevel_Trusted: t = CKT_NETSCAPE_TRUSTED; break;
1148
case nssTrustLevel_Valid: t = CKT_NETSCAPE_VALID; break;
1149
case nssTrustLevel_Unknown:
1150
default: t = CKT_NETSCAPE_TRUST_UNKNOWN; break;
1155
NSS_IMPLEMENT nssCryptokiObject *
1156
nssToken_ImportTrust (
1158
nssSession *sessionOpt,
1159
NSSDER *certEncoding,
1162
nssTrustLevel serverAuth,
1163
nssTrustLevel clientAuth,
1164
nssTrustLevel codeSigning,
1165
nssTrustLevel emailProtection,
1166
PRBool stepUpApproved,
1167
PRBool asTokenObject
1170
nssCryptokiObject *object;
1171
CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
1172
CK_TRUST ckSA, ckCA, ckCS, ckEP;
1173
CK_ATTRIBUTE_PTR attr;
1174
CK_ATTRIBUTE trust_tmpl[11];
1176
PRUint8 sha1[20]; /* this is cheating... */
1178
NSSItem sha1_result, md5_result;
1179
sha1_result.data = sha1; sha1_result.size = sizeof sha1;
1180
md5_result.data = md5; md5_result.size = sizeof md5;
1181
sha1_hash(certEncoding, &sha1_result);
1182
md5_hash(certEncoding, &md5_result);
1183
ckSA = get_ck_trust(serverAuth);
1184
ckCA = get_ck_trust(clientAuth);
1185
ckCS = get_ck_trust(codeSigning);
1186
ckEP = get_ck_trust(emailProtection);
1187
NSS_CK_TEMPLATE_START(trust_tmpl, attr, tsize);
1188
if (asTokenObject) {
1189
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1191
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1193
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc);
1194
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer);
1195
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, certSerial);
1196
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result);
1197
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_MD5_HASH, &md5_result);
1198
/* now set the trust values */
1199
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, ckSA);
1200
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, ckCA);
1201
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, ckCS);
1202
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, ckEP);
1203
if (stepUpApproved) {
1204
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TRUST_STEP_UP_APPROVED,
1207
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TRUST_STEP_UP_APPROVED,
1210
NSS_CK_TEMPLATE_FINISH(trust_tmpl, attr, tsize);
1211
/* import the trust object onto the token */
1212
object = import_object(tok, sessionOpt, trust_tmpl, tsize);
1213
if (object && tok->cache) {
1214
nssTokenObjectCache_ImportObject(tok->cache, object, tobjc,
1220
NSS_IMPLEMENT nssCryptokiObject **
1221
nssToken_FindTrustObjects (
1223
nssSession *sessionOpt,
1224
nssTokenSearchType searchType,
1225
PRUint32 maximumOpt,
1229
CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
1230
CK_ATTRIBUTE_PTR attr;
1231
CK_ATTRIBUTE tobj_template[2];
1233
nssCryptokiObject **objects;
1234
nssSession *session = sessionOpt ? sessionOpt : token->defaultSession;
1236
NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size);
1237
if (searchType == nssTokenSearchType_SessionOnly) {
1238
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1239
} else if (searchType == nssTokenSearchType_TokenOnly ||
1240
searchType == nssTokenSearchType_TokenForced) {
1241
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1243
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc);
1244
NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size);
1246
if (searchType == nssTokenSearchType_TokenForced) {
1247
objects = find_objects(token, session,
1248
tobj_template, tobj_size,
1249
maximumOpt, statusOpt);
1251
objects = find_objects_by_template(token, session,
1252
tobj_template, tobj_size,
1253
maximumOpt, statusOpt);
1258
NSS_IMPLEMENT nssCryptokiObject *
1259
nssToken_FindTrustForCertificate (
1261
nssSession *sessionOpt,
1262
NSSDER *certEncoding,
1265
nssTokenSearchType searchType
1268
CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
1269
CK_ATTRIBUTE_PTR attr;
1270
CK_ATTRIBUTE tobj_template[5];
1272
nssSession *session = sessionOpt ? sessionOpt : token->defaultSession;
1273
nssCryptokiObject *object, **objects;
1275
NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size);
1276
if (searchType == nssTokenSearchType_SessionOnly) {
1277
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1278
} else if (searchType == nssTokenSearchType_TokenOnly) {
1279
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1281
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc);
1282
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer);
1283
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER , certSerial);
1284
NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size);
1286
objects = find_objects_by_template(token, session,
1287
tobj_template, tobj_size,
1290
object = objects[0];
1291
nss_ZFreeIf(objects);
1296
NSS_IMPLEMENT nssCryptokiObject *
1297
nssToken_ImportCRL (
1299
nssSession *sessionOpt,
1304
PRBool asTokenObject
1307
nssCryptokiObject *object;
1308
CK_OBJECT_CLASS crlobjc = CKO_NETSCAPE_CRL;
1309
CK_ATTRIBUTE_PTR attr;
1310
CK_ATTRIBUTE crl_tmpl[6];
1313
NSS_CK_TEMPLATE_START(crl_tmpl, attr, crlsize);
1314
if (asTokenObject) {
1315
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1317
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1319
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc);
1320
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
1321
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding);
1322
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NETSCAPE_URL, url);
1324
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NETSCAPE_KRL, &g_ck_true);
1326
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NETSCAPE_KRL, &g_ck_false);
1328
NSS_CK_TEMPLATE_FINISH(crl_tmpl, attr, crlsize);
1330
/* import the crl object onto the token */
1331
object = import_object(token, sessionOpt, crl_tmpl, crlsize);
1332
if (object && token->cache) {
1333
nssTokenObjectCache_ImportObject(token->cache, object, crlobjc,
1339
NSS_IMPLEMENT nssCryptokiObject **
1342
nssSession *sessionOpt,
1343
nssTokenSearchType searchType,
1344
PRUint32 maximumOpt,
1348
CK_OBJECT_CLASS crlobjc = CKO_NETSCAPE_CRL;
1349
CK_ATTRIBUTE_PTR attr;
1350
CK_ATTRIBUTE crlobj_template[2];
1351
CK_ULONG crlobj_size;
1352
nssCryptokiObject **objects;
1353
nssSession *session = sessionOpt ? sessionOpt : token->defaultSession;
1355
NSS_CK_TEMPLATE_START(crlobj_template, attr, crlobj_size);
1356
if (searchType == nssTokenSearchType_SessionOnly) {
1357
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1358
} else if (searchType == nssTokenSearchType_TokenOnly ||
1359
searchType == nssTokenSearchType_TokenForced) {
1360
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1362
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc);
1363
NSS_CK_TEMPLATE_FINISH(crlobj_template, attr, crlobj_size);
1365
if (searchType == nssTokenSearchType_TokenForced) {
1366
objects = find_objects(token, session,
1367
crlobj_template, crlobj_size,
1368
maximumOpt, statusOpt);
1370
objects = find_objects_by_template(token, session,
1371
crlobj_template, crlobj_size,
1372
maximumOpt, statusOpt);
1377
NSS_IMPLEMENT nssCryptokiObject **
1378
nssToken_FindCRLsBySubject (
1380
nssSession *sessionOpt,
1382
nssTokenSearchType searchType,
1383
PRUint32 maximumOpt,
1387
CK_OBJECT_CLASS crlobjc = CKO_NETSCAPE_CRL;
1388
CK_ATTRIBUTE_PTR attr;
1389
CK_ATTRIBUTE crlobj_template[3];
1390
CK_ULONG crlobj_size;
1391
nssCryptokiObject **objects;
1392
nssSession *session = sessionOpt ? sessionOpt : token->defaultSession;
1394
NSS_CK_TEMPLATE_START(crlobj_template, attr, crlobj_size);
1395
if (searchType == nssTokenSearchType_SessionOnly) {
1396
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1397
} else if (searchType == nssTokenSearchType_TokenOnly ||
1398
searchType == nssTokenSearchType_TokenForced) {
1399
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1401
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc);
1402
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
1403
NSS_CK_TEMPLATE_FINISH(crlobj_template, attr, crlobj_size);
1405
objects = find_objects_by_template(token, session,
1406
crlobj_template, crlobj_size,
1407
maximumOpt, statusOpt);
1411
NSS_IMPLEMENT PRStatus
1412
nssToken_GetCachedObjectAttributes (
1415
nssCryptokiObject *object,
1416
CK_OBJECT_CLASS objclass,
1417
CK_ATTRIBUTE_PTR atemplate,
1421
if (!token->cache) {
1424
return nssTokenObjectCache_GetObjectAttributes(token->cache, arenaOpt,
1429
NSS_IMPLEMENT NSSItem *
1432
nssSession *sessionOpt,
1433
NSSAlgorithmAndParameters *ap,
1442
NSSItem *rvItem = NULL;
1443
void *epv = nssToken_GetCryptokiEPV(tok);
1444
nssSession *session;
1445
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
1446
nssSession_EnterMonitor(session);
1447
ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism);
1448
if (ckrv != CKR_OK) {
1449
nssSession_ExitMonitor(session);
1453
/* XXX the standard says this should work, but it doesn't */
1454
ckrv = CKAPI(epv)->C_Digest(session->handle, NULL, 0, NULL, &digestLen);
1455
if (ckrv != CKR_OK) {
1456
nssSession_ExitMonitor(session);
1460
digestLen = 0; /* XXX for now */
1463
if (rvOpt->size > 0 && rvOpt->size < digestLen) {
1464
nssSession_ExitMonitor(session);
1465
/* the error should be bad args */
1469
digest = rvOpt->data;
1471
digestLen = rvOpt->size;
1474
digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen);
1476
nssSession_ExitMonitor(session);
1480
ckrv = CKAPI(epv)->C_Digest(session->handle,
1481
(CK_BYTE_PTR)data->data,
1482
(CK_ULONG)data->size,
1483
(CK_BYTE_PTR)digest,
1485
nssSession_ExitMonitor(session);
1486
if (ckrv != CKR_OK) {
1487
nss_ZFreeIf(digest);
1491
rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
1496
NSS_IMPLEMENT PRStatus
1497
nssToken_BeginDigest (
1499
nssSession *sessionOpt,
1500
NSSAlgorithmAndParameters *ap
1504
nssSession *session;
1505
void *epv = nssToken_GetCryptokiEPV(tok);
1506
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
1507
nssSession_EnterMonitor(session);
1508
ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism);
1509
nssSession_ExitMonitor(session);
1510
return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
1513
NSS_IMPLEMENT PRStatus
1514
nssToken_ContinueDigest (
1516
nssSession *sessionOpt,
1521
nssSession *session;
1522
void *epv = nssToken_GetCryptokiEPV(tok);
1523
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
1524
nssSession_EnterMonitor(session);
1525
ckrv = CKAPI(epv)->C_DigestUpdate(session->handle,
1526
(CK_BYTE_PTR)item->data,
1527
(CK_ULONG)item->size);
1528
nssSession_ExitMonitor(session);
1529
return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
1532
NSS_IMPLEMENT NSSItem *
1533
nssToken_FinishDigest (
1535
nssSession *sessionOpt,
1543
NSSItem *rvItem = NULL;
1544
void *epv = nssToken_GetCryptokiEPV(tok);
1545
nssSession *session;
1546
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
1547
nssSession_EnterMonitor(session);
1548
ckrv = CKAPI(epv)->C_DigestFinal(session->handle, NULL, &digestLen);
1549
if (ckrv != CKR_OK || digestLen == 0) {
1550
nssSession_ExitMonitor(session);
1555
if (rvOpt->size > 0 && rvOpt->size < digestLen) {
1556
nssSession_ExitMonitor(session);
1557
/* the error should be bad args */
1561
digest = rvOpt->data;
1563
digestLen = rvOpt->size;
1566
digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen);
1568
nssSession_ExitMonitor(session);
1572
ckrv = CKAPI(epv)->C_DigestFinal(session->handle, digest, &digestLen);
1573
nssSession_ExitMonitor(session);
1574
if (ckrv != CKR_OK) {
1575
nss_ZFreeIf(digest);
1579
rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
1584
NSS_IMPLEMENT PRBool
1585
nssToken_IsPresent (
1589
return nssSlot_IsTokenPresent(token->slot);
1592
/* Sigh. The methods to find objects declared above cause problems with
1593
* the low-level object cache in the softoken -- the objects are found in
1594
* toto, then one wave of GetAttributes is done, then another. Having a
1595
* large number of objects causes the cache to be thrashed, as the objects
1596
* are gone before there's any chance to ask for their attributes.
1597
* So, for now, bringing back traversal methods for certs. This way all of
1598
* the cert's attributes can be grabbed immediately after finding it,
1599
* increasing the likelihood that the cache takes care of it.
1601
NSS_IMPLEMENT PRStatus
1602
nssToken_TraverseCertificates (
1604
nssSession *sessionOpt,
1605
nssTokenSearchType searchType,
1606
PRStatus (* callback)(nssCryptokiObject *instance, void *arg),
1612
CK_OBJECT_HANDLE *objectHandles;
1613
CK_ATTRIBUTE_PTR attr;
1614
CK_ATTRIBUTE cert_template[2];
1618
PRUint32 arraySize, numHandles;
1619
nssCryptokiObject **objects;
1620
void *epv = nssToken_GetCryptokiEPV(token);
1621
nssSession *session = (sessionOpt) ? sessionOpt : token->defaultSession;
1623
/* template for all certs */
1624
NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
1625
if (searchType == nssTokenSearchType_SessionOnly) {
1626
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1627
} else if (searchType == nssTokenSearchType_TokenOnly ||
1628
searchType == nssTokenSearchType_TokenForced) {
1629
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1631
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
1632
NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);
1634
/* the arena is only for the array of object handles */
1635
arena = nssArena_Create();
1639
arraySize = OBJECT_STACK_SIZE;
1641
objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize);
1642
if (!objectHandles) {
1645
nssSession_EnterMonitor(session); /* ==== session lock === */
1646
/* Initialize the find with the template */
1647
ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle,
1648
cert_template, ctsize);
1649
if (ckrv != CKR_OK) {
1650
nssSession_ExitMonitor(session);
1654
/* Issue the find for up to arraySize - numHandles objects */
1655
ckrv = CKAPI(epv)->C_FindObjects(session->handle,
1656
objectHandles + numHandles,
1657
arraySize - numHandles,
1659
if (ckrv != CKR_OK) {
1660
nssSession_ExitMonitor(session);
1663
/* bump the number of found objects */
1664
numHandles += count;
1665
if (numHandles < arraySize) {
1668
/* the array is filled, double it and continue */
1670
objectHandles = nss_ZREALLOCARRAY(objectHandles,
1673
if (!objectHandles) {
1674
nssSession_ExitMonitor(session);
1678
ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle);
1679
nssSession_ExitMonitor(session); /* ==== end session lock === */
1680
if (ckrv != CKR_OK) {
1683
if (numHandles > 0) {
1684
objects = create_objects_from_handles(token, session,
1685
objectHandles, numHandles);
1687
nssCryptokiObject **op;
1688
for (op = objects; *op; op++) {
1689
status = (*callback)(*op, arg);
1691
nss_ZFreeIf(objects);
1694
nssArena_Destroy(arena);
1697
nssArena_Destroy(arena);
1701
NSS_IMPLEMENT PRBool
1702
nssToken_IsPrivateKeyAvailable (
1705
nssCryptokiObject *instance
1708
CK_OBJECT_CLASS theClass;
1710
if (token == NULL) return PR_FALSE;
1711
if (c == NULL) return PR_FALSE;
1713
theClass = CKO_PRIVATE_KEY;
1714
if (!nssSlot_IsLoggedIn(token->slot)) {
1715
theClass = CKO_PUBLIC_KEY;
1717
if (PK11_MatchItem(token->pk11slot, instance->handle, theClass)
1718
!= CK_INVALID_HANDLE) {