Coverage Report

Created: 2025-08-18 06:34

/src/nss/lib/pki/pki3hack.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
/*
6
 * Hacks to integrate NSS 3.4 and NSS 4.0 certificates.
7
 */
8
9
#ifndef NSSPKI_H
10
#include "nsspki.h"
11
#endif /* NSSPKI_H */
12
13
#ifndef PKI_H
14
#include "pki.h"
15
#endif /* PKI_H */
16
17
#ifndef PKIM_H
18
#include "pkim.h"
19
#endif /* PKIM_H */
20
21
#ifndef DEV_H
22
#include "dev.h"
23
#endif /* DEV_H */
24
25
#ifndef DEVNSS3HACK_H
26
#include "dev3hack.h"
27
#endif /* DEVNSS3HACK_H */
28
29
#ifndef PKINSS3HACK_H
30
#include "pki3hack.h"
31
#endif /* PKINSS3HACK_H */
32
33
#include "secitem.h"
34
#include "certdb.h"
35
#include "certt.h"
36
#include "cert.h"
37
#include "certi.h"
38
#include "pk11func.h"
39
#include "pkistore.h"
40
#include "secmod.h"
41
#include "nssrwlk.h"
42
43
NSSTrustDomain *g_default_trust_domain = NULL;
44
45
NSSCryptoContext *g_default_crypto_context = NULL;
46
47
NSSTrustDomain *
48
STAN_GetDefaultTrustDomain()
49
2.36k
{
50
2.36k
    return g_default_trust_domain;
51
2.36k
}
52
53
NSSCryptoContext *
54
STAN_GetDefaultCryptoContext()
55
0
{
56
0
    return g_default_crypto_context;
57
0
}
58
59
extern const NSSError NSS_ERROR_ALREADY_INITIALIZED;
60
extern const NSSError NSS_ERROR_INTERNAL_ERROR;
61
62
NSS_IMPLEMENT PRStatus
63
STAN_InitTokenForSlotInfo(NSSTrustDomain *td, PK11SlotInfo *slot)
64
2
{
65
2
    NSSToken *token;
66
2
    if (!td) {
67
0
        td = g_default_trust_domain;
68
0
        if (!td) {
69
            /* we're called while still initting. slot will get added
70
             * appropriately through normal init processes */
71
0
            return PR_SUCCESS;
72
0
        }
73
0
    }
74
2
    token = nssToken_CreateFromPK11SlotInfo(td, slot);
75
2
    if (token) {
76
        /* PK11Slot_SetNSSToken increments the refcount on |token| to 2 */
77
2
        PK11Slot_SetNSSToken(slot, token);
78
79
        /* we give our reference to |td->tokenList| */
80
2
        NSSRWLock_LockWrite(td->tokensLock);
81
2
        nssList_Add(td->tokenList, token);
82
2
        NSSRWLock_UnlockWrite(td->tokensLock);
83
2
    } else {
84
0
        PK11Slot_SetNSSToken(slot, NULL);
85
0
    }
86
2
    return PR_SUCCESS;
87
2
}
88
89
NSS_IMPLEMENT PRStatus
90
STAN_ResetTokenInterator(NSSTrustDomain *td)
91
0
{
92
0
    if (!td) {
93
0
        td = g_default_trust_domain;
94
0
        if (!td) {
95
            /* we're called while still initting. slot will get added
96
             * appropriately through normal init processes */
97
0
            return PR_SUCCESS;
98
0
        }
99
0
    }
100
0
    NSSRWLock_LockWrite(td->tokensLock);
101
0
    nssListIterator_Destroy(td->tokens);
102
0
    td->tokens = nssList_CreateIterator(td->tokenList);
103
0
    NSSRWLock_UnlockWrite(td->tokensLock);
104
0
    return PR_SUCCESS;
105
0
}
106
107
NSS_IMPLEMENT PRStatus
108
STAN_LoadDefaultNSS3TrustDomain(
109
    void)
110
1
{
111
1
    NSSTrustDomain *td;
112
1
    SECMODModuleList *mlp;
113
1
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
114
1
    int i;
115
116
1
    if (g_default_trust_domain || g_default_crypto_context) {
117
        /* Stan is already initialized or a previous shutdown failed. */
118
0
        nss_SetError(NSS_ERROR_ALREADY_INITIALIZED);
119
0
        return PR_FAILURE;
120
0
    }
121
1
    td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL);
122
1
    if (!td) {
123
0
        return PR_FAILURE;
124
0
    }
125
    /*
126
     * Deadlock warning: we should never acquire the moduleLock while
127
     * we hold the tokensLock. We can use the NSSRWLock Rank feature to
128
     * guarrentee this. tokensLock have a higher rank than module lock.
129
     */
130
1
    td->tokenList = nssList_Create(td->arena, PR_TRUE);
131
1
    if (!td->tokenList) {
132
0
        goto loser;
133
0
    }
134
1
    SECMOD_GetReadLock(moduleLock);
135
1
    NSSRWLock_LockWrite(td->tokensLock);
136
2
    for (mlp = SECMOD_GetDefaultModuleList(); mlp != NULL; mlp = mlp->next) {
137
3
        for (i = 0; i < mlp->module->slotCount; i++) {
138
2
            STAN_InitTokenForSlotInfo(td, mlp->module->slots[i]);
139
2
        }
140
1
    }
141
1
    td->tokens = nssList_CreateIterator(td->tokenList);
142
1
    NSSRWLock_UnlockWrite(td->tokensLock);
143
1
    SECMOD_ReleaseReadLock(moduleLock);
144
1
    if (!td->tokens) {
145
0
        goto loser;
146
0
    }
147
1
    g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL);
148
1
    if (!g_default_crypto_context) {
149
0
        goto loser;
150
0
    }
151
1
    g_default_trust_domain = td;
152
1
    return PR_SUCCESS;
153
154
0
loser:
155
0
    NSSTrustDomain_Destroy(td);
156
0
    return PR_FAILURE;
157
1
}
158
159
/*
160
 * must be called holding the ModuleListLock (either read or write).
161
 */
162
NSS_IMPLEMENT SECStatus
163
STAN_AddModuleToDefaultTrustDomain(
164
    SECMODModule *module)
165
0
{
166
0
    NSSTrustDomain *td;
167
0
    int i;
168
0
    td = STAN_GetDefaultTrustDomain();
169
0
    for (i = 0; i < module->slotCount; i++) {
170
0
        STAN_InitTokenForSlotInfo(td, module->slots[i]);
171
0
    }
172
0
    STAN_ResetTokenInterator(td);
173
0
    return SECSuccess;
174
0
}
175
176
/*
177
 * must be called holding the ModuleListLock (either read or write).
178
 */
179
NSS_IMPLEMENT SECStatus
180
STAN_RemoveModuleFromDefaultTrustDomain(
181
    SECMODModule *module)
182
0
{
183
0
    NSSToken *token;
184
0
    NSSTrustDomain *td;
185
0
    int i;
186
0
    td = STAN_GetDefaultTrustDomain();
187
0
    for (i = 0; i < module->slotCount; i++) {
188
0
        token = PK11Slot_GetNSSToken(module->slots[i]);
189
0
        if (token) {
190
0
            nssToken_NotifyCertsNotVisible(token);
191
0
            NSSRWLock_LockWrite(td->tokensLock);
192
0
            nssList_Remove(td->tokenList, token);
193
0
            NSSRWLock_UnlockWrite(td->tokensLock);
194
0
            PK11Slot_SetNSSToken(module->slots[i], NULL);
195
0
            (void)nssToken_Destroy(token); /* for the |td->tokenList| reference */
196
0
            (void)nssToken_Destroy(token); /* for our PK11Slot_GetNSSToken reference */
197
0
        }
198
0
    }
199
0
    NSSRWLock_LockWrite(td->tokensLock);
200
0
    nssListIterator_Destroy(td->tokens);
201
0
    td->tokens = nssList_CreateIterator(td->tokenList);
202
0
    NSSRWLock_UnlockWrite(td->tokensLock);
203
0
    return SECSuccess;
204
0
}
205
206
NSS_IMPLEMENT PRStatus
207
STAN_Shutdown()
208
1
{
209
1
    PRStatus status = PR_SUCCESS;
210
1
    if (g_default_trust_domain) {
211
1
        if (NSSTrustDomain_Destroy(g_default_trust_domain) == PR_SUCCESS) {
212
1
            g_default_trust_domain = NULL;
213
1
        } else {
214
0
            status = PR_FAILURE;
215
0
        }
216
1
    }
217
1
    if (g_default_crypto_context) {
218
1
        if (NSSCryptoContext_Destroy(g_default_crypto_context) == PR_SUCCESS) {
219
1
            g_default_crypto_context = NULL;
220
1
        } else {
221
0
            status = PR_FAILURE;
222
0
        }
223
1
    }
224
1
    return status;
225
1
}
226
227
/* this function should not be a hack; it will be needed in 4.0 (rename) */
228
NSS_IMPLEMENT NSSItem *
229
STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der)
230
0
{
231
0
    NSSItem *rvKey;
232
0
    SECItem secDER;
233
0
    SECItem secKey = { 0 };
234
0
    SECStatus secrv;
235
0
    PLArenaPool *arena;
236
237
0
    SECITEM_FROM_NSSITEM(&secDER, der);
238
239
    /* nss3 call uses nss3 arena's */
240
0
    arena = PORT_NewArena(256);
241
0
    if (!arena) {
242
0
        return NULL;
243
0
    }
244
0
    secrv = CERT_KeyFromDERCert(arena, &secDER, &secKey);
245
0
    if (secrv != SECSuccess) {
246
0
        PORT_FreeArena(arena, PR_FALSE);
247
0
        return NULL;
248
0
    }
249
0
    rvKey = nssItem_Create(arenaOpt, NULL, secKey.len, (void *)secKey.data);
250
0
    PORT_FreeArena(arena, PR_FALSE);
251
0
    return rvKey;
252
0
}
253
254
NSS_IMPLEMENT PRStatus
255
nssPKIX509_GetIssuerAndSerialFromDER(NSSDER *der,
256
                                     NSSDER *issuer, NSSDER *serial)
257
0
{
258
0
    SECItem derCert = { 0 };
259
0
    SECItem derIssuer = { 0 };
260
0
    SECItem derSerial = { 0 };
261
0
    SECStatus secrv;
262
0
    derCert.data = (unsigned char *)der->data;
263
0
    derCert.len = der->size;
264
0
    secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer);
265
0
    if (secrv != SECSuccess) {
266
0
        return PR_FAILURE;
267
0
    }
268
0
    secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial);
269
0
    if (secrv != SECSuccess) {
270
0
        PORT_Free(derSerial.data);
271
0
        return PR_FAILURE;
272
0
    }
273
0
    issuer->data = derIssuer.data;
274
0
    issuer->size = derIssuer.len;
275
0
    serial->data = derSerial.data;
276
0
    serial->size = derSerial.len;
277
0
    return PR_SUCCESS;
278
0
}
279
280
static NSSItem *
281
nss3certificate_getIdentifier(nssDecodedCert *dc)
282
0
{
283
0
    NSSItem *rvID;
284
0
    CERTCertificate *c = (CERTCertificate *)dc->data;
285
0
    rvID = nssItem_Create(NULL, NULL, c->certKey.len, c->certKey.data);
286
0
    return rvID;
287
0
}
288
289
static void *
290
nss3certificate_getIssuerIdentifier(nssDecodedCert *dc)
291
0
{
292
0
    CERTCertificate *c = (CERTCertificate *)dc->data;
293
0
    return (void *)c->authKeyID;
294
0
}
295
296
static nssCertIDMatch
297
nss3certificate_matchIdentifier(nssDecodedCert *dc, void *id)
298
0
{
299
0
    CERTCertificate *c = (CERTCertificate *)dc->data;
300
0
    CERTAuthKeyID *authKeyID = (CERTAuthKeyID *)id;
301
0
    SECItem skid;
302
0
    nssCertIDMatch match = nssCertIDMatch_Unknown;
303
304
    /* keyIdentifier */
305
0
    if (authKeyID->keyID.len > 0 &&
306
0
        CERT_FindSubjectKeyIDExtension(c, &skid) == SECSuccess) {
307
0
        PRBool skiEqual;
308
0
        skiEqual = SECITEM_ItemsAreEqual(&authKeyID->keyID, &skid);
309
0
        PORT_Free(skid.data);
310
0
        if (skiEqual) {
311
            /* change the state to positive match, but keep going */
312
0
            match = nssCertIDMatch_Yes;
313
0
        } else {
314
            /* exit immediately on failure */
315
0
            return nssCertIDMatch_No;
316
0
        }
317
0
    }
318
319
    /* issuer/serial (treated as pair) */
320
0
    if (authKeyID->authCertIssuer) {
321
0
        SECItem *caName = NULL;
322
0
        SECItem *caSN = &authKeyID->authCertSerialNumber;
323
324
0
        caName = (SECItem *)CERT_GetGeneralNameByType(
325
0
            authKeyID->authCertIssuer,
326
0
            certDirectoryName, PR_TRUE);
327
0
        if (caName != NULL &&
328
0
            SECITEM_ItemsAreEqual(&c->derIssuer, caName) &&
329
0
            SECITEM_ItemsAreEqual(&c->serialNumber, caSN)) {
330
0
            match = nssCertIDMatch_Yes;
331
0
        } else {
332
0
            match = nssCertIDMatch_Unknown;
333
0
        }
334
0
    }
335
0
    return match;
336
0
}
337
338
static PRBool
339
nss3certificate_isValidIssuer(nssDecodedCert *dc)
340
0
{
341
0
    CERTCertificate *c = (CERTCertificate *)dc->data;
342
0
    unsigned int ignore;
343
0
    return CERT_IsCACert(c, &ignore);
344
0
}
345
346
static NSSUsage *
347
nss3certificate_getUsage(nssDecodedCert *dc)
348
0
{
349
    /* CERTCertificate *c = (CERTCertificate *)dc->data; */
350
0
    return NULL;
351
0
}
352
353
static PRBool
354
nss3certificate_isValidAtTime(nssDecodedCert *dc, NSSTime *time)
355
0
{
356
0
    SECCertTimeValidity validity;
357
0
    CERTCertificate *c = (CERTCertificate *)dc->data;
358
0
    validity = CERT_CheckCertValidTimes(c, NSSTime_GetPRTime(time), PR_TRUE);
359
0
    if (validity == secCertTimeValid) {
360
0
        return PR_TRUE;
361
0
    }
362
0
    return PR_FALSE;
363
0
}
364
365
static PRBool
366
nss3certificate_isNewerThan(nssDecodedCert *dc, nssDecodedCert *cmpdc)
367
0
{
368
    /* I know this isn't right, but this is glue code anyway */
369
0
    if (cmpdc->type == dc->type) {
370
0
        CERTCertificate *certa = (CERTCertificate *)dc->data;
371
0
        CERTCertificate *certb = (CERTCertificate *)cmpdc->data;
372
0
        return CERT_IsNewer(certa, certb);
373
0
    }
374
0
    return PR_FALSE;
375
0
}
376
377
/* CERT_FilterCertListByUsage */
378
static PRBool
379
nss3certificate_matchUsage(nssDecodedCert *dc, const NSSUsage *usage)
380
0
{
381
0
    CERTCertificate *cc;
382
0
    unsigned int requiredKeyUsage = 0;
383
0
    unsigned int requiredCertType = 0;
384
0
    SECStatus secrv;
385
0
    PRBool match;
386
0
    PRBool ca;
387
388
    /* This is for NSS 3.3 functions that do not specify a usage */
389
0
    if (usage->anyUsage) {
390
0
        return PR_TRUE;
391
0
    }
392
0
    ca = usage->nss3lookingForCA;
393
0
    secrv = CERT_KeyUsageAndTypeForCertUsage(usage->nss3usage, ca,
394
0
                                             &requiredKeyUsage,
395
0
                                             &requiredCertType);
396
0
    if (secrv != SECSuccess) {
397
0
        return PR_FALSE;
398
0
    }
399
0
    cc = (CERTCertificate *)dc->data;
400
0
    secrv = CERT_CheckKeyUsage(cc, requiredKeyUsage);
401
0
    match = (PRBool)(secrv == SECSuccess);
402
0
    if (match) {
403
0
        unsigned int certType = 0;
404
0
        if (ca) {
405
0
            (void)CERT_IsCACert(cc, &certType);
406
0
        } else {
407
0
            certType = cc->nsCertType;
408
0
        }
409
0
        if (!(certType & requiredCertType)) {
410
0
            match = PR_FALSE;
411
0
        }
412
0
    }
413
0
    return match;
414
0
}
415
416
static PRBool
417
nss3certificate_isTrustedForUsage(nssDecodedCert *dc, const NSSUsage *usage)
418
0
{
419
0
    CERTCertificate *cc;
420
0
    PRBool ca;
421
0
    SECStatus secrv;
422
0
    unsigned int requiredFlags;
423
0
    unsigned int trustFlags;
424
0
    SECTrustType trustType;
425
0
    CERTCertTrust trust;
426
427
    /* This is for NSS 3.3 functions that do not specify a usage */
428
0
    if (usage->anyUsage) {
429
0
        return PR_FALSE; /* XXX is this right? */
430
0
    }
431
0
    cc = (CERTCertificate *)dc->data;
432
0
    ca = usage->nss3lookingForCA;
433
0
    if (!ca) {
434
0
        PRBool trusted;
435
0
        unsigned int failedFlags;
436
0
        secrv = cert_CheckLeafTrust(cc, usage->nss3usage,
437
0
                                    &failedFlags, &trusted);
438
0
        return secrv == SECSuccess && trusted;
439
0
    }
440
0
    secrv = CERT_TrustFlagsForCACertUsage(usage->nss3usage, &requiredFlags,
441
0
                                          &trustType);
442
0
    if (secrv != SECSuccess) {
443
0
        return PR_FALSE;
444
0
    }
445
0
    secrv = CERT_GetCertTrust(cc, &trust);
446
0
    if (secrv != SECSuccess) {
447
0
        return PR_FALSE;
448
0
    }
449
0
    if (trustType == trustTypeNone) {
450
        /* normally trustTypeNone usages accept any of the given trust bits
451
         * being on as acceptable. */
452
0
        trustFlags = trust.sslFlags | trust.emailFlags |
453
0
                     trust.objectSigningFlags;
454
0
    } else {
455
0
        trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType);
456
0
    }
457
0
    return (trustFlags & requiredFlags) == requiredFlags;
458
0
}
459
460
static NSSASCII7 *
461
nss3certificate_getEmailAddress(nssDecodedCert *dc)
462
0
{
463
0
    CERTCertificate *cc = (CERTCertificate *)dc->data;
464
0
    return (cc && cc->emailAddr && cc->emailAddr[0])
465
0
               ? (NSSASCII7 *)cc->emailAddr
466
0
               : NULL;
467
0
}
468
469
static PRStatus
470
nss3certificate_getDERSerialNumber(nssDecodedCert *dc,
471
                                   NSSDER *serial, NSSArena *arena)
472
0
{
473
0
    CERTCertificate *cc = (CERTCertificate *)dc->data;
474
0
    SECItem derSerial = { 0 };
475
0
    SECStatus secrv;
476
0
    secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
477
0
    if (secrv == SECSuccess) {
478
0
        (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data);
479
0
        PORT_Free(derSerial.data);
480
0
        return PR_SUCCESS;
481
0
    }
482
0
    return PR_FAILURE;
483
0
}
484
485
/* Returns NULL if "encoding" cannot be decoded. */
486
NSS_IMPLEMENT nssDecodedCert *
487
nssDecodedPKIXCertificate_Create(
488
    NSSArena *arenaOpt,
489
    NSSDER *encoding)
490
0
{
491
0
    nssDecodedCert *rvDC = NULL;
492
0
    CERTCertificate *cert;
493
0
    SECItem secDER;
494
495
0
    SECITEM_FROM_NSSITEM(&secDER, encoding);
496
0
    cert = CERT_DecodeDERCertificate(&secDER, PR_TRUE, NULL);
497
0
    if (cert) {
498
0
        rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
499
0
        if (rvDC) {
500
0
            rvDC->type = NSSCertificateType_PKIX;
501
0
            rvDC->data = (void *)cert;
502
0
            rvDC->getIdentifier = nss3certificate_getIdentifier;
503
0
            rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
504
0
            rvDC->matchIdentifier = nss3certificate_matchIdentifier;
505
0
            rvDC->isValidIssuer = nss3certificate_isValidIssuer;
506
0
            rvDC->getUsage = nss3certificate_getUsage;
507
0
            rvDC->isValidAtTime = nss3certificate_isValidAtTime;
508
0
            rvDC->isNewerThan = nss3certificate_isNewerThan;
509
0
            rvDC->matchUsage = nss3certificate_matchUsage;
510
0
            rvDC->isTrustedForUsage = nss3certificate_isTrustedForUsage;
511
0
            rvDC->getEmailAddress = nss3certificate_getEmailAddress;
512
0
            rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber;
513
0
        } else {
514
0
            CERT_DestroyCertificate(cert);
515
0
        }
516
0
    }
517
0
    return rvDC;
518
0
}
519
520
static nssDecodedCert *
521
create_decoded_pkix_cert_from_nss3cert(
522
    NSSArena *arenaOpt,
523
    CERTCertificate *cc)
524
0
{
525
0
    nssDecodedCert *rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
526
0
    if (rvDC) {
527
0
        rvDC->type = NSSCertificateType_PKIX;
528
0
        rvDC->data = (void *)cc;
529
0
        rvDC->getIdentifier = nss3certificate_getIdentifier;
530
0
        rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
531
0
        rvDC->matchIdentifier = nss3certificate_matchIdentifier;
532
0
        rvDC->isValidIssuer = nss3certificate_isValidIssuer;
533
0
        rvDC->getUsage = nss3certificate_getUsage;
534
0
        rvDC->isValidAtTime = nss3certificate_isValidAtTime;
535
0
        rvDC->isNewerThan = nss3certificate_isNewerThan;
536
0
        rvDC->matchUsage = nss3certificate_matchUsage;
537
0
        rvDC->isTrustedForUsage = nss3certificate_isTrustedForUsage;
538
0
        rvDC->getEmailAddress = nss3certificate_getEmailAddress;
539
0
        rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber;
540
0
    }
541
0
    return rvDC;
542
0
}
543
544
NSS_IMPLEMENT PRStatus
545
nssDecodedPKIXCertificate_Destroy(nssDecodedCert *dc)
546
0
{
547
0
    CERTCertificate *cert = (CERTCertificate *)dc->data;
548
549
    /* The decoder may only be half initialized (the case where we find we
550
     * could not decode the certificate). In this case, there is not cert to
551
     * free, just free the dc structure. */
552
0
    if (cert) {
553
0
        PRBool freeSlot = cert->ownSlot;
554
0
        PK11SlotInfo *slot = cert->slot;
555
0
        PLArenaPool *arena = cert->arena;
556
        /* zero cert before freeing. Any stale references to this cert
557
         * after this point will probably cause an exception.  */
558
0
        PORT_Memset(cert, 0, sizeof *cert);
559
        /* free the arena that contains the cert. */
560
0
        PORT_FreeArena(arena, PR_FALSE);
561
0
        if (slot && freeSlot) {
562
0
            PK11_FreeSlot(slot);
563
0
        }
564
0
    }
565
0
    nss_ZFreeIf(dc);
566
0
    return PR_SUCCESS;
567
0
}
568
569
/* see pk11cert.c:pk11_HandleTrustObject */
570
static unsigned int
571
get_nss3trust_from_nss4trust(nssTrustLevel t)
572
0
{
573
0
    unsigned int rt = 0;
574
0
    if (t == nssTrustLevel_Trusted) {
575
0
        rt |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
576
0
    }
577
0
    if (t == nssTrustLevel_TrustedDelegator) {
578
0
        rt |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
579
0
    }
580
0
    if (t == nssTrustLevel_NotTrusted) {
581
0
        rt |= CERTDB_TERMINAL_RECORD;
582
0
    }
583
0
    if (t == nssTrustLevel_ValidDelegator) {
584
0
        rt |= CERTDB_VALID_CA;
585
0
    }
586
0
    return rt;
587
0
}
588
589
static CERTCertTrust *
590
cert_trust_from_stan_trust(NSSTrust *t, PLArenaPool *arena)
591
0
{
592
0
    CERTCertTrust *rvTrust;
593
0
    unsigned int client;
594
0
    if (!t) {
595
0
        return NULL;
596
0
    }
597
0
    rvTrust = PORT_ArenaAlloc(arena, sizeof(CERTCertTrust));
598
0
    if (!rvTrust)
599
0
        return NULL;
600
0
    rvTrust->sslFlags = get_nss3trust_from_nss4trust(t->serverAuth);
601
0
    client = get_nss3trust_from_nss4trust(t->clientAuth);
602
0
    if (client & (CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA)) {
603
0
        client &= ~(CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA);
604
0
        rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA;
605
0
    }
606
0
    rvTrust->sslFlags |= client;
607
0
    rvTrust->emailFlags = get_nss3trust_from_nss4trust(t->emailProtection);
608
0
    rvTrust->objectSigningFlags = get_nss3trust_from_nss4trust(t->codeSigning);
609
0
    return rvTrust;
610
0
}
611
612
PRBool
613
nssTrust_HandleTrustForCERTCert(CERTCertificate *cert, CERTCertTrust *trustPtr)
614
0
{
615
0
    NSSCertificate *c = cert->nssCertificate;
616
0
    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
617
0
    NSSTrust *t;
618
0
    t = nssTrustDomain_FindTrustForCertificate(td, c);
619
0
    if (t) {
620
0
        CERTCertTrust *rvTrust;
621
0
        rvTrust = cert_trust_from_stan_trust(t, cert->arena);
622
0
        nssTrust_Destroy(t);
623
0
        if (rvTrust) {
624
0
            *trustPtr = *rvTrust;
625
0
            return PR_TRUE;
626
0
        }
627
0
    }
628
0
    return PR_FALSE;
629
0
}
630
631
CERTCertTrust *
632
nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc)
633
0
{
634
0
    CERTCertTrust *rvTrust = NULL;
635
0
    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
636
0
    NSSTrust *t;
637
0
    t = nssTrustDomain_FindTrustForCertificate(td, c);
638
0
    if (t) {
639
0
        rvTrust = cert_trust_from_stan_trust(t, cc->arena);
640
0
        if (!rvTrust) {
641
0
            nssTrust_Destroy(t);
642
0
            return NULL;
643
0
        }
644
0
        nssTrust_Destroy(t);
645
0
    } else {
646
0
        rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
647
0
        if (!rvTrust) {
648
0
            return NULL;
649
0
        }
650
0
        memset(rvTrust, 0, sizeof(*rvTrust));
651
0
    }
652
0
    if (NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL)) {
653
0
        rvTrust->sslFlags |= CERTDB_USER;
654
0
        rvTrust->emailFlags |= CERTDB_USER;
655
0
        rvTrust->objectSigningFlags |= CERTDB_USER;
656
0
    }
657
0
    return rvTrust;
658
0
}
659
660
static nssCryptokiInstance *
661
get_cert_instance(NSSCertificate *c)
662
0
{
663
0
    nssCryptokiObject *instance, **ci;
664
0
    nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
665
0
    if (!instances) {
666
0
        return NULL;
667
0
    }
668
0
    instance = NULL;
669
0
    for (ci = instances; *ci; ci++) {
670
0
        if (!instance) {
671
0
            instance = nssCryptokiObject_Clone(*ci);
672
0
        } else {
673
            /* This only really works for two instances...  But 3.4 can't
674
             * handle more anyway.  The logic is, if there are multiple
675
             * instances, prefer the one that is not internal (e.g., on
676
             * a hardware device.
677
             */
678
0
            if (PK11_IsInternal(instance->token->pk11slot)) {
679
0
                nssCryptokiObject_Destroy(instance);
680
0
                instance = nssCryptokiObject_Clone(*ci);
681
0
            }
682
0
        }
683
0
    }
684
0
    nssCryptokiObjectArray_Destroy(instances);
685
0
    return instance;
686
0
}
687
688
char *
689
STAN_GetCERTCertificateNameForInstance(
690
    PLArenaPool *arenaOpt,
691
    NSSCertificate *c,
692
    nssCryptokiInstance *instance)
693
0
{
694
0
    NSSCryptoContext *context = c->object.cryptoContext;
695
0
    PRStatus nssrv;
696
0
    int nicklen, tokenlen, len;
697
0
    NSSUTF8 *tokenName = NULL;
698
0
    NSSUTF8 *stanNick = NULL;
699
0
    char *nickname = NULL;
700
0
    char *nick;
701
702
0
    if (instance) {
703
0
        stanNick = instance->label;
704
0
    } else if (context) {
705
0
        stanNick = c->object.tempName;
706
0
    }
707
0
    if (stanNick) {
708
        /* fill other fields needed by NSS3 functions using CERTCertificate */
709
0
        if (instance && (!PK11_IsInternalKeySlot(instance->token->pk11slot) ||
710
0
                         PORT_Strchr(stanNick, ':') != NULL)) {
711
0
            tokenName = nssToken_GetName(instance->token);
712
0
            tokenlen = nssUTF8_Size(tokenName, &nssrv);
713
0
        } else {
714
            /* don't use token name for internal slot; 3.3 didn't */
715
0
            tokenlen = 0;
716
0
        }
717
0
        nicklen = nssUTF8_Size(stanNick, &nssrv);
718
0
        len = tokenlen + nicklen;
719
0
        if (arenaOpt) {
720
0
            nickname = PORT_ArenaAlloc(arenaOpt, len);
721
0
        } else {
722
0
            nickname = PORT_Alloc(len);
723
0
        }
724
0
        nick = nickname;
725
0
        if (tokenName) {
726
0
            memcpy(nick, tokenName, tokenlen - 1);
727
0
            nick += tokenlen - 1;
728
0
            *nick++ = ':';
729
0
        }
730
0
        memcpy(nick, stanNick, nicklen - 1);
731
0
        nickname[len - 1] = '\0';
732
0
    }
733
0
    return nickname;
734
0
}
735
736
char *
737
STAN_GetCERTCertificateName(PLArenaPool *arenaOpt, NSSCertificate *c)
738
0
{
739
0
    char *result;
740
0
    nssCryptokiInstance *instance = get_cert_instance(c);
741
    /* It's OK to call this function, even if instance is NULL */
742
0
    result = STAN_GetCERTCertificateNameForInstance(arenaOpt, c, instance);
743
0
    if (instance)
744
0
        nssCryptokiObject_Destroy(instance);
745
0
    return result;
746
0
}
747
748
static void
749
fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced)
750
0
{
751
0
    CERTCertTrust *trust = NULL;
752
0
    NSSTrust *nssTrust;
753
0
    NSSCryptoContext *context = c->object.cryptoContext;
754
0
    nssCryptokiInstance *instance;
755
0
    NSSUTF8 *stanNick = NULL;
756
757
    /* We are holding the base class object's lock on entry of this function
758
     * This lock protects writes to fields of the CERTCertificate .
759
     * It is also needed by some functions to compute values such as trust.
760
     */
761
0
    instance = get_cert_instance(c);
762
763
0
    if (instance) {
764
0
        stanNick = instance->label;
765
0
    } else if (context) {
766
0
        stanNick = c->object.tempName;
767
0
    }
768
    /* fill other fields needed by NSS3 functions using CERTCertificate */
769
0
    if ((!cc->nickname && stanNick) || forced) {
770
0
        PRStatus nssrv;
771
0
        int nicklen, tokenlen, len;
772
0
        NSSUTF8 *tokenName = NULL;
773
0
        char *nick;
774
0
        if (instance &&
775
0
            (!PK11_IsInternalKeySlot(instance->token->pk11slot) ||
776
0
             (stanNick && PORT_Strchr(stanNick, ':') != NULL))) {
777
0
            tokenName = nssToken_GetName(instance->token);
778
0
            tokenlen = nssUTF8_Size(tokenName, &nssrv);
779
0
        } else {
780
            /* don't use token name for internal slot; 3.3 didn't */
781
0
            tokenlen = 0;
782
0
        }
783
0
        if (stanNick) {
784
0
            nicklen = nssUTF8_Size(stanNick, &nssrv);
785
0
            len = tokenlen + nicklen;
786
0
            nick = PORT_ArenaAlloc(cc->arena, len);
787
0
            if (tokenName) {
788
0
                memcpy(nick, tokenName, tokenlen - 1);
789
0
                nick[tokenlen - 1] = ':';
790
0
                memcpy(nick + tokenlen, stanNick, nicklen - 1);
791
0
            } else {
792
0
                memcpy(nick, stanNick, nicklen - 1);
793
0
            }
794
0
            nick[len - 1] = '\0';
795
0
            cc->nickname = nick;
796
0
        } else {
797
0
            cc->nickname = NULL;
798
0
        }
799
0
    }
800
0
    if (context) {
801
        /* trust */
802
0
        nssTrust = nssCryptoContext_FindTrustForCertificate(context, c);
803
0
        if (!nssTrust) {
804
            /* chicken and egg issue:
805
             *
806
             * c->issuer and c->serial are empty at this point, but
807
             * nssTrustDomain_FindTrustForCertificate use them to look up
808
             * up the trust object, so we point them to cc->derIssuer and
809
             * cc->serialNumber.
810
             *
811
             * Our caller will fill these in with proper arena copies when we
812
             * return. */
813
0
            c->issuer.data = cc->derIssuer.data;
814
0
            c->issuer.size = cc->derIssuer.len;
815
0
            c->serial.data = cc->serialNumber.data;
816
0
            c->serial.size = cc->serialNumber.len;
817
0
            nssTrust = nssTrustDomain_FindTrustForCertificate(context->td, c);
818
0
        }
819
0
        if (nssTrust) {
820
0
            trust = cert_trust_from_stan_trust(nssTrust, cc->arena);
821
0
            if (trust) {
822
                /* we should destroy cc->trust before replacing it, but it's
823
                   allocated in cc->arena, so memory growth will occur on each
824
                   refresh */
825
0
                CERT_LockCertTrust(cc);
826
0
                cc->trust = trust;
827
0
                CERT_UnlockCertTrust(cc);
828
0
            }
829
0
            nssTrust_Destroy(nssTrust);
830
0
        }
831
0
    } else if (instance) {
832
        /* slot */
833
0
        if (cc->slot != instance->token->pk11slot) {
834
0
            if (cc->slot) {
835
0
                PK11_FreeSlot(cc->slot);
836
0
            }
837
0
            cc->slot = PK11_ReferenceSlot(instance->token->pk11slot);
838
0
        }
839
0
        cc->ownSlot = PR_TRUE;
840
        /* pkcs11ID */
841
0
        cc->pkcs11ID = instance->handle;
842
        /* trust */
843
0
        trust = nssTrust_GetCERTCertTrustForCert(c, cc);
844
0
        if (trust) {
845
            /* we should destroy cc->trust before replacing it, but it's
846
               allocated in cc->arena, so memory growth will occur on each
847
               refresh */
848
0
            CERT_LockCertTrust(cc);
849
0
            cc->trust = trust;
850
0
            CERT_UnlockCertTrust(cc);
851
0
        }
852
        /* Read the distrust fields from a nssckbi/builtins certificate and
853
         * fill the fields in CERTCertificate structure when any valid date
854
         * is found. */
855
0
        if (PK11_IsReadOnly(cc->slot) && PK11_HasRootCerts(cc->slot)) {
856
            /* The values are hard-coded and readonly. Read just once. */
857
0
            if (cc->distrust == NULL) {
858
0
                CERTCertDistrust distrustModel;
859
0
                SECItem model = { siUTCTime, NULL, 0 };
860
0
                distrustModel.serverDistrustAfter = model;
861
0
                distrustModel.emailDistrustAfter = model;
862
0
                SECStatus rServer = PK11_ReadAttribute(
863
0
                    cc->slot, cc->pkcs11ID, CKA_NSS_SERVER_DISTRUST_AFTER,
864
0
                    cc->arena, &distrustModel.serverDistrustAfter);
865
0
                SECStatus rEmail = PK11_ReadAttribute(
866
0
                    cc->slot, cc->pkcs11ID, CKA_NSS_EMAIL_DISTRUST_AFTER,
867
0
                    cc->arena, &distrustModel.emailDistrustAfter);
868
                /* Only allocate the Distrust structure if a valid date is found.
869
                 * The result length of a encoded valid timestamp is exactly 13 */
870
0
                const unsigned int kDistrustFieldSize = 13;
871
0
                if ((rServer == SECSuccess && rEmail == SECSuccess) &&
872
0
                    (distrustModel.serverDistrustAfter.len == kDistrustFieldSize ||
873
0
                     distrustModel.emailDistrustAfter.len == kDistrustFieldSize)) {
874
0
                    CERTCertDistrust *tmpPtr = PORT_ArenaAlloc(
875
0
                        cc->arena, sizeof(CERTCertDistrust));
876
0
                    PORT_Memcpy(tmpPtr, &distrustModel,
877
0
                                sizeof(CERTCertDistrust));
878
0
                    cc->distrust = tmpPtr;
879
0
                }
880
0
            }
881
0
        }
882
0
    }
883
0
    if (instance) {
884
0
        nssCryptokiObject_Destroy(instance);
885
0
    }
886
    /* database handle is now the trust domain */
887
0
    cc->dbhandle = c->object.trustDomain;
888
    /* subjectList ? */
889
    /* istemp and isperm are supported in NSS 3.4 */
890
0
    CERT_LockCertTempPerm(cc);
891
0
    cc->istemp = PR_FALSE; /* CERT_NewTemp will override this */
892
0
    cc->isperm = PR_TRUE;  /* by default */
893
    /* pointer back */
894
0
    cc->nssCertificate = c;
895
0
    CERT_UnlockCertTempPerm(cc);
896
0
    if (trust) {
897
        /* force the cert type to be recomputed to include trust info */
898
0
        PRUint32 nsCertType = cert_ComputeCertType(cc);
899
900
        /* Assert that it is safe to cast &cc->nsCertType to "PRInt32 *" */
901
0
        PORT_Assert(sizeof(cc->nsCertType) == sizeof(PRInt32));
902
0
        PR_ATOMIC_SET((PRInt32 *)&cc->nsCertType, nsCertType);
903
0
    }
904
0
}
905
906
static CERTCertificate *
907
stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate)
908
0
{
909
0
    nssDecodedCert *dc = NULL;
910
0
    CERTCertificate *cc = NULL;
911
0
    CERTCertTrust certTrust;
912
913
    /* make sure object does not go away until we finish */
914
0
    nssPKIObject_AddRef(&c->object);
915
0
    nssPKIObject_Lock(&c->object);
916
917
0
    dc = c->decoding;
918
0
    if (!dc) {
919
0
        dc = nssDecodedPKIXCertificate_Create(NULL, &c->encoding);
920
0
        if (!dc) {
921
0
            goto loser;
922
0
        }
923
0
        cc = (CERTCertificate *)dc->data;
924
0
        PORT_Assert(cc); /* software error */
925
0
        if (!cc) {
926
0
            nssDecodedPKIXCertificate_Destroy(dc);
927
0
            nss_SetError(NSS_ERROR_INTERNAL_ERROR);
928
0
            goto loser;
929
0
        }
930
0
        PORT_Assert(!c->decoding);
931
0
        if (!c->decoding) {
932
0
            c->decoding = dc;
933
0
        } else {
934
            /* this should never happen. Fail. */
935
0
            nssDecodedPKIXCertificate_Destroy(dc);
936
0
            nss_SetError(NSS_ERROR_INTERNAL_ERROR);
937
0
            goto loser;
938
0
        }
939
0
    }
940
0
    cc = (CERTCertificate *)dc->data;
941
0
    PORT_Assert(cc);
942
0
    if (!cc) {
943
0
        nss_SetError(NSS_ERROR_INTERNAL_ERROR);
944
0
        goto loser;
945
0
    }
946
0
    CERT_LockCertTempPerm(cc);
947
0
    NSSCertificate *nssCert = cc->nssCertificate;
948
0
    CERT_UnlockCertTempPerm(cc);
949
0
    if (!nssCert || forceUpdate) {
950
0
        fill_CERTCertificateFields(c, cc, forceUpdate);
951
0
    } else if (CERT_GetCertTrust(cc, &certTrust) != SECSuccess) {
952
0
        CERTCertTrust *trust;
953
0
        if (!c->object.cryptoContext) {
954
            /* If it's a perm cert, it might have been stored before the
955
             * trust, so look for the trust again.
956
             */
957
0
            trust = nssTrust_GetCERTCertTrustForCert(c, cc);
958
0
        } else {
959
            /* If it's a temp cert, it might have been stored before the
960
             * builtin trust module is loaded, so look for the trust
961
             * again, but don't set the empty trust if it is not found.
962
             */
963
0
            NSSTrust *t = nssTrustDomain_FindTrustForCertificate(c->object.cryptoContext->td, c);
964
0
            if (!t) {
965
0
                goto loser;
966
0
            }
967
0
            trust = cert_trust_from_stan_trust(t, cc->arena);
968
0
            nssTrust_Destroy(t);
969
0
            if (!trust) {
970
0
                goto loser;
971
0
            }
972
0
        }
973
974
0
        CERT_LockCertTrust(cc);
975
0
        cc->trust = trust;
976
0
        CERT_UnlockCertTrust(cc);
977
0
    }
978
979
0
loser:
980
0
    nssPKIObject_Unlock(&c->object);
981
0
    nssPKIObject_Destroy(&c->object);
982
0
    return cc;
983
0
}
984
985
NSS_IMPLEMENT CERTCertificate *
986
STAN_ForceCERTCertificateUpdate(NSSCertificate *c)
987
0
{
988
0
    if (c->decoding) {
989
0
        return stan_GetCERTCertificate(c, PR_TRUE);
990
0
    }
991
0
    return NULL;
992
0
}
993
994
NSS_IMPLEMENT CERTCertificate *
995
STAN_GetCERTCertificate(NSSCertificate *c)
996
0
{
997
0
    return stan_GetCERTCertificate(c, PR_FALSE);
998
0
}
999
/*
1000
 * many callers of STAN_GetCERTCertificate() intend that
1001
 * the CERTCertificate returned inherits the reference to the
1002
 * NSSCertificate. For these callers it's convenient to have
1003
 * this function 'own' the reference and either return a valid
1004
 * CERTCertificate structure which inherits the reference or
1005
 * destroy the reference to NSSCertificate and returns NULL.
1006
 */
1007
NSS_IMPLEMENT CERTCertificate *
1008
STAN_GetCERTCertificateOrRelease(NSSCertificate *c)
1009
0
{
1010
0
    CERTCertificate *nss3cert = stan_GetCERTCertificate(c, PR_FALSE);
1011
0
    if (!nss3cert) {
1012
0
        nssCertificate_Destroy(c);
1013
0
    }
1014
0
    return nss3cert;
1015
0
}
1016
1017
static nssTrustLevel
1018
get_stan_trust(unsigned int t, PRBool isClientAuth)
1019
0
{
1020
0
    if (isClientAuth) {
1021
0
        if (t & CERTDB_TRUSTED_CLIENT_CA) {
1022
0
            return nssTrustLevel_TrustedDelegator;
1023
0
        }
1024
0
    } else {
1025
0
        if (t & CERTDB_TRUSTED_CA || t & CERTDB_NS_TRUSTED_CA) {
1026
0
            return nssTrustLevel_TrustedDelegator;
1027
0
        }
1028
0
    }
1029
0
    if (t & CERTDB_TRUSTED) {
1030
0
        return nssTrustLevel_Trusted;
1031
0
    }
1032
0
    if (t & CERTDB_TERMINAL_RECORD) {
1033
0
        return nssTrustLevel_NotTrusted;
1034
0
    }
1035
0
    if (t & CERTDB_VALID_CA) {
1036
0
        return nssTrustLevel_ValidDelegator;
1037
0
    }
1038
0
    return nssTrustLevel_MustVerify;
1039
0
}
1040
1041
NSS_EXTERN NSSCertificate *
1042
STAN_GetNSSCertificate(CERTCertificate *cc)
1043
0
{
1044
0
    NSSCertificate *c;
1045
0
    nssCryptokiInstance *instance;
1046
0
    nssPKIObject *pkiob;
1047
0
    NSSArena *arena;
1048
0
    CERT_LockCertTempPerm(cc);
1049
0
    c = cc->nssCertificate;
1050
0
    CERT_UnlockCertTempPerm(cc);
1051
0
    if (c) {
1052
0
        return c;
1053
0
    }
1054
    /* i don't think this should happen.  but if it can, need to create
1055
     * NSSCertificate from CERTCertificate values here.  */
1056
    /* Yup, it can happen. */
1057
0
    arena = NSSArena_Create();
1058
0
    if (!arena) {
1059
0
        return NULL;
1060
0
    }
1061
0
    c = nss_ZNEW(arena, NSSCertificate);
1062
0
    if (!c) {
1063
0
        nssArena_Destroy(arena);
1064
0
        return NULL;
1065
0
    }
1066
0
    NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert);
1067
0
    c->type = NSSCertificateType_PKIX;
1068
0
    pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKIMonitor);
1069
0
    if (!pkiob) {
1070
0
        nssArena_Destroy(arena);
1071
0
        return NULL;
1072
0
    }
1073
0
    c->object = *pkiob;
1074
0
    nssItem_Create(arena,
1075
0
                   &c->issuer, cc->derIssuer.len, cc->derIssuer.data);
1076
0
    nssItem_Create(arena,
1077
0
                   &c->subject, cc->derSubject.len, cc->derSubject.data);
1078
    /* CERTCertificate stores serial numbers decoded.  I need the DER
1079
     * here.  sigh.
1080
     */
1081
0
    SECItem derSerial;
1082
0
    SECStatus secrv;
1083
0
    secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
1084
0
    if (secrv == SECFailure) {
1085
0
        nssArena_Destroy(arena);
1086
0
        return NULL;
1087
0
    }
1088
0
    nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data);
1089
0
    PORT_Free(derSerial.data);
1090
1091
0
    if (cc->emailAddr && cc->emailAddr[0]) {
1092
0
        c->email = nssUTF8_Create(arena,
1093
0
                                  nssStringType_PrintableString,
1094
0
                                  (NSSUTF8 *)cc->emailAddr,
1095
0
                                  PORT_Strlen(cc->emailAddr));
1096
0
    }
1097
0
    if (cc->slot) {
1098
0
        instance = nss_ZNEW(arena, nssCryptokiInstance);
1099
0
        if (!instance) {
1100
0
            nssArena_Destroy(arena);
1101
0
            return NULL;
1102
0
        }
1103
0
        instance->token = PK11Slot_GetNSSToken(cc->slot);
1104
0
        if (!instance->token) {
1105
0
            nssArena_Destroy(arena);
1106
0
            return NULL;
1107
0
        }
1108
0
        instance->handle = cc->pkcs11ID;
1109
0
        instance->isTokenObject = PR_TRUE;
1110
0
        if (cc->nickname) {
1111
0
            instance->label = nssUTF8_Create(arena,
1112
0
                                             nssStringType_UTF8String,
1113
0
                                             (NSSUTF8 *)cc->nickname,
1114
0
                                             PORT_Strlen(cc->nickname));
1115
0
        }
1116
0
        nssPKIObject_AddInstance(&c->object, instance);
1117
0
    }
1118
0
    c->decoding = create_decoded_pkix_cert_from_nss3cert(NULL, cc);
1119
0
    CERT_LockCertTempPerm(cc);
1120
0
    cc->nssCertificate = c;
1121
0
    CERT_UnlockCertTempPerm(cc);
1122
0
    return c;
1123
0
}
1124
1125
static NSSToken *
1126
stan_GetTrustToken(
1127
    NSSCertificate *c)
1128
0
{
1129
0
    NSSToken *ttok = NULL;
1130
0
    NSSToken *rtok = NULL;
1131
0
    NSSToken *tok = NULL;
1132
0
    nssCryptokiObject **ip;
1133
0
    nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
1134
0
    if (!instances) {
1135
0
        return PR_FALSE;
1136
0
    }
1137
0
    for (ip = instances; *ip; ip++) {
1138
0
        nssCryptokiObject *instance = *ip;
1139
0
        nssCryptokiObject *to =
1140
0
            nssToken_FindTrustForCertificate(instance->token, NULL,
1141
0
                                             &c->encoding, &c->issuer, &c->serial,
1142
0
                                             nssTokenSearchType_TokenOnly);
1143
0
        NSSToken *ctok = instance->token;
1144
0
        PRBool ro = PK11_IsReadOnly(ctok->pk11slot);
1145
1146
0
        if (to) {
1147
0
            nssCryptokiObject_Destroy(to);
1148
0
            ttok = ctok;
1149
0
            if (!ro) {
1150
0
                break;
1151
0
            }
1152
0
        } else {
1153
0
            if (!rtok && ro) {
1154
0
                rtok = ctok;
1155
0
            }
1156
0
            if (!tok && !ro) {
1157
0
                tok = ctok;
1158
0
            }
1159
0
        }
1160
0
    }
1161
0
    nssCryptokiObjectArray_Destroy(instances);
1162
0
    return ttok ? ttok : (tok ? tok : rtok);
1163
0
}
1164
1165
NSS_EXTERN PRStatus
1166
STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust)
1167
0
{
1168
0
    PRStatus nssrv;
1169
0
    NSSCertificate *c = STAN_GetNSSCertificate(cc);
1170
0
    NSSToken *tok;
1171
0
    NSSTrustDomain *td;
1172
0
    NSSTrust *nssTrust;
1173
0
    NSSArena *arena;
1174
0
    CERTCertTrust *oldTrust;
1175
0
    CERTCertTrust *newTrust;
1176
0
    nssListIterator *tokens;
1177
0
    PRBool moving_object;
1178
0
    nssCryptokiObject *newInstance;
1179
0
    nssPKIObject *pkiob;
1180
1181
0
    if (c == NULL) {
1182
0
        return PR_FAILURE;
1183
0
    }
1184
0
    oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc);
1185
0
    if (oldTrust) {
1186
0
        if (memcmp(oldTrust, trust, sizeof(CERTCertTrust)) == 0) {
1187
            /* ... and the new trust is no different, done) */
1188
0
            return PR_SUCCESS;
1189
0
        } else {
1190
            /* take over memory already allocated in cc's arena */
1191
0
            newTrust = oldTrust;
1192
0
        }
1193
0
    } else {
1194
0
        newTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
1195
0
    }
1196
0
    memcpy(newTrust, trust, sizeof(CERTCertTrust));
1197
0
    CERT_LockCertTrust(cc);
1198
0
    cc->trust = newTrust;
1199
0
    CERT_UnlockCertTrust(cc);
1200
    /* Set the NSSCerticate's trust */
1201
0
    arena = nssArena_Create();
1202
0
    if (!arena)
1203
0
        return PR_FAILURE;
1204
0
    nssTrust = nss_ZNEW(arena, NSSTrust);
1205
0
    if (!nssTrust) {
1206
0
        nssArena_Destroy(arena);
1207
0
        return PR_FAILURE;
1208
0
    }
1209
0
    pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock);
1210
0
    if (!pkiob) {
1211
0
        nssArena_Destroy(arena);
1212
0
        return PR_FAILURE;
1213
0
    }
1214
0
    nssTrust->object = *pkiob;
1215
0
    nssTrust->certificate = c;
1216
0
    nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE);
1217
0
    nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE);
1218
0
    nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE);
1219
0
    nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE);
1220
0
    nssTrust->stepUpApproved =
1221
0
        (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA);
1222
0
    if (c->object.cryptoContext != NULL) {
1223
        /* The cert is in a context, set the trust there */
1224
0
        NSSCryptoContext *cctx = c->object.cryptoContext;
1225
0
        nssrv = nssCryptoContext_ImportTrust(cctx, nssTrust);
1226
0
        if (nssrv != PR_SUCCESS) {
1227
0
            goto done;
1228
0
        }
1229
0
        if (c->object.numInstances == 0) {
1230
            /* The context is the only instance, finished */
1231
0
            goto done;
1232
0
        }
1233
0
    }
1234
0
    td = STAN_GetDefaultTrustDomain();
1235
0
    tok = stan_GetTrustToken(c);
1236
0
    moving_object = PR_FALSE;
1237
0
    if (tok && PK11_IsReadOnly(tok->pk11slot)) {
1238
0
        NSSRWLock_LockRead(td->tokensLock);
1239
0
        tokens = nssList_CreateIterator(td->tokenList);
1240
0
        if (!tokens) {
1241
0
            nssrv = PR_FAILURE;
1242
0
            NSSRWLock_UnlockRead(td->tokensLock);
1243
0
            goto done;
1244
0
        }
1245
0
        for (tok = (NSSToken *)nssListIterator_Start(tokens);
1246
0
             tok != (NSSToken *)NULL;
1247
0
             tok = (NSSToken *)nssListIterator_Next(tokens)) {
1248
0
            if (!PK11_IsReadOnly(tok->pk11slot))
1249
0
                break;
1250
0
        }
1251
0
        nssListIterator_Finish(tokens);
1252
0
        nssListIterator_Destroy(tokens);
1253
0
        NSSRWLock_UnlockRead(td->tokensLock);
1254
0
        moving_object = PR_TRUE;
1255
0
    }
1256
0
    if (tok) {
1257
0
        if (moving_object) {
1258
            /* this is kind of hacky.  the softoken needs the cert
1259
             * object in order to store trust.  forcing it to be perm
1260
             */
1261
0
            NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
1262
0
            NSSASCII7 *email = NULL;
1263
1264
0
            if (PK11_IsInternal(tok->pk11slot)) {
1265
0
                email = c->email;
1266
0
            }
1267
0
            newInstance = nssToken_ImportCertificate(tok, NULL,
1268
0
                                                     NSSCertificateType_PKIX,
1269
0
                                                     &c->id,
1270
0
                                                     nickname,
1271
0
                                                     &c->encoding,
1272
0
                                                     &c->issuer,
1273
0
                                                     &c->subject,
1274
0
                                                     &c->serial,
1275
0
                                                     email,
1276
0
                                                     PR_TRUE);
1277
0
            nss_ZFreeIf(nickname);
1278
0
            nickname = NULL;
1279
0
            if (!newInstance) {
1280
0
                nssrv = PR_FAILURE;
1281
0
                goto done;
1282
0
            }
1283
0
            nssPKIObject_AddInstance(&c->object, newInstance);
1284
0
        }
1285
0
        newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
1286
0
                                           &c->issuer, &c->serial,
1287
0
                                           nssTrust->serverAuth,
1288
0
                                           nssTrust->clientAuth,
1289
0
                                           nssTrust->codeSigning,
1290
0
                                           nssTrust->emailProtection,
1291
0
                                           nssTrust->stepUpApproved, PR_TRUE);
1292
        /* If the selected token can't handle trust, dump the trust on
1293
         * the internal token */
1294
0
        if (!newInstance && !PK11_IsInternalKeySlot(tok->pk11slot)) {
1295
0
            PK11SlotInfo *slot = PK11_GetInternalKeySlot();
1296
0
            NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
1297
0
            NSSASCII7 *email = c->email;
1298
0
            tok = PK11Slot_GetNSSToken(slot);
1299
0
            PK11_FreeSlot(slot);
1300
0
            if (!tok) {
1301
0
                nssrv = PR_FAILURE;
1302
0
                goto done;
1303
0
            }
1304
1305
0
            newInstance = nssToken_ImportCertificate(tok, NULL,
1306
0
                                                     NSSCertificateType_PKIX,
1307
0
                                                     &c->id,
1308
0
                                                     nickname,
1309
0
                                                     &c->encoding,
1310
0
                                                     &c->issuer,
1311
0
                                                     &c->subject,
1312
0
                                                     &c->serial,
1313
0
                                                     email,
1314
0
                                                     PR_TRUE);
1315
0
            nss_ZFreeIf(nickname);
1316
0
            nickname = NULL;
1317
0
            if (!newInstance) {
1318
0
                (void)nssToken_Destroy(tok);
1319
0
                nssrv = PR_FAILURE;
1320
0
                goto done;
1321
0
            }
1322
0
            nssPKIObject_AddInstance(&c->object, newInstance);
1323
0
            newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
1324
0
                                               &c->issuer, &c->serial,
1325
0
                                               nssTrust->serverAuth,
1326
0
                                               nssTrust->clientAuth,
1327
0
                                               nssTrust->codeSigning,
1328
0
                                               nssTrust->emailProtection,
1329
0
                                               nssTrust->stepUpApproved, PR_TRUE);
1330
0
            (void)nssToken_Destroy(tok);
1331
0
        }
1332
0
        if (newInstance) {
1333
0
            nssCryptokiObject_Destroy(newInstance);
1334
0
            nssrv = PR_SUCCESS;
1335
0
        } else {
1336
0
            nssrv = PR_FAILURE;
1337
0
        }
1338
0
    } else {
1339
0
        nssrv = PR_FAILURE;
1340
0
    }
1341
0
done:
1342
0
    (void)nssTrust_Destroy(nssTrust);
1343
0
    return nssrv;
1344
0
}
1345
1346
/*
1347
** Delete trust objects matching the given slot.
1348
** Returns error if a device fails to delete.
1349
**
1350
** This function has the side effect of moving the
1351
** surviving entries to the front of the object list
1352
** and nullifying the rest.
1353
*/
1354
static PRStatus
1355
DeleteCertTrustMatchingSlot(PK11SlotInfo *pk11slot, nssPKIObject *tObject)
1356
0
{
1357
0
    int numNotDestroyed = 0; /* the ones skipped plus the failures */
1358
0
    int failureCount = 0;    /* actual deletion failures by devices */
1359
0
    unsigned int index;
1360
1361
0
    nssPKIObject_AddRef(tObject);
1362
0
    nssPKIObject_Lock(tObject);
1363
    /* Keep going even if a module fails to delete. */
1364
0
    for (index = 0; index < tObject->numInstances; index++) {
1365
0
        nssCryptokiObject *instance = tObject->instances[index];
1366
0
        if (!instance) {
1367
0
            continue;
1368
0
        }
1369
1370
        /* ReadOnly and not matched treated the same */
1371
0
        if (PK11_IsReadOnly(instance->token->pk11slot) ||
1372
0
            pk11slot != instance->token->pk11slot) {
1373
0
            tObject->instances[numNotDestroyed++] = instance;
1374
0
            continue;
1375
0
        }
1376
1377
        /* Here we have found a matching one */
1378
0
        tObject->instances[index] = NULL;
1379
0
        if (nssToken_DeleteStoredObject(instance) == PR_SUCCESS) {
1380
0
            nssCryptokiObject_Destroy(instance);
1381
0
        } else {
1382
0
            tObject->instances[numNotDestroyed++] = instance;
1383
0
            failureCount++;
1384
0
        }
1385
0
    }
1386
0
    if (numNotDestroyed == 0) {
1387
0
        nss_ZFreeIf(tObject->instances);
1388
0
        tObject->numInstances = 0;
1389
0
    } else {
1390
0
        tObject->numInstances = numNotDestroyed;
1391
0
    }
1392
1393
0
    nssPKIObject_Unlock(tObject);
1394
0
    nssPKIObject_Destroy(tObject);
1395
1396
0
    return failureCount == 0 ? PR_SUCCESS : PR_FAILURE;
1397
0
}
1398
1399
/*
1400
** Delete trust objects matching the slot of the given certificate.
1401
** Returns an error if any device fails to delete.
1402
*/
1403
NSS_EXTERN PRStatus
1404
STAN_DeleteCertTrustMatchingSlot(NSSCertificate *c)
1405
0
{
1406
0
    PRStatus nssrv = PR_SUCCESS;
1407
1408
0
    unsigned int i;
1409
0
    nssPKIObject *tobject = NULL;
1410
0
    nssPKIObject *cobject = &c->object;
1411
1412
0
    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
1413
0
    NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c);
1414
0
    if (!nssTrust) {
1415
0
        return PR_FAILURE;
1416
0
    }
1417
1418
0
    tobject = &nssTrust->object;
1419
1420
    /* Iterate through the cert and trust object instances looking for
1421
     * those with matching pk11 slots to delete. Even if some device
1422
     * can't delete we keep going. Keeping a status variable for the
1423
     * loop so that once it's failed the other gets set.
1424
     */
1425
0
    NSSRWLock_LockRead(td->tokensLock);
1426
0
    nssPKIObject_AddRef(cobject);
1427
0
    nssPKIObject_Lock(cobject);
1428
0
    for (i = 0; i < cobject->numInstances; i++) {
1429
0
        nssCryptokiObject *cInstance = cobject->instances[i];
1430
0
        if (cInstance && !PK11_IsReadOnly(cInstance->token->pk11slot)) {
1431
0
            PRStatus status;
1432
0
            if (!tobject->numInstances || !tobject->instances)
1433
0
                continue;
1434
0
            status = DeleteCertTrustMatchingSlot(cInstance->token->pk11slot, tobject);
1435
0
            if (status == PR_FAILURE) {
1436
                /* set the outer one but keep going */
1437
0
                nssrv = PR_FAILURE;
1438
0
            }
1439
0
        }
1440
0
    }
1441
0
    nssTrust_Destroy(nssTrust);
1442
0
    nssPKIObject_Unlock(cobject);
1443
0
    nssPKIObject_Destroy(cobject);
1444
0
    NSSRWLock_UnlockRead(td->tokensLock);
1445
0
    return nssrv;
1446
0
}
1447
1448
/* CERT_TraversePermCertsForSubject */
1449
NSS_IMPLEMENT PRStatus
1450
nssTrustDomain_TraverseCertificatesBySubject(
1451
    NSSTrustDomain *td,
1452
    NSSDER *subject,
1453
    PRStatus (*callback)(NSSCertificate *c, void *arg),
1454
    void *arg)
1455
0
{
1456
0
    PRStatus nssrv = PR_SUCCESS;
1457
0
    NSSArena *tmpArena;
1458
0
    NSSCertificate **subjectCerts;
1459
0
    NSSCertificate *c;
1460
0
    PRIntn i;
1461
0
    tmpArena = NSSArena_Create();
1462
0
    if (!tmpArena) {
1463
0
        return PR_FAILURE;
1464
0
    }
1465
0
    subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, subject, NULL,
1466
0
                                                            0, tmpArena);
1467
0
    if (subjectCerts) {
1468
0
        for (i = 0, c = subjectCerts[i]; c; i++) {
1469
0
            nssrv = callback(c, arg);
1470
0
            if (nssrv != PR_SUCCESS)
1471
0
                break;
1472
0
        }
1473
0
    }
1474
0
    nssArena_Destroy(tmpArena);
1475
0
    return nssrv;
1476
0
}
1477
1478
/* CERT_TraversePermCertsForNickname */
1479
NSS_IMPLEMENT PRStatus
1480
nssTrustDomain_TraverseCertificatesByNickname(
1481
    NSSTrustDomain *td,
1482
    NSSUTF8 *nickname,
1483
    PRStatus (*callback)(NSSCertificate *c, void *arg),
1484
    void *arg)
1485
0
{
1486
0
    PRStatus nssrv = PR_SUCCESS;
1487
0
    NSSArena *tmpArena;
1488
0
    NSSCertificate **nickCerts;
1489
0
    NSSCertificate *c;
1490
0
    PRIntn i;
1491
0
    tmpArena = NSSArena_Create();
1492
0
    if (!tmpArena) {
1493
0
        return PR_FAILURE;
1494
0
    }
1495
0
    nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL,
1496
0
                                                          0, tmpArena);
1497
0
    if (nickCerts) {
1498
0
        for (i = 0, c = nickCerts[i]; c; i++) {
1499
0
            nssrv = callback(c, arg);
1500
0
            if (nssrv != PR_SUCCESS)
1501
0
                break;
1502
0
        }
1503
0
    }
1504
0
    nssArena_Destroy(tmpArena);
1505
0
    return nssrv;
1506
0
}
1507
1508
static void
1509
cert_dump_iter(const void *k, void *v, void *a)
1510
0
{
1511
0
    NSSCertificate *c = (NSSCertificate *)k;
1512
0
    CERTCertificate *cert = STAN_GetCERTCertificate(c);
1513
0
    printf("[%2d] \"%s\"\n", c->object.refCount, cert->subjectName);
1514
0
}
1515
1516
void
1517
nss_DumpCertificateCacheInfo()
1518
0
{
1519
0
    NSSTrustDomain *td;
1520
0
    NSSCryptoContext *cc;
1521
0
    td = STAN_GetDefaultTrustDomain();
1522
0
    cc = STAN_GetDefaultCryptoContext();
1523
0
    printf("\n\nCertificates in the cache:\n");
1524
0
    nssTrustDomain_DumpCacheInfo(td, cert_dump_iter, NULL);
1525
0
    printf("\n\nCertificates in the temporary store:\n");
1526
0
    if (cc->certStore) {
1527
0
        nssCertificateStore_DumpStoreInfo(cc->certStore, cert_dump_iter, NULL);
1528
0
    }
1529
0
}