Bug Summary

File:root/firefox-clang/security/nss/lib/pki/pkibase.c
Warning:line 791, column 9
Value stored to 'status' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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