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.43 $ $Date: 2008/02/05 03:22:38 $";
43 #endif /* NSSCKEPV_H */
51 #endif /* CKHELPER_H */
57 extern const NSSError NSS_ERROR_NOT_FOUND
;
58 extern const NSSError NSS_ERROR_INVALID_ARGUMENT
;
59 extern const NSSError NSS_ERROR_PKCS11
;
61 /* The number of object handles to grab during each call to C_FindObjects */
62 #define OBJECT_STACK_SIZE 16
64 NSS_IMPLEMENT PRStatus
70 if (PR_AtomicDecrement(&tok
->base
.refCount
) == 0) {
71 PZ_DestroyLock(tok
->base
.lock
);
72 nssTokenObjectCache_Destroy(tok
->cache
);
73 return nssArena_Destroy(tok
->base
.arena
);
84 nssTokenObjectCache_Clear(tok
->cache
);
92 (void)nssToken_Destroy(tok
);
95 NSS_IMPLEMENT NSSToken
*
100 PR_AtomicIncrement(&tok
->base
.refCount
);
104 NSS_IMPLEMENT NSSSlot
*
109 return nssSlot_AddRef(tok
->slot
);
113 nssToken_GetCryptokiEPV (
117 return nssSlot_GetCryptokiEPV(token
->slot
);
120 NSS_IMPLEMENT nssSession
*
121 nssToken_GetDefaultSession (
125 return token
->defaultSession
;
128 NSS_IMPLEMENT NSSUTF8
*
136 if (tok
->base
.name
[0] == 0) {
137 (void) nssSlot_IsTokenPresent(tok
->slot
);
139 return tok
->base
.name
;
142 NSS_IMPLEMENT NSSUTF8
*
147 return nssToken_GetName(token
);
151 nssToken_IsLoginRequired (
155 return (token
->ckFlags
& CKF_LOGIN_REQUIRED
);
159 nssToken_NeedsPINInitialization (
163 return (!(token
->ckFlags
& CKF_USER_PIN_INITIALIZED
));
166 NSS_IMPLEMENT PRStatus
167 nssToken_DeleteStoredObject (
168 nssCryptokiObject
*instance
173 PRBool createdSession
= PR_FALSE
;
174 NSSToken
*token
= instance
->token
;
175 nssSession
*session
= NULL
;
176 void *epv
= nssToken_GetCryptokiEPV(instance
->token
);
178 nssTokenObjectCache_RemoveObject(token
->cache
, instance
);
180 if (instance
->isTokenObject
) {
181 if (nssSession_IsReadWrite(token
->defaultSession
)) {
182 session
= token
->defaultSession
;
184 session
= nssSlot_CreateSession(token
->slot
, NULL
, PR_TRUE
);
185 createdSession
= PR_TRUE
;
188 if (session
== NULL
) {
191 nssSession_EnterMonitor(session
);
192 ckrv
= CKAPI(epv
)->C_DestroyObject(session
->handle
, instance
->handle
);
193 nssSession_ExitMonitor(session
);
194 if (createdSession
) {
195 nssSession_Destroy(session
);
198 if (ckrv
!= CKR_OK
) {
200 /* use the error stack to pass the PKCS #11 error out */
202 nss_SetError(NSS_ERROR_PKCS11
);
207 static nssCryptokiObject
*
210 nssSession
*sessionOpt
,
211 CK_ATTRIBUTE_PTR objectTemplate
,
215 nssSession
*session
= NULL
;
216 PRBool createdSession
= PR_FALSE
;
217 nssCryptokiObject
*object
= NULL
;
218 CK_OBJECT_HANDLE handle
;
220 void *epv
= nssToken_GetCryptokiEPV(tok
);
221 if (nssCKObject_IsTokenObjectTemplate(objectTemplate
, otsize
)) {
223 if (!nssSession_IsReadWrite(sessionOpt
)) {
224 nss_SetError(NSS_ERROR_INVALID_ARGUMENT
);
227 session
= sessionOpt
;
229 } else if (nssSession_IsReadWrite(tok
->defaultSession
)) {
230 session
= tok
->defaultSession
;
232 session
= nssSlot_CreateSession(tok
->slot
, NULL
, PR_TRUE
);
233 createdSession
= PR_TRUE
;
236 session
= (sessionOpt
) ? sessionOpt
: tok
->defaultSession
;
238 if (session
== NULL
) {
239 nss_SetError(NSS_ERROR_INVALID_ARGUMENT
);
242 nssSession_EnterMonitor(session
);
243 ckrv
= CKAPI(epv
)->C_CreateObject(session
->handle
,
244 objectTemplate
, otsize
,
246 nssSession_ExitMonitor(session
);
247 if (ckrv
== CKR_OK
) {
248 object
= nssCryptokiObject_Create(tok
, session
, handle
);
251 nss_SetError(NSS_ERROR_PKCS11
);
253 if (createdSession
) {
254 nssSession_Destroy(session
);
259 static nssCryptokiObject
**
260 create_objects_from_handles (
263 CK_OBJECT_HANDLE
*handles
,
267 nssCryptokiObject
**objects
;
268 objects
= nss_ZNEWARRAY(NULL
, nssCryptokiObject
*, numH
+ 1);
271 for (i
=0; i
<(PRInt32
)numH
; i
++) {
272 objects
[i
] = nssCryptokiObject_Create(tok
, session
, handles
[i
]);
274 for (--i
; i
>0; --i
) {
275 nssCryptokiObject_Destroy(objects
[i
]);
277 nss_ZFreeIf(objects
);
286 static nssCryptokiObject
**
289 nssSession
*sessionOpt
,
290 CK_ATTRIBUTE_PTR obj_template
,
298 CK_OBJECT_HANDLE
*objectHandles
;
299 CK_OBJECT_HANDLE staticObjects
[OBJECT_STACK_SIZE
];
300 PRUint32 arraySize
, numHandles
;
301 void *epv
= nssToken_GetCryptokiEPV(tok
);
302 nssCryptokiObject
**objects
;
303 nssSession
*session
= (sessionOpt
) ? sessionOpt
: tok
->defaultSession
;
305 /* the arena is only for the array of object handles */
306 if (maximumOpt
> 0) {
307 arraySize
= maximumOpt
;
309 arraySize
= OBJECT_STACK_SIZE
;
312 if (arraySize
<= OBJECT_STACK_SIZE
) {
313 objectHandles
= staticObjects
;
315 objectHandles
= nss_ZNEWARRAY(NULL
, CK_OBJECT_HANDLE
, arraySize
);
317 if (!objectHandles
) {
318 ckrv
= CKR_HOST_MEMORY
;
321 nssSession_EnterMonitor(session
); /* ==== session lock === */
322 /* Initialize the find with the template */
323 ckrv
= CKAPI(epv
)->C_FindObjectsInit(session
->handle
,
324 obj_template
, otsize
);
325 if (ckrv
!= CKR_OK
) {
326 nssSession_ExitMonitor(session
);
330 /* Issue the find for up to arraySize - numHandles objects */
331 ckrv
= CKAPI(epv
)->C_FindObjects(session
->handle
,
332 objectHandles
+ numHandles
,
333 arraySize
- numHandles
,
335 if (ckrv
!= CKR_OK
) {
336 nssSession_ExitMonitor(session
);
339 /* bump the number of found objects */
341 if (maximumOpt
> 0 || numHandles
< arraySize
) {
342 /* When a maximum is provided, the search is done all at once,
343 * so the search is finished. If the number returned was less
344 * than the number sought, the search is finished.
348 /* the array is filled, double it and continue */
350 if (objectHandles
== staticObjects
) {
351 objectHandles
= nss_ZNEWARRAY(NULL
,CK_OBJECT_HANDLE
, arraySize
);
353 PORT_Memcpy(objectHandles
, staticObjects
,
354 OBJECT_STACK_SIZE
* sizeof(objectHandles
[1]));
357 objectHandles
= nss_ZREALLOCARRAY(objectHandles
,
361 if (!objectHandles
) {
362 nssSession_ExitMonitor(session
);
363 ckrv
= CKR_HOST_MEMORY
;
367 ckrv
= CKAPI(epv
)->C_FindObjectsFinal(session
->handle
);
368 nssSession_ExitMonitor(session
); /* ==== end session lock === */
369 if (ckrv
!= CKR_OK
) {
372 if (numHandles
> 0) {
373 objects
= create_objects_from_handles(tok
, session
,
374 objectHandles
, numHandles
);
376 nss_SetError(NSS_ERROR_NOT_FOUND
);
379 if (objectHandles
&& objectHandles
!= staticObjects
) {
380 nss_ZFreeIf(objectHandles
);
382 if (statusOpt
) *statusOpt
= PR_SUCCESS
;
385 if (objectHandles
&& objectHandles
!= staticObjects
) {
386 nss_ZFreeIf(objectHandles
);
389 * These errors should be treated the same as if the objects just weren't
392 if ((ckrv
== CKR_ATTRIBUTE_TYPE_INVALID
) ||
393 (ckrv
== CKR_ATTRIBUTE_VALUE_INVALID
) ||
394 (ckrv
== CKR_DATA_INVALID
) ||
395 (ckrv
== CKR_DATA_LEN_RANGE
) ||
396 (ckrv
== CKR_FUNCTION_NOT_SUPPORTED
) ||
397 (ckrv
== CKR_TEMPLATE_INCOMPLETE
) ||
398 (ckrv
== CKR_TEMPLATE_INCONSISTENT
)) {
400 nss_SetError(NSS_ERROR_NOT_FOUND
);
401 if (statusOpt
) *statusOpt
= PR_SUCCESS
;
404 nss_SetError(NSS_ERROR_PKCS11
);
405 if (statusOpt
) *statusOpt
= PR_FAILURE
;
407 return (nssCryptokiObject
**)NULL
;
410 static nssCryptokiObject
**
411 find_objects_by_template (
413 nssSession
*sessionOpt
,
414 CK_ATTRIBUTE_PTR obj_template
,
420 CK_OBJECT_CLASS objclass
= (CK_OBJECT_CLASS
)-1;
421 nssCryptokiObject
**objects
= NULL
;
423 for (i
=0; i
<otsize
; i
++) {
424 if (obj_template
[i
].type
== CKA_CLASS
) {
425 objclass
= *(CK_OBJECT_CLASS
*)obj_template
[i
].pValue
;
429 PR_ASSERT(i
< otsize
);
431 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
432 if (statusOpt
) *statusOpt
= PR_FAILURE
;
435 /* If these objects are being cached, try looking there first */
437 nssTokenObjectCache_HaveObjectClass(token
->cache
, objclass
))
440 objects
= nssTokenObjectCache_FindObjectsByTemplate(token
->cache
,
446 if (status
== PR_SUCCESS
) {
447 if (statusOpt
) *statusOpt
= status
;
451 /* Either they are not cached, or cache failed; look on token. */
452 objects
= find_objects(token
, sessionOpt
,
453 obj_template
, otsize
,
454 maximumOpt
, statusOpt
);
458 extern const NSSError NSS_ERROR_INVALID_CERTIFICATE
;
460 NSS_IMPLEMENT nssCryptokiObject
*
461 nssToken_ImportCertificate (
463 nssSession
*sessionOpt
,
464 NSSCertificateType certType
,
476 CK_CERTIFICATE_TYPE cert_type
;
477 CK_ATTRIBUTE_PTR attr
;
478 CK_ATTRIBUTE cert_tmpl
[10];
480 nssTokenSearchType searchType
;
481 nssCryptokiObject
*rvObject
= NULL
;
483 if (certType
== NSSCertificateType_PKIX
) {
484 cert_type
= CKC_X_509
;
486 return (nssCryptokiObject
*)NULL
;
488 NSS_CK_TEMPLATE_START(cert_tmpl
, attr
, ctsize
);
490 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
491 searchType
= nssTokenSearchType_TokenOnly
;
493 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
494 searchType
= nssTokenSearchType_SessionOnly
;
496 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CLASS
, &g_ck_class_cert
);
497 NSS_CK_SET_ATTRIBUTE_VAR( attr
, CKA_CERTIFICATE_TYPE
, cert_type
);
498 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_ID
, id
);
499 NSS_CK_SET_ATTRIBUTE_UTF8(attr
, CKA_LABEL
, nickname
);
500 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_VALUE
, encoding
);
501 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_ISSUER
, issuer
);
502 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_SUBJECT
, subject
);
503 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_SERIAL_NUMBER
, serial
);
505 NSS_CK_SET_ATTRIBUTE_UTF8(attr
, CKA_NETSCAPE_EMAIL
, email
);
507 NSS_CK_TEMPLATE_FINISH(cert_tmpl
, attr
, ctsize
);
508 /* see if the cert is already there */
509 rvObject
= nssToken_FindCertificateByIssuerAndSerialNumber(tok
,
517 NSSSlot
*slot
= nssToken_GetSlot(tok
);
518 nssSession
*session
= nssSlot_CreateSession(slot
, NULL
, PR_TRUE
);
520 nssCryptokiObject_Destroy(rvObject
);
521 nssSlot_Destroy(slot
);
522 return (nssCryptokiObject
*)NULL
;
524 /* Reject any attempt to import a new cert that has the same
525 * issuer/serial as an existing cert, but does not have the
528 NSS_CK_TEMPLATE_START(cert_tmpl
, attr
, ctsize
);
529 NSS_CK_SET_ATTRIBUTE_NULL(attr
, CKA_VALUE
);
530 NSS_CK_TEMPLATE_FINISH(cert_tmpl
, attr
, ctsize
);
531 status
= nssCKObject_GetAttributes(rvObject
->handle
,
532 cert_tmpl
, ctsize
, NULL
,
534 NSS_CK_ATTRIBUTE_TO_ITEM(cert_tmpl
, &existingDER
);
535 if (status
== PR_SUCCESS
) {
536 if (!nssItem_Equal(encoding
, &existingDER
, NULL
)) {
537 nss_SetError(NSS_ERROR_INVALID_CERTIFICATE
);
540 nss_ZFreeIf(existingDER
.data
);
542 if (status
== PR_FAILURE
) {
543 nssCryptokiObject_Destroy(rvObject
);
544 nssSession_Destroy(session
);
545 nssSlot_Destroy(slot
);
546 return (nssCryptokiObject
*)NULL
;
548 /* according to PKCS#11, label, ID, issuer, and serial number
549 * may change after the object has been created. For PKIX, the
550 * last two attributes can't change, so for now we'll only worry
551 * about the first two.
553 NSS_CK_TEMPLATE_START(cert_tmpl
, attr
, ctsize
);
554 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_ID
, id
);
555 NSS_CK_SET_ATTRIBUTE_UTF8(attr
, CKA_LABEL
, nickname
);
556 NSS_CK_TEMPLATE_FINISH(cert_tmpl
, attr
, ctsize
);
557 /* reset the mutable attributes on the token */
558 nssCKObject_SetAttributes(rvObject
->handle
,
561 if (!rvObject
->label
&& nickname
) {
562 rvObject
->label
= nssUTF8_Duplicate(nickname
, NULL
);
564 nssSession_Destroy(session
);
565 nssSlot_Destroy(slot
);
567 /* Import the certificate onto the token */
568 rvObject
= import_object(tok
, sessionOpt
, cert_tmpl
, ctsize
);
570 if (rvObject
&& tok
->cache
) {
571 /* The cache will overwrite the attributes if the object already
574 nssTokenObjectCache_ImportObject(tok
->cache
, rvObject
,
581 /* traverse all certificates - this should only happen if the token
582 * has been marked as "traversable"
584 NSS_IMPLEMENT nssCryptokiObject
**
585 nssToken_FindCertificates (
587 nssSession
*sessionOpt
,
588 nssTokenSearchType searchType
,
593 CK_ATTRIBUTE_PTR attr
;
594 CK_ATTRIBUTE cert_template
[2];
596 nssCryptokiObject
**objects
;
597 NSS_CK_TEMPLATE_START(cert_template
, attr
, ctsize
);
598 /* Set the search to token/session only if provided */
599 if (searchType
== nssTokenSearchType_SessionOnly
) {
600 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
601 } else if (searchType
== nssTokenSearchType_TokenOnly
||
602 searchType
== nssTokenSearchType_TokenForced
) {
603 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
605 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CLASS
, &g_ck_class_cert
);
606 NSS_CK_TEMPLATE_FINISH(cert_template
, attr
, ctsize
);
608 if (searchType
== nssTokenSearchType_TokenForced
) {
609 objects
= find_objects(token
, sessionOpt
,
610 cert_template
, ctsize
,
611 maximumOpt
, statusOpt
);
613 objects
= find_objects_by_template(token
, sessionOpt
,
614 cert_template
, ctsize
,
615 maximumOpt
, statusOpt
);
620 NSS_IMPLEMENT nssCryptokiObject
**
621 nssToken_FindCertificatesBySubject (
623 nssSession
*sessionOpt
,
625 nssTokenSearchType searchType
,
630 CK_ATTRIBUTE_PTR attr
;
631 CK_ATTRIBUTE subj_template
[3];
633 nssCryptokiObject
**objects
;
634 NSS_CK_TEMPLATE_START(subj_template
, attr
, stsize
);
635 /* Set the search to token/session only if provided */
636 if (searchType
== nssTokenSearchType_SessionOnly
) {
637 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
638 } else if (searchType
== nssTokenSearchType_TokenOnly
) {
639 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
641 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CLASS
, &g_ck_class_cert
);
642 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_SUBJECT
, subject
);
643 NSS_CK_TEMPLATE_FINISH(subj_template
, attr
, stsize
);
644 /* now locate the token certs matching this template */
645 objects
= find_objects_by_template(token
, sessionOpt
,
646 subj_template
, stsize
,
647 maximumOpt
, statusOpt
);
651 NSS_IMPLEMENT nssCryptokiObject
**
652 nssToken_FindCertificatesByNickname (
654 nssSession
*sessionOpt
,
656 nssTokenSearchType searchType
,
661 CK_ATTRIBUTE_PTR attr
;
662 CK_ATTRIBUTE nick_template
[3];
664 nssCryptokiObject
**objects
;
665 NSS_CK_TEMPLATE_START(nick_template
, attr
, ntsize
);
666 NSS_CK_SET_ATTRIBUTE_UTF8(attr
, CKA_LABEL
, name
);
667 /* Set the search to token/session only if provided */
668 if (searchType
== nssTokenSearchType_SessionOnly
) {
669 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
670 } else if (searchType
== nssTokenSearchType_TokenOnly
) {
671 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
673 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CLASS
, &g_ck_class_cert
);
674 NSS_CK_TEMPLATE_FINISH(nick_template
, attr
, ntsize
);
675 /* now locate the token certs matching this template */
676 objects
= find_objects_by_template(token
, sessionOpt
,
677 nick_template
, ntsize
,
678 maximumOpt
, statusOpt
);
680 /* This is to workaround the fact that PKCS#11 doesn't specify
681 * whether the '\0' should be included. XXX Is that still true?
682 * im - this is not needed by the current softoken. However, I'm
683 * leaving it in until I have surveyed more tokens to see if it needed.
684 * well, its needed by the builtin token...
686 nick_template
[0].ulValueLen
++;
687 objects
= find_objects_by_template(token
, sessionOpt
,
688 nick_template
, ntsize
,
689 maximumOpt
, statusOpt
);
695 * This function *does not* use the token object cache, because not even
696 * the softoken will return a value for CKA_NETSCAPE_EMAIL from a call
697 * to GetAttributes. The softoken does allow searches with that attribute,
698 * it just won't return a value for it.
700 NSS_IMPLEMENT nssCryptokiObject
**
701 nssToken_FindCertificatesByEmail (
703 nssSession
*sessionOpt
,
705 nssTokenSearchType searchType
,
710 CK_ATTRIBUTE_PTR attr
;
711 CK_ATTRIBUTE email_template
[3];
713 nssCryptokiObject
**objects
;
714 NSS_CK_TEMPLATE_START(email_template
, attr
, etsize
);
715 NSS_CK_SET_ATTRIBUTE_UTF8(attr
, CKA_NETSCAPE_EMAIL
, email
);
716 /* Set the search to token/session only if provided */
717 if (searchType
== nssTokenSearchType_SessionOnly
) {
718 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
719 } else if (searchType
== nssTokenSearchType_TokenOnly
) {
720 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
722 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CLASS
, &g_ck_class_cert
);
723 NSS_CK_TEMPLATE_FINISH(email_template
, attr
, etsize
);
724 /* now locate the token certs matching this template */
725 objects
= find_objects(token
, sessionOpt
,
726 email_template
, etsize
,
727 maximumOpt
, statusOpt
);
729 /* This is to workaround the fact that PKCS#11 doesn't specify
730 * whether the '\0' should be included. XXX Is that still true?
731 * im - this is not needed by the current softoken. However, I'm
732 * leaving it in until I have surveyed more tokens to see if it needed.
733 * well, its needed by the builtin token...
735 email_template
[0].ulValueLen
++;
736 objects
= find_objects(token
, sessionOpt
,
737 email_template
, etsize
,
738 maximumOpt
, statusOpt
);
743 NSS_IMPLEMENT nssCryptokiObject
**
744 nssToken_FindCertificatesByID (
746 nssSession
*sessionOpt
,
748 nssTokenSearchType searchType
,
753 CK_ATTRIBUTE_PTR attr
;
754 CK_ATTRIBUTE id_template
[3];
756 nssCryptokiObject
**objects
;
757 NSS_CK_TEMPLATE_START(id_template
, attr
, idtsize
);
758 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_ID
, id
);
759 /* Set the search to token/session only if provided */
760 if (searchType
== nssTokenSearchType_SessionOnly
) {
761 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
762 } else if (searchType
== nssTokenSearchType_TokenOnly
) {
763 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
765 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CLASS
, &g_ck_class_cert
);
766 NSS_CK_TEMPLATE_FINISH(id_template
, attr
, idtsize
);
767 /* now locate the token certs matching this template */
768 objects
= find_objects_by_template(token
, sessionOpt
,
769 id_template
, idtsize
,
770 maximumOpt
, statusOpt
);
775 * decode the serial item and return our result.
776 * NOTE serialDecode's data is really stored in serial. Don't free it.
779 nssToken_decodeSerialItem(NSSItem
*serial
, NSSItem
*serialDecode
)
781 unsigned char *data
= (unsigned char *)serial
->data
;
782 int data_left
, data_len
, index
;
784 if ((serial
->size
>= 3) && (data
[0] == 0x2)) {
785 /* remove the der encoding of the serial number before generating the
787 data_left
= serial
->size
-2;
791 /* extended length ? (not very likely for a serial number) */
792 if (data_len
& 0x80) {
793 int len_count
= data_len
& 0x7f;
796 data_left
-= len_count
;
798 while (len_count
--) {
799 data_len
= (data_len
<< 8) | data
[index
++];
803 /* XXX leaving any leading zeros on the serial number for backwards
806 /* not a valid der, must be just an unlucky serial number value */
807 if (data_len
== data_left
) {
808 serialDecode
->size
= data_len
;
809 serialDecode
->data
= &data
[index
];
816 NSS_IMPLEMENT nssCryptokiObject
*
817 nssToken_FindCertificateByIssuerAndSerialNumber (
819 nssSession
*sessionOpt
,
822 nssTokenSearchType searchType
,
826 CK_ATTRIBUTE_PTR attr
;
827 CK_ATTRIBUTE_PTR serialAttr
;
828 CK_ATTRIBUTE cert_template
[4];
830 nssCryptokiObject
**objects
;
831 nssCryptokiObject
*rvObject
= NULL
;
832 NSS_CK_TEMPLATE_START(cert_template
, attr
, ctsize
);
833 /* Set the search to token/session only if provided */
834 if (searchType
== nssTokenSearchType_SessionOnly
) {
835 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
836 } else if ((searchType
== nssTokenSearchType_TokenOnly
) ||
837 (searchType
== nssTokenSearchType_TokenForced
)) {
838 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
840 /* Set the unique id */
841 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CLASS
, &g_ck_class_cert
);
842 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_ISSUER
, issuer
);
844 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_SERIAL_NUMBER
, serial
);
845 NSS_CK_TEMPLATE_FINISH(cert_template
, attr
, ctsize
);
846 /* get the object handle */
847 if (searchType
== nssTokenSearchType_TokenForced
) {
848 objects
= find_objects(token
, sessionOpt
,
849 cert_template
, ctsize
,
852 objects
= find_objects_by_template(token
, sessionOpt
,
853 cert_template
, ctsize
,
857 rvObject
= objects
[0];
858 nss_ZFreeIf(objects
);
862 * NSS used to incorrectly store serial numbers in their decoded form.
863 * because of this old tokens have decoded serial numbers.
866 NSSItem serialDecode
;
869 status
= nssToken_decodeSerialItem(serial
, &serialDecode
);
870 if (status
!= PR_SUCCESS
) {
873 NSS_CK_SET_ATTRIBUTE_ITEM(serialAttr
,CKA_SERIAL_NUMBER
,&serialDecode
);
874 if (searchType
== nssTokenSearchType_TokenForced
) {
875 objects
= find_objects(token
, sessionOpt
,
876 cert_template
, ctsize
,
879 objects
= find_objects_by_template(token
, sessionOpt
,
880 cert_template
, ctsize
,
884 rvObject
= objects
[0];
885 nss_ZFreeIf(objects
);
891 NSS_IMPLEMENT nssCryptokiObject
*
892 nssToken_FindCertificateByEncodedCertificate (
894 nssSession
*sessionOpt
,
895 NSSBER
*encodedCertificate
,
896 nssTokenSearchType searchType
,
900 CK_ATTRIBUTE_PTR attr
;
901 CK_ATTRIBUTE cert_template
[3];
903 nssCryptokiObject
**objects
;
904 nssCryptokiObject
*rvObject
= NULL
;
905 NSS_CK_TEMPLATE_START(cert_template
, attr
, ctsize
);
906 /* Set the search to token/session only if provided */
907 if (searchType
== nssTokenSearchType_SessionOnly
) {
908 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
909 } else if (searchType
== nssTokenSearchType_TokenOnly
) {
910 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
912 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CLASS
, &g_ck_class_cert
);
913 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_VALUE
, encodedCertificate
);
914 NSS_CK_TEMPLATE_FINISH(cert_template
, attr
, ctsize
);
915 /* get the object handle */
916 objects
= find_objects_by_template(token
, sessionOpt
,
917 cert_template
, ctsize
,
920 rvObject
= objects
[0];
921 nss_ZFreeIf(objects
);
926 NSS_IMPLEMENT nssCryptokiObject
**
927 nssToken_FindPrivateKeys (
929 nssSession
*sessionOpt
,
930 nssTokenSearchType searchType
,
935 CK_ATTRIBUTE_PTR attr
;
936 CK_ATTRIBUTE key_template
[2];
938 nssCryptokiObject
**objects
;
940 NSS_CK_TEMPLATE_START(key_template
, attr
, ktsize
);
941 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CLASS
, &g_ck_class_privkey
);
942 if (searchType
== nssTokenSearchType_SessionOnly
) {
943 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
944 } else if (searchType
== nssTokenSearchType_TokenOnly
) {
945 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
947 NSS_CK_TEMPLATE_FINISH(key_template
, attr
, ktsize
);
949 objects
= find_objects_by_template(token
, sessionOpt
,
950 key_template
, ktsize
,
951 maximumOpt
, statusOpt
);
955 /* XXX ?there are no session cert objects, so only search token objects */
956 NSS_IMPLEMENT nssCryptokiObject
*
957 nssToken_FindPrivateKeyByID (
959 nssSession
*sessionOpt
,
963 CK_ATTRIBUTE_PTR attr
;
964 CK_ATTRIBUTE key_template
[3];
966 nssCryptokiObject
**objects
;
967 nssCryptokiObject
*rvKey
= NULL
;
969 NSS_CK_TEMPLATE_START(key_template
, attr
, ktsize
);
970 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CLASS
, &g_ck_class_privkey
);
971 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
972 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_ID
, keyID
);
973 NSS_CK_TEMPLATE_FINISH(key_template
, attr
, ktsize
);
975 objects
= find_objects_by_template(token
, sessionOpt
,
976 key_template
, ktsize
,
980 nss_ZFreeIf(objects
);
985 /* XXX ?there are no session cert objects, so only search token objects */
986 NSS_IMPLEMENT nssCryptokiObject
*
987 nssToken_FindPublicKeyByID (
989 nssSession
*sessionOpt
,
993 CK_ATTRIBUTE_PTR attr
;
994 CK_ATTRIBUTE key_template
[3];
996 nssCryptokiObject
**objects
;
997 nssCryptokiObject
*rvKey
= NULL
;
999 NSS_CK_TEMPLATE_START(key_template
, attr
, ktsize
);
1000 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CLASS
, &g_ck_class_pubkey
);
1001 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
1002 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_ID
, keyID
);
1003 NSS_CK_TEMPLATE_FINISH(key_template
, attr
, ktsize
);
1005 objects
= find_objects_by_template(token
, sessionOpt
,
1006 key_template
, ktsize
,
1010 nss_ZFreeIf(objects
);
1016 sha1_hash(NSSItem
*input
, NSSItem
*output
)
1018 NSSAlgorithmAndParameters
*ap
;
1019 PK11SlotInfo
*internal
= PK11_GetInternalSlot();
1020 NSSToken
*token
= PK11Slot_GetNSSToken(internal
);
1021 ap
= NSSAlgorithmAndParameters_CreateSHA1Digest(NULL
);
1022 (void)nssToken_Digest(token
, NULL
, ap
, input
, output
, NULL
);
1023 PK11_FreeSlot(token
->pk11slot
);
1028 md5_hash(NSSItem
*input
, NSSItem
*output
)
1030 NSSAlgorithmAndParameters
*ap
;
1031 PK11SlotInfo
*internal
= PK11_GetInternalSlot();
1032 NSSToken
*token
= PK11Slot_GetNSSToken(internal
);
1033 ap
= NSSAlgorithmAndParameters_CreateMD5Digest(NULL
);
1034 (void)nssToken_Digest(token
, NULL
, ap
, input
, output
, NULL
);
1035 PK11_FreeSlot(token
->pk11slot
);
1041 nssTrustLevel nssTrust
1046 case nssTrustLevel_NotTrusted
: t
= CKT_NETSCAPE_UNTRUSTED
; break;
1047 case nssTrustLevel_TrustedDelegator
: t
= CKT_NETSCAPE_TRUSTED_DELEGATOR
;
1049 case nssTrustLevel_ValidDelegator
: t
= CKT_NETSCAPE_VALID_DELEGATOR
; break;
1050 case nssTrustLevel_Trusted
: t
= CKT_NETSCAPE_TRUSTED
; break;
1051 case nssTrustLevel_Valid
: t
= CKT_NETSCAPE_VALID
; break;
1052 case nssTrustLevel_Unknown
:
1053 default: t
= CKT_NETSCAPE_TRUST_UNKNOWN
; break;
1058 NSS_IMPLEMENT nssCryptokiObject
*
1059 nssToken_ImportTrust (
1061 nssSession
*sessionOpt
,
1062 NSSDER
*certEncoding
,
1065 nssTrustLevel serverAuth
,
1066 nssTrustLevel clientAuth
,
1067 nssTrustLevel codeSigning
,
1068 nssTrustLevel emailProtection
,
1069 PRBool stepUpApproved
,
1070 PRBool asTokenObject
1073 nssCryptokiObject
*object
;
1074 CK_OBJECT_CLASS tobjc
= CKO_NETSCAPE_TRUST
;
1075 CK_TRUST ckSA
, ckCA
, ckCS
, ckEP
;
1076 CK_ATTRIBUTE_PTR attr
;
1077 CK_ATTRIBUTE trust_tmpl
[11];
1079 PRUint8 sha1
[20]; /* this is cheating... */
1081 NSSItem sha1_result
, md5_result
;
1082 sha1_result
.data
= sha1
; sha1_result
.size
= sizeof sha1
;
1083 md5_result
.data
= md5
; md5_result
.size
= sizeof md5
;
1084 sha1_hash(certEncoding
, &sha1_result
);
1085 md5_hash(certEncoding
, &md5_result
);
1086 ckSA
= get_ck_trust(serverAuth
);
1087 ckCA
= get_ck_trust(clientAuth
);
1088 ckCS
= get_ck_trust(codeSigning
);
1089 ckEP
= get_ck_trust(emailProtection
);
1090 NSS_CK_TEMPLATE_START(trust_tmpl
, attr
, tsize
);
1091 if (asTokenObject
) {
1092 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
1094 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
1096 NSS_CK_SET_ATTRIBUTE_VAR( attr
, CKA_CLASS
, tobjc
);
1097 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_ISSUER
, certIssuer
);
1098 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_SERIAL_NUMBER
, certSerial
);
1099 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CERT_SHA1_HASH
, &sha1_result
);
1100 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CERT_MD5_HASH
, &md5_result
);
1101 /* now set the trust values */
1102 NSS_CK_SET_ATTRIBUTE_VAR(attr
, CKA_TRUST_SERVER_AUTH
, ckSA
);
1103 NSS_CK_SET_ATTRIBUTE_VAR(attr
, CKA_TRUST_CLIENT_AUTH
, ckCA
);
1104 NSS_CK_SET_ATTRIBUTE_VAR(attr
, CKA_TRUST_CODE_SIGNING
, ckCS
);
1105 NSS_CK_SET_ATTRIBUTE_VAR(attr
, CKA_TRUST_EMAIL_PROTECTION
, ckEP
);
1106 if (stepUpApproved
) {
1107 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TRUST_STEP_UP_APPROVED
,
1110 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TRUST_STEP_UP_APPROVED
,
1113 NSS_CK_TEMPLATE_FINISH(trust_tmpl
, attr
, tsize
);
1114 /* import the trust object onto the token */
1115 object
= import_object(tok
, sessionOpt
, trust_tmpl
, tsize
);
1116 if (object
&& tok
->cache
) {
1117 nssTokenObjectCache_ImportObject(tok
->cache
, object
, tobjc
,
1123 NSS_IMPLEMENT nssCryptokiObject
**
1124 nssToken_FindTrustObjects (
1126 nssSession
*sessionOpt
,
1127 nssTokenSearchType searchType
,
1128 PRUint32 maximumOpt
,
1132 CK_OBJECT_CLASS tobjc
= CKO_NETSCAPE_TRUST
;
1133 CK_ATTRIBUTE_PTR attr
;
1134 CK_ATTRIBUTE tobj_template
[2];
1136 nssCryptokiObject
**objects
;
1137 nssSession
*session
= sessionOpt
? sessionOpt
: token
->defaultSession
;
1139 NSS_CK_TEMPLATE_START(tobj_template
, attr
, tobj_size
);
1140 if (searchType
== nssTokenSearchType_SessionOnly
) {
1141 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
1142 } else if (searchType
== nssTokenSearchType_TokenOnly
||
1143 searchType
== nssTokenSearchType_TokenForced
) {
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_TEMPLATE_FINISH(tobj_template
, attr
, tobj_size
);
1149 if (searchType
== nssTokenSearchType_TokenForced
) {
1150 objects
= find_objects(token
, session
,
1151 tobj_template
, tobj_size
,
1152 maximumOpt
, statusOpt
);
1154 objects
= find_objects_by_template(token
, session
,
1155 tobj_template
, tobj_size
,
1156 maximumOpt
, statusOpt
);
1161 NSS_IMPLEMENT nssCryptokiObject
*
1162 nssToken_FindTrustForCertificate (
1164 nssSession
*sessionOpt
,
1165 NSSDER
*certEncoding
,
1168 nssTokenSearchType searchType
1171 CK_OBJECT_CLASS tobjc
= CKO_NETSCAPE_TRUST
;
1172 CK_ATTRIBUTE_PTR attr
;
1173 CK_ATTRIBUTE tobj_template
[5];
1175 nssSession
*session
= sessionOpt
? sessionOpt
: token
->defaultSession
;
1176 nssCryptokiObject
*object
, **objects
;
1178 NSS_CK_TEMPLATE_START(tobj_template
, attr
, tobj_size
);
1179 if (searchType
== nssTokenSearchType_SessionOnly
) {
1180 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
1181 } else if (searchType
== nssTokenSearchType_TokenOnly
) {
1182 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
1184 NSS_CK_SET_ATTRIBUTE_VAR( attr
, CKA_CLASS
, tobjc
);
1185 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_ISSUER
, certIssuer
);
1186 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_SERIAL_NUMBER
, certSerial
);
1187 NSS_CK_TEMPLATE_FINISH(tobj_template
, attr
, tobj_size
);
1189 objects
= find_objects_by_template(token
, session
,
1190 tobj_template
, tobj_size
,
1193 object
= objects
[0];
1194 nss_ZFreeIf(objects
);
1199 NSS_IMPLEMENT nssCryptokiObject
*
1200 nssToken_ImportCRL (
1202 nssSession
*sessionOpt
,
1207 PRBool asTokenObject
1210 nssCryptokiObject
*object
;
1211 CK_OBJECT_CLASS crlobjc
= CKO_NETSCAPE_CRL
;
1212 CK_ATTRIBUTE_PTR attr
;
1213 CK_ATTRIBUTE crl_tmpl
[6];
1216 NSS_CK_TEMPLATE_START(crl_tmpl
, attr
, crlsize
);
1217 if (asTokenObject
) {
1218 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
1220 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
1222 NSS_CK_SET_ATTRIBUTE_VAR( attr
, CKA_CLASS
, crlobjc
);
1223 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_SUBJECT
, subject
);
1224 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_VALUE
, encoding
);
1225 NSS_CK_SET_ATTRIBUTE_UTF8(attr
, CKA_NETSCAPE_URL
, url
);
1227 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_NETSCAPE_KRL
, &g_ck_true
);
1229 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_NETSCAPE_KRL
, &g_ck_false
);
1231 NSS_CK_TEMPLATE_FINISH(crl_tmpl
, attr
, crlsize
);
1233 /* import the crl object onto the token */
1234 object
= import_object(token
, sessionOpt
, crl_tmpl
, crlsize
);
1235 if (object
&& token
->cache
) {
1236 nssTokenObjectCache_ImportObject(token
->cache
, object
, crlobjc
,
1242 NSS_IMPLEMENT nssCryptokiObject
**
1245 nssSession
*sessionOpt
,
1246 nssTokenSearchType searchType
,
1247 PRUint32 maximumOpt
,
1251 CK_OBJECT_CLASS crlobjc
= CKO_NETSCAPE_CRL
;
1252 CK_ATTRIBUTE_PTR attr
;
1253 CK_ATTRIBUTE crlobj_template
[2];
1254 CK_ULONG crlobj_size
;
1255 nssCryptokiObject
**objects
;
1256 nssSession
*session
= sessionOpt
? sessionOpt
: token
->defaultSession
;
1258 NSS_CK_TEMPLATE_START(crlobj_template
, attr
, crlobj_size
);
1259 if (searchType
== nssTokenSearchType_SessionOnly
) {
1260 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
1261 } else if (searchType
== nssTokenSearchType_TokenOnly
||
1262 searchType
== nssTokenSearchType_TokenForced
) {
1263 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
1265 NSS_CK_SET_ATTRIBUTE_VAR( attr
, CKA_CLASS
, crlobjc
);
1266 NSS_CK_TEMPLATE_FINISH(crlobj_template
, attr
, crlobj_size
);
1268 if (searchType
== nssTokenSearchType_TokenForced
) {
1269 objects
= find_objects(token
, session
,
1270 crlobj_template
, crlobj_size
,
1271 maximumOpt
, statusOpt
);
1273 objects
= find_objects_by_template(token
, session
,
1274 crlobj_template
, crlobj_size
,
1275 maximumOpt
, statusOpt
);
1280 NSS_IMPLEMENT nssCryptokiObject
**
1281 nssToken_FindCRLsBySubject (
1283 nssSession
*sessionOpt
,
1285 nssTokenSearchType searchType
,
1286 PRUint32 maximumOpt
,
1290 CK_OBJECT_CLASS crlobjc
= CKO_NETSCAPE_CRL
;
1291 CK_ATTRIBUTE_PTR attr
;
1292 CK_ATTRIBUTE crlobj_template
[3];
1293 CK_ULONG crlobj_size
;
1294 nssCryptokiObject
**objects
;
1295 nssSession
*session
= sessionOpt
? sessionOpt
: token
->defaultSession
;
1297 NSS_CK_TEMPLATE_START(crlobj_template
, attr
, crlobj_size
);
1298 if (searchType
== nssTokenSearchType_SessionOnly
) {
1299 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
1300 } else if (searchType
== nssTokenSearchType_TokenOnly
||
1301 searchType
== nssTokenSearchType_TokenForced
) {
1302 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
1304 NSS_CK_SET_ATTRIBUTE_VAR( attr
, CKA_CLASS
, crlobjc
);
1305 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_SUBJECT
, subject
);
1306 NSS_CK_TEMPLATE_FINISH(crlobj_template
, attr
, crlobj_size
);
1308 objects
= find_objects_by_template(token
, session
,
1309 crlobj_template
, crlobj_size
,
1310 maximumOpt
, statusOpt
);
1314 NSS_IMPLEMENT PRStatus
1315 nssToken_GetCachedObjectAttributes (
1318 nssCryptokiObject
*object
,
1319 CK_OBJECT_CLASS objclass
,
1320 CK_ATTRIBUTE_PTR atemplate
,
1324 if (!token
->cache
) {
1327 return nssTokenObjectCache_GetObjectAttributes(token
->cache
, arenaOpt
,
1332 NSS_IMPLEMENT NSSItem
*
1335 nssSession
*sessionOpt
,
1336 NSSAlgorithmAndParameters
*ap
,
1345 NSSItem
*rvItem
= NULL
;
1346 void *epv
= nssToken_GetCryptokiEPV(tok
);
1347 nssSession
*session
;
1348 session
= (sessionOpt
) ? sessionOpt
: tok
->defaultSession
;
1349 nssSession_EnterMonitor(session
);
1350 ckrv
= CKAPI(epv
)->C_DigestInit(session
->handle
, &ap
->mechanism
);
1351 if (ckrv
!= CKR_OK
) {
1352 nssSession_ExitMonitor(session
);
1356 /* XXX the standard says this should work, but it doesn't */
1357 ckrv
= CKAPI(epv
)->C_Digest(session
->handle
, NULL
, 0, NULL
, &digestLen
);
1358 if (ckrv
!= CKR_OK
) {
1359 nssSession_ExitMonitor(session
);
1363 digestLen
= 0; /* XXX for now */
1366 if (rvOpt
->size
> 0 && rvOpt
->size
< digestLen
) {
1367 nssSession_ExitMonitor(session
);
1368 /* the error should be bad args */
1372 digest
= rvOpt
->data
;
1374 digestLen
= rvOpt
->size
;
1377 digest
= (CK_BYTE_PTR
)nss_ZAlloc(arenaOpt
, digestLen
);
1379 nssSession_ExitMonitor(session
);
1383 ckrv
= CKAPI(epv
)->C_Digest(session
->handle
,
1384 (CK_BYTE_PTR
)data
->data
,
1385 (CK_ULONG
)data
->size
,
1386 (CK_BYTE_PTR
)digest
,
1388 nssSession_ExitMonitor(session
);
1389 if (ckrv
!= CKR_OK
) {
1390 nss_ZFreeIf(digest
);
1394 rvItem
= nssItem_Create(arenaOpt
, NULL
, digestLen
, (void *)digest
);
1399 NSS_IMPLEMENT PRStatus
1400 nssToken_BeginDigest (
1402 nssSession
*sessionOpt
,
1403 NSSAlgorithmAndParameters
*ap
1407 nssSession
*session
;
1408 void *epv
= nssToken_GetCryptokiEPV(tok
);
1409 session
= (sessionOpt
) ? sessionOpt
: tok
->defaultSession
;
1410 nssSession_EnterMonitor(session
);
1411 ckrv
= CKAPI(epv
)->C_DigestInit(session
->handle
, &ap
->mechanism
);
1412 nssSession_ExitMonitor(session
);
1413 return (ckrv
== CKR_OK
) ? PR_SUCCESS
: PR_FAILURE
;
1416 NSS_IMPLEMENT PRStatus
1417 nssToken_ContinueDigest (
1419 nssSession
*sessionOpt
,
1424 nssSession
*session
;
1425 void *epv
= nssToken_GetCryptokiEPV(tok
);
1426 session
= (sessionOpt
) ? sessionOpt
: tok
->defaultSession
;
1427 nssSession_EnterMonitor(session
);
1428 ckrv
= CKAPI(epv
)->C_DigestUpdate(session
->handle
,
1429 (CK_BYTE_PTR
)item
->data
,
1430 (CK_ULONG
)item
->size
);
1431 nssSession_ExitMonitor(session
);
1432 return (ckrv
== CKR_OK
) ? PR_SUCCESS
: PR_FAILURE
;
1435 NSS_IMPLEMENT NSSItem
*
1436 nssToken_FinishDigest (
1438 nssSession
*sessionOpt
,
1446 NSSItem
*rvItem
= NULL
;
1447 void *epv
= nssToken_GetCryptokiEPV(tok
);
1448 nssSession
*session
;
1449 session
= (sessionOpt
) ? sessionOpt
: tok
->defaultSession
;
1450 nssSession_EnterMonitor(session
);
1451 ckrv
= CKAPI(epv
)->C_DigestFinal(session
->handle
, NULL
, &digestLen
);
1452 if (ckrv
!= CKR_OK
|| digestLen
== 0) {
1453 nssSession_ExitMonitor(session
);
1458 if (rvOpt
->size
> 0 && rvOpt
->size
< digestLen
) {
1459 nssSession_ExitMonitor(session
);
1460 /* the error should be bad args */
1464 digest
= rvOpt
->data
;
1466 digestLen
= rvOpt
->size
;
1469 digest
= (CK_BYTE_PTR
)nss_ZAlloc(arenaOpt
, digestLen
);
1471 nssSession_ExitMonitor(session
);
1475 ckrv
= CKAPI(epv
)->C_DigestFinal(session
->handle
, digest
, &digestLen
);
1476 nssSession_ExitMonitor(session
);
1477 if (ckrv
!= CKR_OK
) {
1478 nss_ZFreeIf(digest
);
1482 rvItem
= nssItem_Create(arenaOpt
, NULL
, digestLen
, (void *)digest
);
1487 NSS_IMPLEMENT PRBool
1488 nssToken_IsPresent (
1492 return nssSlot_IsTokenPresent(token
->slot
);
1495 /* Sigh. The methods to find objects declared above cause problems with
1496 * the low-level object cache in the softoken -- the objects are found in
1497 * toto, then one wave of GetAttributes is done, then another. Having a
1498 * large number of objects causes the cache to be thrashed, as the objects
1499 * are gone before there's any chance to ask for their attributes.
1500 * So, for now, bringing back traversal methods for certs. This way all of
1501 * the cert's attributes can be grabbed immediately after finding it,
1502 * increasing the likelihood that the cache takes care of it.
1504 NSS_IMPLEMENT PRStatus
1505 nssToken_TraverseCertificates (
1507 nssSession
*sessionOpt
,
1508 nssTokenSearchType searchType
,
1509 PRStatus (* callback
)(nssCryptokiObject
*instance
, void *arg
),
1515 CK_OBJECT_HANDLE
*objectHandles
;
1516 CK_ATTRIBUTE_PTR attr
;
1517 CK_ATTRIBUTE cert_template
[2];
1521 PRUint32 arraySize
, numHandles
;
1522 nssCryptokiObject
**objects
;
1523 void *epv
= nssToken_GetCryptokiEPV(token
);
1524 nssSession
*session
= (sessionOpt
) ? sessionOpt
: token
->defaultSession
;
1526 /* template for all certs */
1527 NSS_CK_TEMPLATE_START(cert_template
, attr
, ctsize
);
1528 if (searchType
== nssTokenSearchType_SessionOnly
) {
1529 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_false
);
1530 } else if (searchType
== nssTokenSearchType_TokenOnly
||
1531 searchType
== nssTokenSearchType_TokenForced
) {
1532 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_TOKEN
, &g_ck_true
);
1534 NSS_CK_SET_ATTRIBUTE_ITEM(attr
, CKA_CLASS
, &g_ck_class_cert
);
1535 NSS_CK_TEMPLATE_FINISH(cert_template
, attr
, ctsize
);
1537 /* the arena is only for the array of object handles */
1538 arena
= nssArena_Create();
1542 arraySize
= OBJECT_STACK_SIZE
;
1544 objectHandles
= nss_ZNEWARRAY(arena
, CK_OBJECT_HANDLE
, arraySize
);
1545 if (!objectHandles
) {
1548 nssSession_EnterMonitor(session
); /* ==== session lock === */
1549 /* Initialize the find with the template */
1550 ckrv
= CKAPI(epv
)->C_FindObjectsInit(session
->handle
,
1551 cert_template
, ctsize
);
1552 if (ckrv
!= CKR_OK
) {
1553 nssSession_ExitMonitor(session
);
1557 /* Issue the find for up to arraySize - numHandles objects */
1558 ckrv
= CKAPI(epv
)->C_FindObjects(session
->handle
,
1559 objectHandles
+ numHandles
,
1560 arraySize
- numHandles
,
1562 if (ckrv
!= CKR_OK
) {
1563 nssSession_ExitMonitor(session
);
1566 /* bump the number of found objects */
1567 numHandles
+= count
;
1568 if (numHandles
< arraySize
) {
1571 /* the array is filled, double it and continue */
1573 objectHandles
= nss_ZREALLOCARRAY(objectHandles
,
1576 if (!objectHandles
) {
1577 nssSession_ExitMonitor(session
);
1581 ckrv
= CKAPI(epv
)->C_FindObjectsFinal(session
->handle
);
1582 nssSession_ExitMonitor(session
); /* ==== end session lock === */
1583 if (ckrv
!= CKR_OK
) {
1586 if (numHandles
> 0) {
1587 objects
= create_objects_from_handles(token
, session
,
1588 objectHandles
, numHandles
);
1590 nssCryptokiObject
**op
;
1591 for (op
= objects
; *op
; op
++) {
1592 status
= (*callback
)(*op
, arg
);
1594 nss_ZFreeIf(objects
);
1597 nssArena_Destroy(arena
);
1600 nssArena_Destroy(arena
);
1604 NSS_IMPLEMENT PRBool
1605 nssToken_IsPrivateKeyAvailable (
1608 nssCryptokiObject
*instance
1611 CK_OBJECT_CLASS theClass
;
1613 if (token
== NULL
) return PR_FALSE
;
1614 if (c
== NULL
) return PR_FALSE
;
1616 theClass
= CKO_PRIVATE_KEY
;
1617 if (!nssSlot_IsLoggedIn(token
->slot
)) {
1618 theClass
= CKO_PUBLIC_KEY
;
1620 if (PK11_MatchItem(token
->pk11slot
, instance
->handle
, theClass
)
1621 != CK_INVALID_HANDLE
) {