~ubuntu-branches/ubuntu/trusty/xulrunner/trusty

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/pki/pkibase.c

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2008-08-25 13:04:18 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825130418-ck1i2ms384tzb9m0
Tags: 1.8.1.16+nobinonly-0ubuntu1
* New upstream release (taken from upstream CVS), LP: #254618.
* Fix MFSA 2008-35, MFSA 2008-34, MFSA 2008-33, MFSA 2008-32, MFSA 2008-31,
  MFSA 2008-30, MFSA 2008-29, MFSA 2008-28, MFSA 2008-27, MFSA 2008-25,
  MFSA 2008-24, MFSA 2008-23, MFSA 2008-22, MFSA 2008-21, MFSA 2008-26 also
  known as CVE-2008-2933, CVE-2008-2785, CVE-2008-2811, CVE-2008-2810,
  CVE-2008-2809, CVE-2008-2808, CVE-2008-2807, CVE-2008-2806, CVE-2008-2805,
  CVE-2008-2803, CVE-2008-2802, CVE-2008-2801, CVE-2008-2800, CVE-2008-2798.
* Drop 89_bz419350_attachment_306066 patch, merged upstream.
* Bump Standards-Version to 3.8.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
4
 * The contents of this file are subject to the Mozilla Public License Version
 
5
 * 1.1 (the "License"); you may not use this file except in compliance with
 
6
 * the License. You may obtain a copy of the License at
 
7
 * http://www.mozilla.org/MPL/
 
8
 *
 
9
 * Software distributed under the License is distributed on an "AS IS" basis,
 
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
11
 * for the specific language governing rights and limitations under the
 
12
 * License.
 
13
 *
 
14
 * The Original Code is the Netscape security libraries.
 
15
 *
 
16
 * The Initial Developer of the Original Code is
 
17
 * Netscape Communications Corporation.
 
18
 * Portions created by the Initial Developer are Copyright (C) 1994-2000
 
19
 * the Initial Developer. All Rights Reserved.
 
20
 *
 
21
 * Contributor(s):
 
22
 *
 
23
 * Alternatively, the contents of this file may be used under the terms of
 
24
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
25
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
26
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
27
 * of those above. If you wish to allow use of your version of this file only
 
28
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
29
 * use your version of this file under the terms of the MPL, indicate your
 
30
 * decision by deleting the provisions above and replace them with the notice
 
31
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
32
 * the provisions above, a recipient may use your version of this file under
 
33
 * the terms of any one of the MPL, the GPL or the LGPL.
 
34
 *
 
35
 * ***** END LICENSE BLOCK ***** */
 
36
 
 
37
#ifdef DEBUG
 
38
static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.25.28.1 $ $Date: 2006/08/23 01:36:31 $";
 
39
#endif /* DEBUG */
 
40
 
 
41
#ifndef DEV_H
 
42
#include "dev.h"
 
43
#endif /* DEV_H */
 
44
 
 
45
#ifndef PKIM_H
 
46
#include "pkim.h"
 
47
#endif /* PKIM_H */
 
48
 
 
49
#ifdef NSS_3_4_CODE
 
50
#include "pki3hack.h"
 
51
#endif
 
52
 
 
53
extern const NSSError NSS_ERROR_NOT_FOUND;
 
54
 
 
55
NSS_IMPLEMENT void
 
56
nssPKIObject_Lock(nssPKIObject * object)
 
57
{
 
58
    switch (object->lockType) {
 
59
    case nssPKIMonitor:
 
60
        PZ_EnterMonitor(object->sync.mlock);
 
61
        break;
 
62
    case nssPKILock:
 
63
        PZ_Lock(object->sync.lock);
 
64
        break;
 
65
    default:
 
66
        PORT_Assert(0);
 
67
    }
 
68
}
 
69
 
 
70
NSS_IMPLEMENT void
 
71
nssPKIObject_Unlock(nssPKIObject * object)
 
72
{
 
73
    switch (object->lockType) {
 
74
    case nssPKIMonitor:
 
75
        PZ_ExitMonitor(object->sync.mlock);
 
76
        break;
 
77
    case nssPKILock:
 
78
        PZ_Unlock(object->sync.lock);
 
79
        break;
 
80
    default:
 
81
        PORT_Assert(0);
 
82
    }
 
83
}
 
84
 
 
85
NSS_IMPLEMENT PRStatus
 
86
nssPKIObject_NewLock(nssPKIObject * object, nssPKILockType lockType)
 
87
{
 
88
    object->lockType = lockType;
 
89
    switch (lockType) {
 
90
    case nssPKIMonitor:
 
91
        object->sync.mlock = PZ_NewMonitor(nssILockSSL);
 
92
        return (object->sync.mlock ? PR_SUCCESS : PR_FAILURE);
 
93
    case nssPKILock:
 
94
        object->sync.lock = PZ_NewLock(nssILockSSL);
 
95
        return (object->sync.lock ? PR_SUCCESS : PR_FAILURE);
 
96
    default:
 
97
        PORT_Assert(0);
 
98
        return PR_FAILURE;
 
99
    }
 
100
}
 
101
 
 
102
NSS_IMPLEMENT void
 
103
nssPKIObject_DestroyLock(nssPKIObject * object)
 
104
{
 
105
    switch (object->lockType) {
 
106
    case nssPKIMonitor:
 
107
        PZ_DestroyMonitor(object->sync.mlock);
 
108
        object->sync.mlock = NULL;
 
109
        break;
 
110
    case nssPKILock:
 
111
        PZ_DestroyLock(object->sync.lock);
 
112
        object->sync.lock = NULL;
 
113
        break;
 
114
    default:
 
115
        PORT_Assert(0);
 
116
    }
 
117
}
 
118
 
 
119
 
 
120
 
 
121
NSS_IMPLEMENT nssPKIObject *
 
122
nssPKIObject_Create (
 
123
  NSSArena *arenaOpt,
 
124
  nssCryptokiObject *instanceOpt,
 
125
  NSSTrustDomain *td,
 
126
  NSSCryptoContext *cc,
 
127
  nssPKILockType lockType
 
128
)
 
129
{
 
130
    NSSArena *arena;
 
131
    nssArenaMark *mark = NULL;
 
132
    nssPKIObject *object;
 
133
    if (arenaOpt) {
 
134
        arena = arenaOpt;
 
135
        mark = nssArena_Mark(arena);
 
136
    } else {
 
137
        arena = nssArena_Create();
 
138
        if (!arena) {
 
139
            return (nssPKIObject *)NULL;
 
140
        }
 
141
    }
 
142
    object = nss_ZNEW(arena, nssPKIObject);
 
143
    if (!object) {
 
144
        goto loser;
 
145
    }
 
146
    object->arena = arena;
 
147
    object->trustDomain = td; /* XXX */
 
148
    object->cryptoContext = cc;
 
149
    if (PR_SUCCESS != nssPKIObject_NewLock(object, lockType)) {
 
150
        goto loser;
 
151
    }
 
152
    if (instanceOpt) {
 
153
        if (nssPKIObject_AddInstance(object, instanceOpt) != PR_SUCCESS) {
 
154
            goto loser;
 
155
        }
 
156
    }
 
157
    PR_AtomicIncrement(&object->refCount);
 
158
    if (mark) {
 
159
        nssArena_Unmark(arena, mark);
 
160
    }
 
161
    return object;
 
162
loser:
 
163
    if (mark) {
 
164
        nssArena_Release(arena, mark);
 
165
    } else {
 
166
        nssArena_Destroy(arena);
 
167
    }
 
168
    return (nssPKIObject *)NULL;
 
169
}
 
170
 
 
171
NSS_IMPLEMENT PRBool
 
172
nssPKIObject_Destroy (
 
173
  nssPKIObject *object
 
174
)
 
175
{
 
176
    PRUint32 i;
 
177
    PR_ASSERT(object->refCount > 0);
 
178
    if (PR_AtomicDecrement(&object->refCount) == 0) {
 
179
        for (i=0; i<object->numInstances; i++) {
 
180
            nssCryptokiObject_Destroy(object->instances[i]);
 
181
        }
 
182
        nssPKIObject_DestroyLock(object);
 
183
        nssArena_Destroy(object->arena);
 
184
        return PR_TRUE;
 
185
    }
 
186
    return PR_FALSE;
 
187
}
 
188
 
 
189
NSS_IMPLEMENT nssPKIObject *
 
190
nssPKIObject_AddRef (
 
191
  nssPKIObject *object
 
192
)
 
193
{
 
194
    PR_AtomicIncrement(&object->refCount);
 
195
    return object;
 
196
}
 
197
 
 
198
NSS_IMPLEMENT PRStatus
 
199
nssPKIObject_AddInstance (
 
200
  nssPKIObject *object,
 
201
  nssCryptokiObject *instance
 
202
)
 
203
{
 
204
    nssPKIObject_Lock(object);
 
205
    if (object->numInstances == 0) {
 
206
        object->instances = nss_ZNEWARRAY(object->arena,
 
207
                                          nssCryptokiObject *,
 
208
                                          object->numInstances + 1);
 
209
    } else {
 
210
        PRUint32 i;
 
211
        for (i=0; i<object->numInstances; i++) {
 
212
            if (nssCryptokiObject_Equal(object->instances[i], instance)) {
 
213
                nssPKIObject_Unlock(object);
 
214
                if (instance->label) {
 
215
                    if (!object->instances[i]->label ||
 
216
                        !nssUTF8_Equal(instance->label,
 
217
                                       object->instances[i]->label, NULL))
 
218
                    {
 
219
                        /* Either the old instance did not have a label,
 
220
                         * or the label has changed.
 
221
                         */
 
222
                        nss_ZFreeIf(object->instances[i]->label);
 
223
                        object->instances[i]->label = instance->label;
 
224
                        instance->label = NULL;
 
225
                    }
 
226
                } else if (object->instances[i]->label) {
 
227
                    /* The old label was removed */
 
228
                    nss_ZFreeIf(object->instances[i]->label);
 
229
                    object->instances[i]->label = NULL;
 
230
                }
 
231
                nssCryptokiObject_Destroy(instance);
 
232
                return PR_SUCCESS;
 
233
            }
 
234
        }
 
235
        object->instances = nss_ZREALLOCARRAY(object->instances,
 
236
                                              nssCryptokiObject *,
 
237
                                              object->numInstances + 1);
 
238
    }
 
239
    if (!object->instances) {
 
240
        nssPKIObject_Unlock(object);
 
241
        return PR_FAILURE;
 
242
    }
 
243
    object->instances[object->numInstances++] = instance;
 
244
    nssPKIObject_Unlock(object);
 
245
    return PR_SUCCESS;
 
246
}
 
247
 
 
248
NSS_IMPLEMENT PRBool
 
249
nssPKIObject_HasInstance (
 
250
  nssPKIObject *object,
 
251
  nssCryptokiObject *instance
 
252
)
 
253
{
 
254
    PRUint32 i;
 
255
    PRBool hasIt = PR_FALSE;;
 
256
    nssPKIObject_Lock(object);
 
257
    for (i=0; i<object->numInstances; i++) {
 
258
        if (nssCryptokiObject_Equal(object->instances[i], instance)) {
 
259
            hasIt = PR_TRUE;
 
260
            break;
 
261
        }
 
262
    }
 
263
    nssPKIObject_Unlock(object);
 
264
    return hasIt;
 
265
}
 
266
 
 
267
NSS_IMPLEMENT PRStatus
 
268
nssPKIObject_RemoveInstanceForToken (
 
269
  nssPKIObject *object,
 
270
  NSSToken *token
 
271
)
 
272
{
 
273
    PRUint32 i;
 
274
    nssCryptokiObject *instanceToRemove = NULL;
 
275
    nssPKIObject_Lock(object);
 
276
    if (object->numInstances == 0) {
 
277
        nssPKIObject_Unlock(object);
 
278
        return PR_SUCCESS;
 
279
    }
 
280
    for (i=0; i<object->numInstances; i++) {
 
281
        if (object->instances[i]->token == token) {
 
282
            instanceToRemove = object->instances[i];
 
283
            object->instances[i] = object->instances[object->numInstances-1];
 
284
            object->instances[object->numInstances-1] = NULL;
 
285
            break;
 
286
        }
 
287
    }
 
288
    if (--object->numInstances > 0) {
 
289
        nssCryptokiObject **instances = nss_ZREALLOCARRAY(object->instances,
 
290
                                              nssCryptokiObject *,
 
291
                                              object->numInstances);
 
292
        if (instances) {
 
293
            object->instances = instances;
 
294
        }
 
295
    } else {
 
296
        nss_ZFreeIf(object->instances);
 
297
    }
 
298
    nssCryptokiObject_Destroy(instanceToRemove);
 
299
    nssPKIObject_Unlock(object);
 
300
    return PR_SUCCESS;
 
301
}
 
302
 
 
303
/* this needs more thought on what will happen when there are multiple
 
304
 * instances
 
305
 */
 
306
NSS_IMPLEMENT PRStatus
 
307
nssPKIObject_DeleteStoredObject (
 
308
  nssPKIObject *object,
 
309
  NSSCallback *uhh,
 
310
  PRBool isFriendly
 
311
)
 
312
{
 
313
    PRUint32 i, numNotDestroyed;
 
314
    PRStatus status = PR_SUCCESS;
 
315
#ifndef NSS_3_4_CODE
 
316
    NSSTrustDomain *td = object->trustDomain;
 
317
    NSSCallback *pwcb = uhh ?  /* is this optional? */
 
318
                        uhh : 
 
319
                        nssTrustDomain_GetDefaultCallback(td, NULL);
 
320
#endif
 
321
    numNotDestroyed = 0;
 
322
    nssPKIObject_Lock(object);
 
323
    for (i=0; i<object->numInstances; i++) {
 
324
        nssCryptokiObject *instance = object->instances[i];
 
325
#ifndef NSS_3_4_CODE
 
326
        NSSSlot *slot = nssToken_GetSlot(instance->token);
 
327
        /* If both the operation and the slot are friendly, login is
 
328
         * not required.  If either or both are not friendly, it is
 
329
         * required.
 
330
         */
 
331
        if (!(isFriendly && nssSlot_IsFriendly(slot))) {
 
332
            status = nssSlot_Login(slot, pwcb);
 
333
            nssSlot_Destroy(slot);
 
334
            if (status == PR_SUCCESS) {
 
335
                /* XXX this should be fixed to understand read-only tokens,
 
336
                 * for now, to handle the builtins, just make the attempt.
 
337
                 */
 
338
                status = nssToken_DeleteStoredObject(instance);
 
339
            }
 
340
        }
 
341
#else
 
342
        status = nssToken_DeleteStoredObject(instance);
 
343
#endif
 
344
        object->instances[i] = NULL;
 
345
        if (status == PR_SUCCESS) {
 
346
            nssCryptokiObject_Destroy(instance);
 
347
        } else {
 
348
            object->instances[numNotDestroyed++] = instance;
 
349
        }
 
350
    }
 
351
    if (numNotDestroyed == 0) {
 
352
        nss_ZFreeIf(object->instances);
 
353
        object->numInstances = 0;
 
354
    } else {
 
355
        object->numInstances = numNotDestroyed;
 
356
    }
 
357
    nssPKIObject_Unlock(object);
 
358
    return status;
 
359
}
 
360
 
 
361
NSS_IMPLEMENT NSSToken **
 
362
nssPKIObject_GetTokens (
 
363
  nssPKIObject *object,
 
364
  PRStatus *statusOpt
 
365
)
 
366
{
 
367
    NSSToken **tokens = NULL;
 
368
    nssPKIObject_Lock(object);
 
369
    if (object->numInstances > 0) {
 
370
        tokens = nss_ZNEWARRAY(NULL, NSSToken *, object->numInstances + 1);
 
371
        if (tokens) {
 
372
            PRUint32 i;
 
373
            for (i=0; i<object->numInstances; i++) {
 
374
                tokens[i] = nssToken_AddRef(object->instances[i]->token);
 
375
            }
 
376
        }
 
377
    }
 
378
    nssPKIObject_Unlock(object);
 
379
    if (statusOpt) *statusOpt = PR_SUCCESS; /* until more logic here */
 
380
    return tokens;
 
381
}
 
382
 
 
383
NSS_IMPLEMENT NSSUTF8 *
 
384
nssPKIObject_GetNicknameForToken (
 
385
  nssPKIObject *object,
 
386
  NSSToken *tokenOpt
 
387
)
 
388
{
 
389
    PRUint32 i;
 
390
    NSSUTF8 *nickname = NULL;
 
391
    nssPKIObject_Lock(object);
 
392
    for (i=0; i<object->numInstances; i++) {
 
393
        if ((!tokenOpt && object->instances[i]->label) ||
 
394
            (object->instances[i]->token == tokenOpt)) 
 
395
        {
 
396
            /* XXX should be copy? safe as long as caller has reference */
 
397
            nickname = object->instances[i]->label; 
 
398
            break;
 
399
        }
 
400
    }
 
401
    nssPKIObject_Unlock(object);
 
402
    return nickname;
 
403
}
 
404
 
 
405
#ifdef NSS_3_4_CODE
 
406
NSS_IMPLEMENT nssCryptokiObject **
 
407
nssPKIObject_GetInstances (
 
408
  nssPKIObject *object
 
409
)
 
410
{
 
411
    nssCryptokiObject **instances = NULL;
 
412
    PRUint32 i;
 
413
    if (object->numInstances == 0) {
 
414
        return (nssCryptokiObject **)NULL;
 
415
    }
 
416
    nssPKIObject_Lock(object);
 
417
    instances = nss_ZNEWARRAY(NULL, nssCryptokiObject *, 
 
418
                              object->numInstances + 1);
 
419
    if (instances) {
 
420
        for (i=0; i<object->numInstances; i++) {
 
421
            instances[i] = nssCryptokiObject_Clone(object->instances[i]);
 
422
        }
 
423
    }
 
424
    nssPKIObject_Unlock(object);
 
425
    return instances;
 
426
}
 
427
#endif
 
428
 
 
429
NSS_IMPLEMENT void
 
430
nssCertificateArray_Destroy (
 
431
  NSSCertificate **certs
 
432
)
 
433
{
 
434
    if (certs) {
 
435
        NSSCertificate **certp;
 
436
        for (certp = certs; *certp; certp++) {
 
437
#ifdef NSS_3_4_CODE
 
438
            if ((*certp)->decoding) {
 
439
                CERTCertificate *cc = STAN_GetCERTCertificate(*certp);
 
440
                if (cc) {
 
441
                    CERT_DestroyCertificate(cc);
 
442
                }
 
443
                continue;
 
444
            }
 
445
#endif
 
446
            nssCertificate_Destroy(*certp);
 
447
        }
 
448
        nss_ZFreeIf(certs);
 
449
    }
 
450
}
 
451
 
 
452
NSS_IMPLEMENT void
 
453
NSSCertificateArray_Destroy (
 
454
  NSSCertificate **certs
 
455
)
 
456
{
 
457
    nssCertificateArray_Destroy(certs);
 
458
}
 
459
 
 
460
NSS_IMPLEMENT NSSCertificate **
 
461
nssCertificateArray_Join (
 
462
  NSSCertificate **certs1,
 
463
  NSSCertificate **certs2
 
464
)
 
465
{
 
466
    if (certs1 && certs2) {
 
467
        NSSCertificate **certs, **cp;
 
468
        PRUint32 count = 0;
 
469
        PRUint32 count1 = 0;
 
470
        cp = certs1;
 
471
        while (*cp++) count1++;
 
472
        count = count1;
 
473
        cp = certs2;
 
474
        while (*cp++) count++;
 
475
        certs = nss_ZREALLOCARRAY(certs1, NSSCertificate *, count + 1);
 
476
        if (!certs) {
 
477
            nss_ZFreeIf(certs1);
 
478
            nss_ZFreeIf(certs2);
 
479
            return (NSSCertificate **)NULL;
 
480
        }
 
481
        for (cp = certs2; *cp; cp++, count1++) {
 
482
            certs[count1] = *cp;
 
483
        }
 
484
        nss_ZFreeIf(certs2);
 
485
        return certs;
 
486
    } else if (certs1) {
 
487
        return certs1;
 
488
    } else {
 
489
        return certs2;
 
490
    }
 
491
}
 
492
 
 
493
NSS_IMPLEMENT NSSCertificate * 
 
494
nssCertificateArray_FindBestCertificate (
 
495
  NSSCertificate **certs, 
 
496
  NSSTime *timeOpt,
 
497
  const NSSUsage *usage,
 
498
  NSSPolicies *policiesOpt
 
499
)
 
500
{
 
501
    NSSCertificate *bestCert = NULL;
 
502
    NSSTime *time, sTime;
 
503
    PRBool haveUsageMatch = PR_FALSE;
 
504
    PRBool thisCertMatches;
 
505
 
 
506
    if (timeOpt) {
 
507
        time = timeOpt;
 
508
    } else {
 
509
        NSSTime_Now(&sTime);
 
510
        time = &sTime;
 
511
    }
 
512
    if (!certs) {
 
513
        return (NSSCertificate *)NULL;
 
514
    }
 
515
    for (; *certs; certs++) {
 
516
        nssDecodedCert *dc, *bestdc;
 
517
        NSSCertificate *c = *certs;
 
518
        dc = nssCertificate_GetDecoding(c);
 
519
        if (!dc) continue;
 
520
        thisCertMatches = dc->matchUsage(dc, usage);
 
521
        if (!bestCert) {
 
522
            /* always take the first cert, but remember whether or not
 
523
             * the usage matched 
 
524
             */
 
525
            bestCert = nssCertificate_AddRef(c);
 
526
            haveUsageMatch = thisCertMatches;
 
527
            continue;
 
528
        } else {
 
529
            if (haveUsageMatch && !thisCertMatches) {
 
530
                /* if already have a cert for this usage, and if this cert 
 
531
                 * doesn't have the correct usage, continue
 
532
                 */
 
533
                continue;
 
534
            } else if (!haveUsageMatch && thisCertMatches) {
 
535
                /* this one does match usage, replace the other */
 
536
                nssCertificate_Destroy(bestCert);
 
537
                bestCert = nssCertificate_AddRef(c);
 
538
                haveUsageMatch = PR_TRUE;
 
539
                continue;
 
540
            }
 
541
            /* this cert match as well as any cert we've found so far, 
 
542
             * defer to time/policies 
 
543
             * */
 
544
        }
 
545
        bestdc = nssCertificate_GetDecoding(bestCert);
 
546
        /* time */
 
547
        if (bestdc->isValidAtTime(bestdc, time)) {
 
548
            /* The current best cert is valid at time */
 
549
            if (!dc->isValidAtTime(dc, time)) {
 
550
                /* If the new cert isn't valid at time, it's not better */
 
551
                continue;
 
552
            }
 
553
        } else {
 
554
            /* The current best cert is not valid at time */
 
555
            if (dc->isValidAtTime(dc, time)) {
 
556
                /* If the new cert is valid at time, it's better */
 
557
                nssCertificate_Destroy(bestCert);
 
558
                bestCert = nssCertificate_AddRef(c);
 
559
            }
 
560
        }
 
561
        /* either they are both valid at time, or neither valid; 
 
562
         * take the newer one
 
563
         */
 
564
        if (!bestdc->isNewerThan(bestdc, dc)) {
 
565
            nssCertificate_Destroy(bestCert);
 
566
            bestCert = nssCertificate_AddRef(c);
 
567
        }
 
568
        /* policies */
 
569
        /* XXX later -- defer to policies */
 
570
    }
 
571
    return bestCert;
 
572
}
 
573
 
 
574
NSS_IMPLEMENT PRStatus
 
575
nssCertificateArray_Traverse (
 
576
  NSSCertificate **certs,
 
577
  PRStatus (* callback)(NSSCertificate *c, void *arg),
 
578
  void *arg
 
579
)
 
580
{
 
581
    PRStatus status = PR_SUCCESS;
 
582
    if (certs) {
 
583
        NSSCertificate **certp;
 
584
        for (certp = certs; *certp; certp++) {
 
585
            status = (*callback)(*certp, arg);
 
586
            if (status != PR_SUCCESS) {
 
587
                break;
 
588
            }
 
589
        }
 
590
    }
 
591
    return status;
 
592
}
 
593
 
 
594
 
 
595
NSS_IMPLEMENT void
 
596
nssCRLArray_Destroy (
 
597
  NSSCRL **crls
 
598
)
 
599
{
 
600
    if (crls) {
 
601
        NSSCRL **crlp;
 
602
        for (crlp = crls; *crlp; crlp++) {
 
603
            nssCRL_Destroy(*crlp);
 
604
        }
 
605
        nss_ZFreeIf(crls);
 
606
    }
 
607
}
 
608
 
 
609
/*
 
610
 * Object collections
 
611
 */
 
612
 
 
613
typedef enum
 
614
{
 
615
  pkiObjectType_Certificate = 0,
 
616
  pkiObjectType_CRL = 1,
 
617
  pkiObjectType_PrivateKey = 2,
 
618
  pkiObjectType_PublicKey = 3
 
619
} pkiObjectType;
 
620
 
 
621
/* Each object is defined by a set of items that uniquely identify it.
 
622
 * Here are the uid sets:
 
623
 *
 
624
 * NSSCertificate ==>  { issuer, serial }
 
625
 * NSSPrivateKey
 
626
 *         (RSA) ==> { modulus, public exponent }
 
627
 *
 
628
 */
 
629
#define MAX_ITEMS_FOR_UID 2
 
630
 
 
631
/* pkiObjectCollectionNode
 
632
 *
 
633
 * A node in the collection is the set of unique identifiers for a single
 
634
 * object, along with either the actual object or a proto-object.
 
635
 */
 
636
typedef struct
 
637
{
 
638
  PRCList link;
 
639
  PRBool haveObject;
 
640
  nssPKIObject *object;
 
641
  NSSItem uid[MAX_ITEMS_FOR_UID];
 
642
 
643
pkiObjectCollectionNode;
 
644
 
 
645
/* nssPKIObjectCollection
 
646
 *
 
647
 * The collection is the set of all objects, plus the interfaces needed
 
648
 * to manage the objects.
 
649
 *
 
650
 */
 
651
struct nssPKIObjectCollectionStr
 
652
{
 
653
  NSSArena *arena;
 
654
  NSSTrustDomain *td;
 
655
  NSSCryptoContext *cc;
 
656
  PRCList head; /* list of pkiObjectCollectionNode's */
 
657
  PRUint32 size;
 
658
  pkiObjectType objectType;
 
659
  void           (*      destroyObject)(nssPKIObject *o);
 
660
  PRStatus       (*   getUIDFromObject)(nssPKIObject *o, NSSItem *uid);
 
661
  PRStatus       (* getUIDFromInstance)(nssCryptokiObject *co, NSSItem *uid, 
 
662
                                        NSSArena *arena);
 
663
  nssPKIObject * (*       createObject)(nssPKIObject *o);
 
664
  nssPKILockType lockType; /* type of lock to use for new proto-objects */
 
665
};
 
666
 
 
667
static nssPKIObjectCollection *
 
668
nssPKIObjectCollection_Create (
 
669
  NSSTrustDomain *td,
 
670
  NSSCryptoContext *ccOpt,
 
671
  nssPKILockType lockType
 
672
)
 
673
{
 
674
    NSSArena *arena;
 
675
    nssPKIObjectCollection *rvCollection = NULL;
 
676
    arena = nssArena_Create();
 
677
    if (!arena) {
 
678
        return (nssPKIObjectCollection *)NULL;
 
679
    }
 
680
    rvCollection = nss_ZNEW(arena, nssPKIObjectCollection);
 
681
    if (!rvCollection) {
 
682
        goto loser;
 
683
    }
 
684
    PR_INIT_CLIST(&rvCollection->head);
 
685
    rvCollection->arena = arena;
 
686
    rvCollection->td = td; /* XXX */
 
687
    rvCollection->cc = ccOpt;
 
688
    rvCollection->lockType = lockType;
 
689
    return rvCollection;
 
690
loser:
 
691
    nssArena_Destroy(arena);
 
692
    return (nssPKIObjectCollection *)NULL;
 
693
}
 
694
 
 
695
NSS_IMPLEMENT void
 
696
nssPKIObjectCollection_Destroy (
 
697
  nssPKIObjectCollection *collection
 
698
)
 
699
{
 
700
    if (collection) {
 
701
        PRCList *link;
 
702
        pkiObjectCollectionNode *node;
 
703
        /* first destroy any objects in the collection */
 
704
        link = PR_NEXT_LINK(&collection->head);
 
705
        while (link != &collection->head) {
 
706
            node = (pkiObjectCollectionNode *)link;
 
707
            if (node->haveObject) {
 
708
                (*collection->destroyObject)(node->object);
 
709
            } else {
 
710
                nssPKIObject_Destroy(node->object);
 
711
            }
 
712
            link = PR_NEXT_LINK(link);
 
713
        }
 
714
        /* then destroy it */
 
715
        nssArena_Destroy(collection->arena);
 
716
    }
 
717
}
 
718
 
 
719
NSS_IMPLEMENT PRUint32
 
720
nssPKIObjectCollection_Count (
 
721
  nssPKIObjectCollection *collection
 
722
)
 
723
{
 
724
    return collection->size;
 
725
}
 
726
 
 
727
NSS_IMPLEMENT PRStatus
 
728
nssPKIObjectCollection_AddObject (
 
729
  nssPKIObjectCollection *collection,
 
730
  nssPKIObject *object
 
731
)
 
732
{
 
733
    pkiObjectCollectionNode *node;
 
734
    node = nss_ZNEW(collection->arena, pkiObjectCollectionNode);
 
735
    if (!node) {
 
736
        return PR_FAILURE;
 
737
    }
 
738
    node->haveObject = PR_TRUE;
 
739
    node->object = nssPKIObject_AddRef(object);
 
740
    (*collection->getUIDFromObject)(object, node->uid);
 
741
    PR_INIT_CLIST(&node->link);
 
742
    PR_INSERT_BEFORE(&node->link, &collection->head);
 
743
    collection->size++;
 
744
    return PR_SUCCESS;
 
745
}
 
746
 
 
747
static pkiObjectCollectionNode *
 
748
find_instance_in_collection (
 
749
  nssPKIObjectCollection *collection,
 
750
  nssCryptokiObject *instance
 
751
)
 
752
{
 
753
    PRCList *link;
 
754
    pkiObjectCollectionNode *node;
 
755
    link = PR_NEXT_LINK(&collection->head);
 
756
    while (link != &collection->head) {
 
757
        node = (pkiObjectCollectionNode *)link;
 
758
        if (nssPKIObject_HasInstance(node->object, instance)) {
 
759
            return node;
 
760
        }
 
761
        link = PR_NEXT_LINK(link);
 
762
    }
 
763
    return (pkiObjectCollectionNode *)NULL;
 
764
}
 
765
 
 
766
static pkiObjectCollectionNode *
 
767
find_object_in_collection (
 
768
  nssPKIObjectCollection *collection,
 
769
  NSSItem *uid
 
770
)
 
771
{
 
772
    PRUint32 i;
 
773
    PRStatus status;
 
774
    PRCList *link;
 
775
    pkiObjectCollectionNode *node;
 
776
    link = PR_NEXT_LINK(&collection->head);
 
777
    while (link != &collection->head) {
 
778
        node = (pkiObjectCollectionNode *)link;
 
779
        for (i=0; i<MAX_ITEMS_FOR_UID; i++) {
 
780
            if (!nssItem_Equal(&node->uid[i], &uid[i], &status)) {
 
781
                break;
 
782
            }
 
783
        }
 
784
        if (i == MAX_ITEMS_FOR_UID) {
 
785
            return node;
 
786
        }
 
787
        link = PR_NEXT_LINK(link);
 
788
    }
 
789
    return (pkiObjectCollectionNode *)NULL;
 
790
}
 
791
 
 
792
static pkiObjectCollectionNode *
 
793
add_object_instance (
 
794
  nssPKIObjectCollection *collection,
 
795
  nssCryptokiObject *instance,
 
796
  PRBool *foundIt
 
797
)
 
798
{
 
799
    PRUint32 i;
 
800
    PRStatus status;
 
801
    pkiObjectCollectionNode *node;
 
802
    nssArenaMark *mark = NULL;
 
803
    NSSItem uid[MAX_ITEMS_FOR_UID];
 
804
    nsslibc_memset(uid, 0, sizeof uid);
 
805
    /* The list is traversed twice, first (here) looking to match the
 
806
     * { token, handle } tuple, and if that is not found, below a search
 
807
     * for unique identifier is done.  Here, a match means this exact object
 
808
     * instance is already in the collection, and we have nothing to do.
 
809
     */
 
810
    *foundIt = PR_FALSE;
 
811
    node = find_instance_in_collection(collection, instance);
 
812
    if (node) {
 
813
        /* The collection is assumed to take over the instance.  Since we
 
814
         * are not using it, it must be destroyed.
 
815
         */
 
816
        nssCryptokiObject_Destroy(instance);
 
817
        *foundIt = PR_TRUE;
 
818
        return node;
 
819
    }
 
820
    mark = nssArena_Mark(collection->arena);
 
821
    if (!mark) {
 
822
        goto loser;
 
823
    }
 
824
    status = (*collection->getUIDFromInstance)(instance, uid, 
 
825
                                               collection->arena);
 
826
    if (status != PR_SUCCESS) {
 
827
        goto loser;
 
828
    }
 
829
    /* Search for unique identifier.  A match here means the object exists 
 
830
     * in the collection, but does not have this instance, so the instance 
 
831
     * needs to be added.
 
832
     */
 
833
    node = find_object_in_collection(collection, uid);
 
834
    if (node) {
 
835
        /* This is an object with multiple instances */
 
836
        status = nssPKIObject_AddInstance(node->object, instance);
 
837
    } else {
 
838
        /* This is a completely new object.  Create a node for it. */
 
839
        node = nss_ZNEW(collection->arena, pkiObjectCollectionNode);
 
840
        if (!node) {
 
841
            goto loser;
 
842
        }
 
843
        node->object = nssPKIObject_Create(NULL, instance, 
 
844
                                           collection->td, collection->cc,
 
845
                                           collection->lockType);
 
846
        if (!node->object) {
 
847
            goto loser;
 
848
        }
 
849
        for (i=0; i<MAX_ITEMS_FOR_UID; i++) {
 
850
            node->uid[i] = uid[i];
 
851
        }
 
852
        node->haveObject = PR_FALSE;
 
853
        PR_INIT_CLIST(&node->link);
 
854
        PR_INSERT_BEFORE(&node->link, &collection->head);
 
855
        collection->size++;
 
856
        status = PR_SUCCESS;
 
857
    }
 
858
    nssArena_Unmark(collection->arena, mark);
 
859
    return node;
 
860
loser:
 
861
    if (mark) {
 
862
        nssArena_Release(collection->arena, mark);
 
863
    }
 
864
    nssCryptokiObject_Destroy(instance);
 
865
    return (pkiObjectCollectionNode *)NULL;
 
866
}
 
867
 
 
868
NSS_IMPLEMENT PRStatus
 
869
nssPKIObjectCollection_AddInstances (
 
870
  nssPKIObjectCollection *collection,
 
871
  nssCryptokiObject **instances,
 
872
  PRUint32 numInstances
 
873
)
 
874
{
 
875
    PRStatus status = PR_SUCCESS;
 
876
    PRUint32 i = 0;
 
877
    PRBool foundIt;
 
878
    pkiObjectCollectionNode *node;
 
879
    if (instances) {
 
880
        for (; *instances; instances++, i++) {
 
881
            if (numInstances > 0 && i == numInstances) {
 
882
                break;
 
883
            }
 
884
            if (status == PR_SUCCESS) {
 
885
                node = add_object_instance(collection, *instances, &foundIt);
 
886
                if (node == NULL) {
 
887
                    /* add_object_instance freed the current instance */
 
888
                    /* free the remaining instances */
 
889
                    status = PR_FAILURE;
 
890
                }
 
891
            } else {
 
892
                nssCryptokiObject_Destroy(*instances);
 
893
            }
 
894
        }
 
895
    }
 
896
    return status;
 
897
}
 
898
 
 
899
static void
 
900
nssPKIObjectCollection_RemoveNode (
 
901
   nssPKIObjectCollection *collection,
 
902
   pkiObjectCollectionNode *node
 
903
)
 
904
{
 
905
    PR_REMOVE_LINK(&node->link); 
 
906
    collection->size--;
 
907
}
 
908
 
 
909
static PRStatus
 
910
nssPKIObjectCollection_GetObjects (
 
911
  nssPKIObjectCollection *collection,
 
912
  nssPKIObject **rvObjects,
 
913
  PRUint32 rvSize
 
914
)
 
915
{
 
916
    PRUint32 i = 0;
 
917
    PRCList *link = PR_NEXT_LINK(&collection->head);
 
918
    pkiObjectCollectionNode *node;
 
919
    int error=0;
 
920
    while ((i < rvSize) && (link != &collection->head)) {
 
921
        node = (pkiObjectCollectionNode *)link;
 
922
        if (!node->haveObject) {
 
923
            /* Convert the proto-object to an object */
 
924
            node->object = (*collection->createObject)(node->object);
 
925
            if (!node->object) {
 
926
                link = PR_NEXT_LINK(link);
 
927
                /*remove bogus object from list*/
 
928
                nssPKIObjectCollection_RemoveNode(collection,node);
 
929
                error++;
 
930
                continue;
 
931
            }
 
932
            node->haveObject = PR_TRUE;
 
933
        }
 
934
        rvObjects[i++] = nssPKIObject_AddRef(node->object);
 
935
        link = PR_NEXT_LINK(link);
 
936
    }
 
937
    if (!error && *rvObjects == NULL) {
 
938
        nss_SetError(NSS_ERROR_NOT_FOUND);
 
939
    }
 
940
    return PR_SUCCESS;
 
941
}
 
942
 
 
943
NSS_IMPLEMENT PRStatus
 
944
nssPKIObjectCollection_Traverse (
 
945
  nssPKIObjectCollection *collection,
 
946
  nssPKIObjectCallback *callback
 
947
)
 
948
{
 
949
    PRStatus status;
 
950
    PRCList *link = PR_NEXT_LINK(&collection->head);
 
951
    pkiObjectCollectionNode *node;
 
952
    while (link != &collection->head) {
 
953
        node = (pkiObjectCollectionNode *)link;
 
954
        if (!node->haveObject) {
 
955
            node->object = (*collection->createObject)(node->object);
 
956
            if (!node->object) {
 
957
                link = PR_NEXT_LINK(link);
 
958
                /*remove bogus object from list*/
 
959
                nssPKIObjectCollection_RemoveNode(collection,node);
 
960
                continue;
 
961
            }
 
962
            node->haveObject = PR_TRUE;
 
963
        }
 
964
        switch (collection->objectType) {
 
965
        case pkiObjectType_Certificate: 
 
966
            status = (*callback->func.cert)((NSSCertificate *)node->object, 
 
967
                                            callback->arg);
 
968
            break;
 
969
        case pkiObjectType_CRL: 
 
970
            status = (*callback->func.crl)((NSSCRL *)node->object, 
 
971
                                           callback->arg);
 
972
            break;
 
973
        case pkiObjectType_PrivateKey: 
 
974
            status = (*callback->func.pvkey)((NSSPrivateKey *)node->object, 
 
975
                                             callback->arg);
 
976
            break;
 
977
        case pkiObjectType_PublicKey: 
 
978
            status = (*callback->func.pbkey)((NSSPublicKey *)node->object, 
 
979
                                             callback->arg);
 
980
            break;
 
981
        }
 
982
        link = PR_NEXT_LINK(link);
 
983
    }
 
984
    return PR_SUCCESS;
 
985
}
 
986
 
 
987
NSS_IMPLEMENT PRStatus
 
988
nssPKIObjectCollection_AddInstanceAsObject (
 
989
  nssPKIObjectCollection *collection,
 
990
  nssCryptokiObject *instance
 
991
)
 
992
{
 
993
    pkiObjectCollectionNode *node;
 
994
    PRBool foundIt;
 
995
    node = add_object_instance(collection, instance, &foundIt);
 
996
    if (node == NULL) {
 
997
        return PR_FAILURE;
 
998
    }
 
999
    if (!node->haveObject) {
 
1000
        node->object = (*collection->createObject)(node->object);
 
1001
        if (!node->object) {
 
1002
            /*remove bogus object from list*/
 
1003
            nssPKIObjectCollection_RemoveNode(collection,node);
 
1004
            return PR_FAILURE;
 
1005
        }
 
1006
        node->haveObject = PR_TRUE;
 
1007
    }
 
1008
#ifdef NSS_3_4_CODE
 
1009
    else if (!foundIt) {
 
1010
        /* The instance was added to a pre-existing node.  This
 
1011
         * function is *only* being used for certificates, and having
 
1012
         * multiple instances of certs in 3.X requires updating the
 
1013
         * CERTCertificate.
 
1014
         * But only do it if it was a new instance!!!  If the same instance
 
1015
         * is encountered, we set *foundIt to true.  Detect that here and
 
1016
         * ignore it.
 
1017
         */
 
1018
        STAN_ForceCERTCertificateUpdate((NSSCertificate *)node->object);
 
1019
    }
 
1020
#endif
 
1021
    return PR_SUCCESS;
 
1022
}
 
1023
 
 
1024
/*
 
1025
 * Certificate collections
 
1026
 */
 
1027
 
 
1028
static void
 
1029
cert_destroyObject(nssPKIObject *o)
 
1030
{
 
1031
    NSSCertificate *c = (NSSCertificate *)o;
 
1032
#ifdef NSS_3_4_CODE
 
1033
    if (c->decoding) {
 
1034
        CERTCertificate *cc = STAN_GetCERTCertificate(c);
 
1035
        if (cc) {
 
1036
            CERT_DestroyCertificate(cc);
 
1037
            return;
 
1038
        } /* else destroy it as NSSCertificate below */
 
1039
    }
 
1040
#endif
 
1041
    nssCertificate_Destroy(c);
 
1042
}
 
1043
 
 
1044
static PRStatus
 
1045
cert_getUIDFromObject(nssPKIObject *o, NSSItem *uid)
 
1046
{
 
1047
    NSSCertificate *c = (NSSCertificate *)o;
 
1048
#ifdef NSS_3_4_CODE
 
1049
    /* The builtins are still returning decoded serial numbers.  Until
 
1050
     * this compatibility issue is resolved, use the full DER of the
 
1051
     * cert to uniquely identify it.
 
1052
     */
 
1053
    NSSDER *derCert;
 
1054
    derCert = nssCertificate_GetEncoding(c);
 
1055
    uid[0].data = NULL; uid[0].size = 0;
 
1056
    uid[1].data = NULL; uid[1].size = 0;
 
1057
    if (derCert != NULL) {
 
1058
        uid[0] = *derCert;
 
1059
    }
 
1060
#else
 
1061
    NSSDER *issuer, *serial;
 
1062
    issuer = nssCertificate_GetIssuer(c);
 
1063
    serial = nssCertificate_GetSerialNumber(c);
 
1064
    uid[0] = *issuer;
 
1065
    uid[1] = *serial;
 
1066
#endif /* NSS_3_4_CODE */
 
1067
    return PR_SUCCESS;
 
1068
}
 
1069
 
 
1070
static PRStatus
 
1071
cert_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid, 
 
1072
                        NSSArena *arena)
 
1073
{
 
1074
#ifdef NSS_3_4_CODE
 
1075
    /* The builtins are still returning decoded serial numbers.  Until
 
1076
     * this compatibility issue is resolved, use the full DER of the
 
1077
     * cert to uniquely identify it.
 
1078
     */
 
1079
    uid[1].data = NULL; uid[1].size = 0;
 
1080
    return nssCryptokiCertificate_GetAttributes(instance,
 
1081
                                                NULL,  /* XXX sessionOpt */
 
1082
                                                arena, /* arena    */
 
1083
                                                NULL,  /* type     */
 
1084
                                                NULL,  /* id       */
 
1085
                                                &uid[0], /* encoding */
 
1086
                                                NULL,  /* issuer   */
 
1087
                                                NULL,  /* serial   */
 
1088
                                                NULL);  /* subject  */
 
1089
#else
 
1090
    return nssCryptokiCertificate_GetAttributes(instance,
 
1091
                                                NULL,  /* XXX sessionOpt */
 
1092
                                                arena, /* arena    */
 
1093
                                                NULL,  /* type     */
 
1094
                                                NULL,  /* id       */
 
1095
                                                NULL,  /* encoding */
 
1096
                                                &uid[0], /* issuer */
 
1097
                                                &uid[1], /* serial */
 
1098
                                                NULL);  /* subject  */
 
1099
#endif /* NSS_3_4_CODE */
 
1100
}
 
1101
 
 
1102
static nssPKIObject *
 
1103
cert_createObject(nssPKIObject *o)
 
1104
{
 
1105
    NSSCertificate *cert;
 
1106
    cert = nssCertificate_Create(o);
 
1107
#ifdef NSS_3_4_CODE
 
1108
/*    if (STAN_GetCERTCertificate(cert) == NULL) {
 
1109
        nssCertificate_Destroy(cert);
 
1110
        return (nssPKIObject *)NULL;
 
1111
    } */
 
1112
    /* In 3.4, have to maintain uniqueness of cert pointers by caching all
 
1113
     * certs.  Cache the cert here, before returning.  If it is already
 
1114
     * cached, take the cached entry.
 
1115
     */
 
1116
    {
 
1117
        NSSTrustDomain *td = o->trustDomain;
 
1118
        nssTrustDomain_AddCertsToCache(td, &cert, 1);
 
1119
    }
 
1120
#endif
 
1121
    return (nssPKIObject *)cert;
 
1122
}
 
1123
 
 
1124
NSS_IMPLEMENT nssPKIObjectCollection *
 
1125
nssCertificateCollection_Create (
 
1126
  NSSTrustDomain *td,
 
1127
  NSSCertificate **certsOpt
 
1128
)
 
1129
{
 
1130
    PRStatus status;
 
1131
    nssPKIObjectCollection *collection;
 
1132
    collection = nssPKIObjectCollection_Create(td, NULL, nssPKIMonitor);
 
1133
    collection->objectType = pkiObjectType_Certificate;
 
1134
    collection->destroyObject = cert_destroyObject;
 
1135
    collection->getUIDFromObject = cert_getUIDFromObject;
 
1136
    collection->getUIDFromInstance = cert_getUIDFromInstance;
 
1137
    collection->createObject = cert_createObject;
 
1138
    if (certsOpt) {
 
1139
        for (; *certsOpt; certsOpt++) {
 
1140
            nssPKIObject *object = (nssPKIObject *)(*certsOpt);
 
1141
            status = nssPKIObjectCollection_AddObject(collection, object);
 
1142
        }
 
1143
    }
 
1144
    return collection;
 
1145
}
 
1146
 
 
1147
NSS_IMPLEMENT NSSCertificate **
 
1148
nssPKIObjectCollection_GetCertificates (
 
1149
  nssPKIObjectCollection *collection,
 
1150
  NSSCertificate **rvOpt,
 
1151
  PRUint32 maximumOpt,
 
1152
  NSSArena *arenaOpt
 
1153
)
 
1154
{
 
1155
    PRStatus status;
 
1156
    PRUint32 rvSize;
 
1157
    PRBool allocated = PR_FALSE;
 
1158
    if (collection->size == 0) {
 
1159
        return (NSSCertificate **)NULL;
 
1160
    }
 
1161
    if (maximumOpt == 0) {
 
1162
        rvSize = collection->size;
 
1163
    } else {
 
1164
        rvSize = PR_MIN(collection->size, maximumOpt);
 
1165
    }
 
1166
    if (!rvOpt) {
 
1167
        rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCertificate *, rvSize + 1);
 
1168
        if (!rvOpt) {
 
1169
            return (NSSCertificate **)NULL;
 
1170
        }
 
1171
        allocated = PR_TRUE;
 
1172
    }
 
1173
    status = nssPKIObjectCollection_GetObjects(collection, 
 
1174
                                               (nssPKIObject **)rvOpt, 
 
1175
                                               rvSize);
 
1176
    if (status != PR_SUCCESS) {
 
1177
        if (allocated) {
 
1178
            nss_ZFreeIf(rvOpt);
 
1179
        }
 
1180
        return (NSSCertificate **)NULL;
 
1181
    }
 
1182
    return rvOpt;
 
1183
}
 
1184
 
 
1185
/*
 
1186
 * CRL/KRL collections
 
1187
 */
 
1188
 
 
1189
static void
 
1190
crl_destroyObject(nssPKIObject *o)
 
1191
{
 
1192
    NSSCRL *crl = (NSSCRL *)o;
 
1193
    nssCRL_Destroy(crl);
 
1194
}
 
1195
 
 
1196
static PRStatus
 
1197
crl_getUIDFromObject(nssPKIObject *o, NSSItem *uid)
 
1198
{
 
1199
    NSSCRL *crl = (NSSCRL *)o;
 
1200
    NSSDER *encoding;
 
1201
    encoding = nssCRL_GetEncoding(crl);
 
1202
    uid[0] = *encoding;
 
1203
    uid[1].data = NULL; uid[1].size = 0;
 
1204
    return PR_SUCCESS;
 
1205
}
 
1206
 
 
1207
static PRStatus
 
1208
crl_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid, 
 
1209
                       NSSArena *arena)
 
1210
{
 
1211
    return nssCryptokiCRL_GetAttributes(instance,
 
1212
                                        NULL,    /* XXX sessionOpt */
 
1213
                                        arena,   /* arena    */
 
1214
                                        &uid[0], /* encoding */
 
1215
                                        NULL,    /* subject  */
 
1216
                                        NULL,    /* class    */
 
1217
                                        NULL,    /* url      */
 
1218
                                        NULL);   /* isKRL    */
 
1219
}
 
1220
 
 
1221
static nssPKIObject *
 
1222
crl_createObject(nssPKIObject *o)
 
1223
{
 
1224
    return (nssPKIObject *)nssCRL_Create(o);
 
1225
}
 
1226
 
 
1227
NSS_IMPLEMENT nssPKIObjectCollection *
 
1228
nssCRLCollection_Create (
 
1229
  NSSTrustDomain *td,
 
1230
  NSSCRL **crlsOpt
 
1231
)
 
1232
{
 
1233
    PRStatus status;
 
1234
    nssPKIObjectCollection *collection;
 
1235
    collection = nssPKIObjectCollection_Create(td, NULL, nssPKILock);
 
1236
    collection->objectType = pkiObjectType_CRL;
 
1237
    collection->destroyObject = crl_destroyObject;
 
1238
    collection->getUIDFromObject = crl_getUIDFromObject;
 
1239
    collection->getUIDFromInstance = crl_getUIDFromInstance;
 
1240
    collection->createObject = crl_createObject;
 
1241
    if (crlsOpt) {
 
1242
        for (; *crlsOpt; crlsOpt++) {
 
1243
            nssPKIObject *object = (nssPKIObject *)(*crlsOpt);
 
1244
            status = nssPKIObjectCollection_AddObject(collection, object);
 
1245
        }
 
1246
    }
 
1247
    return collection;
 
1248
}
 
1249
 
 
1250
NSS_IMPLEMENT NSSCRL **
 
1251
nssPKIObjectCollection_GetCRLs (
 
1252
  nssPKIObjectCollection *collection,
 
1253
  NSSCRL **rvOpt,
 
1254
  PRUint32 maximumOpt,
 
1255
  NSSArena *arenaOpt
 
1256
)
 
1257
{
 
1258
    PRStatus status;
 
1259
    PRUint32 rvSize;
 
1260
    PRBool allocated = PR_FALSE;
 
1261
    if (collection->size == 0) {
 
1262
        return (NSSCRL **)NULL;
 
1263
    }
 
1264
    if (maximumOpt == 0) {
 
1265
        rvSize = collection->size;
 
1266
    } else {
 
1267
        rvSize = PR_MIN(collection->size, maximumOpt);
 
1268
    }
 
1269
    if (!rvOpt) {
 
1270
        rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCRL *, rvSize + 1);
 
1271
        if (!rvOpt) {
 
1272
            return (NSSCRL **)NULL;
 
1273
        }
 
1274
        allocated = PR_TRUE;
 
1275
    }
 
1276
    status = nssPKIObjectCollection_GetObjects(collection, 
 
1277
                                               (nssPKIObject **)rvOpt, 
 
1278
                                               rvSize);
 
1279
    if (status != PR_SUCCESS) {
 
1280
        if (allocated) {
 
1281
            nss_ZFreeIf(rvOpt);
 
1282
        }
 
1283
        return (NSSCRL **)NULL;
 
1284
    }
 
1285
    return rvOpt;
 
1286
}
 
1287
 
 
1288
#ifdef PURE_STAN_BUILD
 
1289
/*
 
1290
 * PrivateKey collections
 
1291
 */
 
1292
 
 
1293
static void
 
1294
privkey_destroyObject(nssPKIObject *o)
 
1295
{
 
1296
    NSSPrivateKey *pvk = (NSSPrivateKey *)o;
 
1297
    nssPrivateKey_Destroy(pvk);
 
1298
}
 
1299
 
 
1300
static PRStatus
 
1301
privkey_getUIDFromObject(nssPKIObject *o, NSSItem *uid)
 
1302
{
 
1303
    NSSPrivateKey *pvk = (NSSPrivateKey *)o;
 
1304
    NSSItem *id;
 
1305
    id = nssPrivateKey_GetID(pvk);
 
1306
    uid[0] = *id;
 
1307
    return PR_SUCCESS;
 
1308
}
 
1309
 
 
1310
static PRStatus
 
1311
privkey_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid, 
 
1312
                           NSSArena *arena)
 
1313
{
 
1314
    return nssCryptokiPrivateKey_GetAttributes(instance,
 
1315
                                               NULL,  /* XXX sessionOpt */
 
1316
                                               arena,
 
1317
                                               NULL, /* type */
 
1318
                                               &uid[0]);
 
1319
}
 
1320
 
 
1321
static nssPKIObject *
 
1322
privkey_createObject(nssPKIObject *o)
 
1323
{
 
1324
    NSSPrivateKey *pvk;
 
1325
    pvk = nssPrivateKey_Create(o);
 
1326
    return (nssPKIObject *)pvk;
 
1327
}
 
1328
 
 
1329
NSS_IMPLEMENT nssPKIObjectCollection *
 
1330
nssPrivateKeyCollection_Create (
 
1331
  NSSTrustDomain *td,
 
1332
  NSSPrivateKey **pvkOpt
 
1333
)
 
1334
{
 
1335
    PRStatus status;
 
1336
    nssPKIObjectCollection *collection;
 
1337
    collection = nssPKIObjectCollection_Create(td, NULL, nssPKILock);
 
1338
    collection->objectType = pkiObjectType_PrivateKey;
 
1339
    collection->destroyObject = privkey_destroyObject;
 
1340
    collection->getUIDFromObject = privkey_getUIDFromObject;
 
1341
    collection->getUIDFromInstance = privkey_getUIDFromInstance;
 
1342
    collection->createObject = privkey_createObject;
 
1343
    if (pvkOpt) {
 
1344
        for (; *pvkOpt; pvkOpt++) {
 
1345
            nssPKIObject *o = (nssPKIObject *)(*pvkOpt);
 
1346
            status = nssPKIObjectCollection_AddObject(collection, o);
 
1347
        }
 
1348
    }
 
1349
    return collection;
 
1350
}
 
1351
 
 
1352
NSS_IMPLEMENT NSSPrivateKey **
 
1353
nssPKIObjectCollection_GetPrivateKeys (
 
1354
  nssPKIObjectCollection *collection,
 
1355
  NSSPrivateKey **rvOpt,
 
1356
  PRUint32 maximumOpt,
 
1357
  NSSArena *arenaOpt
 
1358
)
 
1359
{
 
1360
    PRStatus status;
 
1361
    PRUint32 rvSize;
 
1362
    PRBool allocated = PR_FALSE;
 
1363
    if (collection->size == 0) {
 
1364
        return (NSSPrivateKey **)NULL;
 
1365
    }
 
1366
    if (maximumOpt == 0) {
 
1367
        rvSize = collection->size;
 
1368
    } else {
 
1369
        rvSize = PR_MIN(collection->size, maximumOpt);
 
1370
    }
 
1371
    if (!rvOpt) {
 
1372
        rvOpt = nss_ZNEWARRAY(arenaOpt, NSSPrivateKey *, rvSize + 1);
 
1373
        if (!rvOpt) {
 
1374
            return (NSSPrivateKey **)NULL;
 
1375
        }
 
1376
        allocated = PR_TRUE;
 
1377
    }
 
1378
    status = nssPKIObjectCollection_GetObjects(collection, 
 
1379
                                               (nssPKIObject **)rvOpt, 
 
1380
                                               rvSize);
 
1381
    if (status != PR_SUCCESS) {
 
1382
        if (allocated) {
 
1383
            nss_ZFreeIf(rvOpt);
 
1384
        }
 
1385
        return (NSSPrivateKey **)NULL;
 
1386
    }
 
1387
    return rvOpt;
 
1388
}
 
1389
 
 
1390
/*
 
1391
 * PublicKey collections
 
1392
 */
 
1393
 
 
1394
static void
 
1395
pubkey_destroyObject(nssPKIObject *o)
 
1396
{
 
1397
    NSSPublicKey *pubk = (NSSPublicKey *)o;
 
1398
    nssPublicKey_Destroy(pubk);
 
1399
}
 
1400
 
 
1401
static PRStatus
 
1402
pubkey_getUIDFromObject(nssPKIObject *o, NSSItem *uid)
 
1403
{
 
1404
    NSSPublicKey *pubk = (NSSPublicKey *)o;
 
1405
    NSSItem *id;
 
1406
    id = nssPublicKey_GetID(pubk);
 
1407
    uid[0] = *id;
 
1408
    return PR_SUCCESS;
 
1409
}
 
1410
 
 
1411
static PRStatus
 
1412
pubkey_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid, 
 
1413
                          NSSArena *arena)
 
1414
{
 
1415
    return nssCryptokiPublicKey_GetAttributes(instance,
 
1416
                                              NULL,  /* XXX sessionOpt */
 
1417
                                              arena,
 
1418
                                              NULL, /* type */
 
1419
                                              &uid[0]);
 
1420
}
 
1421
 
 
1422
static nssPKIObject *
 
1423
pubkey_createObject(nssPKIObject *o)
 
1424
{
 
1425
    NSSPublicKey *pubk;
 
1426
    pubk = nssPublicKey_Create(o);
 
1427
    return (nssPKIObject *)pubk;
 
1428
}
 
1429
 
 
1430
NSS_IMPLEMENT nssPKIObjectCollection *
 
1431
nssPublicKeyCollection_Create (
 
1432
  NSSTrustDomain *td,
 
1433
  NSSPublicKey **pubkOpt
 
1434
)
 
1435
{
 
1436
    PRStatus status;
 
1437
    nssPKIObjectCollection *collection;
 
1438
    collection = nssPKIObjectCollection_Create(td, NULL, nssPKILock);
 
1439
    collection->objectType = pkiObjectType_PublicKey;
 
1440
    collection->destroyObject = pubkey_destroyObject;
 
1441
    collection->getUIDFromObject = pubkey_getUIDFromObject;
 
1442
    collection->getUIDFromInstance = pubkey_getUIDFromInstance;
 
1443
    collection->createObject = pubkey_createObject;
 
1444
    if (pubkOpt) {
 
1445
        for (; *pubkOpt; pubkOpt++) {
 
1446
            nssPKIObject *o = (nssPKIObject *)(*pubkOpt);
 
1447
            status = nssPKIObjectCollection_AddObject(collection, o);
 
1448
        }
 
1449
    }
 
1450
    return collection;
 
1451
}
 
1452
 
 
1453
NSS_IMPLEMENT NSSPublicKey **
 
1454
nssPKIObjectCollection_GetPublicKeys (
 
1455
  nssPKIObjectCollection *collection,
 
1456
  NSSPublicKey **rvOpt,
 
1457
  PRUint32 maximumOpt,
 
1458
  NSSArena *arenaOpt
 
1459
)
 
1460
{
 
1461
    PRStatus status;
 
1462
    PRUint32 rvSize;
 
1463
    PRBool allocated = PR_FALSE;
 
1464
    if (collection->size == 0) {
 
1465
        return (NSSPublicKey **)NULL;
 
1466
    }
 
1467
    if (maximumOpt == 0) {
 
1468
        rvSize = collection->size;
 
1469
    } else {
 
1470
        rvSize = PR_MIN(collection->size, maximumOpt);
 
1471
    }
 
1472
    if (!rvOpt) {
 
1473
        rvOpt = nss_ZNEWARRAY(arenaOpt, NSSPublicKey *, rvSize + 1);
 
1474
        if (!rvOpt) {
 
1475
            return (NSSPublicKey **)NULL;
 
1476
        }
 
1477
        allocated = PR_TRUE;
 
1478
    }
 
1479
    status = nssPKIObjectCollection_GetObjects(collection, 
 
1480
                                               (nssPKIObject **)rvOpt, 
 
1481
                                               rvSize);
 
1482
    if (status != PR_SUCCESS) {
 
1483
        if (allocated) {
 
1484
            nss_ZFreeIf(rvOpt);
 
1485
        }
 
1486
        return (NSSPublicKey **)NULL;
 
1487
    }
 
1488
    return rvOpt;
 
1489
}
 
1490
#endif /* PURE_STAN_BUILD */
 
1491
 
 
1492
/* how bad would it be to have a static now sitting around, updated whenever
 
1493
 * this was called?  would avoid repeated allocs...
 
1494
 */
 
1495
NSS_IMPLEMENT NSSTime *
 
1496
NSSTime_Now (
 
1497
  NSSTime *timeOpt
 
1498
)
 
1499
{
 
1500
    return NSSTime_SetPRTime(timeOpt, PR_Now());
 
1501
}
 
1502
 
 
1503
NSS_IMPLEMENT NSSTime *
 
1504
NSSTime_SetPRTime (
 
1505
  NSSTime *timeOpt,
 
1506
  PRTime prTime
 
1507
)
 
1508
{
 
1509
    NSSTime *rvTime;
 
1510
    rvTime = (timeOpt) ? timeOpt : nss_ZNEW(NULL, NSSTime);
 
1511
    rvTime->prTime = prTime;
 
1512
    return rvTime;
 
1513
}
 
1514
 
 
1515
NSS_IMPLEMENT PRTime
 
1516
NSSTime_GetPRTime (
 
1517
  NSSTime *time
 
1518
)
 
1519
{
 
1520
  return time->prTime;
 
1521
}
 
1522