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

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

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

Powered by Google App Engine
This is Rietveld 408576698