comparison nss/lib/dev/devutil.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #ifndef DEVM_H
6 #include "devm.h"
7 #endif /* DEVM_H */
8
9 #ifndef CKHELPER_H
10 #include "ckhelper.h"
11 #endif /* CKHELPER_H */
12
13 NSS_IMPLEMENT nssCryptokiObject *
14 nssCryptokiObject_Create (
15 NSSToken *t,
16 nssSession *session,
17 CK_OBJECT_HANDLE h
18 )
19 {
20 PRStatus status;
21 NSSSlot *slot;
22 nssCryptokiObject *object;
23 CK_BBOOL *isTokenObject;
24 CK_ATTRIBUTE cert_template[] = {
25 { CKA_TOKEN, NULL, 0 },
26 { CKA_LABEL, NULL, 0 }
27 };
28 slot = nssToken_GetSlot(t);
29 status = nssCKObject_GetAttributes(h, cert_template, 2,
30 NULL, session, slot);
31 nssSlot_Destroy(slot);
32 if (status != PR_SUCCESS) {
33 /* a failure here indicates a device error */
34 return (nssCryptokiObject *)NULL;
35 }
36 object = nss_ZNEW(NULL, nssCryptokiObject);
37 if (!object) {
38 return (nssCryptokiObject *)NULL;
39 }
40 object->handle = h;
41 object->token = nssToken_AddRef(t);
42 isTokenObject = (CK_BBOOL *)cert_template[0].pValue;
43 object->isTokenObject = *isTokenObject;
44 nss_ZFreeIf(isTokenObject);
45 NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[1], object->label);
46 return object;
47 }
48
49 NSS_IMPLEMENT void
50 nssCryptokiObject_Destroy (
51 nssCryptokiObject *object
52 )
53 {
54 if (object) {
55 nssToken_Destroy(object->token);
56 nss_ZFreeIf(object->label);
57 nss_ZFreeIf(object);
58 }
59 }
60
61 NSS_IMPLEMENT nssCryptokiObject *
62 nssCryptokiObject_Clone (
63 nssCryptokiObject *object
64 )
65 {
66 nssCryptokiObject *rvObject;
67 rvObject = nss_ZNEW(NULL, nssCryptokiObject);
68 if (rvObject) {
69 rvObject->handle = object->handle;
70 rvObject->token = nssToken_AddRef(object->token);
71 rvObject->isTokenObject = object->isTokenObject;
72 if (object->label) {
73 rvObject->label = nssUTF8_Duplicate(object->label, NULL);
74 }
75 }
76 return rvObject;
77 }
78
79 NSS_EXTERN PRBool
80 nssCryptokiObject_Equal (
81 nssCryptokiObject *o1,
82 nssCryptokiObject *o2
83 )
84 {
85 return (o1->token == o2->token && o1->handle == o2->handle);
86 }
87
88 NSS_IMPLEMENT PRUint32
89 nssPKCS11String_Length(CK_CHAR *pkcs11Str, PRUint32 bufLen)
90 {
91 PRInt32 i;
92 for (i = bufLen - 1; i>=0; ) {
93 if (pkcs11Str[i] != ' ' && pkcs11Str[i] != '\0') break;
94 --i;
95 }
96 return (PRUint32)(i + 1);
97 }
98
99 /*
100 * Slot arrays
101 */
102
103 NSS_IMPLEMENT NSSSlot **
104 nssSlotArray_Clone (
105 NSSSlot **slots
106 )
107 {
108 NSSSlot **rvSlots = NULL;
109 NSSSlot **sp = slots;
110 PRUint32 count = 0;
111 while (sp && *sp) count++;
112 if (count > 0) {
113 rvSlots = nss_ZNEWARRAY(NULL, NSSSlot *, count + 1);
114 if (rvSlots) {
115 for (sp = slots, count = 0; *sp; sp++) {
116 rvSlots[count++] = nssSlot_AddRef(*sp);
117 }
118 }
119 }
120 return rvSlots;
121 }
122
123 NSS_IMPLEMENT void
124 nssSlotArray_Destroy (
125 NSSSlot **slots
126 )
127 {
128 if (slots) {
129 NSSSlot **slotp;
130 for (slotp = slots; *slotp; slotp++) {
131 nssSlot_Destroy(*slotp);
132 }
133 nss_ZFreeIf(slots);
134 }
135 }
136
137 NSS_IMPLEMENT void
138 NSSSlotArray_Destroy (
139 NSSSlot **slots
140 )
141 {
142 nssSlotArray_Destroy(slots);
143 }
144
145 NSS_IMPLEMENT void
146 nssTokenArray_Destroy (
147 NSSToken **tokens
148 )
149 {
150 if (tokens) {
151 NSSToken **tokenp;
152 for (tokenp = tokens; *tokenp; tokenp++) {
153 nssToken_Destroy(*tokenp);
154 }
155 nss_ZFreeIf(tokens);
156 }
157 }
158
159 NSS_IMPLEMENT void
160 NSSTokenArray_Destroy (
161 NSSToken **tokens
162 )
163 {
164 nssTokenArray_Destroy(tokens);
165 }
166
167 NSS_IMPLEMENT void
168 nssCryptokiObjectArray_Destroy (
169 nssCryptokiObject **objects
170 )
171 {
172 if (objects) {
173 nssCryptokiObject **op;
174 for (op = objects; *op; op++) {
175 nssCryptokiObject_Destroy(*op);
176 }
177 nss_ZFreeIf(objects);
178 }
179 }
180
181 /* object cache for token */
182
183 typedef struct
184 {
185 NSSArena *arena;
186 nssCryptokiObject *object;
187 CK_ATTRIBUTE_PTR attributes;
188 CK_ULONG numAttributes;
189 }
190 nssCryptokiObjectAndAttributes;
191
192 enum {
193 cachedCerts = 0,
194 cachedTrust = 1,
195 cachedCRLs = 2
196 } cachedObjectType;
197
198 struct nssTokenObjectCacheStr
199 {
200 NSSToken *token;
201 PZLock *lock;
202 PRBool loggedIn;
203 PRBool doObjectType[3];
204 PRBool searchedObjectType[3];
205 nssCryptokiObjectAndAttributes **objects[3];
206 };
207
208 NSS_IMPLEMENT nssTokenObjectCache *
209 nssTokenObjectCache_Create (
210 NSSToken *token,
211 PRBool cacheCerts,
212 PRBool cacheTrust,
213 PRBool cacheCRLs
214 )
215 {
216 nssTokenObjectCache *rvCache;
217 rvCache = nss_ZNEW(NULL, nssTokenObjectCache);
218 if (!rvCache) {
219 goto loser;
220 }
221 rvCache->lock = PZ_NewLock(nssILockOther); /* XXX */
222 if (!rvCache->lock) {
223 goto loser;
224 }
225 rvCache->doObjectType[cachedCerts] = cacheCerts;
226 rvCache->doObjectType[cachedTrust] = cacheTrust;
227 rvCache->doObjectType[cachedCRLs] = cacheCRLs;
228 rvCache->token = token; /* cache goes away with token */
229 return rvCache;
230 loser:
231 nssTokenObjectCache_Destroy(rvCache);
232 return (nssTokenObjectCache *)NULL;
233 }
234
235 static void
236 clear_cache (
237 nssTokenObjectCache *cache
238 )
239 {
240 nssCryptokiObjectAndAttributes **oa;
241 PRUint32 objectType;
242 for (objectType = cachedCerts; objectType <= cachedCRLs; objectType++) {
243 cache->searchedObjectType[objectType] = PR_FALSE;
244 if (!cache->objects[objectType]) {
245 continue;
246 }
247 for (oa = cache->objects[objectType]; *oa; oa++) {
248 /* prevent the token from being destroyed */
249 (*oa)->object->token = NULL;
250 nssCryptokiObject_Destroy((*oa)->object);
251 nssArena_Destroy((*oa)->arena);
252 }
253 nss_ZFreeIf(cache->objects[objectType]);
254 cache->objects[objectType] = NULL;
255 }
256 }
257
258 NSS_IMPLEMENT void
259 nssTokenObjectCache_Clear (
260 nssTokenObjectCache *cache
261 )
262 {
263 if (cache) {
264 PZ_Lock(cache->lock);
265 clear_cache(cache);
266 PZ_Unlock(cache->lock);
267 }
268 }
269
270 NSS_IMPLEMENT void
271 nssTokenObjectCache_Destroy (
272 nssTokenObjectCache *cache
273 )
274 {
275 if (cache) {
276 clear_cache(cache);
277 if (cache->lock) {
278 PZ_DestroyLock(cache->lock);
279 }
280 nss_ZFreeIf(cache);
281 }
282 }
283
284 NSS_IMPLEMENT PRBool
285 nssTokenObjectCache_HaveObjectClass (
286 nssTokenObjectCache *cache,
287 CK_OBJECT_CLASS objclass
288 )
289 {
290 PRBool haveIt;
291 PZ_Lock(cache->lock);
292 switch (objclass) {
293 case CKO_CERTIFICATE: haveIt = cache->doObjectType[cachedCerts]; break;
294 case CKO_NETSCAPE_TRUST: haveIt = cache->doObjectType[cachedTrust]; break;
295 case CKO_NETSCAPE_CRL: haveIt = cache->doObjectType[cachedCRLs]; break;
296 default: haveIt = PR_FALSE;
297 }
298 PZ_Unlock(cache->lock);
299 return haveIt;
300 }
301
302 static nssCryptokiObjectAndAttributes **
303 create_object_array (
304 nssCryptokiObject **objects,
305 PRBool *doObjects,
306 PRUint32 *numObjects,
307 PRStatus *status
308 )
309 {
310 nssCryptokiObjectAndAttributes **rvOandA = NULL;
311 *numObjects = 0;
312 /* There are no objects for this type */
313 if (!objects || !*objects) {
314 *status = PR_SUCCESS;
315 return rvOandA;
316 }
317 while (*objects++) (*numObjects)++;
318 if (*numObjects >= MAX_LOCAL_CACHE_OBJECTS) {
319 /* Hit the maximum allowed, so don't use a cache (there are
320 * too many objects to make caching worthwhile, presumably, if
321 * the token can handle that many objects, it can handle searching.
322 */
323 *doObjects = PR_FALSE;
324 *status = PR_FAILURE;
325 *numObjects = 0;
326 } else {
327 rvOandA = nss_ZNEWARRAY(NULL,
328 nssCryptokiObjectAndAttributes *,
329 *numObjects + 1);
330 *status = rvOandA ? PR_SUCCESS : PR_FAILURE;
331 }
332 return rvOandA;
333 }
334
335 static nssCryptokiObjectAndAttributes *
336 create_object (
337 nssCryptokiObject *object,
338 const CK_ATTRIBUTE_TYPE *types,
339 PRUint32 numTypes,
340 PRStatus *status
341 )
342 {
343 PRUint32 j;
344 NSSArena *arena = NULL;
345 NSSSlot *slot = NULL;
346 nssSession *session = NULL;
347 nssCryptokiObjectAndAttributes *rvCachedObject = NULL;
348
349 slot = nssToken_GetSlot(object->token);
350 if (!slot) {
351 nss_SetError(NSS_ERROR_INVALID_POINTER);
352 goto loser;
353 }
354 session = nssToken_GetDefaultSession(object->token);
355 if (!session) {
356 nss_SetError(NSS_ERROR_INVALID_POINTER);
357 goto loser;
358 }
359 arena = nssArena_Create();
360 if (!arena) {
361 goto loser;
362 }
363 rvCachedObject = nss_ZNEW(arena, nssCryptokiObjectAndAttributes);
364 if (!rvCachedObject) {
365 goto loser;
366 }
367 rvCachedObject->arena = arena;
368 /* The cache is tied to the token, and therefore the objects
369 * in it should not hold references to the token.
370 */
371 nssToken_Destroy(object->token);
372 rvCachedObject->object = object;
373 rvCachedObject->attributes = nss_ZNEWARRAY(arena, CK_ATTRIBUTE, numTypes);
374 if (!rvCachedObject->attributes) {
375 goto loser;
376 }
377 for (j=0; j<numTypes; j++) {
378 rvCachedObject->attributes[j].type = types[j];
379 }
380 *status = nssCKObject_GetAttributes(object->handle,
381 rvCachedObject->attributes,
382 numTypes,
383 arena,
384 session,
385 slot);
386 if (*status != PR_SUCCESS) {
387 goto loser;
388 }
389 rvCachedObject->numAttributes = numTypes;
390 *status = PR_SUCCESS;
391 nssSlot_Destroy(slot);
392
393 return rvCachedObject;
394 loser:
395 *status = PR_FAILURE;
396 if (slot) {
397 nssSlot_Destroy(slot);
398 }
399 if (arena)
400 nssArena_Destroy(arena);
401 return (nssCryptokiObjectAndAttributes *)NULL;
402 }
403
404 /*
405 *
406 * State diagram for cache:
407 *
408 * token !present token removed
409 * +-------------------------+<----------------------+
410 * | ^ |
411 * v | |
412 * +----------+ slot friendly | token present +----------+
413 * | cache | -----------------> % ---------------> | cache |
414 * | unloaded | | loaded |
415 * +----------+ +----------+
416 * ^ | ^ |
417 * | | slot !friendly slot logged in | |
418 * | +-----------------------> % ----------------------+ |
419 * | | |
420 * | slot logged out v slot !friendly |
421 * +-----------------------------+<--------------------------+
422 *
423 */
424
425 /* This function must not be called with cache->lock locked. */
426 static PRBool
427 token_is_present (
428 nssTokenObjectCache *cache
429 )
430 {
431 NSSSlot *slot = nssToken_GetSlot(cache->token);
432 PRBool tokenPresent = nssSlot_IsTokenPresent(slot);
433 nssSlot_Destroy(slot);
434 return tokenPresent;
435 }
436
437 static PRBool
438 search_for_objects (
439 nssTokenObjectCache *cache
440 )
441 {
442 PRBool doSearch = PR_FALSE;
443 NSSSlot *slot = nssToken_GetSlot(cache->token);
444 /* Handle non-friendly slots (slots which require login for objects) */
445 if (!nssSlot_IsFriendly(slot)) {
446 if (nssSlot_IsLoggedIn(slot)) {
447 /* Either no state change, or went from !logged in -> logged in */
448 cache->loggedIn = PR_TRUE;
449 doSearch = PR_TRUE;
450 } else {
451 if (cache->loggedIn) {
452 /* went from logged in -> !logged in, destroy cached objects */
453 clear_cache(cache);
454 cache->loggedIn = PR_FALSE;
455 } /* else no state change, still not logged in, so exit */
456 }
457 } else {
458 /* slot is friendly, thus always available for search */
459 doSearch = PR_TRUE;
460 }
461 nssSlot_Destroy(slot);
462 return doSearch;
463 }
464
465 static nssCryptokiObjectAndAttributes *
466 create_cert (
467 nssCryptokiObject *object,
468 PRStatus *status
469 )
470 {
471 static const CK_ATTRIBUTE_TYPE certAttr[] = {
472 CKA_CLASS,
473 CKA_TOKEN,
474 CKA_LABEL,
475 CKA_CERTIFICATE_TYPE,
476 CKA_ID,
477 CKA_VALUE,
478 CKA_ISSUER,
479 CKA_SERIAL_NUMBER,
480 CKA_SUBJECT,
481 CKA_NETSCAPE_EMAIL
482 };
483 static const PRUint32 numCertAttr = sizeof(certAttr) / sizeof(certAttr[0]);
484 return create_object(object, certAttr, numCertAttr, status);
485 }
486
487 static nssCryptokiObjectAndAttributes *
488 create_trust (
489 nssCryptokiObject *object,
490 PRStatus *status
491 )
492 {
493 static const CK_ATTRIBUTE_TYPE trustAttr[] = {
494 CKA_CLASS,
495 CKA_TOKEN,
496 CKA_LABEL,
497 CKA_CERT_SHA1_HASH,
498 CKA_CERT_MD5_HASH,
499 CKA_ISSUER,
500 CKA_SUBJECT,
501 CKA_TRUST_SERVER_AUTH,
502 CKA_TRUST_CLIENT_AUTH,
503 CKA_TRUST_EMAIL_PROTECTION,
504 CKA_TRUST_CODE_SIGNING
505 };
506 static const PRUint32 numTrustAttr = sizeof(trustAttr) / sizeof(trustAttr[0]);
507 return create_object(object, trustAttr, numTrustAttr, status);
508 }
509
510 static nssCryptokiObjectAndAttributes *
511 create_crl (
512 nssCryptokiObject *object,
513 PRStatus *status
514 )
515 {
516 static const CK_ATTRIBUTE_TYPE crlAttr[] = {
517 CKA_CLASS,
518 CKA_TOKEN,
519 CKA_LABEL,
520 CKA_VALUE,
521 CKA_SUBJECT,
522 CKA_NETSCAPE_KRL,
523 CKA_NETSCAPE_URL
524 };
525 static const PRUint32 numCRLAttr = sizeof(crlAttr) / sizeof(crlAttr[0]);
526 return create_object(object, crlAttr, numCRLAttr, status);
527 }
528
529 /* Dispatch to the create function for the object type */
530 static nssCryptokiObjectAndAttributes *
531 create_object_of_type (
532 nssCryptokiObject *object,
533 PRUint32 objectType,
534 PRStatus *status
535 )
536 {
537 if (objectType == cachedCerts) {
538 return create_cert(object, status);
539 }
540 if (objectType == cachedTrust) {
541 return create_trust(object, status);
542 }
543 if (objectType == cachedCRLs) {
544 return create_crl(object, status);
545 }
546 return (nssCryptokiObjectAndAttributes *)NULL;
547 }
548
549 static PRStatus
550 get_token_objects_for_cache (
551 nssTokenObjectCache *cache,
552 PRUint32 objectType,
553 CK_OBJECT_CLASS objclass
554 )
555 {
556 PRStatus status;
557 nssCryptokiObject **objects;
558 PRBool *doIt = &cache->doObjectType[objectType];
559 PRUint32 i, numObjects;
560
561 if (!search_for_objects(cache) ||
562 cache->searchedObjectType[objectType] ||
563 !cache->doObjectType[objectType])
564 {
565 /* Either there was a state change that prevents a search
566 * (token logged out), or the search was already done,
567 * or objects of this type are not being cached.
568 */
569 return PR_SUCCESS;
570 }
571 objects = nssToken_FindObjects(cache->token, NULL, objclass,
572 nssTokenSearchType_TokenForced,
573 MAX_LOCAL_CACHE_OBJECTS, &status);
574 if (status != PR_SUCCESS) {
575 return status;
576 }
577 cache->objects[objectType] = create_object_array(objects,
578 doIt,
579 &numObjects,
580 &status);
581 if (status != PR_SUCCESS) {
582 return status;
583 }
584 for (i=0; i<numObjects; i++) {
585 cache->objects[objectType][i] = create_object_of_type(objects[i],
586 objectType,
587 &status);
588 if (status != PR_SUCCESS) {
589 break;
590 }
591 }
592 if (status == PR_SUCCESS) {
593 nss_ZFreeIf(objects);
594 } else {
595 PRUint32 j;
596 for (j=0; j<i; j++) {
597 /* sigh */
598 nssToken_AddRef(cache->objects[objectType][j]->object->token);
599 nssArena_Destroy(cache->objects[objectType][j]->arena);
600 }
601 nss_ZFreeIf(cache->objects[objectType]);
602 cache->objects[objectType] = NULL;
603 nssCryptokiObjectArray_Destroy(objects);
604 }
605 cache->searchedObjectType[objectType] = PR_TRUE;
606 return status;
607 }
608
609 static CK_ATTRIBUTE_PTR
610 find_attribute_in_object (
611 nssCryptokiObjectAndAttributes *obj,
612 CK_ATTRIBUTE_TYPE attrType
613 )
614 {
615 PRUint32 j;
616 for (j=0; j<obj->numAttributes; j++) {
617 if (attrType == obj->attributes[j].type) {
618 return &obj->attributes[j];
619 }
620 }
621 return (CK_ATTRIBUTE_PTR)NULL;
622 }
623
624 /* Find all objects in the array that match the supplied template */
625 static nssCryptokiObject **
626 find_objects_in_array (
627 nssCryptokiObjectAndAttributes **objArray,
628 CK_ATTRIBUTE_PTR ot,
629 CK_ULONG otlen,
630 PRUint32 maximumOpt
631 )
632 {
633 PRIntn oi = 0;
634 PRUint32 i;
635 NSSArena *arena;
636 PRUint32 size = 8;
637 PRUint32 numMatches = 0;
638 nssCryptokiObject **objects = NULL;
639 nssCryptokiObjectAndAttributes **matches = NULL;
640 CK_ATTRIBUTE_PTR attr;
641
642 if (!objArray) {
643 return (nssCryptokiObject **)NULL;
644 }
645 arena = nssArena_Create();
646 if (!arena) {
647 return (nssCryptokiObject **)NULL;
648 }
649 matches = nss_ZNEWARRAY(arena, nssCryptokiObjectAndAttributes *, size);
650 if (!matches) {
651 goto loser;
652 }
653 if (maximumOpt == 0) maximumOpt = ~0;
654 /* loop over the cached objects */
655 for (; *objArray && numMatches < maximumOpt; objArray++) {
656 nssCryptokiObjectAndAttributes *obj = *objArray;
657 /* loop over the test template */
658 for (i=0; i<otlen; i++) {
659 /* see if the object has the attribute */
660 attr = find_attribute_in_object(obj, ot[i].type);
661 if (!attr) {
662 /* nope, match failed */
663 break;
664 }
665 /* compare the attribute against the test value */
666 if (ot[i].ulValueLen != attr->ulValueLen ||
667 !nsslibc_memequal(ot[i].pValue,
668 attr->pValue,
669 attr->ulValueLen, NULL))
670 {
671 /* nope, match failed */
672 break;
673 }
674 }
675 if (i == otlen) {
676 /* all of the attributes in the test template were found
677 * in the object's template, and they all matched
678 */
679 matches[numMatches++] = obj;
680 if (numMatches == size) {
681 size *= 2;
682 matches = nss_ZREALLOCARRAY(matches,
683 nssCryptokiObjectAndAttributes *,
684 size);
685 if (!matches) {
686 goto loser;
687 }
688 }
689 }
690 }
691 if (numMatches > 0) {
692 objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numMatches + 1);
693 if (!objects) {
694 goto loser;
695 }
696 for (oi=0; oi<(PRIntn)numMatches; oi++) {
697 objects[oi] = nssCryptokiObject_Clone(matches[oi]->object);
698 if (!objects[oi]) {
699 goto loser;
700 }
701 }
702 }
703 nssArena_Destroy(arena);
704 return objects;
705 loser:
706 nssCryptokiObjectArray_Destroy(objects);
707 nssArena_Destroy(arena);
708 return (nssCryptokiObject **)NULL;
709 }
710
711 NSS_IMPLEMENT nssCryptokiObject **
712 nssTokenObjectCache_FindObjectsByTemplate (
713 nssTokenObjectCache *cache,
714 CK_OBJECT_CLASS objclass,
715 CK_ATTRIBUTE_PTR otemplate,
716 CK_ULONG otlen,
717 PRUint32 maximumOpt,
718 PRStatus *statusOpt
719 )
720 {
721 PRStatus status = PR_FAILURE;
722 nssCryptokiObject **rvObjects = NULL;
723 PRUint32 objectType;
724 if (!token_is_present(cache)) {
725 status = PR_SUCCESS;
726 goto finish;
727 }
728 switch (objclass) {
729 case CKO_CERTIFICATE: objectType = cachedCerts; break;
730 case CKO_NETSCAPE_TRUST: objectType = cachedTrust; break;
731 case CKO_NETSCAPE_CRL: objectType = cachedCRLs; break;
732 default: goto finish;
733 }
734 PZ_Lock(cache->lock);
735 if (cache->doObjectType[objectType]) {
736 status = get_token_objects_for_cache(cache, objectType, objclass);
737 if (status == PR_SUCCESS) {
738 rvObjects = find_objects_in_array(cache->objects[objectType],
739 otemplate, otlen, maximumOpt);
740 }
741 }
742 PZ_Unlock(cache->lock);
743 finish:
744 if (statusOpt) {
745 *statusOpt = status;
746 }
747 return rvObjects;
748 }
749
750 static PRBool
751 cache_available_for_object_type (
752 nssTokenObjectCache *cache,
753 PRUint32 objectType
754 )
755 {
756 if (!cache->doObjectType[objectType]) {
757 /* not caching this object kind */
758 return PR_FALSE;
759 }
760 if (!cache->searchedObjectType[objectType]) {
761 /* objects are not cached yet */
762 return PR_FALSE;
763 }
764 if (!search_for_objects(cache)) {
765 /* not logged in */
766 return PR_FALSE;
767 }
768 return PR_TRUE;
769 }
770
771 NSS_IMPLEMENT PRStatus
772 nssTokenObjectCache_GetObjectAttributes (
773 nssTokenObjectCache *cache,
774 NSSArena *arenaOpt,
775 nssCryptokiObject *object,
776 CK_OBJECT_CLASS objclass,
777 CK_ATTRIBUTE_PTR atemplate,
778 CK_ULONG atlen
779 )
780 {
781 PRUint32 i, j;
782 NSSArena *arena = NULL;
783 nssArenaMark *mark = NULL;
784 nssCryptokiObjectAndAttributes *cachedOA = NULL;
785 nssCryptokiObjectAndAttributes **oa = NULL;
786 PRUint32 objectType;
787 if (!token_is_present(cache)) {
788 return PR_FAILURE;
789 }
790 PZ_Lock(cache->lock);
791 switch (objclass) {
792 case CKO_CERTIFICATE: objectType = cachedCerts; break;
793 case CKO_NETSCAPE_TRUST: objectType = cachedTrust; break;
794 case CKO_NETSCAPE_CRL: objectType = cachedCRLs; break;
795 default: goto loser;
796 }
797 if (!cache_available_for_object_type(cache, objectType)) {
798 goto loser;
799 }
800 oa = cache->objects[objectType];
801 if (!oa) {
802 goto loser;
803 }
804 for (; *oa; oa++) {
805 if (nssCryptokiObject_Equal((*oa)->object, object)) {
806 cachedOA = *oa;
807 break;
808 }
809 }
810 if (!cachedOA) {
811 goto loser; /* don't have this object */
812 }
813 if (arenaOpt) {
814 arena = arenaOpt;
815 mark = nssArena_Mark(arena);
816 }
817 for (i=0; i<atlen; i++) {
818 for (j=0; j<cachedOA->numAttributes; j++) {
819 if (atemplate[i].type == cachedOA->attributes[j].type) {
820 CK_ATTRIBUTE_PTR attr = &cachedOA->attributes[j];
821 if (cachedOA->attributes[j].ulValueLen == 0 ||
822 cachedOA->attributes[j].ulValueLen == (CK_ULONG)-1)
823 {
824 break; /* invalid attribute */
825 }
826 if (atemplate[i].ulValueLen > 0) {
827 if (atemplate[i].pValue == NULL ||
828 atemplate[i].ulValueLen < attr->ulValueLen)
829 {
830 goto loser;
831 }
832 } else {
833 atemplate[i].pValue = nss_ZAlloc(arena, attr->ulValueLen);
834 if (!atemplate[i].pValue) {
835 goto loser;
836 }
837 }
838 nsslibc_memcpy(atemplate[i].pValue,
839 attr->pValue, attr->ulValueLen);
840 atemplate[i].ulValueLen = attr->ulValueLen;
841 break;
842 }
843 }
844 if (j == cachedOA->numAttributes) {
845 atemplate[i].ulValueLen = (CK_ULONG)-1;
846 }
847 }
848 PZ_Unlock(cache->lock);
849 if (mark) {
850 nssArena_Unmark(arena, mark);
851 }
852 return PR_SUCCESS;
853 loser:
854 PZ_Unlock(cache->lock);
855 if (mark) {
856 nssArena_Release(arena, mark);
857 }
858 return PR_FAILURE;
859 }
860
861 NSS_IMPLEMENT PRStatus
862 nssTokenObjectCache_ImportObject (
863 nssTokenObjectCache *cache,
864 nssCryptokiObject *object,
865 CK_OBJECT_CLASS objclass,
866 CK_ATTRIBUTE_PTR ot,
867 CK_ULONG otlen
868 )
869 {
870 PRStatus status = PR_SUCCESS;
871 PRUint32 count;
872 nssCryptokiObjectAndAttributes **oa, ***otype;
873 PRUint32 objectType;
874 PRBool haveIt = PR_FALSE;
875
876 if (!token_is_present(cache)) {
877 return PR_SUCCESS; /* cache not active, ignored */
878 }
879 PZ_Lock(cache->lock);
880 switch (objclass) {
881 case CKO_CERTIFICATE: objectType = cachedCerts; break;
882 case CKO_NETSCAPE_TRUST: objectType = cachedTrust; break;
883 case CKO_NETSCAPE_CRL: objectType = cachedCRLs; break;
884 default:
885 PZ_Unlock(cache->lock);
886 return PR_SUCCESS; /* don't need to import it here */
887 }
888 if (!cache_available_for_object_type(cache, objectType)) {
889 PZ_Unlock(cache->lock);
890 return PR_SUCCESS; /* cache not active, ignored */
891 }
892 count = 0;
893 otype = &cache->objects[objectType]; /* index into array of types */
894 oa = *otype; /* the array of objects for this type */
895 while (oa && *oa) {
896 if (nssCryptokiObject_Equal((*oa)->object, object)) {
897 haveIt = PR_TRUE;
898 break;
899 }
900 count++;
901 oa++;
902 }
903 if (haveIt) {
904 /* Destroy the old entry */
905 (*oa)->object->token = NULL;
906 nssCryptokiObject_Destroy((*oa)->object);
907 nssArena_Destroy((*oa)->arena);
908 } else {
909 /* Create space for a new entry */
910 if (count > 0) {
911 *otype = nss_ZREALLOCARRAY(*otype,
912 nssCryptokiObjectAndAttributes *,
913 count + 2);
914 } else {
915 *otype = nss_ZNEWARRAY(NULL, nssCryptokiObjectAndAttributes *, 2);
916 }
917 }
918 if (*otype) {
919 nssCryptokiObject *copyObject = nssCryptokiObject_Clone(object);
920 (*otype)[count] = create_object_of_type(copyObject, objectType,
921 &status);
922 } else {
923 status = PR_FAILURE;
924 }
925 PZ_Unlock(cache->lock);
926 return status;
927 }
928
929 NSS_IMPLEMENT void
930 nssTokenObjectCache_RemoveObject (
931 nssTokenObjectCache *cache,
932 nssCryptokiObject *object
933 )
934 {
935 PRUint32 oType;
936 nssCryptokiObjectAndAttributes **oa, **swp = NULL;
937 if (!token_is_present(cache)) {
938 return;
939 }
940 PZ_Lock(cache->lock);
941 for (oType=0; oType<3; oType++) {
942 if (!cache_available_for_object_type(cache, oType) ||
943 !cache->objects[oType])
944 {
945 continue;
946 }
947 for (oa = cache->objects[oType]; *oa; oa++) {
948 if (nssCryptokiObject_Equal((*oa)->object, object)) {
949 swp = oa; /* the entry to remove */
950 while (oa[1]) oa++; /* go to the tail */
951 (*swp)->object->token = NULL;
952 nssCryptokiObject_Destroy((*swp)->object);
953 nssArena_Destroy((*swp)->arena); /* destroy it */
954 *swp = *oa; /* swap the last with the removed */
955 *oa = NULL; /* null-terminate the array */
956 break;
957 }
958 }
959 if (swp) {
960 break;
961 }
962 }
963 if ((oType <3) &&
964 cache->objects[oType] && cache->objects[oType][0] == NULL) {
965 nss_ZFreeIf(cache->objects[oType]); /* no entries remaining */
966 cache->objects[oType] = NULL;
967 }
968 PZ_Unlock(cache->lock);
969 }
970
971 /* These two hash algorithms are presently sufficient.
972 ** They are used for fingerprints of certs which are stored as the
973 ** CKA_CERT_SHA1_HASH and CKA_CERT_MD5_HASH attributes.
974 ** We don't need to add SHAxxx to these now.
975 */
976 /* XXX of course this doesn't belong here */
977 NSS_IMPLEMENT NSSAlgorithmAndParameters *
978 NSSAlgorithmAndParameters_CreateSHA1Digest (
979 NSSArena *arenaOpt
980 )
981 {
982 NSSAlgorithmAndParameters *rvAP = NULL;
983 rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters);
984 if (rvAP) {
985 rvAP->mechanism.mechanism = CKM_SHA_1;
986 rvAP->mechanism.pParameter = NULL;
987 rvAP->mechanism.ulParameterLen = 0;
988 }
989 return rvAP;
990 }
991
992 NSS_IMPLEMENT NSSAlgorithmAndParameters *
993 NSSAlgorithmAndParameters_CreateMD5Digest (
994 NSSArena *arenaOpt
995 )
996 {
997 NSSAlgorithmAndParameters *rvAP = NULL;
998 rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters);
999 if (rvAP) {
1000 rvAP->mechanism.mechanism = CKM_MD5;
1001 rvAP->mechanism.pParameter = NULL;
1002 rvAP->mechanism.ulParameterLen = 0;
1003 }
1004 return rvAP;
1005 }
1006
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)