Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Side by Side Diff: mozilla/security/nss/lib/pki/pkibase.c

Issue 14249009: Change the NSS and NSPR source tree to the new directory structure to be (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mozilla/security/nss/lib/pki/pki3hack.c ('k') | mozilla/security/nss/lib/pki/pkim.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 #ifdef DEBUG
6 static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.36 $ $Da te: 2012/07/27 21:41:52 $";
7 #endif /* DEBUG */
8
9 #ifndef DEV_H
10 #include "dev.h"
11 #endif /* DEV_H */
12
13 #ifndef PKIM_H
14 #include "pkim.h"
15 #endif /* PKIM_H */
16
17 #include "pki3hack.h"
18
19 extern const NSSError NSS_ERROR_NOT_FOUND;
20
21 NSS_IMPLEMENT void
22 nssPKIObject_Lock(nssPKIObject * object)
23 {
24 switch (object->lockType) {
25 case nssPKIMonitor:
26 PZ_EnterMonitor(object->sync.mlock);
27 break;
28 case nssPKILock:
29 PZ_Lock(object->sync.lock);
30 break;
31 default:
32 PORT_Assert(0);
33 }
34 }
35
36 NSS_IMPLEMENT void
37 nssPKIObject_Unlock(nssPKIObject * object)
38 {
39 switch (object->lockType) {
40 case nssPKIMonitor:
41 PZ_ExitMonitor(object->sync.mlock);
42 break;
43 case nssPKILock:
44 PZ_Unlock(object->sync.lock);
45 break;
46 default:
47 PORT_Assert(0);
48 }
49 }
50
51 NSS_IMPLEMENT PRStatus
52 nssPKIObject_NewLock(nssPKIObject * object, nssPKILockType lockType)
53 {
54 object->lockType = lockType;
55 switch (lockType) {
56 case nssPKIMonitor:
57 object->sync.mlock = PZ_NewMonitor(nssILockSSL);
58 return (object->sync.mlock ? PR_SUCCESS : PR_FAILURE);
59 case nssPKILock:
60 object->sync.lock = PZ_NewLock(nssILockSSL);
61 return (object->sync.lock ? PR_SUCCESS : PR_FAILURE);
62 default:
63 PORT_Assert(0);
64 return PR_FAILURE;
65 }
66 }
67
68 NSS_IMPLEMENT void
69 nssPKIObject_DestroyLock(nssPKIObject * object)
70 {
71 switch (object->lockType) {
72 case nssPKIMonitor:
73 PZ_DestroyMonitor(object->sync.mlock);
74 object->sync.mlock = NULL;
75 break;
76 case nssPKILock:
77 PZ_DestroyLock(object->sync.lock);
78 object->sync.lock = NULL;
79 break;
80 default:
81 PORT_Assert(0);
82 }
83 }
84
85
86
87 NSS_IMPLEMENT nssPKIObject *
88 nssPKIObject_Create (
89 NSSArena *arenaOpt,
90 nssCryptokiObject *instanceOpt,
91 NSSTrustDomain *td,
92 NSSCryptoContext *cc,
93 nssPKILockType lockType
94 )
95 {
96 NSSArena *arena;
97 nssArenaMark *mark = NULL;
98 nssPKIObject *object;
99 if (arenaOpt) {
100 arena = arenaOpt;
101 mark = nssArena_Mark(arena);
102 } else {
103 arena = nssArena_Create();
104 if (!arena) {
105 return (nssPKIObject *)NULL;
106 }
107 }
108 object = nss_ZNEW(arena, nssPKIObject);
109 if (!object) {
110 goto loser;
111 }
112 object->arena = arena;
113 object->trustDomain = td; /* XXX */
114 object->cryptoContext = cc;
115 if (PR_SUCCESS != nssPKIObject_NewLock(object, lockType)) {
116 goto loser;
117 }
118 if (instanceOpt) {
119 if (nssPKIObject_AddInstance(object, instanceOpt) != PR_SUCCESS) {
120 goto loser;
121 }
122 }
123 PR_ATOMIC_INCREMENT(&object->refCount);
124 if (mark) {
125 nssArena_Unmark(arena, mark);
126 }
127 return object;
128 loser:
129 if (mark) {
130 nssArena_Release(arena, mark);
131 } else {
132 nssArena_Destroy(arena);
133 }
134 return (nssPKIObject *)NULL;
135 }
136
137 NSS_IMPLEMENT PRBool
138 nssPKIObject_Destroy (
139 nssPKIObject *object
140 )
141 {
142 PRUint32 i;
143 PR_ASSERT(object->refCount > 0);
144 if (PR_ATOMIC_DECREMENT(&object->refCount) == 0) {
145 for (i=0; i<object->numInstances; i++) {
146 nssCryptokiObject_Destroy(object->instances[i]);
147 }
148 nssPKIObject_DestroyLock(object);
149 nssArena_Destroy(object->arena);
150 return PR_TRUE;
151 }
152 return PR_FALSE;
153 }
154
155 NSS_IMPLEMENT nssPKIObject *
156 nssPKIObject_AddRef (
157 nssPKIObject *object
158 )
159 {
160 PR_ATOMIC_INCREMENT(&object->refCount);
161 return object;
162 }
163
164 NSS_IMPLEMENT PRStatus
165 nssPKIObject_AddInstance (
166 nssPKIObject *object,
167 nssCryptokiObject *instance
168 )
169 {
170 nssCryptokiObject **newInstances = NULL;
171
172 nssPKIObject_Lock(object);
173 if (object->numInstances == 0) {
174 newInstances = nss_ZNEWARRAY(object->arena,
175 nssCryptokiObject *,
176 object->numInstances + 1);
177 } else {
178 PRBool found = PR_FALSE;
179 PRUint32 i;
180 for (i=0; i<object->numInstances; i++) {
181 if (nssCryptokiObject_Equal(object->instances[i], instance)) {
182 found = PR_TRUE;
183 break;
184 }
185 }
186 if (found) {
187 /* The new instance is identical to one in the array, except
188 * perhaps that the label may be different. So replace
189 * the label in the array instance with the label from the
190 * new instance, and discard the new instance.
191 */
192 nss_ZFreeIf(object->instances[i]->label);
193 object->instances[i]->label = instance->label;
194 nssPKIObject_Unlock(object);
195 instance->label = NULL;
196 nssCryptokiObject_Destroy(instance);
197 return PR_SUCCESS;
198 }
199 newInstances = nss_ZREALLOCARRAY(object->instances,
200 nssCryptokiObject *,
201 object->numInstances + 1);
202 }
203 if (newInstances) {
204 object->instances = newInstances;
205 newInstances[object->numInstances++] = instance;
206 }
207 nssPKIObject_Unlock(object);
208 return (newInstances ? PR_SUCCESS : PR_FAILURE);
209 }
210
211 NSS_IMPLEMENT PRBool
212 nssPKIObject_HasInstance (
213 nssPKIObject *object,
214 nssCryptokiObject *instance
215 )
216 {
217 PRUint32 i;
218 PRBool hasIt = PR_FALSE;;
219 nssPKIObject_Lock(object);
220 for (i=0; i<object->numInstances; i++) {
221 if (nssCryptokiObject_Equal(object->instances[i], instance)) {
222 hasIt = PR_TRUE;
223 break;
224 }
225 }
226 nssPKIObject_Unlock(object);
227 return hasIt;
228 }
229
230 NSS_IMPLEMENT PRStatus
231 nssPKIObject_RemoveInstanceForToken (
232 nssPKIObject *object,
233 NSSToken *token
234 )
235 {
236 PRUint32 i;
237 nssCryptokiObject *instanceToRemove = NULL;
238 nssPKIObject_Lock(object);
239 if (object->numInstances == 0) {
240 nssPKIObject_Unlock(object);
241 return PR_SUCCESS;
242 }
243 for (i=0; i<object->numInstances; i++) {
244 if (object->instances[i]->token == token) {
245 instanceToRemove = object->instances[i];
246 object->instances[i] = object->instances[object->numInstances-1];
247 object->instances[object->numInstances-1] = NULL;
248 break;
249 }
250 }
251 if (--object->numInstances > 0) {
252 nssCryptokiObject **instances = nss_ZREALLOCARRAY(object->instances,
253 nssCryptokiObject *,
254 object->numInstances);
255 if (instances) {
256 object->instances = instances;
257 }
258 } else {
259 nss_ZFreeIf(object->instances);
260 }
261 nssCryptokiObject_Destroy(instanceToRemove);
262 nssPKIObject_Unlock(object);
263 return PR_SUCCESS;
264 }
265
266 /* this needs more thought on what will happen when there are multiple
267 * instances
268 */
269 NSS_IMPLEMENT PRStatus
270 nssPKIObject_DeleteStoredObject (
271 nssPKIObject *object,
272 NSSCallback *uhh,
273 PRBool isFriendly
274 )
275 {
276 PRUint32 i, numNotDestroyed;
277 PRStatus status = PR_SUCCESS;
278 numNotDestroyed = 0;
279 nssPKIObject_Lock(object);
280 for (i=0; i<object->numInstances; i++) {
281 nssCryptokiObject *instance = object->instances[i];
282 status = nssToken_DeleteStoredObject(instance);
283 object->instances[i] = NULL;
284 if (status == PR_SUCCESS) {
285 nssCryptokiObject_Destroy(instance);
286 } else {
287 object->instances[numNotDestroyed++] = instance;
288 }
289 }
290 if (numNotDestroyed == 0) {
291 nss_ZFreeIf(object->instances);
292 object->numInstances = 0;
293 } else {
294 object->numInstances = numNotDestroyed;
295 }
296 nssPKIObject_Unlock(object);
297 return status;
298 }
299
300 NSS_IMPLEMENT NSSToken **
301 nssPKIObject_GetTokens (
302 nssPKIObject *object,
303 PRStatus *statusOpt
304 )
305 {
306 NSSToken **tokens = NULL;
307 nssPKIObject_Lock(object);
308 if (object->numInstances > 0) {
309 tokens = nss_ZNEWARRAY(NULL, NSSToken *, object->numInstances + 1);
310 if (tokens) {
311 PRUint32 i;
312 for (i=0; i<object->numInstances; i++) {
313 tokens[i] = nssToken_AddRef(object->instances[i]->token);
314 }
315 }
316 }
317 nssPKIObject_Unlock(object);
318 if (statusOpt) *statusOpt = PR_SUCCESS; /* until more logic here */
319 return tokens;
320 }
321
322 NSS_IMPLEMENT NSSUTF8 *
323 nssPKIObject_GetNicknameForToken (
324 nssPKIObject *object,
325 NSSToken *tokenOpt
326 )
327 {
328 PRUint32 i;
329 NSSUTF8 *nickname = NULL;
330 nssPKIObject_Lock(object);
331 for (i=0; i<object->numInstances; i++) {
332 if ((!tokenOpt && object->instances[i]->label) ||
333 (object->instances[i]->token == tokenOpt))
334 {
335 /* Must copy, see bug 745548 */
336 nickname = nssUTF8_Duplicate(object->instances[i]->label, NULL);
337 break;
338 }
339 }
340 nssPKIObject_Unlock(object);
341 return nickname;
342 }
343
344 NSS_IMPLEMENT nssCryptokiObject **
345 nssPKIObject_GetInstances (
346 nssPKIObject *object
347 )
348 {
349 nssCryptokiObject **instances = NULL;
350 PRUint32 i;
351 if (object->numInstances == 0) {
352 return (nssCryptokiObject **)NULL;
353 }
354 nssPKIObject_Lock(object);
355 instances = nss_ZNEWARRAY(NULL, nssCryptokiObject *,
356 object->numInstances + 1);
357 if (instances) {
358 for (i=0; i<object->numInstances; i++) {
359 instances[i] = nssCryptokiObject_Clone(object->instances[i]);
360 }
361 }
362 nssPKIObject_Unlock(object);
363 return instances;
364 }
365
366 NSS_IMPLEMENT void
367 nssCertificateArray_Destroy (
368 NSSCertificate **certs
369 )
370 {
371 if (certs) {
372 NSSCertificate **certp;
373 for (certp = certs; *certp; certp++) {
374 if ((*certp)->decoding) {
375 CERTCertificate *cc = STAN_GetCERTCertificate(*certp);
376 if (cc) {
377 CERT_DestroyCertificate(cc);
378 }
379 continue;
380 }
381 nssCertificate_Destroy(*certp);
382 }
383 nss_ZFreeIf(certs);
384 }
385 }
386
387 NSS_IMPLEMENT void
388 NSSCertificateArray_Destroy (
389 NSSCertificate **certs
390 )
391 {
392 nssCertificateArray_Destroy(certs);
393 }
394
395 NSS_IMPLEMENT NSSCertificate **
396 nssCertificateArray_Join (
397 NSSCertificate **certs1,
398 NSSCertificate **certs2
399 )
400 {
401 if (certs1 && certs2) {
402 NSSCertificate **certs, **cp;
403 PRUint32 count = 0;
404 PRUint32 count1 = 0;
405 cp = certs1;
406 while (*cp++) count1++;
407 count = count1;
408 cp = certs2;
409 while (*cp++) count++;
410 certs = nss_ZREALLOCARRAY(certs1, NSSCertificate *, count + 1);
411 if (!certs) {
412 nss_ZFreeIf(certs1);
413 nss_ZFreeIf(certs2);
414 return (NSSCertificate **)NULL;
415 }
416 for (cp = certs2; *cp; cp++, count1++) {
417 certs[count1] = *cp;
418 }
419 nss_ZFreeIf(certs2);
420 return certs;
421 } else if (certs1) {
422 return certs1;
423 } else {
424 return certs2;
425 }
426 }
427
428 NSS_IMPLEMENT NSSCertificate *
429 nssCertificateArray_FindBestCertificate (
430 NSSCertificate **certs,
431 NSSTime *timeOpt,
432 const NSSUsage *usage,
433 NSSPolicies *policiesOpt
434 )
435 {
436 NSSCertificate *bestCert = NULL;
437 nssDecodedCert *bestdc = NULL;
438 NSSTime *time, sTime;
439 PRBool bestCertMatches = PR_FALSE;
440 PRBool thisCertMatches;
441 PRBool bestCertIsValidAtTime = PR_FALSE;
442 PRBool bestCertIsTrusted = PR_FALSE;
443
444 if (timeOpt) {
445 time = timeOpt;
446 } else {
447 NSSTime_Now(&sTime);
448 time = &sTime;
449 }
450 if (!certs) {
451 return (NSSCertificate *)NULL;
452 }
453 for (; *certs; certs++) {
454 nssDecodedCert *dc;
455 NSSCertificate *c = *certs;
456 dc = nssCertificate_GetDecoding(c);
457 if (!dc) continue;
458 thisCertMatches = dc->matchUsage(dc, usage);
459 if (!bestCert) {
460 /* always take the first cert, but remember whether or not
461 * the usage matched
462 */
463 bestCert = nssCertificate_AddRef(c);
464 bestCertMatches = thisCertMatches;
465 bestdc = dc;
466 continue;
467 } else {
468 if (bestCertMatches && !thisCertMatches) {
469 /* if already have a cert for this usage, and if this cert
470 * doesn't have the correct usage, continue
471 */
472 continue;
473 } else if (!bestCertMatches && thisCertMatches) {
474 /* this one does match usage, replace the other */
475 nssCertificate_Destroy(bestCert);
476 bestCert = nssCertificate_AddRef(c);
477 bestCertMatches = thisCertMatches;
478 bestdc = dc;
479 continue;
480 }
481 /* this cert match as well as any cert we've found so far,
482 * defer to time/policies
483 * */
484 }
485 /* time */
486 if (bestCertIsValidAtTime || bestdc->isValidAtTime(bestdc, time)) {
487 /* The current best cert is valid at time */
488 bestCertIsValidAtTime = PR_TRUE;
489 if (!dc->isValidAtTime(dc, time)) {
490 /* If the new cert isn't valid at time, it's not better */
491 continue;
492 }
493 } else {
494 /* The current best cert is not valid at time */
495 if (dc->isValidAtTime(dc, time)) {
496 /* If the new cert is valid at time, it's better */
497 nssCertificate_Destroy(bestCert);
498 bestCert = nssCertificate_AddRef(c);
499 bestdc = dc;
500 bestCertIsValidAtTime = PR_TRUE;
501 continue;
502 }
503 }
504 /* Either they are both valid at time, or neither valid.
505 * If only one is trusted for this usage, take it.
506 */
507 if (bestCertIsTrusted || bestdc->isTrustedForUsage(bestdc, usage)) {
508 bestCertIsTrusted = PR_TRUE;
509 if (!dc->isTrustedForUsage(dc, usage)) {
510 continue;
511 }
512 } else {
513 /* The current best cert is not trusted */
514 if (dc->isTrustedForUsage(dc, usage)) {
515 /* If the new cert is trusted, it's better */
516 nssCertificate_Destroy(bestCert);
517 bestCert = nssCertificate_AddRef(c);
518 bestdc = dc;
519 bestCertIsTrusted = PR_TRUE;
520 continue;
521 }
522 }
523 /* Otherwise, take the newer one. */
524 if (!bestdc->isNewerThan(bestdc, dc)) {
525 nssCertificate_Destroy(bestCert);
526 bestCert = nssCertificate_AddRef(c);
527 bestdc = dc;
528 continue;
529 }
530 /* policies */
531 /* XXX later -- defer to policies */
532 }
533 return bestCert;
534 }
535
536 NSS_IMPLEMENT PRStatus
537 nssCertificateArray_Traverse (
538 NSSCertificate **certs,
539 PRStatus (* callback)(NSSCertificate *c, void *arg),
540 void *arg
541 )
542 {
543 PRStatus status = PR_SUCCESS;
544 if (certs) {
545 NSSCertificate **certp;
546 for (certp = certs; *certp; certp++) {
547 status = (*callback)(*certp, arg);
548 if (status != PR_SUCCESS) {
549 break;
550 }
551 }
552 }
553 return status;
554 }
555
556
557 NSS_IMPLEMENT void
558 nssCRLArray_Destroy (
559 NSSCRL **crls
560 )
561 {
562 if (crls) {
563 NSSCRL **crlp;
564 for (crlp = crls; *crlp; crlp++) {
565 nssCRL_Destroy(*crlp);
566 }
567 nss_ZFreeIf(crls);
568 }
569 }
570
571 /*
572 * Object collections
573 */
574
575 typedef enum
576 {
577 pkiObjectType_Certificate = 0,
578 pkiObjectType_CRL = 1,
579 pkiObjectType_PrivateKey = 2,
580 pkiObjectType_PublicKey = 3
581 } pkiObjectType;
582
583 /* Each object is defined by a set of items that uniquely identify it.
584 * Here are the uid sets:
585 *
586 * NSSCertificate ==> { issuer, serial }
587 * NSSPrivateKey
588 * (RSA) ==> { modulus, public exponent }
589 *
590 */
591 #define MAX_ITEMS_FOR_UID 2
592
593 /* pkiObjectCollectionNode
594 *
595 * A node in the collection is the set of unique identifiers for a single
596 * object, along with either the actual object or a proto-object.
597 */
598 typedef struct
599 {
600 PRCList link;
601 PRBool haveObject;
602 nssPKIObject *object;
603 NSSItem uid[MAX_ITEMS_FOR_UID];
604 }
605 pkiObjectCollectionNode;
606
607 /* nssPKIObjectCollection
608 *
609 * The collection is the set of all objects, plus the interfaces needed
610 * to manage the objects.
611 *
612 */
613 struct nssPKIObjectCollectionStr
614 {
615 NSSArena *arena;
616 NSSTrustDomain *td;
617 NSSCryptoContext *cc;
618 PRCList head; /* list of pkiObjectCollectionNode's */
619 PRUint32 size;
620 pkiObjectType objectType;
621 void (* destroyObject)(nssPKIObject *o);
622 PRStatus (* getUIDFromObject)(nssPKIObject *o, NSSItem *uid);
623 PRStatus (* getUIDFromInstance)(nssCryptokiObject *co, NSSItem *uid,
624 NSSArena *arena);
625 nssPKIObject * (* createObject)(nssPKIObject *o);
626 nssPKILockType lockType; /* type of lock to use for new proto-objects */
627 };
628
629 static nssPKIObjectCollection *
630 nssPKIObjectCollection_Create (
631 NSSTrustDomain *td,
632 NSSCryptoContext *ccOpt,
633 nssPKILockType lockType
634 )
635 {
636 NSSArena *arena;
637 nssPKIObjectCollection *rvCollection = NULL;
638 arena = nssArena_Create();
639 if (!arena) {
640 return (nssPKIObjectCollection *)NULL;
641 }
642 rvCollection = nss_ZNEW(arena, nssPKIObjectCollection);
643 if (!rvCollection) {
644 goto loser;
645 }
646 PR_INIT_CLIST(&rvCollection->head);
647 rvCollection->arena = arena;
648 rvCollection->td = td; /* XXX */
649 rvCollection->cc = ccOpt;
650 rvCollection->lockType = lockType;
651 return rvCollection;
652 loser:
653 nssArena_Destroy(arena);
654 return (nssPKIObjectCollection *)NULL;
655 }
656
657 NSS_IMPLEMENT void
658 nssPKIObjectCollection_Destroy (
659 nssPKIObjectCollection *collection
660 )
661 {
662 if (collection) {
663 PRCList *link;
664 pkiObjectCollectionNode *node;
665 /* first destroy any objects in the collection */
666 link = PR_NEXT_LINK(&collection->head);
667 while (link != &collection->head) {
668 node = (pkiObjectCollectionNode *)link;
669 if (node->haveObject) {
670 (*collection->destroyObject)(node->object);
671 } else {
672 nssPKIObject_Destroy(node->object);
673 }
674 link = PR_NEXT_LINK(link);
675 }
676 /* then destroy it */
677 nssArena_Destroy(collection->arena);
678 }
679 }
680
681 NSS_IMPLEMENT PRUint32
682 nssPKIObjectCollection_Count (
683 nssPKIObjectCollection *collection
684 )
685 {
686 return collection->size;
687 }
688
689 NSS_IMPLEMENT PRStatus
690 nssPKIObjectCollection_AddObject (
691 nssPKIObjectCollection *collection,
692 nssPKIObject *object
693 )
694 {
695 pkiObjectCollectionNode *node;
696 node = nss_ZNEW(collection->arena, pkiObjectCollectionNode);
697 if (!node) {
698 return PR_FAILURE;
699 }
700 node->haveObject = PR_TRUE;
701 node->object = nssPKIObject_AddRef(object);
702 (*collection->getUIDFromObject)(object, node->uid);
703 PR_INIT_CLIST(&node->link);
704 PR_INSERT_BEFORE(&node->link, &collection->head);
705 collection->size++;
706 return PR_SUCCESS;
707 }
708
709 static pkiObjectCollectionNode *
710 find_instance_in_collection (
711 nssPKIObjectCollection *collection,
712 nssCryptokiObject *instance
713 )
714 {
715 PRCList *link;
716 pkiObjectCollectionNode *node;
717 link = PR_NEXT_LINK(&collection->head);
718 while (link != &collection->head) {
719 node = (pkiObjectCollectionNode *)link;
720 if (nssPKIObject_HasInstance(node->object, instance)) {
721 return node;
722 }
723 link = PR_NEXT_LINK(link);
724 }
725 return (pkiObjectCollectionNode *)NULL;
726 }
727
728 static pkiObjectCollectionNode *
729 find_object_in_collection (
730 nssPKIObjectCollection *collection,
731 NSSItem *uid
732 )
733 {
734 PRUint32 i;
735 PRStatus status;
736 PRCList *link;
737 pkiObjectCollectionNode *node;
738 link = PR_NEXT_LINK(&collection->head);
739 while (link != &collection->head) {
740 node = (pkiObjectCollectionNode *)link;
741 for (i=0; i<MAX_ITEMS_FOR_UID; i++) {
742 if (!nssItem_Equal(&node->uid[i], &uid[i], &status)) {
743 break;
744 }
745 }
746 if (i == MAX_ITEMS_FOR_UID) {
747 return node;
748 }
749 link = PR_NEXT_LINK(link);
750 }
751 return (pkiObjectCollectionNode *)NULL;
752 }
753
754 static pkiObjectCollectionNode *
755 add_object_instance (
756 nssPKIObjectCollection *collection,
757 nssCryptokiObject *instance,
758 PRBool *foundIt
759 )
760 {
761 PRUint32 i;
762 PRStatus status;
763 pkiObjectCollectionNode *node;
764 nssArenaMark *mark = NULL;
765 NSSItem uid[MAX_ITEMS_FOR_UID];
766 nsslibc_memset(uid, 0, sizeof uid);
767 /* The list is traversed twice, first (here) looking to match the
768 * { token, handle } tuple, and if that is not found, below a search
769 * for unique identifier is done. Here, a match means this exact object
770 * instance is already in the collection, and we have nothing to do.
771 */
772 *foundIt = PR_FALSE;
773 node = find_instance_in_collection(collection, instance);
774 if (node) {
775 /* The collection is assumed to take over the instance. Since we
776 * are not using it, it must be destroyed.
777 */
778 nssCryptokiObject_Destroy(instance);
779 *foundIt = PR_TRUE;
780 return node;
781 }
782 mark = nssArena_Mark(collection->arena);
783 if (!mark) {
784 goto loser;
785 }
786 status = (*collection->getUIDFromInstance)(instance, uid,
787 collection->arena);
788 if (status != PR_SUCCESS) {
789 goto loser;
790 }
791 /* Search for unique identifier. A match here means the object exists
792 * in the collection, but does not have this instance, so the instance
793 * needs to be added.
794 */
795 node = find_object_in_collection(collection, uid);
796 if (node) {
797 /* This is an object with multiple instances */
798 status = nssPKIObject_AddInstance(node->object, instance);
799 } else {
800 /* This is a completely new object. Create a node for it. */
801 node = nss_ZNEW(collection->arena, pkiObjectCollectionNode);
802 if (!node) {
803 goto loser;
804 }
805 node->object = nssPKIObject_Create(NULL, instance,
806 collection->td, collection->cc,
807 collection->lockType);
808 if (!node->object) {
809 goto loser;
810 }
811 for (i=0; i<MAX_ITEMS_FOR_UID; i++) {
812 node->uid[i] = uid[i];
813 }
814 node->haveObject = PR_FALSE;
815 PR_INIT_CLIST(&node->link);
816 PR_INSERT_BEFORE(&node->link, &collection->head);
817 collection->size++;
818 status = PR_SUCCESS;
819 }
820 nssArena_Unmark(collection->arena, mark);
821 return node;
822 loser:
823 if (mark) {
824 nssArena_Release(collection->arena, mark);
825 }
826 nssCryptokiObject_Destroy(instance);
827 return (pkiObjectCollectionNode *)NULL;
828 }
829
830 NSS_IMPLEMENT PRStatus
831 nssPKIObjectCollection_AddInstances (
832 nssPKIObjectCollection *collection,
833 nssCryptokiObject **instances,
834 PRUint32 numInstances
835 )
836 {
837 PRStatus status = PR_SUCCESS;
838 PRUint32 i = 0;
839 PRBool foundIt;
840 pkiObjectCollectionNode *node;
841 if (instances) {
842 while ((!numInstances || i < numInstances) && *instances) {
843 if (status == PR_SUCCESS) {
844 node = add_object_instance(collection, *instances, &foundIt);
845 if (node == NULL) {
846 /* add_object_instance freed the current instance */
847 /* free the remaining instances */
848 status = PR_FAILURE;
849 }
850 } else {
851 nssCryptokiObject_Destroy(*instances);
852 }
853 instances++;
854 i++;
855 }
856 }
857 return status;
858 }
859
860 static void
861 nssPKIObjectCollection_RemoveNode (
862 nssPKIObjectCollection *collection,
863 pkiObjectCollectionNode *node
864 )
865 {
866 PR_REMOVE_LINK(&node->link);
867 collection->size--;
868 }
869
870 static PRStatus
871 nssPKIObjectCollection_GetObjects (
872 nssPKIObjectCollection *collection,
873 nssPKIObject **rvObjects,
874 PRUint32 rvSize
875 )
876 {
877 PRUint32 i = 0;
878 PRCList *link = PR_NEXT_LINK(&collection->head);
879 pkiObjectCollectionNode *node;
880 int error=0;
881 while ((i < rvSize) && (link != &collection->head)) {
882 node = (pkiObjectCollectionNode *)link;
883 if (!node->haveObject) {
884 /* Convert the proto-object to an object */
885 node->object = (*collection->createObject)(node->object);
886 if (!node->object) {
887 link = PR_NEXT_LINK(link);
888 /*remove bogus object from list*/
889 nssPKIObjectCollection_RemoveNode(collection,node);
890 error++;
891 continue;
892 }
893 node->haveObject = PR_TRUE;
894 }
895 rvObjects[i++] = nssPKIObject_AddRef(node->object);
896 link = PR_NEXT_LINK(link);
897 }
898 if (!error && *rvObjects == NULL) {
899 nss_SetError(NSS_ERROR_NOT_FOUND);
900 }
901 return PR_SUCCESS;
902 }
903
904 NSS_IMPLEMENT PRStatus
905 nssPKIObjectCollection_Traverse (
906 nssPKIObjectCollection *collection,
907 nssPKIObjectCallback *callback
908 )
909 {
910 PRStatus status;
911 PRCList *link = PR_NEXT_LINK(&collection->head);
912 pkiObjectCollectionNode *node;
913 while (link != &collection->head) {
914 node = (pkiObjectCollectionNode *)link;
915 if (!node->haveObject) {
916 node->object = (*collection->createObject)(node->object);
917 if (!node->object) {
918 link = PR_NEXT_LINK(link);
919 /*remove bogus object from list*/
920 nssPKIObjectCollection_RemoveNode(collection,node);
921 continue;
922 }
923 node->haveObject = PR_TRUE;
924 }
925 switch (collection->objectType) {
926 case pkiObjectType_Certificate:
927 status = (*callback->func.cert)((NSSCertificate *)node->object,
928 callback->arg);
929 break;
930 case pkiObjectType_CRL:
931 status = (*callback->func.crl)((NSSCRL *)node->object,
932 callback->arg);
933 break;
934 case pkiObjectType_PrivateKey:
935 status = (*callback->func.pvkey)((NSSPrivateKey *)node->object,
936 callback->arg);
937 break;
938 case pkiObjectType_PublicKey:
939 status = (*callback->func.pbkey)((NSSPublicKey *)node->object,
940 callback->arg);
941 break;
942 }
943 link = PR_NEXT_LINK(link);
944 }
945 return PR_SUCCESS;
946 }
947
948 NSS_IMPLEMENT PRStatus
949 nssPKIObjectCollection_AddInstanceAsObject (
950 nssPKIObjectCollection *collection,
951 nssCryptokiObject *instance
952 )
953 {
954 pkiObjectCollectionNode *node;
955 PRBool foundIt;
956 node = add_object_instance(collection, instance, &foundIt);
957 if (node == NULL) {
958 return PR_FAILURE;
959 }
960 if (!node->haveObject) {
961 node->object = (*collection->createObject)(node->object);
962 if (!node->object) {
963 /*remove bogus object from list*/
964 nssPKIObjectCollection_RemoveNode(collection,node);
965 return PR_FAILURE;
966 }
967 node->haveObject = PR_TRUE;
968 } else if (!foundIt) {
969 /* The instance was added to a pre-existing node. This
970 * function is *only* being used for certificates, and having
971 * multiple instances of certs in 3.X requires updating the
972 * CERTCertificate.
973 * But only do it if it was a new instance!!! If the same instance
974 * is encountered, we set *foundIt to true. Detect that here and
975 * ignore it.
976 */
977 STAN_ForceCERTCertificateUpdate((NSSCertificate *)node->object);
978 }
979 return PR_SUCCESS;
980 }
981
982 /*
983 * Certificate collections
984 */
985
986 static void
987 cert_destroyObject(nssPKIObject *o)
988 {
989 NSSCertificate *c = (NSSCertificate *)o;
990 if (c->decoding) {
991 CERTCertificate *cc = STAN_GetCERTCertificate(c);
992 if (cc) {
993 CERT_DestroyCertificate(cc);
994 return;
995 } /* else destroy it as NSSCertificate below */
996 }
997 nssCertificate_Destroy(c);
998 }
999
1000 static PRStatus
1001 cert_getUIDFromObject(nssPKIObject *o, NSSItem *uid)
1002 {
1003 NSSCertificate *c = (NSSCertificate *)o;
1004 /* The builtins are still returning decoded serial numbers. Until
1005 * this compatibility issue is resolved, use the full DER of the
1006 * cert to uniquely identify it.
1007 */
1008 NSSDER *derCert;
1009 derCert = nssCertificate_GetEncoding(c);
1010 uid[0].data = NULL; uid[0].size = 0;
1011 uid[1].data = NULL; uid[1].size = 0;
1012 if (derCert != NULL) {
1013 uid[0] = *derCert;
1014 }
1015 return PR_SUCCESS;
1016 }
1017
1018 static PRStatus
1019 cert_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid,
1020 NSSArena *arena)
1021 {
1022 /* The builtins are still returning decoded serial numbers. Until
1023 * this compatibility issue is resolved, use the full DER of the
1024 * cert to uniquely identify it.
1025 */
1026 uid[1].data = NULL; uid[1].size = 0;
1027 return nssCryptokiCertificate_GetAttributes(instance,
1028 NULL, /* XXX sessionOpt */
1029 arena, /* arena */
1030 NULL, /* type */
1031 NULL, /* id */
1032 &uid[0], /* encoding */
1033 NULL, /* issuer */
1034 NULL, /* serial */
1035 NULL); /* subject */
1036 }
1037
1038 static nssPKIObject *
1039 cert_createObject(nssPKIObject *o)
1040 {
1041 NSSCertificate *cert;
1042 cert = nssCertificate_Create(o);
1043 /* if (STAN_GetCERTCertificate(cert) == NULL) {
1044 nssCertificate_Destroy(cert);
1045 return (nssPKIObject *)NULL;
1046 } */
1047 /* In 3.4, have to maintain uniqueness of cert pointers by caching all
1048 * certs. Cache the cert here, before returning. If it is already
1049 * cached, take the cached entry.
1050 */
1051 {
1052 NSSTrustDomain *td = o->trustDomain;
1053 nssTrustDomain_AddCertsToCache(td, &cert, 1);
1054 }
1055 return (nssPKIObject *)cert;
1056 }
1057
1058 NSS_IMPLEMENT nssPKIObjectCollection *
1059 nssCertificateCollection_Create (
1060 NSSTrustDomain *td,
1061 NSSCertificate **certsOpt
1062 )
1063 {
1064 PRStatus status;
1065 nssPKIObjectCollection *collection;
1066 collection = nssPKIObjectCollection_Create(td, NULL, nssPKIMonitor);
1067 collection->objectType = pkiObjectType_Certificate;
1068 collection->destroyObject = cert_destroyObject;
1069 collection->getUIDFromObject = cert_getUIDFromObject;
1070 collection->getUIDFromInstance = cert_getUIDFromInstance;
1071 collection->createObject = cert_createObject;
1072 if (certsOpt) {
1073 for (; *certsOpt; certsOpt++) {
1074 nssPKIObject *object = (nssPKIObject *)(*certsOpt);
1075 status = nssPKIObjectCollection_AddObject(collection, object);
1076 }
1077 }
1078 return collection;
1079 }
1080
1081 NSS_IMPLEMENT NSSCertificate **
1082 nssPKIObjectCollection_GetCertificates (
1083 nssPKIObjectCollection *collection,
1084 NSSCertificate **rvOpt,
1085 PRUint32 maximumOpt,
1086 NSSArena *arenaOpt
1087 )
1088 {
1089 PRStatus status;
1090 PRUint32 rvSize;
1091 PRBool allocated = PR_FALSE;
1092 if (collection->size == 0) {
1093 return (NSSCertificate **)NULL;
1094 }
1095 if (maximumOpt == 0) {
1096 rvSize = collection->size;
1097 } else {
1098 rvSize = PR_MIN(collection->size, maximumOpt);
1099 }
1100 if (!rvOpt) {
1101 rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCertificate *, rvSize + 1);
1102 if (!rvOpt) {
1103 return (NSSCertificate **)NULL;
1104 }
1105 allocated = PR_TRUE;
1106 }
1107 status = nssPKIObjectCollection_GetObjects(collection,
1108 (nssPKIObject **)rvOpt,
1109 rvSize);
1110 if (status != PR_SUCCESS) {
1111 if (allocated) {
1112 nss_ZFreeIf(rvOpt);
1113 }
1114 return (NSSCertificate **)NULL;
1115 }
1116 return rvOpt;
1117 }
1118
1119 /*
1120 * CRL/KRL collections
1121 */
1122
1123 static void
1124 crl_destroyObject(nssPKIObject *o)
1125 {
1126 NSSCRL *crl = (NSSCRL *)o;
1127 nssCRL_Destroy(crl);
1128 }
1129
1130 static PRStatus
1131 crl_getUIDFromObject(nssPKIObject *o, NSSItem *uid)
1132 {
1133 NSSCRL *crl = (NSSCRL *)o;
1134 NSSDER *encoding;
1135 encoding = nssCRL_GetEncoding(crl);
1136 if (!encoding) {
1137 nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
1138 return PR_FALSE;
1139 }
1140 uid[0] = *encoding;
1141 uid[1].data = NULL; uid[1].size = 0;
1142 return PR_SUCCESS;
1143 }
1144
1145 static PRStatus
1146 crl_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid,
1147 NSSArena *arena)
1148 {
1149 return nssCryptokiCRL_GetAttributes(instance,
1150 NULL, /* XXX sessionOpt */
1151 arena, /* arena */
1152 &uid[0], /* encoding */
1153 NULL, /* subject */
1154 NULL, /* class */
1155 NULL, /* url */
1156 NULL); /* isKRL */
1157 }
1158
1159 static nssPKIObject *
1160 crl_createObject(nssPKIObject *o)
1161 {
1162 return (nssPKIObject *)nssCRL_Create(o);
1163 }
1164
1165 NSS_IMPLEMENT nssPKIObjectCollection *
1166 nssCRLCollection_Create (
1167 NSSTrustDomain *td,
1168 NSSCRL **crlsOpt
1169 )
1170 {
1171 PRStatus status;
1172 nssPKIObjectCollection *collection;
1173 collection = nssPKIObjectCollection_Create(td, NULL, nssPKILock);
1174 collection->objectType = pkiObjectType_CRL;
1175 collection->destroyObject = crl_destroyObject;
1176 collection->getUIDFromObject = crl_getUIDFromObject;
1177 collection->getUIDFromInstance = crl_getUIDFromInstance;
1178 collection->createObject = crl_createObject;
1179 if (crlsOpt) {
1180 for (; *crlsOpt; crlsOpt++) {
1181 nssPKIObject *object = (nssPKIObject *)(*crlsOpt);
1182 status = nssPKIObjectCollection_AddObject(collection, object);
1183 }
1184 }
1185 return collection;
1186 }
1187
1188 NSS_IMPLEMENT NSSCRL **
1189 nssPKIObjectCollection_GetCRLs (
1190 nssPKIObjectCollection *collection,
1191 NSSCRL **rvOpt,
1192 PRUint32 maximumOpt,
1193 NSSArena *arenaOpt
1194 )
1195 {
1196 PRStatus status;
1197 PRUint32 rvSize;
1198 PRBool allocated = PR_FALSE;
1199 if (collection->size == 0) {
1200 return (NSSCRL **)NULL;
1201 }
1202 if (maximumOpt == 0) {
1203 rvSize = collection->size;
1204 } else {
1205 rvSize = PR_MIN(collection->size, maximumOpt);
1206 }
1207 if (!rvOpt) {
1208 rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCRL *, rvSize + 1);
1209 if (!rvOpt) {
1210 return (NSSCRL **)NULL;
1211 }
1212 allocated = PR_TRUE;
1213 }
1214 status = nssPKIObjectCollection_GetObjects(collection,
1215 (nssPKIObject **)rvOpt,
1216 rvSize);
1217 if (status != PR_SUCCESS) {
1218 if (allocated) {
1219 nss_ZFreeIf(rvOpt);
1220 }
1221 return (NSSCRL **)NULL;
1222 }
1223 return rvOpt;
1224 }
1225
1226 /* how bad would it be to have a static now sitting around, updated whenever
1227 * this was called? would avoid repeated allocs...
1228 */
1229 NSS_IMPLEMENT NSSTime *
1230 NSSTime_Now (
1231 NSSTime *timeOpt
1232 )
1233 {
1234 return NSSTime_SetPRTime(timeOpt, PR_Now());
1235 }
1236
1237 NSS_IMPLEMENT NSSTime *
1238 NSSTime_SetPRTime (
1239 NSSTime *timeOpt,
1240 PRTime prTime
1241 )
1242 {
1243 NSSTime *rvTime;
1244 rvTime = (timeOpt) ? timeOpt : nss_ZNEW(NULL, NSSTime);
1245 if (rvTime) {
1246 rvTime->prTime = prTime;
1247 }
1248 return rvTime;
1249 }
1250
1251 NSS_IMPLEMENT PRTime
1252 NSSTime_GetPRTime (
1253 NSSTime *time
1254 )
1255 {
1256 return time->prTime;
1257 }
1258
OLDNEW
« no previous file with comments | « mozilla/security/nss/lib/pki/pki3hack.c ('k') | mozilla/security/nss/lib/pki/pkim.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698