Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/nss/lib/pki/trustdomain.c
Line
Count
Source (jump to first uncovered line)
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 "cert.h"
14
#include "pki3hack.h"
15
#include "pk11pub.h"
16
#include "nssrwlk.h"
17
#include "pk11priv.h"
18
19
0
#define NSSTRUSTDOMAIN_DEFAULT_CACHE_SIZE 32
20
21
extern const NSSError NSS_ERROR_NOT_FOUND;
22
23
typedef PRUint32 nssUpdateLevel;
24
25
NSS_IMPLEMENT NSSTrustDomain *
26
NSSTrustDomain_Create(
27
    NSSUTF8 *moduleOpt,
28
    NSSUTF8 *uriOpt,
29
    NSSUTF8 *opaqueOpt,
30
    void *reserved)
31
0
{
32
0
    NSSArena *arena;
33
0
    NSSTrustDomain *rvTD;
34
0
    arena = NSSArena_Create();
35
0
    if (!arena) {
36
0
        return (NSSTrustDomain *)NULL;
37
0
    }
38
0
    rvTD = nss_ZNEW(arena, NSSTrustDomain);
39
0
    if (!rvTD) {
40
0
        goto loser;
41
0
    }
42
0
    /* protect the token list and the token iterator */
43
0
    rvTD->tokensLock = NSSRWLock_New(100, "tokens");
44
0
    if (!rvTD->tokensLock) {
45
0
        goto loser;
46
0
    }
47
0
    nssTrustDomain_InitializeCache(rvTD, NSSTRUSTDOMAIN_DEFAULT_CACHE_SIZE);
48
0
    rvTD->arena = arena;
49
0
    rvTD->refCount = 1;
50
0
    rvTD->statusConfig = NULL;
51
0
    return rvTD;
52
0
loser:
53
0
    if (rvTD && rvTD->tokensLock) {
54
0
        NSSRWLock_Destroy(rvTD->tokensLock);
55
0
    }
56
0
    nssArena_Destroy(arena);
57
0
    return (NSSTrustDomain *)NULL;
58
0
}
59
60
static void
61
token_destructor(void *t)
62
0
{
63
0
    NSSToken *tok = (NSSToken *)t;
64
0
    /* The token holds the first/last reference to the slot.
65
0
     * When the token is actually destroyed (ref count == 0),
66
0
     * the slot will also be destroyed.
67
0
     */
68
0
    nssToken_Destroy(tok);
69
0
}
70
71
NSS_IMPLEMENT PRStatus
72
NSSTrustDomain_Destroy(
73
    NSSTrustDomain *td)
74
0
{
75
0
    PRStatus status = PR_SUCCESS;
76
0
    if (--td->refCount == 0) {
77
0
        /* Destroy each token in the list of tokens */
78
0
        if (td->tokens) {
79
0
            nssListIterator_Destroy(td->tokens);
80
0
            td->tokens = NULL;
81
0
        }
82
0
        if (td->tokenList) {
83
0
            nssList_Clear(td->tokenList, token_destructor);
84
0
            nssList_Destroy(td->tokenList);
85
0
            td->tokenList = NULL;
86
0
        }
87
0
        NSSRWLock_Destroy(td->tokensLock);
88
0
        td->tokensLock = NULL;
89
0
        status = nssTrustDomain_DestroyCache(td);
90
0
        if (status == PR_FAILURE) {
91
0
            return status;
92
0
        }
93
0
        if (td->statusConfig) {
94
0
            td->statusConfig->statusDestroy(td->statusConfig);
95
0
            td->statusConfig = NULL;
96
0
        }
97
0
        /* Destroy the trust domain */
98
0
        nssArena_Destroy(td->arena);
99
0
    }
100
0
    return status;
101
0
}
102
103
/* XXX uses tokens until slot list is in place */
104
static NSSSlot **
105
nssTrustDomain_GetActiveSlots(
106
    NSSTrustDomain *td,
107
    nssUpdateLevel *updateLevel)
108
0
{
109
0
    PRUint32 count;
110
0
    NSSSlot **slots = NULL;
111
0
    NSSToken **tp, **tokens;
112
0
    *updateLevel = 1;
113
0
    if (!td->tokenList) {
114
0
        return NULL;
115
0
    }
116
0
    NSSRWLock_LockRead(td->tokensLock);
117
0
    count = nssList_Count(td->tokenList);
118
0
    tokens = nss_ZNEWARRAY(NULL, NSSToken *, count + 1);
119
0
    if (!tokens) {
120
0
        NSSRWLock_UnlockRead(td->tokensLock);
121
0
        return NULL;
122
0
    }
123
0
    slots = nss_ZNEWARRAY(NULL, NSSSlot *, count + 1);
124
0
    if (!slots) {
125
0
        NSSRWLock_UnlockRead(td->tokensLock);
126
0
        nss_ZFreeIf(tokens);
127
0
        return NULL;
128
0
    }
129
0
    nssList_GetArray(td->tokenList, (void **)tokens, count);
130
0
    NSSRWLock_UnlockRead(td->tokensLock);
131
0
    count = 0;
132
0
    for (tp = tokens; *tp; tp++) {
133
0
        NSSSlot *slot = nssToken_GetSlot(*tp);
134
0
        if (!PK11_IsDisabled(slot->pk11slot)) {
135
0
            slots[count++] = slot;
136
0
        } else {
137
0
            nssSlot_Destroy(slot);
138
0
        }
139
0
    }
140
0
    nss_ZFreeIf(tokens);
141
0
    if (!count) {
142
0
        nss_ZFreeIf(slots);
143
0
        slots = NULL;
144
0
    }
145
0
    return slots;
146
0
}
147
148
/* XXX */
149
static nssSession *
150
nssTrustDomain_GetSessionForToken(
151
    NSSTrustDomain *td,
152
    NSSToken *token)
153
0
{
154
0
    return nssToken_GetDefaultSession(token);
155
0
}
156
157
NSS_IMPLEMENT PRStatus
158
NSSTrustDomain_SetDefaultCallback(
159
    NSSTrustDomain *td,
160
    NSSCallback *newCallback,
161
    NSSCallback **oldCallbackOpt)
162
0
{
163
0
    if (oldCallbackOpt) {
164
0
        *oldCallbackOpt = td->defaultCallback;
165
0
    }
166
0
    td->defaultCallback = newCallback;
167
0
    return PR_SUCCESS;
168
0
}
169
170
NSS_IMPLEMENT NSSCallback *
171
nssTrustDomain_GetDefaultCallback(
172
    NSSTrustDomain *td,
173
    PRStatus *statusOpt)
174
0
{
175
0
    if (statusOpt) {
176
0
        *statusOpt = PR_SUCCESS;
177
0
    }
178
0
    return td->defaultCallback;
179
0
}
180
181
NSS_IMPLEMENT NSSCallback *
182
NSSTrustDomain_GetDefaultCallback(
183
    NSSTrustDomain *td,
184
    PRStatus *statusOpt)
185
0
{
186
0
    return nssTrustDomain_GetDefaultCallback(td, statusOpt);
187
0
}
188
189
NSS_IMPLEMENT PRStatus
190
NSSTrustDomain_LoadModule(
191
    NSSTrustDomain *td,
192
    NSSUTF8 *moduleOpt,
193
    NSSUTF8 *uriOpt,
194
    NSSUTF8 *opaqueOpt,
195
    void *reserved)
196
0
{
197
0
    return PR_FAILURE;
198
0
}
199
200
NSS_IMPLEMENT PRStatus
201
NSSTrustDomain_DisableToken(
202
    NSSTrustDomain *td,
203
    NSSToken *token,
204
    NSSError why)
205
0
{
206
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
207
0
    return PR_FAILURE;
208
0
}
209
210
NSS_IMPLEMENT PRStatus
211
NSSTrustDomain_EnableToken(
212
    NSSTrustDomain *td,
213
    NSSToken *token)
214
0
{
215
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
216
0
    return PR_FAILURE;
217
0
}
218
219
NSS_IMPLEMENT PRStatus
220
NSSTrustDomain_IsTokenEnabled(
221
    NSSTrustDomain *td,
222
    NSSToken *token,
223
    NSSError *whyOpt)
224
0
{
225
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
226
0
    return PR_FAILURE;
227
0
}
228
229
NSS_IMPLEMENT NSSSlot *
230
NSSTrustDomain_FindSlotByName(
231
    NSSTrustDomain *td,
232
    NSSUTF8 *slotName)
233
0
{
234
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
235
0
    return NULL;
236
0
}
237
238
NSS_IMPLEMENT NSSToken **
239
NSSTrustDomain_FindTokensByURI(
240
    NSSTrustDomain *td,
241
    PK11URI *uri)
242
0
{
243
0
    NSSToken *tok = NULL;
244
0
    PK11SlotInfo *slotinfo;
245
0
    NSSToken **tokens;
246
0
    int count, i = 0;
247
0
248
0
    NSSRWLock_LockRead(td->tokensLock);
249
0
    count = nssList_Count(td->tokenList);
250
0
    tokens = nss_ZNEWARRAY(NULL, NSSToken *, count + 1);
251
0
    if (!tokens) {
252
0
        return NULL;
253
0
    }
254
0
    for (tok = (NSSToken *)nssListIterator_Start(td->tokens);
255
0
         tok != (NSSToken *)NULL;
256
0
         tok = (NSSToken *)nssListIterator_Next(td->tokens)) {
257
0
        if (nssToken_IsPresent(tok)) {
258
0
            slotinfo = tok->pk11slot;
259
0
            if (pk11_MatchUriTokenInfo(slotinfo, uri))
260
0
                tokens[i++] = nssToken_AddRef(tok);
261
0
        }
262
0
    }
263
0
    tokens[i] = NULL;
264
0
    nssListIterator_Finish(td->tokens);
265
0
    NSSRWLock_UnlockRead(td->tokensLock);
266
0
    return tokens;
267
0
}
268
269
NSS_IMPLEMENT NSSToken *
270
NSSTrustDomain_FindTokenByName(
271
    NSSTrustDomain *td,
272
    NSSUTF8 *tokenName)
273
0
{
274
0
    PRStatus nssrv;
275
0
    NSSUTF8 *myName;
276
0
    NSSToken *tok = NULL;
277
0
    NSSRWLock_LockRead(td->tokensLock);
278
0
    for (tok = (NSSToken *)nssListIterator_Start(td->tokens);
279
0
         tok != (NSSToken *)NULL;
280
0
         tok = (NSSToken *)nssListIterator_Next(td->tokens)) {
281
0
        if (nssToken_IsPresent(tok)) {
282
0
            myName = nssToken_GetName(tok);
283
0
            if (nssUTF8_Equal(tokenName, myName, &nssrv)) {
284
0
                tok = nssToken_AddRef(tok);
285
0
                break;
286
0
            }
287
0
        }
288
0
    }
289
0
    nssListIterator_Finish(td->tokens);
290
0
    NSSRWLock_UnlockRead(td->tokensLock);
291
0
    return tok;
292
0
}
293
294
NSS_IMPLEMENT NSSToken *
295
NSSTrustDomain_FindTokenBySlotName(
296
    NSSTrustDomain *td,
297
    NSSUTF8 *slotName)
298
0
{
299
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
300
0
    return NULL;
301
0
}
302
303
NSS_IMPLEMENT NSSToken *
304
NSSTrustDomain_FindTokenForAlgorithm(
305
    NSSTrustDomain *td,
306
    NSSOID *algorithm)
307
0
{
308
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
309
0
    return NULL;
310
0
}
311
312
NSS_IMPLEMENT NSSToken *
313
NSSTrustDomain_FindBestTokenForAlgorithms(
314
    NSSTrustDomain *td,
315
    NSSOID *algorithms[],   /* may be null-terminated */
316
    PRUint32 nAlgorithmsOpt /* limits the array if nonzero */
317
    )
318
0
{
319
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
320
0
    return NULL;
321
0
}
322
323
NSS_IMPLEMENT PRStatus
324
NSSTrustDomain_Login(
325
    NSSTrustDomain *td,
326
    NSSCallback *uhhOpt)
327
0
{
328
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
329
0
    return PR_FAILURE;
330
0
}
331
332
NSS_IMPLEMENT PRStatus
333
NSSTrustDomain_Logout(NSSTrustDomain *td)
334
0
{
335
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
336
0
    return PR_FAILURE;
337
0
}
338
339
NSS_IMPLEMENT NSSCertificate *
340
NSSTrustDomain_ImportCertificate(
341
    NSSTrustDomain *td,
342
    NSSCertificate *c)
343
0
{
344
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
345
0
    return NULL;
346
0
}
347
348
NSS_IMPLEMENT NSSCertificate *
349
NSSTrustDomain_ImportPKIXCertificate(
350
    NSSTrustDomain *td,
351
    /* declared as a struct until these "data types" are defined */
352
    struct NSSPKIXCertificateStr *pc)
353
0
{
354
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
355
0
    return NULL;
356
0
}
357
358
NSS_IMPLEMENT NSSCertificate *
359
NSSTrustDomain_ImportEncodedCertificate(
360
    NSSTrustDomain *td,
361
    NSSBER *ber)
362
0
{
363
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
364
0
    return NULL;
365
0
}
366
367
NSS_IMPLEMENT NSSCertificate **
368
NSSTrustDomain_ImportEncodedCertificateChain(
369
    NSSTrustDomain *td,
370
    NSSBER *ber,
371
    NSSCertificate *rvOpt[],
372
    PRUint32 maximumOpt, /* 0 for no max */
373
    NSSArena *arenaOpt)
374
0
{
375
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
376
0
    return NULL;
377
0
}
378
379
NSS_IMPLEMENT NSSPrivateKey *
380
NSSTrustDomain_ImportEncodedPrivateKey(
381
    NSSTrustDomain *td,
382
    NSSBER *ber,
383
    NSSItem *passwordOpt, /* NULL will cause a callback */
384
    NSSCallback *uhhOpt,
385
    NSSToken *destination)
386
0
{
387
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
388
0
    return NULL;
389
0
}
390
391
NSS_IMPLEMENT NSSPublicKey *
392
NSSTrustDomain_ImportEncodedPublicKey(
393
    NSSTrustDomain *td,
394
    NSSBER *ber)
395
0
{
396
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
397
0
    return NULL;
398
0
}
399
400
static NSSCertificate **
401
get_certs_from_list(nssList *list)
402
0
{
403
0
    PRUint32 count = nssList_Count(list);
404
0
    NSSCertificate **certs = NULL;
405
0
    if (count > 0) {
406
0
        certs = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1);
407
0
        if (certs) {
408
0
            nssList_GetArray(list, (void **)certs, count);
409
0
        }
410
0
    }
411
0
    return certs;
412
0
}
413
414
NSS_IMPLEMENT NSSCertificate **
415
nssTrustDomain_FindCertificatesByNickname(
416
    NSSTrustDomain *td,
417
    const NSSUTF8 *name,
418
    NSSCertificate *rvOpt[],
419
    PRUint32 maximumOpt, /* 0 for no max */
420
    NSSArena *arenaOpt)
421
0
{
422
0
    NSSToken *token = NULL;
423
0
    NSSSlot **slots = NULL;
424
0
    NSSSlot **slotp;
425
0
    NSSCertificate **rvCerts = NULL;
426
0
    nssPKIObjectCollection *collection = NULL;
427
0
    nssUpdateLevel updateLevel;
428
0
    nssList *nameList;
429
0
    PRUint32 numRemaining = maximumOpt;
430
0
    PRUint32 collectionCount = 0;
431
0
    PRUint32 errors = 0;
432
0
433
0
    /* First, grab from the cache */
434
0
    nameList = nssList_Create(NULL, PR_FALSE);
435
0
    if (!nameList) {
436
0
        return NULL;
437
0
    }
438
0
    (void)nssTrustDomain_GetCertsForNicknameFromCache(td, name, nameList);
439
0
    rvCerts = get_certs_from_list(nameList);
440
0
    /* initialize the collection of token certificates with the set of
441
0
     * cached certs (if any).
442
0
     */
443
0
    collection = nssCertificateCollection_Create(td, rvCerts);
444
0
    nssCertificateArray_Destroy(rvCerts);
445
0
    nssList_Destroy(nameList);
446
0
    if (!collection) {
447
0
        return (NSSCertificate **)NULL;
448
0
    }
449
0
    /* obtain the current set of active slots in the trust domain */
450
0
    slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
451
0
    if (!slots) {
452
0
        goto loser;
453
0
    }
454
0
    /* iterate over the slots */
455
0
    for (slotp = slots; *slotp; slotp++) {
456
0
        token = nssSlot_GetToken(*slotp);
457
0
        if (token) {
458
0
            nssSession *session;
459
0
            nssCryptokiObject **instances = NULL;
460
0
            nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
461
0
            PRStatus status = PR_FAILURE;
462
0
463
0
            session = nssTrustDomain_GetSessionForToken(td, token);
464
0
            if (session) {
465
0
                instances = nssToken_FindCertificatesByNickname(token,
466
0
                                                                session,
467
0
                                                                name,
468
0
                                                                tokenOnly,
469
0
                                                                numRemaining,
470
0
                                                                &status);
471
0
            }
472
0
            nssToken_Destroy(token);
473
0
            if (status != PR_SUCCESS) {
474
0
                errors++;
475
0
                continue;
476
0
            }
477
0
            if (instances) {
478
0
                status = nssPKIObjectCollection_AddInstances(collection,
479
0
                                                             instances, 0);
480
0
                nss_ZFreeIf(instances);
481
0
                if (status != PR_SUCCESS) {
482
0
                    errors++;
483
0
                    continue;
484
0
                }
485
0
                collectionCount = nssPKIObjectCollection_Count(collection);
486
0
                if (maximumOpt > 0) {
487
0
                    if (collectionCount >= maximumOpt)
488
0
                        break;
489
0
                    numRemaining = maximumOpt - collectionCount;
490
0
                }
491
0
            }
492
0
        }
493
0
    }
494
0
    if (!collectionCount && errors)
495
0
        goto loser;
496
0
    /* Grab the certs collected in the search. */
497
0
    rvCerts = nssPKIObjectCollection_GetCertificates(collection,
498
0
                                                     rvOpt, maximumOpt,
499
0
                                                     arenaOpt);
500
0
    /* clean up */
501
0
    nssPKIObjectCollection_Destroy(collection);
502
0
    nssSlotArray_Destroy(slots);
503
0
    return rvCerts;
504
0
loser:
505
0
    if (slots) {
506
0
        nssSlotArray_Destroy(slots);
507
0
    }
508
0
    if (collection) {
509
0
        nssPKIObjectCollection_Destroy(collection);
510
0
    }
511
0
    return (NSSCertificate **)NULL;
512
0
}
513
514
NSS_IMPLEMENT NSSCertificate **
515
NSSTrustDomain_FindCertificatesByNickname(
516
    NSSTrustDomain *td,
517
    NSSUTF8 *name,
518
    NSSCertificate *rvOpt[],
519
    PRUint32 maximumOpt, /* 0 for no max */
520
    NSSArena *arenaOpt)
521
0
{
522
0
    return nssTrustDomain_FindCertificatesByNickname(td,
523
0
                                                     name,
524
0
                                                     rvOpt,
525
0
                                                     maximumOpt,
526
0
                                                     arenaOpt);
527
0
}
528
529
NSS_IMPLEMENT NSSCertificate *
530
nssTrustDomain_FindBestCertificateByNickname(
531
    NSSTrustDomain *td,
532
    const NSSUTF8 *name,
533
    NSSTime *timeOpt,
534
    NSSUsage *usage,
535
    NSSPolicies *policiesOpt)
536
0
{
537
0
    NSSCertificate **nicknameCerts;
538
0
    NSSCertificate *rvCert = NULL;
539
0
    nicknameCerts = nssTrustDomain_FindCertificatesByNickname(td, name,
540
0
                                                              NULL,
541
0
                                                              0,
542
0
                                                              NULL);
543
0
    if (nicknameCerts) {
544
0
        rvCert = nssCertificateArray_FindBestCertificate(nicknameCerts,
545
0
                                                         timeOpt,
546
0
                                                         usage,
547
0
                                                         policiesOpt);
548
0
        nssCertificateArray_Destroy(nicknameCerts);
549
0
    }
550
0
    return rvCert;
551
0
}
552
553
NSS_IMPLEMENT NSSCertificate *
554
NSSTrustDomain_FindBestCertificateByNickname(
555
    NSSTrustDomain *td,
556
    const NSSUTF8 *name,
557
    NSSTime *timeOpt,
558
    NSSUsage *usage,
559
    NSSPolicies *policiesOpt)
560
0
{
561
0
    return nssTrustDomain_FindBestCertificateByNickname(td,
562
0
                                                        name,
563
0
                                                        timeOpt,
564
0
                                                        usage,
565
0
                                                        policiesOpt);
566
0
}
567
568
NSS_IMPLEMENT NSSCertificate **
569
nssTrustDomain_FindCertificatesBySubject(
570
    NSSTrustDomain *td,
571
    NSSDER *subject,
572
    NSSCertificate *rvOpt[],
573
    PRUint32 maximumOpt, /* 0 for no max */
574
    NSSArena *arenaOpt)
575
0
{
576
0
    NSSToken *token = NULL;
577
0
    NSSSlot **slots = NULL;
578
0
    NSSSlot **slotp;
579
0
    NSSCertificate **rvCerts = NULL;
580
0
    nssPKIObjectCollection *collection = NULL;
581
0
    nssUpdateLevel updateLevel;
582
0
    nssList *subjectList;
583
0
    PRUint32 numRemaining = maximumOpt;
584
0
    PRUint32 collectionCount = 0;
585
0
    PRUint32 errors = 0;
586
0
587
0
    /* look in cache */
588
0
    subjectList = nssList_Create(NULL, PR_FALSE);
589
0
    if (!subjectList) {
590
0
        return NULL;
591
0
    }
592
0
    (void)nssTrustDomain_GetCertsForSubjectFromCache(td, subject, subjectList);
593
0
    rvCerts = get_certs_from_list(subjectList);
594
0
    collection = nssCertificateCollection_Create(td, rvCerts);
595
0
    nssCertificateArray_Destroy(rvCerts);
596
0
    nssList_Destroy(subjectList);
597
0
    if (!collection) {
598
0
        return (NSSCertificate **)NULL;
599
0
    }
600
0
    slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
601
0
    if (!slots) {
602
0
        goto loser;
603
0
    }
604
0
    for (slotp = slots; *slotp; slotp++) {
605
0
        token = nssSlot_GetToken(*slotp);
606
0
        if (token) {
607
0
            nssSession *session;
608
0
            nssCryptokiObject **instances = NULL;
609
0
            nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
610
0
            PRStatus status = PR_FAILURE;
611
0
612
0
            session = nssTrustDomain_GetSessionForToken(td, token);
613
0
            if (session) {
614
0
                instances = nssToken_FindCertificatesBySubject(token,
615
0
                                                               session,
616
0
                                                               subject,
617
0
                                                               tokenOnly,
618
0
                                                               numRemaining,
619
0
                                                               &status);
620
0
            }
621
0
            nssToken_Destroy(token);
622
0
            if (status != PR_SUCCESS) {
623
0
                errors++;
624
0
                continue;
625
0
            }
626
0
            if (instances) {
627
0
                status = nssPKIObjectCollection_AddInstances(collection,
628
0
                                                             instances, 0);
629
0
                nss_ZFreeIf(instances);
630
0
                if (status != PR_SUCCESS) {
631
0
                    errors++;
632
0
                    continue;
633
0
                }
634
0
                collectionCount = nssPKIObjectCollection_Count(collection);
635
0
                if (maximumOpt > 0) {
636
0
                    if (collectionCount >= maximumOpt)
637
0
                        break;
638
0
                    numRemaining = maximumOpt - collectionCount;
639
0
                }
640
0
            }
641
0
        }
642
0
    }
643
0
    if (!collectionCount && errors)
644
0
        goto loser;
645
0
    rvCerts = nssPKIObjectCollection_GetCertificates(collection,
646
0
                                                     rvOpt, maximumOpt,
647
0
                                                     arenaOpt);
648
0
    nssPKIObjectCollection_Destroy(collection);
649
0
    nssSlotArray_Destroy(slots);
650
0
    return rvCerts;
651
0
loser:
652
0
    if (slots) {
653
0
        nssSlotArray_Destroy(slots);
654
0
    }
655
0
    if (collection) {
656
0
        nssPKIObjectCollection_Destroy(collection);
657
0
    }
658
0
    return (NSSCertificate **)NULL;
659
0
}
660
661
NSS_IMPLEMENT NSSCertificate **
662
NSSTrustDomain_FindCertificatesBySubject(
663
    NSSTrustDomain *td,
664
    NSSDER *subject,
665
    NSSCertificate *rvOpt[],
666
    PRUint32 maximumOpt,
667
    NSSArena *arenaOpt)
668
0
{
669
0
    return nssTrustDomain_FindCertificatesBySubject(td,
670
0
                                                    subject,
671
0
                                                    rvOpt,
672
0
                                                    maximumOpt,
673
0
                                                    arenaOpt);
674
0
}
675
676
NSS_IMPLEMENT NSSCertificate *
677
nssTrustDomain_FindBestCertificateBySubject(
678
    NSSTrustDomain *td,
679
    NSSDER *subject,
680
    NSSTime *timeOpt,
681
    NSSUsage *usage,
682
    NSSPolicies *policiesOpt)
683
0
{
684
0
    NSSCertificate **subjectCerts;
685
0
    NSSCertificate *rvCert = NULL;
686
0
    subjectCerts = nssTrustDomain_FindCertificatesBySubject(td, subject,
687
0
                                                            NULL,
688
0
                                                            0,
689
0
                                                            NULL);
690
0
    if (subjectCerts) {
691
0
        rvCert = nssCertificateArray_FindBestCertificate(subjectCerts,
692
0
                                                         timeOpt,
693
0
                                                         usage,
694
0
                                                         policiesOpt);
695
0
        nssCertificateArray_Destroy(subjectCerts);
696
0
    }
697
0
    return rvCert;
698
0
}
699
700
NSS_IMPLEMENT NSSCertificate *
701
NSSTrustDomain_FindBestCertificateBySubject(
702
    NSSTrustDomain *td,
703
    NSSDER *subject,
704
    NSSTime *timeOpt,
705
    NSSUsage *usage,
706
    NSSPolicies *policiesOpt)
707
0
{
708
0
    return nssTrustDomain_FindBestCertificateBySubject(td,
709
0
                                                       subject,
710
0
                                                       timeOpt,
711
0
                                                       usage,
712
0
                                                       policiesOpt);
713
0
}
714
715
NSS_IMPLEMENT NSSCertificate *
716
NSSTrustDomain_FindBestCertificateByNameComponents(
717
    NSSTrustDomain *td,
718
    NSSUTF8 *nameComponents,
719
    NSSTime *timeOpt,
720
    NSSUsage *usage,
721
    NSSPolicies *policiesOpt)
722
0
{
723
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
724
0
    return NULL;
725
0
}
726
727
NSS_IMPLEMENT NSSCertificate **
728
NSSTrustDomain_FindCertificatesByNameComponents(
729
    NSSTrustDomain *td,
730
    NSSUTF8 *nameComponents,
731
    NSSCertificate *rvOpt[],
732
    PRUint32 maximumOpt, /* 0 for no max */
733
    NSSArena *arenaOpt)
734
0
{
735
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
736
0
    return NULL;
737
0
}
738
739
/* This returns at most a single certificate, so it can stop the loop
740
 * when one is found.
741
 */
742
NSS_IMPLEMENT NSSCertificate *
743
nssTrustDomain_FindCertificateByIssuerAndSerialNumber(
744
    NSSTrustDomain *td,
745
    NSSDER *issuer,
746
    NSSDER *serial)
747
0
{
748
0
    NSSSlot **slots = NULL;
749
0
    NSSSlot **slotp;
750
0
    NSSCertificate *rvCert = NULL;
751
0
    nssPKIObjectCollection *collection = NULL;
752
0
    nssUpdateLevel updateLevel;
753
0
754
0
    /* see if this search is already cached */
755
0
    rvCert = nssTrustDomain_GetCertForIssuerAndSNFromCache(td,
756
0
                                                           issuer,
757
0
                                                           serial);
758
0
    if (rvCert) {
759
0
        return rvCert;
760
0
    }
761
0
    slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
762
0
    if (slots) {
763
0
        for (slotp = slots; *slotp; slotp++) {
764
0
            NSSToken *token = nssSlot_GetToken(*slotp);
765
0
            nssSession *session;
766
0
            nssCryptokiObject *instance;
767
0
            nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
768
0
            PRStatus status = PR_FAILURE;
769
0
770
0
            if (!token)
771
0
                continue;
772
0
            session = nssTrustDomain_GetSessionForToken(td, token);
773
0
            if (session) {
774
0
                instance = nssToken_FindCertificateByIssuerAndSerialNumber(
775
0
                    token,
776
0
                    session,
777
0
                    issuer,
778
0
                    serial,
779
0
                    tokenOnly,
780
0
                    &status);
781
0
            }
782
0
            nssToken_Destroy(token);
783
0
            if (status != PR_SUCCESS) {
784
0
                continue;
785
0
            }
786
0
            if (instance) {
787
0
                if (!collection) {
788
0
                    collection = nssCertificateCollection_Create(td, NULL);
789
0
                    if (!collection) {
790
0
                        break; /* don't keep looping if out if memory */
791
0
                    }
792
0
                }
793
0
                status = nssPKIObjectCollection_AddInstances(collection,
794
0
                                                             &instance, 1);
795
0
                if (status == PR_SUCCESS) {
796
0
                    (void)nssPKIObjectCollection_GetCertificates(
797
0
                        collection, &rvCert, 1, NULL);
798
0
                }
799
0
                if (rvCert) {
800
0
                    break; /* found one cert, all done */
801
0
                }
802
0
            }
803
0
        }
804
0
    }
805
0
    if (collection) {
806
0
        nssPKIObjectCollection_Destroy(collection);
807
0
    }
808
0
    if (slots) {
809
0
        nssSlotArray_Destroy(slots);
810
0
    }
811
0
    return rvCert;
812
0
}
813
814
NSS_IMPLEMENT NSSCertificate *
815
NSSTrustDomain_FindCertificateByIssuerAndSerialNumber(
816
    NSSTrustDomain *td,
817
    NSSDER *issuer,
818
    NSSDER *serial)
819
0
{
820
0
    return nssTrustDomain_FindCertificateByIssuerAndSerialNumber(td,
821
0
                                                                 issuer,
822
0
                                                                 serial);
823
0
}
824
825
NSS_IMPLEMENT NSSCertificate *
826
nssTrustDomain_FindCertificateByEncodedCertificate(
827
    NSSTrustDomain *td,
828
    NSSBER *ber)
829
0
{
830
0
    PRStatus status;
831
0
    NSSCertificate *rvCert = NULL;
832
0
    NSSDER issuer = { 0 };
833
0
    NSSDER serial = { 0 };
834
0
    /* XXX this is not generic...  will any cert crack into issuer/serial? */
835
0
    status = nssPKIX509_GetIssuerAndSerialFromDER(ber, &issuer, &serial);
836
0
    if (status != PR_SUCCESS) {
837
0
        return NULL;
838
0
    }
839
0
    rvCert = nssTrustDomain_FindCertificateByIssuerAndSerialNumber(td,
840
0
                                                                   &issuer,
841
0
                                                                   &serial);
842
0
    PORT_Free(issuer.data);
843
0
    PORT_Free(serial.data);
844
0
    return rvCert;
845
0
}
846
847
NSS_IMPLEMENT NSSCertificate *
848
NSSTrustDomain_FindCertificateByEncodedCertificate(
849
    NSSTrustDomain *td,
850
    NSSBER *ber)
851
0
{
852
0
    return nssTrustDomain_FindCertificateByEncodedCertificate(td, ber);
853
0
}
854
855
NSS_IMPLEMENT NSSCertificate *
856
NSSTrustDomain_FindBestCertificateByEmail(
857
    NSSTrustDomain *td,
858
    NSSASCII7 *email,
859
    NSSTime *timeOpt,
860
    NSSUsage *usage,
861
    NSSPolicies *policiesOpt)
862
0
{
863
0
    return 0;
864
0
}
865
866
NSS_IMPLEMENT NSSCertificate **
867
NSSTrustDomain_FindCertificatesByEmail(
868
    NSSTrustDomain *td,
869
    NSSASCII7 *email,
870
    NSSCertificate *rvOpt[],
871
    PRUint32 maximumOpt, /* 0 for no max */
872
    NSSArena *arenaOpt)
873
0
{
874
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
875
0
    return NULL;
876
0
}
877
878
NSS_IMPLEMENT NSSCertificate *
879
NSSTrustDomain_FindCertificateByOCSPHash(
880
    NSSTrustDomain *td,
881
    NSSItem *hash)
882
0
{
883
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
884
0
    return NULL;
885
0
}
886
887
NSS_IMPLEMENT NSSCertificate *
888
NSSTrustDomain_FindBestUserCertificate(
889
    NSSTrustDomain *td,
890
    NSSTime *timeOpt,
891
    NSSUsage *usage,
892
    NSSPolicies *policiesOpt)
893
0
{
894
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
895
0
    return NULL;
896
0
}
897
898
NSS_IMPLEMENT NSSCertificate **
899
NSSTrustDomain_FindUserCertificates(
900
    NSSTrustDomain *td,
901
    NSSTime *timeOpt,
902
    NSSUsage *usageOpt,
903
    NSSPolicies *policiesOpt,
904
    NSSCertificate **rvOpt,
905
    PRUint32 rvLimit, /* zero for no limit */
906
    NSSArena *arenaOpt)
907
0
{
908
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
909
0
    return NULL;
910
0
}
911
912
NSS_IMPLEMENT NSSCertificate *
913
NSSTrustDomain_FindBestUserCertificateForSSLClientAuth(
914
    NSSTrustDomain *td,
915
    NSSUTF8 *sslHostOpt,
916
    NSSDER *rootCAsOpt[],   /* null pointer for none */
917
    PRUint32 rootCAsMaxOpt, /* zero means list is null-terminated */
918
    NSSAlgorithmAndParameters *apOpt,
919
    NSSPolicies *policiesOpt)
920
0
{
921
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
922
0
    return NULL;
923
0
}
924
925
NSS_IMPLEMENT NSSCertificate **
926
NSSTrustDomain_FindUserCertificatesForSSLClientAuth(
927
    NSSTrustDomain *td,
928
    NSSUTF8 *sslHostOpt,
929
    NSSDER *rootCAsOpt[],   /* null pointer for none */
930
    PRUint32 rootCAsMaxOpt, /* zero means list is null-terminated */
931
    NSSAlgorithmAndParameters *apOpt,
932
    NSSPolicies *policiesOpt,
933
    NSSCertificate **rvOpt,
934
    PRUint32 rvLimit, /* zero for no limit */
935
    NSSArena *arenaOpt)
936
0
{
937
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
938
0
    return NULL;
939
0
}
940
941
NSS_IMPLEMENT NSSCertificate *
942
NSSTrustDomain_FindBestUserCertificateForEmailSigning(
943
    NSSTrustDomain *td,
944
    NSSASCII7 *signerOpt,
945
    NSSASCII7 *recipientOpt,
946
    /* anything more here? */
947
    NSSAlgorithmAndParameters *apOpt,
948
    NSSPolicies *policiesOpt)
949
0
{
950
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
951
0
    return NULL;
952
0
}
953
954
NSS_IMPLEMENT NSSCertificate **
955
NSSTrustDomain_FindUserCertificatesForEmailSigning(
956
    NSSTrustDomain *td,
957
    NSSASCII7 *signerOpt,
958
    NSSASCII7 *recipientOpt,
959
    /* anything more here? */
960
    NSSAlgorithmAndParameters *apOpt,
961
    NSSPolicies *policiesOpt,
962
    NSSCertificate **rvOpt,
963
    PRUint32 rvLimit, /* zero for no limit */
964
    NSSArena *arenaOpt)
965
0
{
966
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
967
0
    return NULL;
968
0
}
969
970
static PRStatus
971
collector(nssCryptokiObject *instance, void *arg)
972
0
{
973
0
    nssPKIObjectCollection *collection = (nssPKIObjectCollection *)arg;
974
0
    return nssPKIObjectCollection_AddInstanceAsObject(collection, instance);
975
0
}
976
977
NSS_IMPLEMENT PRStatus *
978
NSSTrustDomain_TraverseCertificates(
979
    NSSTrustDomain *td,
980
    PRStatus (*callback)(NSSCertificate *c, void *arg),
981
    void *arg)
982
0
{
983
0
    NSSToken *token = NULL;
984
0
    NSSSlot **slots = NULL;
985
0
    NSSSlot **slotp;
986
0
    nssPKIObjectCollection *collection = NULL;
987
0
    nssPKIObjectCallback pkiCallback;
988
0
    nssUpdateLevel updateLevel;
989
0
    NSSCertificate **cached = NULL;
990
0
    nssList *certList;
991
0
992
0
    certList = nssList_Create(NULL, PR_FALSE);
993
0
    if (!certList)
994
0
        return NULL;
995
0
    (void)nssTrustDomain_GetCertsFromCache(td, certList);
996
0
    cached = get_certs_from_list(certList);
997
0
    collection = nssCertificateCollection_Create(td, cached);
998
0
    nssCertificateArray_Destroy(cached);
999
0
    nssList_Destroy(certList);
1000
0
    if (!collection) {
1001
0
        return (PRStatus *)NULL;
1002
0
    }
1003
0
    /* obtain the current set of active slots in the trust domain */
1004
0
    slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
1005
0
    if (!slots) {
1006
0
        goto loser;
1007
0
    }
1008
0
    /* iterate over the slots */
1009
0
    for (slotp = slots; *slotp; slotp++) {
1010
0
        /* get the token for the slot, if present */
1011
0
        token = nssSlot_GetToken(*slotp);
1012
0
        if (token) {
1013
0
            nssSession *session;
1014
0
            nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
1015
0
            /* get a session for the token */
1016
0
            session = nssTrustDomain_GetSessionForToken(td, token);
1017
0
            if (session) {
1018
0
                /* perform the traversal */
1019
0
                (void)nssToken_TraverseCertificates(token,
1020
0
                                                    session,
1021
0
                                                    tokenOnly,
1022
0
                                                    collector,
1023
0
                                                    collection);
1024
0
            }
1025
0
            nssToken_Destroy(token);
1026
0
        }
1027
0
    }
1028
0
1029
0
    /* Traverse the collection */
1030
0
    pkiCallback.func.cert = callback;
1031
0
    pkiCallback.arg = arg;
1032
0
    (void)nssPKIObjectCollection_Traverse(collection, &pkiCallback);
1033
0
loser:
1034
0
    if (slots) {
1035
0
        nssSlotArray_Destroy(slots);
1036
0
    }
1037
0
    if (collection) {
1038
0
        nssPKIObjectCollection_Destroy(collection);
1039
0
    }
1040
0
    return NULL;
1041
0
}
1042
1043
NSS_IMPLEMENT NSSTrust *
1044
nssTrustDomain_FindTrustForCertificate(
1045
    NSSTrustDomain *td,
1046
    NSSCertificate *c)
1047
0
{
1048
0
    NSSSlot **slots;
1049
0
    NSSSlot **slotp;
1050
0
    nssCryptokiObject *to = NULL;
1051
0
    nssPKIObject *pkio = NULL;
1052
0
    NSSTrust *rvt = NULL;
1053
0
    nssUpdateLevel updateLevel;
1054
0
    slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
1055
0
    if (!slots) {
1056
0
        return (NSSTrust *)NULL;
1057
0
    }
1058
0
    for (slotp = slots; *slotp; slotp++) {
1059
0
        NSSToken *token = nssSlot_GetToken(*slotp);
1060
0
1061
0
        if (token) {
1062
0
            to = nssToken_FindTrustForCertificate(token, NULL,
1063
0
                                                  &c->encoding,
1064
0
                                                  &c->issuer,
1065
0
                                                  &c->serial,
1066
0
                                                  nssTokenSearchType_TokenOnly);
1067
0
            if (to) {
1068
0
                PRStatus status;
1069
0
                if (!pkio) {
1070
0
                    pkio = nssPKIObject_Create(NULL, to, td, NULL, nssPKILock);
1071
0
                    status = pkio ? PR_SUCCESS : PR_FAILURE;
1072
0
                } else {
1073
0
                    status = nssPKIObject_AddInstance(pkio, to);
1074
0
                }
1075
0
                if (status != PR_SUCCESS) {
1076
0
                    nssCryptokiObject_Destroy(to);
1077
0
                }
1078
0
            }
1079
0
            nssToken_Destroy(token);
1080
0
        }
1081
0
    }
1082
0
    if (pkio) {
1083
0
        rvt = nssTrust_Create(pkio, &c->encoding);
1084
0
        if (rvt) {
1085
0
            pkio = NULL; /* rvt object now owns the pkio reference */
1086
0
        }
1087
0
    }
1088
0
    nssSlotArray_Destroy(slots);
1089
0
    if (pkio) {
1090
0
        nssPKIObject_Destroy(pkio);
1091
0
    }
1092
0
    return rvt;
1093
0
}
1094
1095
NSS_IMPLEMENT NSSCRL **
1096
nssTrustDomain_FindCRLsBySubject(
1097
    NSSTrustDomain *td,
1098
    NSSDER *subject)
1099
0
{
1100
0
    NSSSlot **slots;
1101
0
    NSSSlot **slotp;
1102
0
    NSSToken *token;
1103
0
    nssUpdateLevel updateLevel;
1104
0
    nssPKIObjectCollection *collection;
1105
0
    NSSCRL **rvCRLs = NULL;
1106
0
    collection = nssCRLCollection_Create(td, NULL);
1107
0
    if (!collection) {
1108
0
        return (NSSCRL **)NULL;
1109
0
    }
1110
0
    slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
1111
0
    if (!slots) {
1112
0
        goto loser;
1113
0
    }
1114
0
    for (slotp = slots; *slotp; slotp++) {
1115
0
        token = nssSlot_GetToken(*slotp);
1116
0
        if (token) {
1117
0
            PRStatus status = PR_FAILURE;
1118
0
            nssSession *session;
1119
0
            nssCryptokiObject **instances = NULL;
1120
0
            nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
1121
0
1122
0
            /* get a session for the token */
1123
0
            session = nssTrustDomain_GetSessionForToken(td, token);
1124
0
            if (session) {
1125
0
                /* perform the traversal */
1126
0
                instances = nssToken_FindCRLsBySubject(token, session, subject,
1127
0
                                                       tokenOnly, 0, &status);
1128
0
            }
1129
0
            nssToken_Destroy(token);
1130
0
            if (status == PR_SUCCESS) {
1131
0
                /* add the found CRL's to the collection */
1132
0
                status = nssPKIObjectCollection_AddInstances(collection,
1133
0
                                                             instances, 0);
1134
0
            }
1135
0
            nss_ZFreeIf(instances);
1136
0
        }
1137
0
    }
1138
0
    rvCRLs = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL);
1139
0
loser:
1140
0
    nssPKIObjectCollection_Destroy(collection);
1141
0
    nssSlotArray_Destroy(slots);
1142
0
    return rvCRLs;
1143
0
}
1144
1145
NSS_IMPLEMENT PRStatus
1146
NSSTrustDomain_GenerateKeyPair(
1147
    NSSTrustDomain *td,
1148
    NSSAlgorithmAndParameters *ap,
1149
    NSSPrivateKey **pvkOpt,
1150
    NSSPublicKey **pbkOpt,
1151
    PRBool privateKeyIsSensitive,
1152
    NSSToken *destination,
1153
    NSSCallback *uhhOpt)
1154
0
{
1155
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
1156
0
    return PR_FAILURE;
1157
0
}
1158
1159
NSS_IMPLEMENT NSSSymmetricKey *
1160
NSSTrustDomain_GenerateSymmetricKey(
1161
    NSSTrustDomain *td,
1162
    NSSAlgorithmAndParameters *ap,
1163
    PRUint32 keysize,
1164
    NSSToken *destination,
1165
    NSSCallback *uhhOpt)
1166
0
{
1167
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
1168
0
    return NULL;
1169
0
}
1170
1171
NSS_IMPLEMENT NSSSymmetricKey *
1172
NSSTrustDomain_GenerateSymmetricKeyFromPassword(
1173
    NSSTrustDomain *td,
1174
    NSSAlgorithmAndParameters *ap,
1175
    NSSUTF8 *passwordOpt, /* if null, prompt */
1176
    NSSToken *destinationOpt,
1177
    NSSCallback *uhhOpt)
1178
0
{
1179
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
1180
0
    return NULL;
1181
0
}
1182
1183
NSS_IMPLEMENT NSSSymmetricKey *
1184
NSSTrustDomain_FindSymmetricKeyByAlgorithmAndKeyID(
1185
    NSSTrustDomain *td,
1186
    NSSOID *algorithm,
1187
    NSSItem *keyID,
1188
    NSSCallback *uhhOpt)
1189
0
{
1190
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
1191
0
    return NULL;
1192
0
}
1193
1194
NSS_IMPLEMENT NSSCryptoContext *
1195
nssTrustDomain_CreateCryptoContext(
1196
    NSSTrustDomain *td,
1197
    NSSCallback *uhhOpt)
1198
0
{
1199
0
    return nssCryptoContext_Create(td, uhhOpt);
1200
0
}
1201
1202
NSS_IMPLEMENT NSSCryptoContext *
1203
NSSTrustDomain_CreateCryptoContext(
1204
    NSSTrustDomain *td,
1205
    NSSCallback *uhhOpt)
1206
0
{
1207
0
    return nssTrustDomain_CreateCryptoContext(td, uhhOpt);
1208
0
}
1209
1210
NSS_IMPLEMENT NSSCryptoContext *
1211
NSSTrustDomain_CreateCryptoContextForAlgorithm(
1212
    NSSTrustDomain *td,
1213
    NSSOID *algorithm)
1214
0
{
1215
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
1216
0
    return NULL;
1217
0
}
1218
1219
NSS_IMPLEMENT NSSCryptoContext *
1220
NSSTrustDomain_CreateCryptoContextForAlgorithmAndParameters(
1221
    NSSTrustDomain *td,
1222
    NSSAlgorithmAndParameters *ap)
1223
0
{
1224
0
    nss_SetError(NSS_ERROR_NOT_FOUND);
1225
0
    return NULL;
1226
0
}