Mercurial > trustbridge > nss-cmake-static
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 |