Coverage Report

Created: 2026-04-04 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nss/lib/certhigh/certvfy.c
Line
Count
Source
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
#include "nspr.h"
5
#include "secerr.h"
6
#include "secport.h"
7
#include "seccomon.h"
8
#include "secoid.h"
9
#include "genname.h"
10
#include "keyhi.h"
11
#include "cert.h"
12
#include "certdb.h"
13
#include "certi.h"
14
#include "cryptohi.h"
15
16
#ifndef NSS_DISABLE_LIBPKIX
17
#include "pkix.h"
18
#include "pkix_pl_cert.h"
19
#else
20
#include "nss.h"
21
#endif /* NSS_DISABLE_LIBPKIX */
22
23
#include "nsspki.h"
24
#include "pkitm.h"
25
#include "pkim.h"
26
#include "pki3hack.h"
27
#include "base.h"
28
#include "keyi.h"
29
30
/*
31
 * Check the validity times of a certificate
32
 */
33
SECStatus
34
CERT_CertTimesValid(CERTCertificate *c)
35
0
{
36
0
    SECCertTimeValidity valid = CERT_CheckCertValidTimes(c, PR_Now(), PR_TRUE);
37
0
    return (valid == secCertTimeValid) ? SECSuccess : SECFailure;
38
0
}
39
40
static SECStatus
41
checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
42
3.44k
{
43
3.44k
    SECStatus rv;
44
3.44k
    SECOidTag sigAlg;
45
3.44k
    SECOidTag curve;
46
3.44k
    PRUint32 policyFlags = 0;
47
3.44k
    PRInt32 minLen, len, optFlags;
48
49
3.44k
    sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm);
50
51
3.44k
    switch (sigAlg) {
52
0
        case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
53
3
        case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
54
349
        case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
55
357
        case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
56
362
        case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
57
362
            if (key->keyType != ecKey) {
58
0
                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
59
0
                return SECFailure;
60
0
            }
61
62
362
            curve = SECKEY_GetECCOid(&key->u.ec.DEREncodedParams);
63
362
            if (curve != 0) {
64
357
                if (NSS_GetAlgorithmPolicy(curve, &policyFlags) == SECFailure ||
65
357
                    !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
66
1
                    PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
67
1
                    return SECFailure;
68
1
                }
69
356
                return SECSuccess;
70
357
            }
71
5
            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
72
5
            return SECFailure;
73
74
89
        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: {
75
89
            PORTCheapArenaPool tmpArena;
76
89
            SECOidTag hashAlg;
77
89
            SECOidTag maskHashAlg;
78
79
89
            PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
80
89
            rv = sec_DecodeRSAPSSParams(&tmpArena.arena,
81
89
                                        &sigAlgorithm->parameters,
82
89
                                        &hashAlg, &maskHashAlg, NULL);
83
89
            PORT_DestroyCheapArena(&tmpArena);
84
89
            if (rv != SECSuccess) {
85
0
                return SECFailure;
86
0
            }
87
88
89
            if (NSS_GetAlgorithmPolicy(hashAlg, &policyFlags) == SECSuccess &&
89
89
                !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
90
0
                PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
91
0
                return SECFailure;
92
0
            }
93
89
            if (NSS_GetAlgorithmPolicy(maskHashAlg, &policyFlags) == SECSuccess &&
94
89
                !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
95
0
                PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
96
0
                return SECFailure;
97
0
            }
98
89
        }
99
        /* fall through to RSA key checking */
100
89
        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
101
94
        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
102
1.77k
        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
103
1.77k
        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
104
1.77k
        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
105
1.77k
        case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
106
1.77k
        case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
107
1.77k
            if (key->keyType != rsaKey && key->keyType != rsaPssKey) {
108
3
                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
109
3
                return SECFailure;
110
3
            }
111
112
1.77k
            if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) == SECFailure) {
113
0
                return SECSuccess;
114
0
            }
115
1.77k
            if ((optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) == 0) {
116
0
                return SECSuccess;
117
0
            }
118
119
1.77k
            len = 8 * key->u.rsa.modulus.len;
120
121
1.77k
            rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minLen);
122
1.77k
            if (rv != SECSuccess) {
123
0
                return SECFailure;
124
0
            }
125
126
1.77k
            if (len < minLen) {
127
11
                return SECFailure;
128
11
            }
129
130
1.76k
            return SECSuccess;
131
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
132
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
133
0
        case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
134
0
        case SEC_OID_SDN702_DSA_SIGNATURE:
135
1
        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
136
1.29k
        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
137
1.29k
            if (key->keyType != dsaKey) {
138
1
                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
139
1
                return SECFailure;
140
1
            }
141
1.29k
            if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) == SECFailure) {
142
0
                return SECSuccess;
143
0
            }
144
1.29k
            if ((optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) == 0) {
145
0
                return SECSuccess;
146
0
            }
147
148
1.29k
            len = 8 * key->u.dsa.params.prime.len;
149
150
1.29k
            rv = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minLen);
151
1.29k
            if (rv != SECSuccess) {
152
0
                return SECFailure;
153
0
            }
154
155
1.29k
            if (len < minLen) {
156
1
                return SECFailure;
157
1
            }
158
159
1.29k
            return SECSuccess;
160
1
        case SEC_OID_ML_DSA_44:
161
2
        case SEC_OID_ML_DSA_65:
162
2
        case SEC_OID_ML_DSA_87:
163
2
            if (key->keyType != mldsaKey) {
164
2
                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
165
2
                return SECFailure;
166
2
            }
167
0
            if (key->u.mldsa.paramSet != sigAlg) {
168
0
                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
169
0
                return SECFailure;
170
0
            }
171
9
        default:
172
9
            return SECSuccess;
173
3.44k
    }
174
3.44k
}
175
176
/*
177
 * verify the signature of a signed data object with the given DER publickey
178
 */
179
SECStatus
180
CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd,
181
                                   SECKEYPublicKey *pubKey,
182
                                   void *wincx)
183
3.46k
{
184
3.46k
    SECStatus rv;
185
3.46k
    SECItem sig;
186
3.46k
    SECOidTag sigAlg;
187
3.46k
    SECOidTag encAlg;
188
3.46k
    SECOidTag hashAlg;
189
3.46k
    CK_MECHANISM_TYPE mech;
190
3.46k
    PRUint32 policyFlags;
191
192
3.46k
    if (!pubKey || !sd) {
193
0
        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
194
0
        return SECFailure;
195
0
    }
196
197
    /* Can we use this algorithm for signature verification?  */
198
3.46k
    sigAlg = SECOID_GetAlgorithmTag(&sd->signatureAlgorithm);
199
3.46k
    rv = sec_DecodeSigAlg(pubKey, sigAlg,
200
3.46k
                          &sd->signatureAlgorithm.parameters,
201
3.46k
                          &encAlg, &hashAlg, &mech, NULL);
202
3.46k
    if (rv != SECSuccess) {
203
13
        return SECFailure; /* error is set */
204
13
    }
205
3.45k
    rv = NSS_GetAlgorithmPolicy(encAlg, &policyFlags);
206
3.45k
    if (rv == SECSuccess &&
207
3.45k
        !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
208
0
        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
209
0
        return SECFailure;
210
0
    }
211
3.45k
    rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags);
212
3.45k
    if (rv == SECSuccess &&
213
3.45k
        !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
214
6
        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
215
6
        return SECFailure;
216
6
    }
217
3.44k
    rv = checkKeyParams(&sd->signatureAlgorithm, pubKey);
218
3.44k
    if (rv != SECSuccess) {
219
24
        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
220
24
        return SECFailure;
221
24
    }
222
223
    /* check the signature */
224
3.42k
    sig = sd->signature;
225
    /* convert sig->len from bit counts to byte count. */
226
3.42k
    DER_ConvertBitString(&sig);
227
228
3.42k
    rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey,
229
3.42k
                                       &sig, &sd->signatureAlgorithm,
230
3.42k
                                       &hashAlg, wincx);
231
3.42k
    if (rv != SECSuccess) {
232
2.76k
        return SECFailure; /* error is set */
233
2.76k
    }
234
235
    /* for some algorithms, hash algorithm is only known after verification */
236
657
    rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags);
237
657
    if (rv == SECSuccess &&
238
657
        !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
239
0
        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
240
0
        return SECFailure;
241
0
    }
242
657
    return SECSuccess;
243
657
}
244
245
/*
246
 * verify the signature of a signed data object with the given DER publickey
247
 */
248
SECStatus
249
CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData *sd,
250
                                       CERTSubjectPublicKeyInfo *pubKeyInfo,
251
                                       void *wincx)
252
0
{
253
0
    SECKEYPublicKey *pubKey;
254
0
    SECStatus rv = SECFailure;
255
256
    /* get cert's public key */
257
0
    pubKey = SECKEY_ExtractPublicKey(pubKeyInfo);
258
0
    if (pubKey) {
259
0
        rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx);
260
0
        SECKEY_DestroyPublicKey(pubKey);
261
0
    }
262
0
    return rv;
263
0
}
264
265
/*
266
 * verify the signature of a signed data object with the given certificate
267
 */
268
SECStatus
269
CERT_VerifySignedData(CERTSignedData *sd, CERTCertificate *cert,
270
                      PRTime t, void *wincx)
271
3.51k
{
272
3.51k
    SECKEYPublicKey *pubKey = 0;
273
3.51k
    SECStatus rv = SECFailure;
274
3.51k
    SECCertTimeValidity validity;
275
276
    /* check the certificate's validity */
277
3.51k
    validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE);
278
3.51k
    if (validity != secCertTimeValid) {
279
0
        return rv;
280
0
    }
281
282
    /* get cert's public key */
283
3.51k
    pubKey = CERT_ExtractPublicKey(cert);
284
3.51k
    if (pubKey) {
285
3.46k
        rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx);
286
3.46k
        SECKEY_DestroyPublicKey(pubKey);
287
3.46k
    }
288
3.51k
    return rv;
289
3.51k
}
290
291
SECStatus
292
SEC_CheckCRL(CERTCertDBHandle *handle, CERTCertificate *cert,
293
             CERTCertificate *caCert, PRTime t, void *wincx)
294
499
{
295
499
    return CERT_CheckCRL(cert, caCert, NULL, t, wincx);
296
499
}
297
298
/*
299
 * Find the issuer of a cert.  Use the authorityKeyID if it exists.
300
 */
301
CERTCertificate *
302
CERT_FindCertIssuer(CERTCertificate *cert, PRTime validTime, SECCertUsage usage)
303
6.99k
{
304
6.99k
    NSSCertificate *me;
305
6.99k
    NSSTime *nssTime;
306
6.99k
    NSSTrustDomain *td;
307
6.99k
    NSSCryptoContext *cc;
308
6.99k
    NSSCertificate *chain[3];
309
6.99k
    NSSUsage nssUsage;
310
6.99k
    PRStatus status;
311
312
6.99k
    me = STAN_GetNSSCertificate(cert);
313
6.99k
    if (!me) {
314
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
315
0
        return NULL;
316
0
    }
317
6.99k
    nssTime = NSSTime_SetPRTime(NULL, validTime);
318
6.99k
    nssUsage.anyUsage = PR_FALSE;
319
6.99k
    nssUsage.nss3usage = usage;
320
6.99k
    nssUsage.nss3lookingForCA = PR_TRUE;
321
6.99k
    memset(chain, 0, 3 * sizeof(NSSCertificate *));
322
6.99k
    td = STAN_GetDefaultTrustDomain();
323
6.99k
    cc = STAN_GetDefaultCryptoContext();
324
6.99k
    (void)NSSCertificate_BuildChain(me, nssTime, &nssUsage, NULL,
325
6.99k
                                    chain, 2, NULL, &status, td, cc);
326
6.99k
    nss_ZFreeIf(nssTime);
327
6.99k
    if (status == PR_SUCCESS) {
328
4.81k
        PORT_Assert(me == chain[0]);
329
        /* if it's a root, the chain will only have one cert */
330
4.81k
        if (!chain[1]) {
331
            /* already has a reference from the call to BuildChain */
332
3.49k
            return cert;
333
3.49k
        }
334
1.31k
        NSSCertificate_Destroy(chain[0]);         /* the first cert in the chain */
335
1.31k
        return STAN_GetCERTCertificate(chain[1]); /* return the 2nd */
336
4.81k
    }
337
2.17k
    if (chain[0]) {
338
2.17k
        PORT_Assert(me == chain[0]);
339
2.17k
        NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */
340
2.17k
    }
341
2.17k
    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
342
2.17k
    return NULL;
343
6.99k
}
344
345
/*
346
 * return required trust flags for various cert usages for CAs
347
 */
348
SECStatus
349
CERT_TrustFlagsForCACertUsage(SECCertUsage usage,
350
                              unsigned int *retFlags,
351
                              SECTrustType *retTrustType)
352
5.47k
{
353
5.47k
    unsigned int requiredFlags;
354
5.47k
    SECTrustType trustType;
355
356
5.47k
    switch (usage) {
357
3.31k
        case certUsageSSLClient:
358
3.31k
            requiredFlags = CERTDB_TRUSTED_CLIENT_CA;
359
3.31k
            trustType = trustSSL;
360
3.31k
            break;
361
338
        case certUsageSSLServer:
362
533
        case certUsageSSLCA:
363
533
            requiredFlags = CERTDB_TRUSTED_CA;
364
533
            trustType = trustSSL;
365
533
            break;
366
587
        case certUsageIPsec:
367
587
            requiredFlags = CERTDB_TRUSTED_CA;
368
587
            trustType = trustSSL;
369
587
            break;
370
8
        case certUsageSSLServerWithStepUp:
371
8
            requiredFlags = CERTDB_TRUSTED_CA | CERTDB_GOVT_APPROVED_CA;
372
8
            trustType = trustSSL;
373
8
            break;
374
571
        case certUsageEmailSigner:
375
864
        case certUsageEmailRecipient:
376
864
            requiredFlags = CERTDB_TRUSTED_CA;
377
864
            trustType = trustEmail;
378
864
            break;
379
20
        case certUsageObjectSigner:
380
20
            requiredFlags = CERTDB_TRUSTED_CA;
381
20
            trustType = trustObjectSigning;
382
20
            break;
383
0
        case certUsageVerifyCA:
384
0
        case certUsageAnyCA:
385
150
        case certUsageStatusResponder:
386
150
            requiredFlags = CERTDB_TRUSTED_CA;
387
150
            trustType = trustTypeNone;
388
150
            break;
389
0
        default:
390
0
            PORT_Assert(0);
391
0
            goto loser;
392
5.47k
    }
393
5.47k
    if (retFlags != NULL) {
394
5.47k
        *retFlags = requiredFlags;
395
5.47k
    }
396
5.47k
    if (retTrustType != NULL) {
397
5.47k
        *retTrustType = trustType;
398
5.47k
    }
399
400
5.47k
    return (SECSuccess);
401
0
loser:
402
0
    return (SECFailure);
403
5.47k
}
404
405
void
406
cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, long error,
407
                    unsigned int depth, void *arg)
408
0
{
409
0
    CERTVerifyLogNode *node, *tnode;
410
411
0
    PORT_Assert(log != NULL);
412
413
0
    node = (CERTVerifyLogNode *)PORT_ArenaAlloc(log->arena,
414
0
                                                sizeof(CERTVerifyLogNode));
415
0
    if (node != NULL) {
416
0
        node->cert = CERT_DupCertificate(cert);
417
0
        node->error = error;
418
0
        node->depth = depth;
419
0
        node->arg = arg;
420
421
0
        if (log->tail == NULL) {
422
            /* empty list */
423
0
            log->head = log->tail = node;
424
0
            node->prev = NULL;
425
0
            node->next = NULL;
426
0
        } else if (depth >= log->tail->depth) {
427
            /* add to tail */
428
0
            node->prev = log->tail;
429
0
            log->tail->next = node;
430
0
            log->tail = node;
431
0
            node->next = NULL;
432
0
        } else if (depth < log->head->depth) {
433
            /* add at head */
434
0
            node->prev = NULL;
435
0
            node->next = log->head;
436
0
            log->head->prev = node;
437
0
            log->head = node;
438
0
        } else {
439
            /* add in middle */
440
0
            tnode = log->tail;
441
0
            while (tnode != NULL) {
442
0
                if (depth >= tnode->depth) {
443
                    /* insert after tnode */
444
0
                    node->prev = tnode;
445
0
                    node->next = tnode->next;
446
0
                    tnode->next->prev = node;
447
0
                    tnode->next = node;
448
0
                    break;
449
0
                }
450
451
0
                tnode = tnode->prev;
452
0
            }
453
0
        }
454
455
0
        log->count++;
456
0
    }
457
0
    return;
458
0
}
459
460
#define EXIT_IF_NOT_LOGGING(log) \
461
0
    if (log == NULL) {           \
462
0
        goto loser;              \
463
0
    }
464
465
#define LOG_ERROR_OR_EXIT(log, cert, depth, arg)               \
466
4.40k
    if (log != NULL) {                                         \
467
0
        cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
468
0
                            (void *)(PRWord)arg);              \
469
4.40k
    } else {                                                   \
470
4.40k
        goto loser;                                            \
471
4.40k
    }
472
473
#define LOG_ERROR(log, cert, depth, arg)                       \
474
16.6k
    if (log != NULL) {                                         \
475
0
        cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
476
0
                            (void *)(PRWord)arg);              \
477
0
    }
478
479
/* /C=CN/O=WoSign CA Limited/CN=CA \xE6\xB2\x83\xE9\x80\x9A\xE6\xA0\xB9\xE8\xAF\x81\xE4\xB9\xA6
480
 * Using a consistent naming convention, this would actually be called
481
 * 'CA沃通根证书DN', but since GCC 6.2.1 apparently can't handle UTF-8
482
 * identifiers, this will have to do.
483
 */
484
static const unsigned char CAWoSignRootDN[72] = {
485
    0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
486
    0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11,
487
    0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D,
488
    0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03,
489
    0x0C, 0x12, 0x43, 0x41, 0x20, 0xE6, 0xB2, 0x83, 0xE9, 0x80, 0x9A, 0xE6, 0xA0,
490
    0xB9, 0xE8, 0xAF, 0x81, 0xE4, 0xB9, 0xA6
491
};
492
493
/* /C=CN/O=WoSign CA Limited/CN=CA WoSign ECC Root */
494
static const unsigned char CAWoSignECCRootDN[72] = {
495
    0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
496
    0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11,
497
    0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D,
498
    0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03,
499
    0x13, 0x12, 0x43, 0x41, 0x20, 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45,
500
    0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74
501
};
502
503
/* /C=CN/O=WoSign CA Limited/CN=Certification Authority of WoSign */
504
static const unsigned char CertificationAuthorityofWoSignDN[87] = {
505
    0x30, 0x55, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
506
    0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11,
507
    0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D,
508
    0x69, 0x74, 0x65, 0x64, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03,
509
    0x13, 0x21, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
510
    0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20,
511
    0x6F, 0x66, 0x20, 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E
512
};
513
514
/* /C=CN/O=WoSign CA Limited/CN=Certification Authority of WoSign G2 */
515
static const unsigned char CertificationAuthorityofWoSignG2DN[90] = {
516
    0x30, 0x58, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
517
    0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11,
518
    0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D,
519
    0x69, 0x74, 0x65, 0x64, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03,
520
    0x13, 0x24, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
521
    0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20,
522
    0x6F, 0x66, 0x20, 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, 0x32
523
};
524
525
/* /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority */
526
static const unsigned char StartComCertificationAuthorityDN[127] = {
527
    0x30, 0x7D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
528
    0x49, 0x4C, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D,
529
    0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 0x4C, 0x74, 0x64, 0x2E,
530
    0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x22, 0x53, 0x65,
531
    0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6C, 0x20,
532
    0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53,
533
    0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55,
534
    0x04, 0x03, 0x13, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20,
535
    0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E,
536
    0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79
537
};
538
539
/* /C=IL/O=StartCom Ltd./CN=StartCom Certification Authority G2 */
540
static const unsigned char StartComCertificationAuthorityG2DN[85] = {
541
    0x30, 0x53, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
542
    0x49, 0x4C, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D,
543
    0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 0x4C, 0x74, 0x64, 0x2E,
544
    0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x23, 0x53, 0x74,
545
    0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
546
    0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F,
547
    0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32
548
};
549
550
struct DataAndLength {
551
    const unsigned char *data;
552
    PRUint32 len;
553
};
554
555
static const struct DataAndLength StartComAndWoSignDNs[] = {
556
    { CAWoSignRootDN,
557
      sizeof(CAWoSignRootDN) },
558
    { CAWoSignECCRootDN,
559
      sizeof(CAWoSignECCRootDN) },
560
    { CertificationAuthorityofWoSignDN,
561
      sizeof(CertificationAuthorityofWoSignDN) },
562
    { CertificationAuthorityofWoSignG2DN,
563
      sizeof(CertificationAuthorityofWoSignG2DN) },
564
    { StartComCertificationAuthorityDN,
565
      sizeof(StartComCertificationAuthorityDN) },
566
    { StartComCertificationAuthorityG2DN,
567
      sizeof(StartComCertificationAuthorityG2DN) },
568
};
569
570
static PRBool
571
CertIsStartComOrWoSign(const CERTCertificate *cert)
572
499
{
573
499
    int i;
574
499
    const struct DataAndLength *dn = StartComAndWoSignDNs;
575
576
3.49k
    for (i = 0; i < sizeof(StartComAndWoSignDNs) / sizeof(struct DataAndLength); ++i, dn++) {
577
2.99k
        if (cert->derSubject.len == dn->len &&
578
0
            memcmp(cert->derSubject.data, dn->data, dn->len) == 0) {
579
0
            return PR_TRUE;
580
0
        }
581
2.99k
    }
582
499
    return PR_FALSE;
583
499
}
584
585
SECStatus
586
isIssuerCertAllowedAtCertIssuanceTime(CERTCertificate *issuerCert,
587
                                      CERTCertificate *referenceCert)
588
499
{
589
499
    if (!issuerCert || !referenceCert) {
590
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
591
0
        return SECFailure;
592
0
    }
593
594
499
    if (CertIsStartComOrWoSign(issuerCert)) {
595
        /* PRTime is microseconds since the epoch, whereas JS time is milliseconds.
596
         * (new Date("2016-10-21T00:00:00Z")).getTime() * 1000
597
         */
598
0
        static const PRTime OCTOBER_21_2016 = 1477008000000000;
599
600
0
        PRTime notBefore, notAfter;
601
0
        SECStatus rv;
602
603
0
        rv = CERT_GetCertTimes(referenceCert, &notBefore, &notAfter);
604
0
        if (rv != SECSuccess)
605
0
            return rv;
606
607
0
        if (notBefore > OCTOBER_21_2016) {
608
0
            return SECFailure;
609
0
        }
610
0
    }
611
612
499
    return SECSuccess;
613
499
}
614
615
static SECStatus
616
cert_VerifyCertChainOld(CERTCertDBHandle *handle, CERTCertificate *cert,
617
                        PRBool checkSig, PRBool *sigerror,
618
                        SECCertUsage certUsage, PRTime t, void *wincx,
619
                        CERTVerifyLog *log, PRBool *revoked)
620
5.47k
{
621
5.47k
    SECTrustType trustType;
622
5.47k
    CERTBasicConstraints basicConstraint;
623
5.47k
    CERTCertificate *issuerCert = NULL;
624
5.47k
    CERTCertificate *subjectCert = NULL;
625
5.47k
    CERTCertificate *badCert = NULL;
626
5.47k
    PRBool isca;
627
5.47k
    SECStatus rv;
628
5.47k
    SECStatus rvFinal = SECSuccess;
629
5.47k
    int count;
630
5.47k
    int currentPathLen = 0;
631
5.47k
    int pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT;
632
5.47k
    unsigned int caCertType;
633
5.47k
    unsigned int requiredCAKeyUsage;
634
5.47k
    unsigned int requiredFlags;
635
5.47k
    PLArenaPool *arena = NULL;
636
5.47k
    CERTGeneralName *namesList = NULL;
637
5.47k
    CERTCertificate **certsList = NULL;
638
5.47k
    int certsListLen = 16;
639
5.47k
    int namesCount = 0;
640
5.47k
    PRBool subjectCertIsSelfIssued;
641
5.47k
    CERTCertTrust issuerTrust;
642
643
5.47k
    if (revoked) {
644
5.47k
        *revoked = PR_FALSE;
645
5.47k
    }
646
647
5.47k
    if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE,
648
5.47k
                                         &requiredCAKeyUsage,
649
5.47k
                                         &caCertType) !=
650
5.47k
        SECSuccess) {
651
0
        PORT_Assert(0);
652
0
        EXIT_IF_NOT_LOGGING(log);
653
0
        requiredCAKeyUsage = 0;
654
0
        caCertType = 0;
655
0
    }
656
657
5.47k
    switch (certUsage) {
658
3.31k
        case certUsageSSLClient:
659
3.64k
        case certUsageSSLServer:
660
4.23k
        case certUsageIPsec:
661
4.43k
        case certUsageSSLCA:
662
4.43k
        case certUsageSSLServerWithStepUp:
663
5.01k
        case certUsageEmailSigner:
664
5.30k
        case certUsageEmailRecipient:
665
5.32k
        case certUsageObjectSigner:
666
5.32k
        case certUsageVerifyCA:
667
5.32k
        case certUsageAnyCA:
668
5.47k
        case certUsageStatusResponder:
669
5.47k
            if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
670
5.47k
                                              &trustType) != SECSuccess) {
671
0
                PORT_Assert(0);
672
0
                EXIT_IF_NOT_LOGGING(log);
673
                /* XXX continuing with requiredFlags = 0 seems wrong.  It'll
674
                 * cause the following test to be true incorrectly:
675
                 *   flags = SEC_GET_TRUST_FLAGS(issuerCert->trust, trustType);
676
                 *   if (( flags & requiredFlags ) == requiredFlags) {
677
                 *       rv = rvFinal;
678
                 *       goto done;
679
                 *   }
680
                 * There are three other instances of this problem.
681
                 */
682
0
                requiredFlags = 0;
683
0
                trustType = trustSSL;
684
0
            }
685
5.47k
            break;
686
5.47k
        default:
687
0
            PORT_Assert(0);
688
0
            EXIT_IF_NOT_LOGGING(log);
689
0
            requiredFlags = 0;
690
0
            trustType = trustSSL; /* This used to be 0, but we need something
691
                                   * that matches the enumeration type.
692
                                   */
693
0
            caCertType = 0;
694
5.47k
    }
695
696
5.47k
    subjectCert = CERT_DupCertificate(cert);
697
5.47k
    if (subjectCert == NULL) {
698
0
        goto loser;
699
0
    }
700
701
5.47k
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
702
5.47k
    if (arena == NULL) {
703
0
        goto loser;
704
0
    }
705
706
5.47k
    certsList = PORT_ZNewArray(CERTCertificate *, certsListLen);
707
5.47k
    if (certsList == NULL)
708
0
        goto loser;
709
710
    /* RFC 3280 says that the name constraints will apply to the names
711
    ** in the leaf (EE) cert, whether it is self issued or not, so
712
    ** we pretend that it is not.
713
    */
714
5.47k
    subjectCertIsSelfIssued = PR_FALSE;
715
5.47k
    for (count = 0; count < CERT_MAX_CERT_CHAIN; count++) {
716
5.47k
        PRBool validCAOverride = PR_FALSE;
717
718
        /* Construct a list of names for the current and all previous
719
         * certifcates (except leaf (EE) certs, root CAs, and self-issued
720
         * intermediate CAs) to be verified against the name constraints
721
         * extension of the issuer certificate.
722
         */
723
5.47k
        if (subjectCertIsSelfIssued == PR_FALSE) {
724
5.47k
            CERTGeneralName *subjectNameList;
725
5.47k
            int subjectNameListLen;
726
5.47k
            int i;
727
5.47k
            PRBool getSubjectCN = (!count &&
728
5.47k
                                   (certUsage == certUsageSSLServer || certUsage == certUsageIPsec));
729
5.47k
            subjectNameList =
730
5.47k
                CERT_GetConstrainedCertificateNames(subjectCert, arena,
731
5.47k
                                                    getSubjectCN);
732
5.47k
            if (!subjectNameList)
733
41
                goto loser;
734
5.43k
            subjectNameListLen = CERT_GetNamesLength(subjectNameList);
735
5.43k
            if (!subjectNameListLen)
736
0
                goto loser;
737
5.43k
            if (certsListLen <= namesCount + subjectNameListLen) {
738
82
                CERTCertificate **tmpCertsList;
739
82
                certsListLen = (namesCount + subjectNameListLen) * 2;
740
82
                tmpCertsList =
741
82
                    (CERTCertificate **)PORT_Realloc(certsList,
742
82
                                                     certsListLen *
743
82
                                                         sizeof(CERTCertificate *));
744
82
                if (tmpCertsList == NULL) {
745
0
                    goto loser;
746
0
                }
747
82
                certsList = tmpCertsList;
748
82
            }
749
15.8k
            for (i = 0; i < subjectNameListLen; i++) {
750
10.3k
                certsList[namesCount + i] = subjectCert;
751
10.3k
            }
752
5.43k
            namesCount += subjectNameListLen;
753
5.43k
            namesList = cert_CombineNamesLists(namesList, subjectNameList);
754
5.43k
        }
755
756
        /* check if the cert has an unsupported critical extension */
757
5.43k
        if (subjectCert->options.bits.hasUnsupportedCriticalExt) {
758
134
            PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
759
134
            LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
760
0
        }
761
762
        /* check that the signatureAlgorithm field of the certificate
763
         * matches the signature field of the tbsCertificate */
764
5.29k
        if (SECOID_CompareAlgorithmID(
765
5.29k
                &subjectCert->signatureWrap.signatureAlgorithm,
766
5.29k
                &subjectCert->signature)) {
767
907
            PORT_SetError(SEC_ERROR_ALGORITHM_MISMATCH);
768
907
            LOG_ERROR(log, subjectCert, count, 0);
769
907
            goto loser;
770
907
        }
771
772
        /* find the certificate of the issuer */
773
4.39k
        issuerCert = CERT_FindCertIssuer(subjectCert, t, certUsage);
774
4.39k
        if (!issuerCert) {
775
877
            PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
776
877
            LOG_ERROR(log, subjectCert, count, 0);
777
877
            goto loser;
778
877
        }
779
780
        /* verify the signature on the cert */
781
3.51k
        if (checkSig) {
782
3.51k
            rv = CERT_VerifySignedData(&subjectCert->signatureWrap,
783
3.51k
                                       issuerCert, t, wincx);
784
785
3.51k
            if (rv != SECSuccess) {
786
2.85k
                if (sigerror) {
787
2.85k
                    *sigerror = PR_TRUE;
788
2.85k
                }
789
2.85k
                if (PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE) {
790
0
                    PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE);
791
0
                    LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
792
2.85k
                } else {
793
2.85k
                    if (PORT_GetError() !=
794
2.85k
                        SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) {
795
2.82k
                        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
796
2.82k
                    }
797
2.85k
                    LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
798
0
                }
799
2.85k
            }
800
3.51k
        }
801
802
        /* If the basicConstraint extension is included in an immediate CA
803
         * certificate, make sure that the isCA flag is on.  If the
804
         * pathLenConstraint component exists, it must be greater than the
805
         * number of CA certificates we have seen so far.  If the extension
806
         * is omitted, we will assume that this is a CA certificate with
807
         * an unlimited pathLenConstraint (since it already passes the
808
         * netscape-cert-type extension checking).
809
         */
810
811
657
        rv = CERT_FindBasicConstraintExten(issuerCert, &basicConstraint);
812
657
        if (rv != SECSuccess) {
813
492
            if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
814
16
                LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
815
0
            }
816
476
            pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT;
817
            /* no basic constraints found, we aren't (yet) a CA. */
818
476
            isca = PR_FALSE;
819
476
        } else {
820
165
            if (basicConstraint.isCA == PR_FALSE) {
821
124
                PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
822
124
                LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
823
0
            }
824
41
            pathLengthLimit = basicConstraint.pathLenConstraint;
825
41
            isca = PR_TRUE;
826
41
        }
827
        /* make sure that the path len constraint is properly set.*/
828
517
        if (pathLengthLimit >= 0 && currentPathLen > pathLengthLimit) {
829
0
            PORT_SetError(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID);
830
0
            LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, pathLengthLimit);
831
0
        }
832
833
        /* make sure that the entire chain is within the name space of the
834
         * current issuer certificate.
835
         */
836
517
        rv = CERT_CompareNameSpace(issuerCert, namesList, certsList,
837
517
                                   arena, &badCert);
838
517
        if (rv != SECSuccess || badCert != NULL) {
839
18
            PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE);
840
18
            LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0);
841
0
            goto loser;
842
18
        }
843
844
499
        rv = isIssuerCertAllowedAtCertIssuanceTime(issuerCert, cert);
845
499
        if (rv != SECSuccess) {
846
0
            PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
847
0
            LOG_ERROR(log, issuerCert, count + 1, 0);
848
0
            goto loser;
849
0
        }
850
851
        /* XXX - the error logging may need to go down into CRL stuff at some
852
         * point
853
         */
854
        /* check revoked list (issuer) */
855
499
        rv = SEC_CheckCRL(handle, subjectCert, issuerCert, t, wincx);
856
499
        if (rv == SECFailure) {
857
0
            if (revoked) {
858
0
                *revoked = PR_TRUE;
859
0
            }
860
0
            LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
861
499
        } else if (rv == SECWouldBlock) {
862
            /* We found something fishy, so we intend to issue an
863
             * error to the user, but the user may wish to continue
864
             * processing, in which case we better make sure nothing
865
             * worse has happened... so keep cranking the loop */
866
0
            rvFinal = SECFailure;
867
0
            if (revoked) {
868
0
                *revoked = PR_TRUE;
869
0
            }
870
0
            LOG_ERROR(log, subjectCert, count, 0);
871
0
        }
872
873
499
        if (CERT_GetCertTrust(issuerCert, &issuerTrust) == SECSuccess) {
874
            /* we have some trust info, but this does NOT imply that this
875
             * cert is actually trusted for any purpose.  The cert may be
876
             * explicitly UNtrusted.  We won't know until we examine the
877
             * trust bits.
878
             */
879
0
            unsigned int flags;
880
881
0
            if (certUsage != certUsageAnyCA &&
882
0
                certUsage != certUsageStatusResponder) {
883
884
                /*
885
                 * XXX This choice of trustType seems arbitrary.
886
                 */
887
0
                if (certUsage == certUsageVerifyCA) {
888
0
                    if (subjectCert->nsCertType & NS_CERT_TYPE_EMAIL_CA) {
889
0
                        trustType = trustEmail;
890
0
                    } else if (subjectCert->nsCertType & NS_CERT_TYPE_SSL_CA) {
891
0
                        trustType = trustSSL;
892
0
                    } else {
893
0
                        trustType = trustObjectSigning;
894
0
                    }
895
0
                }
896
897
0
                flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
898
0
                if ((flags & requiredFlags) == requiredFlags) {
899
                    /* we found a trusted one, so return */
900
0
                    rv = rvFinal;
901
0
                    goto done;
902
0
                }
903
0
                if (flags & CERTDB_VALID_CA) {
904
0
                    validCAOverride = PR_TRUE;
905
0
                }
906
                /* is it explicitly distrusted? */
907
0
                if ((flags & CERTDB_TERMINAL_RECORD) &&
908
0
                    ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
909
                    /* untrusted -- the cert is explicitly untrusted, not
910
                     * just that it doesn't chain to a trusted cert */
911
0
                    PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
912
0
                    LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags);
913
0
                }
914
0
            } else {
915
                /* Check if we have any valid trust when cheching for
916
                 * certUsageAnyCA or certUsageStatusResponder. */
917
0
                for (trustType = trustSSL; trustType < trustTypeNone;
918
0
                     trustType++) {
919
0
                    flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
920
0
                    if ((flags & requiredFlags) == requiredFlags) {
921
0
                        rv = rvFinal;
922
0
                        goto done;
923
0
                    }
924
0
                    if (flags & CERTDB_VALID_CA)
925
0
                        validCAOverride = PR_TRUE;
926
0
                }
927
                /* We have 2 separate loops because we want any single trust
928
                 * bit to allow this usage to return trusted. Only if none of
929
                 * the trust bits are on do we check to see if the cert is
930
                 * untrusted */
931
0
                for (trustType = trustSSL; trustType < trustTypeNone;
932
0
                     trustType++) {
933
0
                    flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
934
                    /* is it explicitly distrusted? */
935
0
                    if ((flags & CERTDB_TERMINAL_RECORD) &&
936
0
                        ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
937
                        /* untrusted -- the cert is explicitly untrusted, not
938
                         * just that it doesn't chain to a trusted cert */
939
0
                        PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
940
0
                        LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags);
941
0
                    }
942
0
                }
943
0
            }
944
0
        }
945
946
499
        if (!validCAOverride) {
947
            /*
948
             * Make sure that if this is an intermediate CA in the chain that
949
             * it was given permission by its signer to be a CA.
950
             */
951
            /*
952
             * if basicConstraints says it is a ca, then we check the
953
             * nsCertType.  If the nsCertType has any CA bits set, then
954
             * it must have the right one.
955
             */
956
499
            if (!isca || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) {
957
499
                isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE;
958
499
            }
959
960
499
            if (!isca) {
961
65
                PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
962
65
                LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
963
0
            }
964
965
            /* make sure key usage allows cert signing */
966
434
            if (CERT_CheckKeyUsage(issuerCert, requiredCAKeyUsage) != SECSuccess) {
967
48
                PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
968
48
                LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, requiredCAKeyUsage);
969
0
            }
970
434
        }
971
972
        /* make sure that the issuer is not self signed.  If it is, then
973
         * stop here to prevent looping.
974
         */
975
386
        if (issuerCert->isRoot) {
976
386
            PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
977
386
            LOG_ERROR(log, issuerCert, count + 1, 0);
978
386
            goto loser;
979
386
        }
980
        /* The issuer cert will be the subject cert in the next loop.
981
         * A cert is self-issued if its subject and issuer are equal and
982
         * both are of non-zero length.
983
         */
984
0
        subjectCertIsSelfIssued = (PRBool)
985
0
                                      SECITEM_ItemsAreEqual(&issuerCert->derIssuer,
986
0
                                                            &issuerCert->derSubject) &&
987
0
                                  issuerCert->derSubject.len >
988
0
                                      0;
989
0
        if (subjectCertIsSelfIssued == PR_FALSE) {
990
            /* RFC 3280 says only non-self-issued intermediate CA certs
991
             * count in path length.
992
             */
993
0
            ++currentPathLen;
994
0
        }
995
996
0
        CERT_DestroyCertificate(subjectCert);
997
0
        subjectCert = issuerCert;
998
0
        issuerCert = NULL;
999
0
    }
1000
1001
0
    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
1002
0
    LOG_ERROR(log, subjectCert, count, 0);
1003
5.47k
loser:
1004
5.47k
    rv = SECFailure;
1005
5.47k
done:
1006
5.47k
    if (certsList != NULL) {
1007
5.47k
        PORT_Free(certsList);
1008
5.47k
    }
1009
5.47k
    if (issuerCert) {
1010
3.51k
        CERT_DestroyCertificate(issuerCert);
1011
3.51k
    }
1012
1013
5.47k
    if (subjectCert) {
1014
5.47k
        CERT_DestroyCertificate(subjectCert);
1015
5.47k
    }
1016
1017
5.47k
    if (arena != NULL) {
1018
5.47k
        PORT_FreeArena(arena, PR_FALSE);
1019
5.47k
    }
1020
5.47k
    return rv;
1021
5.47k
}
1022
1023
SECStatus
1024
cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
1025
                     PRBool checkSig, PRBool *sigerror,
1026
                     SECCertUsage certUsage, PRTime t, void *wincx,
1027
                     CERTVerifyLog *log, PRBool *revoked)
1028
5.47k
{
1029
5.47k
    if (CERT_GetUsePKIXForValidation()) {
1030
0
        return cert_VerifyCertChainPkix(cert, checkSig, certUsage, t,
1031
0
                                        wincx, log, sigerror, revoked);
1032
0
    }
1033
5.47k
    return cert_VerifyCertChainOld(handle, cert, checkSig, sigerror,
1034
5.47k
                                   certUsage, t, wincx, log, revoked);
1035
5.47k
}
1036
1037
SECStatus
1038
CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
1039
                     PRBool checkSig, SECCertUsage certUsage, PRTime t,
1040
                     void *wincx, CERTVerifyLog *log)
1041
0
{
1042
0
    return cert_VerifyCertChain(handle, cert, checkSig, NULL, certUsage, t,
1043
0
                                wincx, log, NULL);
1044
0
}
1045
1046
/*
1047
 * verify that a CA can sign a certificate with the requested usage.
1048
 */
1049
SECStatus
1050
CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, CERTCertificate *cert,
1051
                          PRBool checkSig, SECCertUsage certUsage, PRTime t,
1052
                          void *wincx, CERTVerifyLog *log)
1053
0
{
1054
0
    SECTrustType trustType;
1055
0
    CERTBasicConstraints basicConstraint;
1056
0
    PRBool isca;
1057
0
    PRBool validCAOverride = PR_FALSE;
1058
0
    SECStatus rv;
1059
0
    SECStatus rvFinal = SECSuccess;
1060
0
    unsigned int flags;
1061
0
    unsigned int caCertType;
1062
0
    unsigned int requiredCAKeyUsage;
1063
0
    unsigned int requiredFlags;
1064
0
    CERTCertificate *issuerCert;
1065
0
    CERTCertTrust certTrust;
1066
1067
0
    if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE,
1068
0
                                         &requiredCAKeyUsage,
1069
0
                                         &caCertType) != SECSuccess) {
1070
0
        PORT_Assert(0);
1071
0
        EXIT_IF_NOT_LOGGING(log);
1072
0
        requiredCAKeyUsage = 0;
1073
0
        caCertType = 0;
1074
0
    }
1075
1076
0
    switch (certUsage) {
1077
0
        case certUsageSSLClient:
1078
0
        case certUsageSSLServer:
1079
0
        case certUsageIPsec:
1080
0
        case certUsageSSLCA:
1081
0
        case certUsageSSLServerWithStepUp:
1082
0
        case certUsageEmailSigner:
1083
0
        case certUsageEmailRecipient:
1084
0
        case certUsageObjectSigner:
1085
0
        case certUsageVerifyCA:
1086
0
        case certUsageStatusResponder:
1087
0
            if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
1088
0
                                              &trustType) != SECSuccess) {
1089
0
                PORT_Assert(0);
1090
0
                EXIT_IF_NOT_LOGGING(log);
1091
0
                requiredFlags = 0;
1092
0
                trustType = trustSSL;
1093
0
            }
1094
0
            break;
1095
0
        default:
1096
0
            PORT_Assert(0);
1097
0
            EXIT_IF_NOT_LOGGING(log);
1098
0
            requiredFlags = 0;
1099
0
            trustType = trustSSL; /* This used to be 0, but we need something
1100
                                   * that matches the enumeration type.
1101
                                   */
1102
0
            caCertType = 0;
1103
0
    }
1104
1105
    /* If the basicConstraint extension is included in an intermmediate CA
1106
     * certificate, make sure that the isCA flag is on.  If the
1107
     * pathLenConstraint component exists, it must be greater than the
1108
     * number of CA certificates we have seen so far.  If the extension
1109
     * is omitted, we will assume that this is a CA certificate with
1110
     * an unlimited pathLenConstraint (since it already passes the
1111
     * netscape-cert-type extension checking).
1112
     */
1113
1114
0
    rv = CERT_FindBasicConstraintExten(cert, &basicConstraint);
1115
0
    if (rv != SECSuccess) {
1116
0
        if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
1117
0
            LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1118
0
        }
1119
        /* no basic constraints found, we aren't (yet) a CA. */
1120
0
        isca = PR_FALSE;
1121
0
    } else {
1122
0
        if (basicConstraint.isCA == PR_FALSE) {
1123
0
            PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
1124
0
            LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1125
0
        }
1126
1127
        /* can't check path length if we don't know the previous path */
1128
0
        isca = PR_TRUE;
1129
0
    }
1130
1131
0
    if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) {
1132
        /* we have some trust info, but this does NOT imply that this
1133
         * cert is actually trusted for any purpose.  The cert may be
1134
         * explicitly UNtrusted.  We won't know until we examine the
1135
         * trust bits.
1136
         */
1137
0
        if (certUsage == certUsageStatusResponder) {
1138
            /* Check the special case of certUsageStatusResponder */
1139
0
            issuerCert = CERT_FindCertIssuer(cert, t, certUsage);
1140
0
            if (issuerCert) {
1141
0
                if (SEC_CheckCRL(handle, cert, issuerCert, t, wincx) !=
1142
0
                    SECSuccess) {
1143
0
                    PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
1144
0
                    CERT_DestroyCertificate(issuerCert);
1145
0
                    goto loser;
1146
0
                }
1147
0
                CERT_DestroyCertificate(issuerCert);
1148
0
            }
1149
            /* XXX We have NOT determined that this cert is trusted.
1150
             * For years, NSS has treated this as trusted,
1151
             * but it seems incorrect.
1152
             */
1153
0
            rv = rvFinal;
1154
0
            goto done;
1155
0
        }
1156
1157
        /*
1158
         * check the trust params of the issuer
1159
         */
1160
0
        flags = SEC_GET_TRUST_FLAGS(&certTrust, trustType);
1161
0
        if ((flags & requiredFlags) == requiredFlags) {
1162
            /* we found a trusted one, so return */
1163
0
            rv = rvFinal;
1164
0
            goto done;
1165
0
        }
1166
0
        if (flags & CERTDB_VALID_CA) {
1167
0
            validCAOverride = PR_TRUE;
1168
0
        }
1169
        /* is it explicitly distrusted? */
1170
0
        if ((flags & CERTDB_TERMINAL_RECORD) &&
1171
0
            ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
1172
            /* untrusted -- the cert is explicitly untrusted, not
1173
             * just that it doesn't chain to a trusted cert */
1174
0
            PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
1175
0
            LOG_ERROR_OR_EXIT(log, cert, 0, flags);
1176
0
        }
1177
0
    }
1178
0
    if (!validCAOverride) {
1179
        /*
1180
         * Make sure that if this is an intermediate CA in the chain that
1181
         * it was given permission by its signer to be a CA.
1182
         */
1183
        /*
1184
         * if basicConstraints says it is a ca, then we check the
1185
         * nsCertType.  If the nsCertType has any CA bits set, then
1186
         * it must have the right one.
1187
         */
1188
0
        if (!isca || (cert->nsCertType & NS_CERT_TYPE_CA)) {
1189
0
            isca = (cert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE;
1190
0
        }
1191
1192
0
        if (!isca) {
1193
0
            PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
1194
0
            LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1195
0
        }
1196
1197
        /* make sure key usage allows cert signing */
1198
0
        if (CERT_CheckKeyUsage(cert, requiredCAKeyUsage) != SECSuccess) {
1199
0
            PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
1200
0
            LOG_ERROR_OR_EXIT(log, cert, 0, requiredCAKeyUsage);
1201
0
        }
1202
0
    }
1203
    /* make sure that the issuer is not self signed.  If it is, then
1204
     * stop here to prevent looping.
1205
     */
1206
0
    if (cert->isRoot) {
1207
0
        PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
1208
0
        LOG_ERROR(log, cert, 0, 0);
1209
0
        goto loser;
1210
0
    }
1211
1212
0
    return CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t,
1213
0
                                wincx, log);
1214
0
loser:
1215
0
    rv = SECFailure;
1216
0
done:
1217
0
    return rv;
1218
0
}
1219
1220
#define NEXT_USAGE() \
1221
14.0k
    {                \
1222
14.0k
        i *= 2;      \
1223
14.0k
        certUsage++; \
1224
14.0k
        continue;    \
1225
45.7k
    }
1226
1227
#define VALID_USAGE() \
1228
0
    {                 \
1229
0
        NEXT_USAGE(); \
1230
0
    }
1231
1232
#define INVALID_USAGE()                 \
1233
0
    {                                   \
1234
31.6k
        if (returnedUsages) {           \
1235
31.6k
            *returnedUsages &= (~i);    \
1236
31.6k
        }                               \
1237
31.6k
        if (PR_TRUE == requiredUsage) { \
1238
0
            valid = SECFailure;         \
1239
0
        }                               \
1240
31.6k
        NEXT_USAGE();                   \
1241
0
    }
1242
1243
/*
1244
 * check the leaf cert against trust and usage.
1245
 *   returns success if the cert is not distrusted. If the cert is
1246
 *       trusted, then the trusted bool will be true.
1247
 *   returns failure if the cert is distrusted. If failure, flags
1248
 *       will return the flag bits that indicated distrust.
1249
 */
1250
SECStatus
1251
cert_CheckLeafTrust(CERTCertificate *cert, SECCertUsage certUsage,
1252
                    unsigned int *failedFlags, PRBool *trusted)
1253
17.1k
{
1254
17.1k
    unsigned int flags;
1255
17.1k
    CERTCertTrust trust;
1256
1257
17.1k
    *failedFlags = 0;
1258
17.1k
    *trusted = PR_FALSE;
1259
1260
    /* check trust flags to see if this cert is directly trusted */
1261
17.1k
    if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
1262
0
        switch (certUsage) {
1263
0
            case certUsageSSLClient:
1264
0
            case certUsageSSLServer:
1265
0
            case certUsageIPsec:
1266
0
                flags = trust.sslFlags;
1267
1268
                /* is the cert directly trusted or not trusted ? */
1269
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1270
                                                       * authoritative */
1271
0
                    if (flags & CERTDB_TRUSTED) {     /* trust this cert */
1272
0
                        *trusted = PR_TRUE;
1273
0
                        return SECSuccess;
1274
0
                    } else { /* don't trust this cert */
1275
0
                        *failedFlags = flags;
1276
0
                        return SECFailure;
1277
0
                    }
1278
0
                }
1279
0
                break;
1280
0
            case certUsageSSLServerWithStepUp:
1281
                /* XXX - step up certs can't be directly trusted, only distrust */
1282
0
                flags = trust.sslFlags;
1283
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1284
                                                       * authoritative */
1285
0
                    if ((flags & CERTDB_TRUSTED) == 0) {
1286
                        /* don't trust this cert */
1287
0
                        *failedFlags = flags;
1288
0
                        return SECFailure;
1289
0
                    }
1290
0
                }
1291
0
                break;
1292
0
            case certUsageSSLCA:
1293
0
                flags = trust.sslFlags;
1294
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1295
                                                       * authoritative */
1296
0
                    if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
1297
                        /* don't trust this cert */
1298
0
                        *failedFlags = flags;
1299
0
                        return SECFailure;
1300
0
                    }
1301
0
                }
1302
0
                break;
1303
0
            case certUsageEmailSigner:
1304
0
            case certUsageEmailRecipient:
1305
0
                flags = trust.emailFlags;
1306
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1307
                                                       * authoritative */
1308
0
                    if (flags & CERTDB_TRUSTED) {     /* trust this cert */
1309
0
                        *trusted = PR_TRUE;
1310
0
                        return SECSuccess;
1311
0
                    } else { /* don't trust this cert */
1312
0
                        *failedFlags = flags;
1313
0
                        return SECFailure;
1314
0
                    }
1315
0
                }
1316
1317
0
                break;
1318
0
            case certUsageObjectSigner:
1319
0
                flags = trust.objectSigningFlags;
1320
1321
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1322
                                                       * authoritative */
1323
0
                    if (flags & CERTDB_TRUSTED) {     /* trust this cert */
1324
0
                        *trusted = PR_TRUE;
1325
0
                        return SECSuccess;
1326
0
                    } else { /* don't trust this cert */
1327
0
                        *failedFlags = flags;
1328
0
                        return SECFailure;
1329
0
                    }
1330
0
                }
1331
0
                break;
1332
0
            case certUsageVerifyCA:
1333
0
            case certUsageStatusResponder:
1334
0
                flags = trust.sslFlags;
1335
                /* is the cert directly trusted or not trusted ? */
1336
0
                if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
1337
0
                    (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
1338
0
                    *trusted = PR_TRUE;
1339
0
                    return SECSuccess;
1340
0
                }
1341
0
                flags = trust.emailFlags;
1342
                /* is the cert directly trusted or not trusted ? */
1343
0
                if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
1344
0
                    (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
1345
0
                    *trusted = PR_TRUE;
1346
0
                    return SECSuccess;
1347
0
                }
1348
0
                flags = trust.objectSigningFlags;
1349
                /* is the cert directly trusted or not trusted ? */
1350
0
                if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
1351
0
                    (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
1352
0
                    *trusted = PR_TRUE;
1353
0
                    return SECSuccess;
1354
0
                }
1355
            /* fall through to test distrust */
1356
0
            case certUsageAnyCA:
1357
0
            case certUsageUserCertImport:
1358
                /* do we distrust these certs explicitly */
1359
0
                flags = trust.sslFlags;
1360
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1361
                                                       * authoritative */
1362
0
                    if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
1363
0
                        *failedFlags = flags;
1364
0
                        return SECFailure;
1365
0
                    }
1366
0
                }
1367
0
                flags = trust.emailFlags;
1368
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1369
                                                       * authoritative */
1370
0
                    if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
1371
0
                        *failedFlags = flags;
1372
0
                        return SECFailure;
1373
0
                    }
1374
0
                }
1375
            /* fall through */
1376
0
            case certUsageProtectedObjectSigner:
1377
0
                flags = trust.objectSigningFlags;
1378
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1379
                                                       * authoritative */
1380
0
                    if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
1381
0
                        *failedFlags = flags;
1382
0
                        return SECFailure;
1383
0
                    }
1384
0
                }
1385
0
                break;
1386
0
        }
1387
0
    }
1388
17.1k
    return SECSuccess;
1389
17.1k
}
1390
1391
/*
1392
 * verify a certificate by checking if it's valid and that we
1393
 * trust the issuer.
1394
 *
1395
 * certificateUsage contains a bitfield of all cert usages that are
1396
 * required for verification to succeed
1397
 *
1398
 * a bitfield of cert usages is returned in *returnedUsages
1399
 * if requiredUsages is non-zero, the returned bitmap is only
1400
 * for those required usages, otherwise it is for all usages
1401
 *
1402
 */
1403
SECStatus
1404
CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
1405
                       PRBool checkSig, SECCertificateUsage requiredUsages, PRTime t,
1406
                       void *wincx, CERTVerifyLog *log, SECCertificateUsage *returnedUsages)
1407
4.66k
{
1408
4.66k
    SECStatus rv;
1409
4.66k
    SECStatus valid;
1410
4.66k
    unsigned int requiredKeyUsage;
1411
4.66k
    unsigned int requiredCertType;
1412
4.66k
    unsigned int flags;
1413
4.66k
    unsigned int certType;
1414
4.66k
    PRBool allowOverride;
1415
4.66k
    SECCertTimeValidity validity;
1416
4.66k
    CERTStatusConfig *statusConfig;
1417
4.66k
    PRInt32 i;
1418
4.66k
    SECCertUsage certUsage = 0;
1419
4.66k
    PRBool checkedOCSP = PR_FALSE;
1420
4.66k
    PRBool checkAllUsages = PR_FALSE;
1421
4.66k
    PRBool revoked = PR_FALSE;
1422
4.66k
    PRBool sigerror = PR_FALSE;
1423
4.66k
    PRBool trusted = PR_FALSE;
1424
1425
4.66k
    if (!requiredUsages) {
1426
        /* there are no required usages, so the user probably wants to
1427
           get status for all usages */
1428
4.66k
        checkAllUsages = PR_TRUE;
1429
4.66k
    }
1430
1431
4.66k
    if (returnedUsages) {
1432
4.66k
        *returnedUsages = 0;
1433
4.66k
    } else {
1434
        /* we don't have a place to return status for all usages,
1435
           so we can skip checks for usages that aren't required */
1436
0
        checkAllUsages = PR_FALSE;
1437
0
    }
1438
4.66k
    valid = SECSuccess; /* start off assuming cert is valid */
1439
1440
    /* make sure that the cert is valid at time t */
1441
4.66k
    allowOverride = (PRBool)((requiredUsages & certificateUsageSSLServer) ||
1442
4.66k
                             (requiredUsages & certificateUsageSSLServerWithStepUp) ||
1443
4.66k
                             (requiredUsages & certificateUsageIPsec));
1444
4.66k
    validity = CERT_CheckCertValidTimes(cert, t, allowOverride);
1445
4.66k
    if (validity != secCertTimeValid) {
1446
1.14k
        valid = SECFailure;
1447
1.14k
        LOG_ERROR_OR_EXIT(log, cert, 0, validity);
1448
0
    }
1449
1450
    /* check key usage and netscape cert type */
1451
3.52k
    cert_GetCertType(cert);
1452
3.52k
    certType = cert->nsCertType;
1453
1454
49.2k
    for (i = 1; i <= certificateUsageHighest &&
1455
45.7k
                (SECSuccess == valid || returnedUsages || log);) {
1456
45.7k
        PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE;
1457
45.7k
        if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) {
1458
0
            NEXT_USAGE();
1459
0
        }
1460
45.7k
        if (returnedUsages) {
1461
45.7k
            *returnedUsages |= i; /* start off assuming this usage is valid */
1462
45.7k
        }
1463
45.7k
        switch (certUsage) {
1464
3.52k
            case certUsageSSLClient:
1465
7.04k
            case certUsageSSLServer:
1466
10.5k
            case certUsageSSLServerWithStepUp:
1467
14.0k
            case certUsageSSLCA:
1468
17.6k
            case certUsageEmailSigner:
1469
21.1k
            case certUsageEmailRecipient:
1470
24.6k
            case certUsageObjectSigner:
1471
28.1k
            case certUsageStatusResponder:
1472
31.6k
            case certUsageIPsec:
1473
31.6k
                rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE,
1474
31.6k
                                                      &requiredKeyUsage,
1475
31.6k
                                                      &requiredCertType);
1476
31.6k
                if (rv != SECSuccess) {
1477
0
                    PORT_Assert(0);
1478
                    /* EXIT_IF_NOT_LOGGING(log); XXX ??? */
1479
0
                    requiredKeyUsage = 0;
1480
0
                    requiredCertType = 0;
1481
0
                    INVALID_USAGE();
1482
0
                }
1483
31.6k
                break;
1484
1485
31.6k
            case certUsageAnyCA:
1486
7.04k
            case certUsageProtectedObjectSigner:
1487
10.5k
            case certUsageUserCertImport:
1488
14.0k
            case certUsageVerifyCA:
1489
                /* these usages cannot be verified */
1490
14.0k
                NEXT_USAGE();
1491
1492
0
            default:
1493
0
                PORT_Assert(0);
1494
0
                requiredKeyUsage = 0;
1495
0
                requiredCertType = 0;
1496
0
                INVALID_USAGE();
1497
45.7k
        }
1498
31.6k
        if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) {
1499
5.52k
            if (PR_TRUE == requiredUsage) {
1500
0
                PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
1501
0
            }
1502
5.52k
            LOG_ERROR(log, cert, 0, requiredKeyUsage);
1503
5.52k
            INVALID_USAGE();
1504
0
        }
1505
26.1k
        if (!(certType & requiredCertType)) {
1506
8.98k
            if (PR_TRUE == requiredUsage) {
1507
0
                PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
1508
0
            }
1509
8.98k
            LOG_ERROR(log, cert, 0, requiredCertType);
1510
8.98k
            INVALID_USAGE();
1511
0
        }
1512
1513
17.1k
        rv = cert_CheckLeafTrust(cert, certUsage, &flags, &trusted);
1514
17.1k
        if (rv == SECFailure) {
1515
0
            if (PR_TRUE == requiredUsage) {
1516
0
                PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
1517
0
            }
1518
0
            LOG_ERROR(log, cert, 0, flags);
1519
0
            INVALID_USAGE();
1520
17.1k
        } else if (trusted) {
1521
0
            VALID_USAGE();
1522
0
        }
1523
1524
17.1k
        if (PR_TRUE == revoked || PR_TRUE == sigerror) {
1525
11.6k
            INVALID_USAGE();
1526
0
        }
1527
1528
5.47k
        rv = cert_VerifyCertChain(handle, cert,
1529
5.47k
                                  checkSig, &sigerror,
1530
5.47k
                                  certUsage, t, wincx, log,
1531
5.47k
                                  &revoked);
1532
1533
5.47k
        if (rv != SECSuccess) {
1534
            /* EXIT_IF_NOT_LOGGING(log); XXX ???? */
1535
5.47k
            INVALID_USAGE();
1536
0
        }
1537
1538
        /*
1539
         * Check OCSP revocation status, but only if the cert we are checking
1540
         * is not a status responder itself. We only do this in the case
1541
         * where we checked the cert chain (above); explicit trust "wins"
1542
         * (avoids status checking, just as it avoids CRL checking) by
1543
         * bypassing this code.
1544
         */
1545
1546
0
        if (PR_FALSE == checkedOCSP) {
1547
0
            checkedOCSP = PR_TRUE; /* only check OCSP once */
1548
0
            statusConfig = CERT_GetStatusConfig(handle);
1549
0
            if (requiredUsages != certificateUsageStatusResponder &&
1550
0
                statusConfig != NULL) {
1551
0
                if (statusConfig->statusChecker != NULL) {
1552
0
                    rv = (*statusConfig->statusChecker)(handle, cert,
1553
0
                                                        t, wincx);
1554
0
                    if (rv != SECSuccess) {
1555
0
                        LOG_ERROR(log, cert, 0, 0);
1556
0
                        revoked = PR_TRUE;
1557
0
                        INVALID_USAGE();
1558
0
                    }
1559
0
                }
1560
0
            }
1561
0
        }
1562
1563
0
        NEXT_USAGE();
1564
0
    }
1565
1566
4.66k
loser:
1567
4.66k
    return (valid);
1568
3.52k
}
1569
1570
SECStatus
1571
CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
1572
                PRBool checkSig, SECCertUsage certUsage, PRTime t,
1573
                void *wincx, CERTVerifyLog *log)
1574
0
{
1575
0
    return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t,
1576
0
                                    CERT_VERIFYCERT_USE_DEFAULTS, wincx, log);
1577
0
}
1578
1579
SECStatus
1580
cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
1581
                         PRBool checkSig, SECCertUsage certUsage, PRTime t,
1582
                         PRUint32 flags, void *wincx, CERTVerifyLog *log)
1583
0
{
1584
0
    SECStatus rv;
1585
0
    unsigned int requiredKeyUsage;
1586
0
    unsigned int requiredCertType;
1587
0
    unsigned int failedFlags;
1588
0
    unsigned int certType;
1589
0
    PRBool trusted;
1590
0
    PRBool allowOverride;
1591
0
    SECCertTimeValidity validity;
1592
0
    CERTStatusConfig *statusConfig;
1593
1594
#ifdef notdef
1595
    /* check if this cert is in the Evil list */
1596
    rv = CERT_CheckForEvilCert(cert);
1597
    if (rv != SECSuccess) {
1598
        PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
1599
        LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1600
    }
1601
#endif
1602
1603
    /* make sure that the cert is valid at time t */
1604
0
    allowOverride = (PRBool)((certUsage == certUsageSSLServer) ||
1605
0
                             (certUsage == certUsageSSLServerWithStepUp) ||
1606
0
                             (certUsage == certUsageIPsec));
1607
0
    validity = CERT_CheckCertValidTimes(cert, t, allowOverride);
1608
0
    if (validity != secCertTimeValid) {
1609
0
        LOG_ERROR_OR_EXIT(log, cert, 0, validity);
1610
0
    }
1611
1612
    /* check key usage and netscape cert type */
1613
0
    cert_GetCertType(cert);
1614
0
    certType = cert->nsCertType;
1615
0
    switch (certUsage) {
1616
0
        case certUsageSSLClient:
1617
0
        case certUsageSSLServer:
1618
0
        case certUsageSSLServerWithStepUp:
1619
0
        case certUsageIPsec:
1620
0
        case certUsageSSLCA:
1621
0
        case certUsageEmailSigner:
1622
0
        case certUsageEmailRecipient:
1623
0
        case certUsageObjectSigner:
1624
0
        case certUsageStatusResponder:
1625
0
            rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE,
1626
0
                                                  &requiredKeyUsage,
1627
0
                                                  &requiredCertType);
1628
0
            if (rv != SECSuccess) {
1629
0
                PORT_Assert(0);
1630
0
                EXIT_IF_NOT_LOGGING(log);
1631
0
                requiredKeyUsage = 0;
1632
0
                requiredCertType = 0;
1633
0
            }
1634
0
            break;
1635
0
        case certUsageVerifyCA:
1636
0
        case certUsageAnyCA:
1637
0
            requiredKeyUsage = KU_KEY_CERT_SIGN;
1638
0
            requiredCertType = NS_CERT_TYPE_CA;
1639
0
            if (!(certType & NS_CERT_TYPE_CA)) {
1640
0
                certType |= NS_CERT_TYPE_CA;
1641
0
            }
1642
0
            break;
1643
0
        default:
1644
0
            PORT_Assert(0);
1645
0
            EXIT_IF_NOT_LOGGING(log);
1646
0
            requiredKeyUsage = 0;
1647
0
            requiredCertType = 0;
1648
0
    }
1649
0
    if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) {
1650
0
        PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
1651
0
        LOG_ERROR_OR_EXIT(log, cert, 0, requiredKeyUsage);
1652
0
    }
1653
0
    if (!(certType & requiredCertType)) {
1654
0
        PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
1655
0
        LOG_ERROR_OR_EXIT(log, cert, 0, requiredCertType);
1656
0
    }
1657
1658
0
    rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted);
1659
0
    if (rv == SECFailure) {
1660
0
        PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
1661
0
        LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags);
1662
0
    } else if (trusted) {
1663
0
        goto done;
1664
0
    }
1665
1666
0
    rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage,
1667
0
                              t, wincx, log);
1668
0
    if (rv != SECSuccess) {
1669
0
        EXIT_IF_NOT_LOGGING(log);
1670
0
    }
1671
1672
    /*
1673
     * Check revocation status, but only if the cert we are checking is not a
1674
     * status responder itself and the caller did not ask us to skip the check.
1675
     * We only do this in the case where we checked the cert chain (above);
1676
     * explicit trust "wins" (avoids status checking, just as it avoids CRL
1677
     * checking, which is all done inside VerifyCertChain) by bypassing this
1678
     * code.
1679
     */
1680
0
    if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) &&
1681
0
        certUsage != certUsageStatusResponder) {
1682
0
        statusConfig = CERT_GetStatusConfig(handle);
1683
0
        if (statusConfig && statusConfig->statusChecker) {
1684
0
            rv = (*statusConfig->statusChecker)(handle, cert,
1685
0
                                                t, wincx);
1686
0
            if (rv != SECSuccess) {
1687
0
                LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1688
0
            }
1689
0
        }
1690
0
    }
1691
1692
0
done:
1693
0
    if (log && log->head) {
1694
0
        return SECFailure;
1695
0
    }
1696
0
    return (SECSuccess);
1697
1698
0
loser:
1699
0
    rv = SECFailure;
1700
1701
0
    return (rv);
1702
0
}
1703
1704
/*
1705
 * verify a certificate by checking if its valid and that we
1706
 * trust the issuer.  Verify time against now.
1707
 */
1708
SECStatus
1709
CERT_VerifyCertificateNow(CERTCertDBHandle *handle, CERTCertificate *cert,
1710
                          PRBool checkSig, SECCertificateUsage requiredUsages,
1711
                          void *wincx, SECCertificateUsage *returnedUsages)
1712
4.66k
{
1713
4.66k
    return (CERT_VerifyCertificate(handle, cert, checkSig,
1714
4.66k
                                   requiredUsages, PR_Now(), wincx, NULL, returnedUsages));
1715
4.66k
}
1716
1717
/* obsolete, do not use for new code */
1718
SECStatus
1719
CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert,
1720
                   PRBool checkSig, SECCertUsage certUsage, void *wincx)
1721
0
{
1722
0
    return (CERT_VerifyCert(handle, cert, checkSig,
1723
0
                            certUsage, PR_Now(), wincx, NULL));
1724
0
}
1725
1726
/* [ FROM pcertdb.c ] */
1727
/*
1728
 * Supported usage values and types:
1729
 *  certUsageSSLClient
1730
 *  certUsageSSLServer
1731
 *  certUsageSSLServerWithStepUp
1732
 *  certUsageIPsec
1733
 *  certUsageEmailSigner
1734
 *  certUsageEmailRecipient
1735
 *  certUsageObjectSigner
1736
 */
1737
1738
CERTCertificate *
1739
CERT_FindMatchingCert(CERTCertDBHandle *handle, SECItem *derName,
1740
                      CERTCertOwner owner, SECCertUsage usage,
1741
                      PRBool preferTrusted, PRTime validTime, PRBool validOnly)
1742
0
{
1743
0
    CERTCertList *certList = NULL;
1744
0
    CERTCertificate *cert = NULL;
1745
0
    CERTCertTrust certTrust;
1746
0
    unsigned int requiredTrustFlags;
1747
0
    SECTrustType requiredTrustType;
1748
0
    unsigned int flags;
1749
1750
0
    PRBool lookingForCA = PR_FALSE;
1751
0
    SECStatus rv;
1752
0
    CERTCertListNode *node;
1753
0
    CERTCertificate *saveUntrustedCA = NULL;
1754
1755
    /* if preferTrusted is set, must be a CA cert */
1756
0
    PORT_Assert(!(preferTrusted && (owner != certOwnerCA)));
1757
1758
0
    if (owner == certOwnerCA) {
1759
0
        lookingForCA = PR_TRUE;
1760
0
        if (preferTrusted) {
1761
0
            rv = CERT_TrustFlagsForCACertUsage(usage, &requiredTrustFlags,
1762
0
                                               &requiredTrustType);
1763
0
            if (rv != SECSuccess) {
1764
0
                goto loser;
1765
0
            }
1766
0
            requiredTrustFlags |= CERTDB_VALID_CA;
1767
0
        }
1768
0
    }
1769
1770
0
    certList = CERT_CreateSubjectCertList(NULL, handle, derName, validTime,
1771
0
                                          validOnly);
1772
0
    if (certList != NULL) {
1773
0
        rv = CERT_FilterCertListByUsage(certList, usage, lookingForCA);
1774
0
        if (rv != SECSuccess) {
1775
0
            goto loser;
1776
0
        }
1777
1778
0
        node = CERT_LIST_HEAD(certList);
1779
1780
0
        while (!CERT_LIST_END(node, certList)) {
1781
0
            cert = node->cert;
1782
1783
            /* looking for a trusted CA cert */
1784
0
            if ((owner == certOwnerCA) && preferTrusted &&
1785
0
                (requiredTrustType != trustTypeNone)) {
1786
1787
0
                if (CERT_GetCertTrust(cert, &certTrust) != SECSuccess) {
1788
0
                    flags = 0;
1789
0
                } else {
1790
0
                    flags = SEC_GET_TRUST_FLAGS(&certTrust, requiredTrustType);
1791
0
                }
1792
1793
0
                if ((flags & requiredTrustFlags) != requiredTrustFlags) {
1794
                    /* cert is not trusted */
1795
                    /* if this is the first cert to get this far, then save
1796
                     * it, so we can use it if we can't find a trusted one
1797
                     */
1798
0
                    if (saveUntrustedCA == NULL) {
1799
0
                        saveUntrustedCA = cert;
1800
0
                    }
1801
0
                    goto endloop;
1802
0
                }
1803
0
            }
1804
            /* if we got this far, then this cert meets all criteria */
1805
0
            break;
1806
1807
0
        endloop:
1808
0
            node = CERT_LIST_NEXT(node);
1809
0
            cert = NULL;
1810
0
        }
1811
1812
        /* use the saved one if we have it */
1813
0
        if (cert == NULL) {
1814
0
            cert = saveUntrustedCA;
1815
0
        }
1816
1817
        /* if we found one then bump the ref count before freeing the list */
1818
0
        if (cert != NULL) {
1819
            /* bump the ref count */
1820
0
            cert = CERT_DupCertificate(cert);
1821
0
        }
1822
1823
0
        CERT_DestroyCertList(certList);
1824
0
    }
1825
1826
0
    return (cert);
1827
1828
0
loser:
1829
0
    if (certList != NULL) {
1830
0
        CERT_DestroyCertList(certList);
1831
0
    }
1832
1833
0
    return (NULL);
1834
0
}
1835
1836
/* [ From certdb.c ] */
1837
/*
1838
 * Filter a list of certificates, removing those certs that do not have
1839
 * one of the named CA certs somewhere in their cert chain.
1840
 *
1841
 *  "certList" - the list of certificates to filter
1842
 *  "nCANames" - number of CA names
1843
 *  "caNames" - array of CA names in string(rfc 1485) form
1844
 *  "usage" - what use the certs are for, this is used when
1845
 *      selecting CA certs
1846
 */
1847
SECStatus
1848
CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames,
1849
                             char **caNames, SECCertUsage usage)
1850
0
{
1851
0
    CERTCertificate *issuerCert = NULL;
1852
0
    CERTCertificate *subjectCert;
1853
0
    CERTCertListNode *node, *freenode;
1854
0
    CERTCertificate *cert;
1855
0
    int n;
1856
0
    char **names;
1857
0
    PRBool found;
1858
0
    PRTime time;
1859
1860
0
    if (nCANames <= 0) {
1861
0
        return (SECSuccess);
1862
0
    }
1863
1864
0
    time = PR_Now();
1865
1866
0
    node = CERT_LIST_HEAD(certList);
1867
1868
0
    while (!CERT_LIST_END(node, certList)) {
1869
0
        cert = node->cert;
1870
1871
0
        subjectCert = CERT_DupCertificate(cert);
1872
1873
        /* traverse the CA certs for this cert */
1874
0
        found = PR_FALSE;
1875
0
        while (subjectCert != NULL) {
1876
0
            n = nCANames;
1877
0
            names = caNames;
1878
1879
0
            if (subjectCert->issuerName != NULL) {
1880
0
                while (n > 0) {
1881
0
                    if (PORT_Strcmp(*names, subjectCert->issuerName) == 0) {
1882
0
                        found = PR_TRUE;
1883
0
                        break;
1884
0
                    }
1885
1886
0
                    n--;
1887
0
                    names++;
1888
0
                }
1889
0
            }
1890
1891
0
            if (found) {
1892
0
                break;
1893
0
            }
1894
1895
0
            issuerCert = CERT_FindCertIssuer(subjectCert, time, usage);
1896
0
            if (issuerCert == subjectCert) {
1897
0
                CERT_DestroyCertificate(issuerCert);
1898
0
                issuerCert = NULL;
1899
0
                break;
1900
0
            }
1901
0
            CERT_DestroyCertificate(subjectCert);
1902
0
            subjectCert = issuerCert;
1903
0
        }
1904
0
        CERT_DestroyCertificate(subjectCert);
1905
0
        if (!found) {
1906
            /* CA was not found, so remove this cert from the list */
1907
0
            freenode = node;
1908
0
            node = CERT_LIST_NEXT(node);
1909
0
            CERT_RemoveCertListNode(freenode);
1910
0
        } else {
1911
            /* CA was found, so leave it in the list */
1912
0
            node = CERT_LIST_NEXT(node);
1913
0
        }
1914
0
    }
1915
1916
0
    return (SECSuccess);
1917
0
}
1918
1919
/*
1920
 * Given a certificate, return a string containing the nickname, and possibly
1921
 * one of the validity strings, based on the current validity state of the
1922
 * certificate.
1923
 *
1924
 * "arena" - arena to allocate returned string from.  If NULL, then heap
1925
 *  is used.
1926
 * "cert" - the cert to get nickname from
1927
 * "expiredString" - the string to append to the nickname if the cert is
1928
 *      expired.
1929
 * "notYetGoodString" - the string to append to the nickname if the cert is
1930
 *      not yet good.
1931
 */
1932
char *
1933
CERT_GetCertNicknameWithValidity(PLArenaPool *arena, CERTCertificate *cert,
1934
                                 char *expiredString, char *notYetGoodString)
1935
0
{
1936
0
    SECCertTimeValidity validity;
1937
0
    char *nickname = NULL, *tmpstr = NULL;
1938
0
    const char *srcNickname = cert->nickname;
1939
0
    if (!srcNickname) {
1940
0
        srcNickname = "{???}";
1941
0
    }
1942
1943
0
    validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE);
1944
1945
    /* if the cert is good, then just use the nickname directly */
1946
0
    if (validity == secCertTimeValid) {
1947
0
        if (arena == NULL) {
1948
0
            nickname = PORT_Strdup(srcNickname);
1949
0
        } else {
1950
0
            nickname = PORT_ArenaStrdup(arena, srcNickname);
1951
0
        }
1952
1953
0
        if (nickname == NULL) {
1954
0
            goto loser;
1955
0
        }
1956
0
    } else {
1957
1958
        /* if the cert is not valid, then tack one of the strings on the
1959
         * end
1960
         */
1961
0
        if (validity == secCertTimeExpired) {
1962
0
            tmpstr = PR_smprintf("%s%s", srcNickname,
1963
0
                                 expiredString);
1964
0
        } else if (validity == secCertTimeNotValidYet) {
1965
            /* not yet valid */
1966
0
            tmpstr = PR_smprintf("%s%s", srcNickname,
1967
0
                                 notYetGoodString);
1968
0
        } else {
1969
            /* undetermined */
1970
0
            tmpstr = PR_smprintf("%s",
1971
0
                                 "(NULL) (Validity Unknown)");
1972
0
        }
1973
1974
0
        if (tmpstr == NULL) {
1975
0
            goto loser;
1976
0
        }
1977
1978
0
        if (arena) {
1979
            /* copy the string into the arena and free the malloc'd one */
1980
0
            nickname = PORT_ArenaStrdup(arena, tmpstr);
1981
0
            PORT_Free(tmpstr);
1982
0
        } else {
1983
0
            nickname = tmpstr;
1984
0
        }
1985
0
        if (nickname == NULL) {
1986
0
            goto loser;
1987
0
        }
1988
0
    }
1989
0
    return (nickname);
1990
1991
0
loser:
1992
0
    return (NULL);
1993
0
}
1994
1995
/*
1996
 * Collect the nicknames from all certs in a CertList.  If the cert is not
1997
 * valid, append a string to that nickname.
1998
 *
1999
 * "certList" - the list of certificates
2000
 * "expiredString" - the string to append to the nickname of any expired cert
2001
 * "notYetGoodString" - the string to append to the nickname of any cert
2002
 *      that is not yet valid
2003
 */
2004
CERTCertNicknames *
2005
CERT_NicknameStringsFromCertList(CERTCertList *certList, char *expiredString,
2006
                                 char *notYetGoodString)
2007
0
{
2008
0
    CERTCertNicknames *names;
2009
0
    PLArenaPool *arena;
2010
0
    CERTCertListNode *node;
2011
0
    char **nn;
2012
2013
    /* allocate an arena */
2014
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2015
0
    if (arena == NULL) {
2016
0
        return (NULL);
2017
0
    }
2018
2019
    /* allocate the structure */
2020
0
    names = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
2021
0
    if (names == NULL) {
2022
0
        goto loser;
2023
0
    }
2024
2025
    /* init the structure */
2026
0
    names->arena = arena;
2027
0
    names->head = NULL;
2028
0
    names->numnicknames = 0;
2029
0
    names->nicknames = NULL;
2030
0
    names->totallen = 0;
2031
2032
    /* count the certs in the list */
2033
0
    node = CERT_LIST_HEAD(certList);
2034
0
    while (!CERT_LIST_END(node, certList)) {
2035
0
        names->numnicknames++;
2036
0
        node = CERT_LIST_NEXT(node);
2037
0
    }
2038
2039
    /* allocate nicknames array */
2040
0
    names->nicknames = PORT_ArenaAlloc(arena,
2041
0
                                       sizeof(char *) * names->numnicknames);
2042
0
    if (names->nicknames == NULL) {
2043
0
        goto loser;
2044
0
    }
2045
2046
    /* just in case printf can't deal with null strings */
2047
0
    if (expiredString == NULL) {
2048
0
        expiredString = "";
2049
0
    }
2050
2051
0
    if (notYetGoodString == NULL) {
2052
0
        notYetGoodString = "";
2053
0
    }
2054
2055
    /* traverse the list of certs and collect the nicknames */
2056
0
    nn = names->nicknames;
2057
0
    node = CERT_LIST_HEAD(certList);
2058
0
    while (!CERT_LIST_END(node, certList)) {
2059
0
        *nn = CERT_GetCertNicknameWithValidity(arena, node->cert,
2060
0
                                               expiredString,
2061
0
                                               notYetGoodString);
2062
0
        if (*nn == NULL) {
2063
0
            goto loser;
2064
0
        }
2065
2066
0
        names->totallen += PORT_Strlen(*nn);
2067
2068
0
        nn++;
2069
0
        node = CERT_LIST_NEXT(node);
2070
0
    }
2071
2072
0
    return (names);
2073
2074
0
loser:
2075
0
    PORT_FreeArena(arena, PR_FALSE);
2076
0
    return (NULL);
2077
0
}
2078
2079
/*
2080
 * Extract the nickname from a nickmake string that may have either
2081
 * expiredString or notYetGoodString appended.
2082
 *
2083
 * Args:
2084
 *  "namestring" - the string containing the nickname, and possibly
2085
 *      one of the validity label strings
2086
 *  "expiredString" - the expired validity label string
2087
 *  "notYetGoodString" - the not yet good validity label string
2088
 *
2089
 * Returns the raw nickname
2090
 */
2091
char *
2092
CERT_ExtractNicknameString(char *namestring, char *expiredString,
2093
                           char *notYetGoodString)
2094
0
{
2095
0
    int explen, nyglen, namelen;
2096
0
    int retlen;
2097
0
    char *retstr;
2098
2099
0
    namelen = PORT_Strlen(namestring);
2100
0
    explen = PORT_Strlen(expiredString);
2101
0
    nyglen = PORT_Strlen(notYetGoodString);
2102
2103
0
    if (namelen > explen) {
2104
0
        if (PORT_Strcmp(expiredString, &namestring[namelen - explen]) == 0) {
2105
0
            retlen = namelen - explen;
2106
0
            retstr = (char *)PORT_Alloc(retlen + 1);
2107
0
            if (retstr == NULL) {
2108
0
                goto loser;
2109
0
            }
2110
2111
0
            PORT_Memcpy(retstr, namestring, retlen);
2112
0
            retstr[retlen] = '\0';
2113
0
            goto done;
2114
0
        }
2115
0
    }
2116
2117
0
    if (namelen > nyglen) {
2118
0
        if (PORT_Strcmp(notYetGoodString, &namestring[namelen - nyglen]) == 0) {
2119
0
            retlen = namelen - nyglen;
2120
0
            retstr = (char *)PORT_Alloc(retlen + 1);
2121
0
            if (retstr == NULL) {
2122
0
                goto loser;
2123
0
            }
2124
2125
0
            PORT_Memcpy(retstr, namestring, retlen);
2126
0
            retstr[retlen] = '\0';
2127
0
            goto done;
2128
0
        }
2129
0
    }
2130
2131
    /* if name string is shorter than either invalid string, then it must
2132
     * be a raw nickname
2133
     */
2134
0
    retstr = PORT_Strdup(namestring);
2135
2136
0
done:
2137
0
    return (retstr);
2138
2139
0
loser:
2140
0
    return (NULL);
2141
0
}
2142
2143
CERTCertList *
2144
CERT_GetCertChainFromCert(CERTCertificate *cert, PRTime time, SECCertUsage usage)
2145
4.66k
{
2146
4.66k
    CERTCertList *chain = NULL;
2147
4.66k
    int count = 0;
2148
2149
4.66k
    if (NULL == cert) {
2150
0
        return NULL;
2151
0
    }
2152
2153
4.66k
    cert = CERT_DupCertificate(cert);
2154
4.66k
    if (NULL == cert) {
2155
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
2156
0
        return NULL;
2157
0
    }
2158
2159
4.66k
    chain = CERT_NewCertList();
2160
4.66k
    if (NULL == chain) {
2161
0
        CERT_DestroyCertificate(cert);
2162
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
2163
0
        return NULL;
2164
0
    }
2165
2166
7.26k
    while (cert != NULL && ++count <= CERT_MAX_CERT_CHAIN) {
2167
5.90k
        if (SECSuccess != CERT_AddCertToListTail(chain, cert)) {
2168
            /* return partial chain */
2169
0
            CERT_DestroyCertificate(cert);
2170
0
            PORT_SetError(SEC_ERROR_NO_MEMORY);
2171
0
            return chain;
2172
0
        }
2173
2174
5.90k
        if (cert->isRoot) {
2175
            /* return complete chain */
2176
3.30k
            return chain;
2177
3.30k
        }
2178
2179
2.60k
        cert = CERT_FindCertIssuer(cert, time, usage);
2180
2.60k
    }
2181
2182
    /* return partial chain */
2183
1.36k
    CERT_DestroyCertificate(cert);
2184
1.36k
    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
2185
1.36k
    return chain;
2186
4.66k
}