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: devutil.c,v $ $Revision: 1.28 $ $Date: 2006/10/31 00:21:24 $";
47 #endif /* CKHELPER_H */
49 NSS_IMPLEMENT nssCryptokiObject
*
50 nssCryptokiObject_Create (
58 nssCryptokiObject
*object
;
59 CK_BBOOL
*isTokenObject
;
60 CK_ATTRIBUTE cert_template
[] = {
61 { CKA_TOKEN
, NULL
, 0 },
62 { CKA_LABEL
, NULL
, 0 }
64 slot
= nssToken_GetSlot(t
);
65 status
= nssCKObject_GetAttributes(h
, cert_template
, 2,
67 nssSlot_Destroy(slot
);
68 if (status
!= PR_SUCCESS
) {
69 /* a failure here indicates a device error */
70 return (nssCryptokiObject
*)NULL
;
72 object
= nss_ZNEW(NULL
, nssCryptokiObject
);
74 return (nssCryptokiObject
*)NULL
;
77 object
->token
= nssToken_AddRef(t
);
78 isTokenObject
= (CK_BBOOL
*)cert_template
[0].pValue
;
79 object
->isTokenObject
= *isTokenObject
;
80 nss_ZFreeIf(isTokenObject
);
81 NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template
[1], object
->label
);
86 nssCryptokiObject_Destroy (
87 nssCryptokiObject
*object
91 nssToken_Destroy(object
->token
);
92 nss_ZFreeIf(object
->label
);
97 NSS_IMPLEMENT nssCryptokiObject
*
98 nssCryptokiObject_Clone (
99 nssCryptokiObject
*object
102 nssCryptokiObject
*rvObject
;
103 rvObject
= nss_ZNEW(NULL
, nssCryptokiObject
);
105 rvObject
->handle
= object
->handle
;
106 rvObject
->token
= nssToken_AddRef(object
->token
);
107 rvObject
->isTokenObject
= object
->isTokenObject
;
109 rvObject
->label
= nssUTF8_Duplicate(object
->label
, NULL
);
116 nssCryptokiObject_Equal (
117 nssCryptokiObject
*o1
,
118 nssCryptokiObject
*o2
121 return (o1
->token
== o2
->token
&& o1
->handle
== o2
->handle
);
124 NSS_IMPLEMENT PRUint32
125 nssPKCS11String_Length(CK_CHAR
*pkcs11Str
, PRUint32 bufLen
)
128 for (i
= bufLen
- 1; i
>=0; ) {
129 if (pkcs11Str
[i
] != ' ' && pkcs11Str
[i
] != '\0') break;
132 return (PRUint32
)(i
+ 1);
139 NSS_IMPLEMENT NSSSlot
**
144 NSSSlot
**rvSlots
= NULL
;
145 NSSSlot
**sp
= slots
;
147 while (sp
&& *sp
) count
++;
149 rvSlots
= nss_ZNEWARRAY(NULL
, NSSSlot
*, count
+ 1);
153 for (sp
= slots
; *sp
; sp
++) {
154 rvSlots
[count
++] = nssSlot_AddRef(*sp
);
161 #ifdef PURE_STAN_BUILD
163 nssModuleArray_Destroy (
169 for (mp
= modules
; *mp
; mp
++) {
170 nssModule_Destroy(*mp
);
172 nss_ZFreeIf(modules
);
178 nssSlotArray_Destroy (
184 for (slotp
= slots
; *slotp
; slotp
++) {
185 nssSlot_Destroy(*slotp
);
192 NSSSlotArray_Destroy (
196 nssSlotArray_Destroy(slots
);
200 nssTokenArray_Destroy (
206 for (tokenp
= tokens
; *tokenp
; tokenp
++) {
207 nssToken_Destroy(*tokenp
);
214 NSSTokenArray_Destroy (
218 nssTokenArray_Destroy(tokens
);
222 nssCryptokiObjectArray_Destroy (
223 nssCryptokiObject
**objects
227 nssCryptokiObject
**op
;
228 for (op
= objects
; *op
; op
++) {
229 nssCryptokiObject_Destroy(*op
);
231 nss_ZFreeIf(objects
);
235 #ifdef PURE_STAN_BUILD
240 struct nssSlotListNodeStr
247 /* XXX separate slots with non-present tokens? */
248 struct nssSlotListStr
251 PRBool i_allocated_arena
;
257 NSS_IMPLEMENT nssSlotList
*
267 mark
= nssArena_Mark(arena
);
269 return (nssSlotList
*)NULL
;
272 arena
= nssArena_Create();
274 return (nssSlotList
*)NULL
;
277 rvList
= nss_ZNEW(arena
, nssSlotList
);
281 rvList
->lock
= PZ_NewLock(nssILockOther
); /* XXX */
285 PR_INIT_CLIST(&rvList
->head
);
286 rvList
->arena
= arena
;
287 rvList
->i_allocated_arena
= (arenaOpt
== NULL
);
288 nssArena_Unmark(arena
, mark
);
292 nssArena_Release(arena
, mark
);
294 nssArena_Destroy(arena
);
296 return (nssSlotList
*)NULL
;
300 nssSlotList_Destroy (
301 nssSlotList
*slotList
305 struct nssSlotListNodeStr
*node
;
307 link
= PR_NEXT_LINK(&slotList
->head
);
308 while (link
!= &slotList
->head
) {
309 node
= (struct nssSlotListNodeStr
*)link
;
310 nssSlot_Destroy(node
->slot
);
311 link
= PR_NEXT_LINK(link
);
313 if (slotList
->i_allocated_arena
) {
314 nssArena_Destroy(slotList
->arena
);
319 /* XXX should do allocs outside of lock */
320 NSS_IMPLEMENT PRStatus
322 nssSlotList
*slotList
,
328 struct nssSlotListNodeStr
*node
;
329 PZ_Lock(slotList
->lock
);
330 link
= PR_NEXT_LINK(&slotList
->head
);
331 while (link
!= &slotList
->head
) {
332 node
= (struct nssSlotListNodeStr
*)link
;
333 if (order
< node
->order
) {
336 link
= PR_NEXT_LINK(link
);
338 node
= nss_ZNEW(slotList
->arena
, struct nssSlotListNodeStr
);
342 PR_INIT_CLIST(&node
->link
);
343 node
->slot
= nssSlot_AddRef(slot
);
345 PR_INSERT_AFTER(&node
->link
, link
);
347 PZ_Unlock(slotList
->lock
);
351 NSS_IMPLEMENT PRStatus
352 nssSlotList_AddModuleSlots (
353 nssSlotList
*slotList
,
358 nssArenaMark
*mark
= NULL
;
359 NSSSlot
**sp
, **slots
= NULL
;
361 struct nssSlotListNodeStr
*node
;
362 PZ_Lock(slotList
->lock
);
363 link
= PR_NEXT_LINK(&slotList
->head
);
364 while (link
!= &slotList
->head
) {
365 node
= (struct nssSlotListNodeStr
*)link
;
366 if (order
< node
->order
) {
369 link
= PR_NEXT_LINK(link
);
371 slots
= nssModule_GetSlots(module
);
373 PZ_Unlock(slotList
->lock
);
376 mark
= nssArena_Mark(slotList
->arena
);
380 for (sp
= slots
; *sp
; sp
++) {
381 node
= nss_ZNEW(slotList
->arena
, struct nssSlotListNodeStr
);
385 PR_INIT_CLIST(&node
->link
);
386 node
->slot
= *sp
; /* have ref from nssModule_GetSlots */
388 PR_INSERT_AFTER(&node
->link
, link
);
391 PZ_Unlock(slotList
->lock
);
392 nssArena_Unmark(slotList
->arena
, mark
);
395 PZ_Unlock(slotList
->lock
);
397 nssArena_Release(slotList
->arena
, mark
);
400 nssSlotArray_Destroy(slots
);
405 NSS_IMPLEMENT NSSSlot
**
406 nssSlotList_GetSlots (
407 nssSlotList
*slotList
412 struct nssSlotListNodeStr
*node
;
413 NSSSlot
**rvSlots
= NULL
;
414 PZ_Lock(slotList
->lock
);
415 rvSlots
= nss_ZNEWARRAY(NULL
, NSSSlot
*, slotList
->count
+ 1);
417 PZ_Unlock(slotList
->lock
);
418 return (NSSSlot
**)NULL
;
421 link
= PR_NEXT_LINK(&slotList
->head
);
422 while (link
!= &slotList
->head
) {
423 node
= (struct nssSlotListNodeStr
*)link
;
424 rvSlots
[i
] = nssSlot_AddRef(node
->slot
);
425 link
= PR_NEXT_LINK(link
);
428 PZ_Unlock(slotList
->lock
);
433 NSS_IMPLEMENT NSSSlot
*
434 nssSlotList_GetBestSlotForAlgorithmAndParameters (
435 nssSlotList
*slotList
,
436 NSSAlgorithmAndParameters
*ap
440 struct nssSlotListNodeStr
*node
;
441 NSSSlot
*rvSlot
= NULL
;
442 PZ_Lock(slotList
->lock
);
443 link
= PR_NEXT_LINK(&slotList
->head
);
444 while (link
!= &slotList
->head
) {
445 node
= (struct nssSlotListNodeStr
*)link
;
446 if (nssSlot_DoesAlgorithmAndParameters(ap
)) {
447 rvSlot
= nssSlot_AddRef(node
->slot
); /* XXX check isPresent? */
449 link
= PR_NEXT_LINK(link
);
451 PZ_Unlock(slotList
->lock
);
456 NSS_IMPLEMENT NSSSlot
*
457 nssSlotList_GetBestSlot (
458 nssSlotList
*slotList
462 struct nssSlotListNodeStr
*node
;
463 NSSSlot
*rvSlot
= NULL
;
464 PZ_Lock(slotList
->lock
);
465 if (PR_CLIST_IS_EMPTY(&slotList
->head
)) {
466 PZ_Unlock(slotList
->lock
);
467 return (NSSSlot
*)NULL
;
469 link
= PR_NEXT_LINK(&slotList
->head
);
470 node
= (struct nssSlotListNodeStr
*)link
;
471 rvSlot
= nssSlot_AddRef(node
->slot
); /* XXX check isPresent? */
472 PZ_Unlock(slotList
->lock
);
476 NSS_IMPLEMENT NSSSlot
*
477 nssSlotList_FindSlotByName (
478 nssSlotList
*slotList
,
483 struct nssSlotListNodeStr
*node
;
484 NSSSlot
*rvSlot
= NULL
;
485 PZ_Lock(slotList
->lock
);
486 link
= PR_NEXT_LINK(&slotList
->head
);
487 while (link
!= &slotList
->head
) {
489 node
= (struct nssSlotListNodeStr
*)link
;
490 sName
= nssSlot_GetName(node
->slot
);
491 if (nssUTF8_Equal(sName
, slotName
, NULL
)) {
492 rvSlot
= nssSlot_AddRef(node
->slot
);
495 link
= PR_NEXT_LINK(link
);
497 PZ_Unlock(slotList
->lock
);
501 NSS_IMPLEMENT NSSToken
*
502 nssSlotList_FindTokenByName (
503 nssSlotList
*slotList
,
508 struct nssSlotListNodeStr
*node
;
509 NSSToken
*rvToken
= NULL
;
510 PZ_Lock(slotList
->lock
);
511 link
= PR_NEXT_LINK(&slotList
->head
);
512 while (link
!= &slotList
->head
) {
514 node
= (struct nssSlotListNodeStr
*)link
;
515 tName
= nssSlot_GetTokenName(node
->slot
);
516 if (nssUTF8_Equal(tName
, tokenName
, NULL
)) {
517 rvToken
= nssSlot_GetToken(node
->slot
);
520 link
= PR_NEXT_LINK(link
);
522 PZ_Unlock(slotList
->lock
);
525 #endif /* PURE_STAN_BUILD */
527 /* object cache for token */
532 nssCryptokiObject
*object
;
533 CK_ATTRIBUTE_PTR attributes
;
534 CK_ULONG numAttributes
;
536 nssCryptokiObjectAndAttributes
;
544 struct nssTokenObjectCacheStr
549 PRBool doObjectType
[3];
550 PRBool searchedObjectType
[3];
551 nssCryptokiObjectAndAttributes
**objects
[3];
554 NSS_IMPLEMENT nssTokenObjectCache
*
555 nssTokenObjectCache_Create (
562 nssTokenObjectCache
*rvCache
;
563 rvCache
= nss_ZNEW(NULL
, nssTokenObjectCache
);
567 rvCache
->lock
= PZ_NewLock(nssILockOther
); /* XXX */
568 if (!rvCache
->lock
) {
571 rvCache
->doObjectType
[cachedCerts
] = cacheCerts
;
572 rvCache
->doObjectType
[cachedTrust
] = cacheTrust
;
573 rvCache
->doObjectType
[cachedCRLs
] = cacheCRLs
;
574 rvCache
->token
= token
; /* cache goes away with token */
577 return (nssTokenObjectCache
*)NULL
;
582 nssTokenObjectCache
*cache
585 nssCryptokiObjectAndAttributes
**oa
;
587 for (objectType
= cachedCerts
; objectType
<= cachedCRLs
; objectType
++) {
588 cache
->searchedObjectType
[objectType
] = PR_FALSE
;
589 if (!cache
->objects
[objectType
]) {
592 for (oa
= cache
->objects
[objectType
]; *oa
; oa
++) {
593 /* prevent the token from being destroyed */
594 (*oa
)->object
->token
= NULL
;
595 nssCryptokiObject_Destroy((*oa
)->object
);
596 nssArena_Destroy((*oa
)->arena
);
598 nss_ZFreeIf(cache
->objects
[objectType
]);
599 cache
->objects
[objectType
] = NULL
;
604 nssTokenObjectCache_Clear (
605 nssTokenObjectCache
*cache
609 PZ_Lock(cache
->lock
);
611 PZ_Unlock(cache
->lock
);
616 nssTokenObjectCache_Destroy (
617 nssTokenObjectCache
*cache
622 PZ_DestroyLock(cache
->lock
);
628 nssTokenObjectCache_HaveObjectClass (
629 nssTokenObjectCache
*cache
,
630 CK_OBJECT_CLASS objclass
634 PZ_Lock(cache
->lock
);
636 case CKO_CERTIFICATE
: haveIt
= cache
->doObjectType
[cachedCerts
]; break;
637 case CKO_NETSCAPE_TRUST
: haveIt
= cache
->doObjectType
[cachedTrust
]; break;
638 case CKO_NETSCAPE_CRL
: haveIt
= cache
->doObjectType
[cachedCRLs
]; break;
639 default: haveIt
= PR_FALSE
;
641 PZ_Unlock(cache
->lock
);
645 static nssCryptokiObjectAndAttributes
**
646 create_object_array (
647 nssCryptokiObject
**objects
,
649 PRUint32
*numObjects
,
653 nssCryptokiObjectAndAttributes
**rvOandA
= NULL
;
655 /* There are no objects for this type */
656 if (!objects
|| !*objects
) {
657 *status
= PR_SUCCESS
;
660 while (*objects
++) (*numObjects
)++;
661 if (*numObjects
>= MAX_LOCAL_CACHE_OBJECTS
) {
662 /* Hit the maximum allowed, so don't use a cache (there are
663 * too many objects to make caching worthwhile, presumably, if
664 * the token can handle that many objects, it can handle searching.
666 *doObjects
= PR_FALSE
;
667 *status
= PR_FAILURE
;
670 rvOandA
= nss_ZNEWARRAY(NULL
,
671 nssCryptokiObjectAndAttributes
*,
673 *status
= rvOandA
? PR_SUCCESS
: PR_FAILURE
;
678 static nssCryptokiObjectAndAttributes
*
680 nssCryptokiObject
*object
,
681 const CK_ATTRIBUTE_TYPE
*types
,
688 NSSSlot
*slot
= NULL
;
689 nssSession
*session
= NULL
;
690 nssCryptokiObjectAndAttributes
*rvCachedObject
= NULL
;
692 slot
= nssToken_GetSlot(object
->token
);
694 nss_SetError(NSS_ERROR_INVALID_POINTER
);
697 session
= nssToken_GetDefaultSession(object
->token
);
699 arena
= nssArena_Create();
703 rvCachedObject
= nss_ZNEW(arena
, nssCryptokiObjectAndAttributes
);
704 if (!rvCachedObject
) {
707 rvCachedObject
->arena
= arena
;
708 /* The cache is tied to the token, and therefore the objects
709 * in it should not hold references to the token.
711 nssToken_Destroy(object
->token
);
712 rvCachedObject
->object
= object
;
713 rvCachedObject
->attributes
= nss_ZNEWARRAY(arena
, CK_ATTRIBUTE
, numTypes
);
714 if (!rvCachedObject
->attributes
) {
717 for (j
=0; j
<numTypes
; j
++) {
718 rvCachedObject
->attributes
[j
].type
= types
[j
];
720 *status
= nssCKObject_GetAttributes(object
->handle
,
721 rvCachedObject
->attributes
,
726 if (*status
!= PR_SUCCESS
) {
729 rvCachedObject
->numAttributes
= numTypes
;
730 *status
= PR_SUCCESS
;
731 nssSlot_Destroy(slot
);
733 return rvCachedObject
;
735 *status
= PR_FAILURE
;
737 nssSlot_Destroy(slot
);
740 nssArena_Destroy(arena
);
741 return (nssCryptokiObjectAndAttributes
*)NULL
;
746 * State diagram for cache:
748 * token !present token removed
749 * +-------------------------+<----------------------+
752 * +----------+ slot friendly | token present +----------+
753 * | cache | -----------------> % ---------------> | cache |
754 * | unloaded | | loaded |
755 * +----------+ +----------+
757 * | | slot !friendly slot logged in | |
758 * | +-----------------------> % ----------------------+ |
760 * | slot logged out v slot !friendly |
761 * +-----------------------------+<--------------------------+
765 /* This function must not be called with cache->lock locked. */
768 nssTokenObjectCache
*cache
771 NSSSlot
*slot
= nssToken_GetSlot(cache
->token
);
772 PRBool tokenPresent
= nssSlot_IsTokenPresent(slot
);
773 nssSlot_Destroy(slot
);
779 nssTokenObjectCache
*cache
782 PRBool doSearch
= PR_FALSE
;
783 NSSSlot
*slot
= nssToken_GetSlot(cache
->token
);
784 /* Handle non-friendly slots (slots which require login for objects) */
785 if (!nssSlot_IsFriendly(slot
)) {
786 if (nssSlot_IsLoggedIn(slot
)) {
787 /* Either no state change, or went from !logged in -> logged in */
788 cache
->loggedIn
= PR_TRUE
;
791 if (cache
->loggedIn
) {
792 /* went from logged in -> !logged in, destroy cached objects */
794 cache
->loggedIn
= PR_FALSE
;
795 } /* else no state change, still not logged in, so exit */
798 /* slot is friendly, thus always available for search */
801 nssSlot_Destroy(slot
);
805 static nssCryptokiObjectAndAttributes
*
807 nssCryptokiObject
*object
,
811 static const CK_ATTRIBUTE_TYPE certAttr
[] = {
815 CKA_CERTIFICATE_TYPE
,
823 static const PRUint32 numCertAttr
= sizeof(certAttr
) / sizeof(certAttr
[0]);
824 return create_object(object
, certAttr
, numCertAttr
, status
);
828 get_token_certs_for_cache (
829 nssTokenObjectCache
*cache
833 nssCryptokiObject
**objects
;
834 PRBool
*doIt
= &cache
->doObjectType
[cachedCerts
];
835 PRUint32 i
, numObjects
;
837 if (!search_for_objects(cache
) ||
838 cache
->searchedObjectType
[cachedCerts
] ||
839 !cache
->doObjectType
[cachedCerts
])
841 /* Either there was a state change that prevents a search
842 * (token logged out), or the search was already done,
843 * or certs are not being cached.
847 objects
= nssToken_FindCertificates(cache
->token
, NULL
,
848 nssTokenSearchType_TokenForced
,
849 MAX_LOCAL_CACHE_OBJECTS
, &status
);
850 if (status
!= PR_SUCCESS
) {
853 cache
->objects
[cachedCerts
] = create_object_array(objects
,
857 if (status
!= PR_SUCCESS
) {
860 for (i
=0; i
<numObjects
; i
++) {
861 cache
->objects
[cachedCerts
][i
] = create_cert(objects
[i
], &status
);
862 if (status
!= PR_SUCCESS
) {
866 if (status
== PR_SUCCESS
) {
867 nss_ZFreeIf(objects
);
870 for (j
=0; j
<i
; j
++) {
872 nssToken_AddRef(cache
->objects
[cachedCerts
][j
]->object
->token
);
873 nssArena_Destroy(cache
->objects
[cachedCerts
][j
]->arena
);
875 nssCryptokiObjectArray_Destroy(objects
);
877 cache
->searchedObjectType
[cachedCerts
] = PR_TRUE
;
881 static nssCryptokiObjectAndAttributes
*
883 nssCryptokiObject
*object
,
887 static const CK_ATTRIBUTE_TYPE trustAttr
[] = {
895 CKA_TRUST_SERVER_AUTH
,
896 CKA_TRUST_CLIENT_AUTH
,
897 CKA_TRUST_EMAIL_PROTECTION
,
898 CKA_TRUST_CODE_SIGNING
900 static const PRUint32 numTrustAttr
= sizeof(trustAttr
) / sizeof(trustAttr
[0]);
901 return create_object(object
, trustAttr
, numTrustAttr
, status
);
905 get_token_trust_for_cache (
906 nssTokenObjectCache
*cache
910 nssCryptokiObject
**objects
;
911 PRBool
*doIt
= &cache
->doObjectType
[cachedTrust
];
912 PRUint32 i
, numObjects
;
914 if (!search_for_objects(cache
) ||
915 cache
->searchedObjectType
[cachedTrust
] ||
916 !cache
->doObjectType
[cachedTrust
])
918 /* Either there was a state change that prevents a search
919 * (token logged out), or the search was already done,
920 * or trust is not being cached.
924 objects
= nssToken_FindTrustObjects(cache
->token
, NULL
,
925 nssTokenSearchType_TokenForced
,
926 MAX_LOCAL_CACHE_OBJECTS
, &status
);
927 if (status
!= PR_SUCCESS
) {
930 cache
->objects
[cachedTrust
] = create_object_array(objects
,
934 if (status
!= PR_SUCCESS
) {
937 for (i
=0; i
<numObjects
; i
++) {
938 cache
->objects
[cachedTrust
][i
] = create_trust(objects
[i
], &status
);
939 if (status
!= PR_SUCCESS
) {
943 if (status
== PR_SUCCESS
) {
944 nss_ZFreeIf(objects
);
947 for (j
=0; j
<i
; j
++) {
949 nssToken_AddRef(cache
->objects
[cachedTrust
][j
]->object
->token
);
950 nssArena_Destroy(cache
->objects
[cachedTrust
][j
]->arena
);
952 nssCryptokiObjectArray_Destroy(objects
);
954 cache
->searchedObjectType
[cachedTrust
] = PR_TRUE
;
958 static nssCryptokiObjectAndAttributes
*
960 nssCryptokiObject
*object
,
964 static const CK_ATTRIBUTE_TYPE crlAttr
[] = {
973 static const PRUint32 numCRLAttr
= sizeof(crlAttr
) / sizeof(crlAttr
[0]);
974 return create_object(object
, crlAttr
, numCRLAttr
, status
);
978 get_token_crls_for_cache (
979 nssTokenObjectCache
*cache
983 nssCryptokiObject
**objects
;
984 PRBool
*doIt
= &cache
->doObjectType
[cachedCRLs
];
985 PRUint32 i
, numObjects
;
987 if (!search_for_objects(cache
) ||
988 cache
->searchedObjectType
[cachedCRLs
] ||
989 !cache
->doObjectType
[cachedCRLs
])
991 /* Either there was a state change that prevents a search
992 * (token logged out), or the search was already done,
993 * or CRLs are not being cached.
997 objects
= nssToken_FindCRLs(cache
->token
, NULL
,
998 nssTokenSearchType_TokenForced
,
999 MAX_LOCAL_CACHE_OBJECTS
, &status
);
1000 if (status
!= PR_SUCCESS
) {
1003 cache
->objects
[cachedCRLs
] = create_object_array(objects
,
1007 if (status
!= PR_SUCCESS
) {
1010 for (i
=0; i
<numObjects
; i
++) {
1011 cache
->objects
[cachedCRLs
][i
] = create_crl(objects
[i
], &status
);
1012 if (status
!= PR_SUCCESS
) {
1016 if (status
== PR_SUCCESS
) {
1017 nss_ZFreeIf(objects
);
1020 for (j
=0; j
<i
; j
++) {
1022 nssToken_AddRef(cache
->objects
[cachedCRLs
][j
]->object
->token
);
1023 nssArena_Destroy(cache
->objects
[cachedCRLs
][j
]->arena
);
1025 nssCryptokiObjectArray_Destroy(objects
);
1027 cache
->searchedObjectType
[cachedCRLs
] = PR_TRUE
;
1031 static CK_ATTRIBUTE_PTR
1032 find_attribute_in_object (
1033 nssCryptokiObjectAndAttributes
*obj
,
1034 CK_ATTRIBUTE_TYPE attrType
1038 for (j
=0; j
<obj
->numAttributes
; j
++) {
1039 if (attrType
== obj
->attributes
[j
].type
) {
1040 return &obj
->attributes
[j
];
1043 return (CK_ATTRIBUTE_PTR
)NULL
;
1046 /* Find all objects in the array that match the supplied template */
1047 static nssCryptokiObject
**
1048 find_objects_in_array (
1049 nssCryptokiObjectAndAttributes
**objArray
,
1050 CK_ATTRIBUTE_PTR ot
,
1059 PRUint32 numMatches
= 0;
1060 nssCryptokiObject
**objects
= NULL
;
1061 nssCryptokiObjectAndAttributes
**matches
= NULL
;
1062 CK_ATTRIBUTE_PTR attr
;
1065 return (nssCryptokiObject
**)NULL
;
1067 arena
= nssArena_Create();
1069 return (nssCryptokiObject
**)NULL
;
1071 matches
= nss_ZNEWARRAY(arena
, nssCryptokiObjectAndAttributes
*, size
);
1075 if (maximumOpt
== 0) maximumOpt
= ~0;
1076 /* loop over the cached objects */
1077 for (; *objArray
&& numMatches
< maximumOpt
; objArray
++) {
1078 nssCryptokiObjectAndAttributes
*obj
= *objArray
;
1079 /* loop over the test template */
1080 for (i
=0; i
<otlen
; i
++) {
1081 /* see if the object has the attribute */
1082 attr
= find_attribute_in_object(obj
, ot
[i
].type
);
1084 /* nope, match failed */
1087 /* compare the attribute against the test value */
1088 if (ot
[i
].ulValueLen
!= attr
->ulValueLen
||
1089 !nsslibc_memequal(ot
[i
].pValue
,
1091 attr
->ulValueLen
, NULL
))
1093 /* nope, match failed */
1098 /* all of the attributes in the test template were found
1099 * in the object's template, and they all matched
1101 matches
[numMatches
++] = obj
;
1102 if (numMatches
== size
) {
1104 matches
= nss_ZREALLOCARRAY(matches
,
1105 nssCryptokiObjectAndAttributes
*,
1113 if (numMatches
> 0) {
1114 objects
= nss_ZNEWARRAY(NULL
, nssCryptokiObject
*, numMatches
+ 1);
1118 for (oi
=0; oi
<(PRIntn
)numMatches
; oi
++) {
1119 objects
[oi
] = nssCryptokiObject_Clone(matches
[oi
]->object
);
1125 nssArena_Destroy(arena
);
1129 for (--oi
; oi
>=0; --oi
) {
1130 nssCryptokiObject_Destroy(objects
[oi
]);
1133 nssArena_Destroy(arena
);
1134 return (nssCryptokiObject
**)NULL
;
1137 NSS_IMPLEMENT nssCryptokiObject
**
1138 nssTokenObjectCache_FindObjectsByTemplate (
1139 nssTokenObjectCache
*cache
,
1140 CK_OBJECT_CLASS objclass
,
1141 CK_ATTRIBUTE_PTR otemplate
,
1143 PRUint32 maximumOpt
,
1147 PRStatus status
= PR_FAILURE
;
1148 nssCryptokiObject
**rvObjects
= NULL
;
1149 if (!token_is_present(cache
)) {
1150 status
= PR_SUCCESS
;
1153 PZ_Lock(cache
->lock
);
1155 case CKO_CERTIFICATE
:
1156 if (cache
->doObjectType
[cachedCerts
]) {
1157 status
= get_token_certs_for_cache(cache
);
1158 if (status
!= PR_SUCCESS
) {
1161 rvObjects
= find_objects_in_array(cache
->objects
[cachedCerts
],
1162 otemplate
, otlen
, maximumOpt
);
1165 case CKO_NETSCAPE_TRUST
:
1166 if (cache
->doObjectType
[cachedTrust
]) {
1167 status
= get_token_trust_for_cache(cache
);
1168 if (status
!= PR_SUCCESS
) {
1171 rvObjects
= find_objects_in_array(cache
->objects
[cachedTrust
],
1172 otemplate
, otlen
, maximumOpt
);
1175 case CKO_NETSCAPE_CRL
:
1176 if (cache
->doObjectType
[cachedCRLs
]) {
1177 status
= get_token_crls_for_cache(cache
);
1178 if (status
!= PR_SUCCESS
) {
1181 rvObjects
= find_objects_in_array(cache
->objects
[cachedCRLs
],
1182 otemplate
, otlen
, maximumOpt
);
1188 PZ_Unlock(cache
->lock
);
1191 *statusOpt
= status
;
1197 cache_available_for_object_type (
1198 nssTokenObjectCache
*cache
,
1202 if (!cache
->doObjectType
[objectType
]) {
1203 /* not caching this object kind */
1206 if (!cache
->searchedObjectType
[objectType
]) {
1207 /* objects are not cached yet */
1210 if (!search_for_objects(cache
)) {
1217 NSS_IMPLEMENT PRStatus
1218 nssTokenObjectCache_GetObjectAttributes (
1219 nssTokenObjectCache
*cache
,
1221 nssCryptokiObject
*object
,
1222 CK_OBJECT_CLASS objclass
,
1223 CK_ATTRIBUTE_PTR atemplate
,
1228 NSSArena
*arena
= NULL
;
1229 nssArenaMark
*mark
= NULL
;
1230 nssCryptokiObjectAndAttributes
*cachedOA
= NULL
;
1231 nssCryptokiObjectAndAttributes
**oa
= NULL
;
1232 PRUint32 objectType
;
1233 if (!token_is_present(cache
)) {
1236 PZ_Lock(cache
->lock
);
1238 case CKO_CERTIFICATE
: objectType
= cachedCerts
; break;
1239 case CKO_NETSCAPE_TRUST
: objectType
= cachedTrust
; break;
1240 case CKO_NETSCAPE_CRL
: objectType
= cachedCRLs
; break;
1241 default: goto loser
;
1243 if (!cache_available_for_object_type(cache
, objectType
)) {
1246 oa
= cache
->objects
[objectType
];
1251 if (nssCryptokiObject_Equal((*oa
)->object
, object
)) {
1257 goto loser
; /* don't have this object */
1261 mark
= nssArena_Mark(arena
);
1263 for (i
=0; i
<atlen
; i
++) {
1264 for (j
=0; j
<cachedOA
->numAttributes
; j
++) {
1265 if (atemplate
[i
].type
== cachedOA
->attributes
[j
].type
) {
1266 CK_ATTRIBUTE_PTR attr
= &cachedOA
->attributes
[j
];
1267 if (cachedOA
->attributes
[j
].ulValueLen
== 0 ||
1268 cachedOA
->attributes
[j
].ulValueLen
== (CK_ULONG
)-1)
1270 break; /* invalid attribute */
1272 if (atemplate
[i
].ulValueLen
> 0) {
1273 if (atemplate
[i
].pValue
== NULL
||
1274 atemplate
[i
].ulValueLen
< attr
->ulValueLen
)
1279 atemplate
[i
].pValue
= nss_ZAlloc(arena
, attr
->ulValueLen
);
1280 if (!atemplate
[i
].pValue
) {
1284 nsslibc_memcpy(atemplate
[i
].pValue
,
1285 attr
->pValue
, attr
->ulValueLen
);
1286 atemplate
[i
].ulValueLen
= attr
->ulValueLen
;
1290 if (j
== cachedOA
->numAttributes
) {
1291 atemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1294 PZ_Unlock(cache
->lock
);
1296 nssArena_Unmark(arena
, mark
);
1300 PZ_Unlock(cache
->lock
);
1302 nssArena_Release(arena
, mark
);
1307 NSS_IMPLEMENT PRStatus
1308 nssTokenObjectCache_ImportObject (
1309 nssTokenObjectCache
*cache
,
1310 nssCryptokiObject
*object
,
1311 CK_OBJECT_CLASS objclass
,
1312 CK_ATTRIBUTE_PTR ot
,
1316 PRStatus status
= PR_SUCCESS
;
1318 nssCryptokiObjectAndAttributes
**oa
, ***otype
;
1319 PRUint32 objectType
;
1320 PRBool haveIt
= PR_FALSE
;
1322 if (!token_is_present(cache
)) {
1323 return PR_SUCCESS
; /* cache not active, ignored */
1325 PZ_Lock(cache
->lock
);
1327 case CKO_CERTIFICATE
: objectType
= cachedCerts
; break;
1328 case CKO_NETSCAPE_TRUST
: objectType
= cachedTrust
; break;
1329 case CKO_NETSCAPE_CRL
: objectType
= cachedCRLs
; break;
1331 PZ_Unlock(cache
->lock
);
1332 return PR_SUCCESS
; /* don't need to import it here */
1334 if (!cache_available_for_object_type(cache
, objectType
)) {
1335 PZ_Unlock(cache
->lock
);
1336 return PR_SUCCESS
; /* cache not active, ignored */
1339 otype
= &cache
->objects
[objectType
]; /* index into array of types */
1340 oa
= *otype
; /* the array of objects for this type */
1342 if (nssCryptokiObject_Equal((*oa
)->object
, object
)) {
1350 /* Destroy the old entry */
1351 (*oa
)->object
->token
= NULL
;
1352 nssCryptokiObject_Destroy((*oa
)->object
);
1353 nssArena_Destroy((*oa
)->arena
);
1355 /* Create space for a new entry */
1357 *otype
= nss_ZREALLOCARRAY(*otype
,
1358 nssCryptokiObjectAndAttributes
*,
1361 *otype
= nss_ZNEWARRAY(NULL
, nssCryptokiObjectAndAttributes
*, 2);
1365 nssCryptokiObject
*copyObject
= nssCryptokiObject_Clone(object
);
1366 if (objectType
== cachedCerts
) {
1367 (*otype
)[count
] = create_cert(copyObject
, &status
);
1368 } else if (objectType
== cachedTrust
) {
1369 (*otype
)[count
] = create_trust(copyObject
, &status
);
1370 } else if (objectType
== cachedCRLs
) {
1371 (*otype
)[count
] = create_crl(copyObject
, &status
);
1374 status
= PR_FAILURE
;
1376 PZ_Unlock(cache
->lock
);
1381 nssTokenObjectCache_RemoveObject (
1382 nssTokenObjectCache
*cache
,
1383 nssCryptokiObject
*object
1387 nssCryptokiObjectAndAttributes
**oa
, **swp
= NULL
;
1388 if (!token_is_present(cache
)) {
1391 PZ_Lock(cache
->lock
);
1392 for (oType
=0; oType
<3; oType
++) {
1393 if (!cache_available_for_object_type(cache
, oType
) ||
1394 !cache
->objects
[oType
])
1398 for (oa
= cache
->objects
[oType
]; *oa
; oa
++) {
1399 if (nssCryptokiObject_Equal((*oa
)->object
, object
)) {
1400 swp
= oa
; /* the entry to remove */
1401 while (oa
[1]) oa
++; /* go to the tail */
1402 (*swp
)->object
->token
= NULL
;
1403 nssCryptokiObject_Destroy((*swp
)->object
);
1404 nssArena_Destroy((*swp
)->arena
); /* destroy it */
1405 *swp
= *oa
; /* swap the last with the removed */
1406 *oa
= NULL
; /* null-terminate the array */
1415 cache
->objects
[oType
] && cache
->objects
[oType
][0] == NULL
) {
1416 nss_ZFreeIf(cache
->objects
[oType
]); /* no entries remaining */
1417 cache
->objects
[oType
] = NULL
;
1419 PZ_Unlock(cache
->lock
);
1422 /* These two hash algorithms are presently sufficient.
1423 ** They are used for fingerprints of certs which are stored as the
1424 ** CKA_CERT_SHA1_HASH and CKA_CERT_MD5_HASH attributes.
1425 ** We don't need to add SHAxxx to these now.
1427 /* XXX of course this doesn't belong here */
1428 NSS_IMPLEMENT NSSAlgorithmAndParameters
*
1429 NSSAlgorithmAndParameters_CreateSHA1Digest (
1433 NSSAlgorithmAndParameters
*rvAP
= NULL
;
1434 rvAP
= nss_ZNEW(arenaOpt
, NSSAlgorithmAndParameters
);
1436 rvAP
->mechanism
.mechanism
= CKM_SHA_1
;
1437 rvAP
->mechanism
.pParameter
= NULL
;
1438 rvAP
->mechanism
.ulParameterLen
= 0;
1443 NSS_IMPLEMENT NSSAlgorithmAndParameters
*
1444 NSSAlgorithmAndParameters_CreateMD5Digest (
1448 NSSAlgorithmAndParameters
*rvAP
= NULL
;
1449 rvAP
= nss_ZNEW(arenaOpt
, NSSAlgorithmAndParameters
);
1451 rvAP
->mechanism
.mechanism
= CKM_MD5
;
1452 rvAP
->mechanism
.pParameter
= NULL
;
1453 rvAP
->mechanism
.ulParameterLen
= 0;