Coverage Report

Created: 2026-08-18 06:34

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
5.20k
{
43
5.20k
    SECStatus rv;
44
5.20k
    SECOidTag sigAlg;
45
5.20k
    SECOidTag curve;
46
5.20k
    PRUint32 policyFlags = 0;
47
5.20k
    PRInt32 minLen, len, optFlags;
48
49
5.20k
    sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm);
50
51
5.20k
    switch (sigAlg) {
52
0
        case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
53
5
        case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
54
1.10k
        case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
55
1.15k
        case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
56
1.15k
        case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
57
1.15k
            if (key->keyType != ecKey) {
58
0
                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
59
0
                return SECFailure;
60
0
            }
61
62
1.15k
            curve = SECKEY_GetECCOid(&key->u.ec.DEREncodedParams);
63
1.15k
            if (curve != 0) {
64
1.13k
                if (NSS_GetAlgorithmPolicy(curve, &policyFlags) == SECFailure ||
65
1.13k
                    !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
66
1
                    PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
67
1
                    return SECFailure;
68
1
                }
69
1.13k
                return SECSuccess;
70
1.13k
            }
71
25
            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
72
25
            return SECFailure;
73
74
490
        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: {
75
490
            PORTCheapArenaPool tmpArena;
76
490
            SECOidTag hashAlg;
77
490
            SECOidTag maskHashAlg;
78
79
490
            PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
80
490
            rv = sec_DecodeRSAPSSParams(&tmpArena.arena,
81
490
                                        &sigAlgorithm->parameters,
82
490
                                        &hashAlg, &maskHashAlg, NULL);
83
490
            PORT_DestroyCheapArena(&tmpArena);
84
490
            if (rv != SECSuccess) {
85
0
                return SECFailure;
86
0
            }
87
88
490
            if (NSS_GetAlgorithmPolicy(hashAlg, &policyFlags) == SECSuccess &&
89
490
                !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
90
0
                PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
91
0
                return SECFailure;
92
0
            }
93
490
            if (NSS_GetAlgorithmPolicy(maskHashAlg, &policyFlags) == SECSuccess &&
94
490
                !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
95
0
                PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
96
0
                return SECFailure;
97
0
            }
98
490
        }
99
        /* fall through to RSA key checking */
100
490
        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
101
492
        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
102
3.17k
        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
103
3.17k
        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
104
3.18k
        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
105
3.18k
        case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
106
3.18k
        case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
107
3.18k
            if (key->keyType != rsaKey && key->keyType != rsaPssKey) {
108
1
                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
109
1
                return SECFailure;
110
1
            }
111
112
3.18k
            if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) == SECFailure) {
113
0
                return SECSuccess;
114
0
            }
115
3.18k
            if ((optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) == 0) {
116
0
                return SECSuccess;
117
0
            }
118
119
3.18k
            len = 8 * key->u.rsa.modulus.len;
120
121
3.18k
            rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minLen);
122
3.18k
            if (rv != SECSuccess) {
123
0
                return SECFailure;
124
0
            }
125
126
3.18k
            if (len < minLen) {
127
4
                return SECFailure;
128
4
            }
129
130
3.17k
            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
3
        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
136
854
        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
137
854
            if (key->keyType != dsaKey) {
138
1
                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
139
1
                return SECFailure;
140
1
            }
141
853
            if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) == SECFailure) {
142
0
                return SECSuccess;
143
0
            }
144
853
            if ((optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) == 0) {
145
0
                return SECSuccess;
146
0
            }
147
148
853
            len = 8 * key->u.dsa.params.prime.len;
149
150
853
            rv = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minLen);
151
853
            if (rv != SECSuccess) {
152
0
                return SECFailure;
153
0
            }
154
155
853
            if (len < minLen) {
156
2
                return SECFailure;
157
2
            }
158
159
851
            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
13
        default:
172
13
            return SECSuccess;
173
5.20k
    }
174
5.20k
}
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
5.28k
{
184
5.28k
    SECStatus rv;
185
5.28k
    SECItem sig;
186
5.28k
    SECOidTag sigAlg;
187
5.28k
    SECOidTag encAlg;
188
5.28k
    SECOidTag hashAlg;
189
5.28k
    CK_MECHANISM_TYPE mech;
190
5.28k
    PRUint32 policyFlags;
191
192
5.28k
    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
5.28k
    sigAlg = SECOID_GetAlgorithmTag(&sd->signatureAlgorithm);
199
5.28k
    rv = sec_DecodeSigAlg(pubKey, sigAlg,
200
5.28k
                          &sd->signatureAlgorithm.parameters,
201
5.28k
                          &encAlg, &hashAlg, &mech, NULL);
202
5.28k
    if (rv != SECSuccess) {
203
52
        return SECFailure; /* error is set */
204
52
    }
205
5.22k
    rv = NSS_GetAlgorithmPolicy(encAlg, &policyFlags);
206
5.22k
    if (rv == SECSuccess &&
207
5.22k
        !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
208
0
        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
209
0
        return SECFailure;
210
0
    }
211
5.22k
    rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags);
212
5.22k
    if (rv == SECSuccess &&
213
5.22k
        !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
214
22
        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
215
22
        return SECFailure;
216
22
    }
217
5.20k
    rv = checkKeyParams(&sd->signatureAlgorithm, pubKey);
218
5.20k
    if (rv != SECSuccess) {
219
36
        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
220
36
        return SECFailure;
221
36
    }
222
223
    /* check the signature */
224
5.17k
    sig = sd->signature;
225
    /* convert sig->len from bit counts to byte count. */
226
5.17k
    DER_ConvertBitString(&sig);
227
228
5.17k
    rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey,
229
5.17k
                                       &sig, &sd->signatureAlgorithm,
230
5.17k
                                       &hashAlg, wincx);
231
5.17k
    if (rv != SECSuccess) {
232
4.92k
        return SECFailure; /* error is set */
233
4.92k
    }
234
235
    /* for some algorithms, hash algorithm is only known after verification */
236
249
    rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags);
237
249
    if (rv == SECSuccess &&
238
249
        !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
239
0
        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
240
0
        return SECFailure;
241
0
    }
242
249
    return SECSuccess;
243
249
}
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
7.18k
{
272
7.18k
    SECKEYPublicKey *pubKey = 0;
273
7.18k
    SECStatus rv = SECFailure;
274
7.18k
    SECCertTimeValidity validity;
275
276
    /* check the certificate's validity */
277
7.18k
    validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE);
278
7.18k
    if (validity != secCertTimeValid) {
279
1.68k
        return rv;
280
1.68k
    }
281
282
    /* get cert's public key */
283
5.50k
    pubKey = CERT_ExtractPublicKey(cert);
284
5.50k
    if (pubKey) {
285
5.28k
        rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx);
286
5.28k
        SECKEY_DestroyPublicKey(pubKey);
287
5.28k
    }
288
5.50k
    return rv;
289
7.18k
}
290
291
SECStatus
292
SEC_CheckCRL(CERTCertDBHandle *handle, CERTCertificate *cert,
293
             CERTCertificate *caCert, PRTime t, void *wincx)
294
7.15k
{
295
7.15k
    return CERT_CheckCRL(cert, caCert, NULL, t, wincx);
296
7.15k
}
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
15.7k
{
304
15.7k
    NSSCertificate *me;
305
15.7k
    NSSTime *nssTime;
306
15.7k
    NSSTrustDomain *td;
307
15.7k
    NSSCryptoContext *cc;
308
15.7k
    NSSCertificate *chain[3];
309
15.7k
    NSSUsage nssUsage;
310
15.7k
    PRStatus status;
311
312
15.7k
    me = STAN_GetNSSCertificate(cert);
313
15.7k
    if (!me) {
314
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
315
0
        return NULL;
316
0
    }
317
15.7k
    nssTime = NSSTime_SetPRTime(NULL, validTime);
318
15.7k
    nssUsage.anyUsage = PR_FALSE;
319
15.7k
    nssUsage.nss3usage = usage;
320
15.7k
    nssUsage.nss3lookingForCA = PR_TRUE;
321
15.7k
    memset(chain, 0, 3 * sizeof(NSSCertificate *));
322
15.7k
    td = STAN_GetDefaultTrustDomain();
323
15.7k
    cc = STAN_GetDefaultCryptoContext();
324
15.7k
    (void)NSSCertificate_BuildChain(me, nssTime, &nssUsage, NULL,
325
15.7k
                                    chain, 2, NULL, &status, td, cc);
326
15.7k
    nss_ZFreeIf(nssTime);
327
15.7k
    if (status == PR_SUCCESS) {
328
12.4k
        PORT_Assert(me == chain[0]);
329
        /* if it's a root, the chain will only have one cert */
330
12.4k
        if (!chain[1]) {
331
            /* already has a reference from the call to BuildChain */
332
2.78k
            return cert;
333
2.78k
        }
334
9.66k
        NSSCertificate_Destroy(chain[0]);         /* the first cert in the chain */
335
9.66k
        return STAN_GetCERTCertificate(chain[1]); /* return the 2nd */
336
12.4k
    }
337
3.26k
    if (chain[0]) {
338
3.26k
        PORT_Assert(me == chain[0]);
339
3.26k
        NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */
340
3.26k
    }
341
3.26k
    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
342
3.26k
    return NULL;
343
15.7k
}
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
8.30k
{
353
8.30k
    unsigned int requiredFlags;
354
8.30k
    SECTrustType trustType;
355
356
8.30k
    switch (usage) {
357
3.94k
        case certUsageSSLClient:
358
3.94k
            requiredFlags = CERTDB_TRUSTED_CLIENT_CA;
359
3.94k
            trustType = trustSSL;
360
3.94k
            break;
361
396
        case certUsageSSLServer:
362
749
        case certUsageSSLCA:
363
749
            requiredFlags = CERTDB_TRUSTED_CA;
364
749
            trustType = trustSSL;
365
749
            break;
366
1.51k
        case certUsageIPsec:
367
1.51k
            requiredFlags = CERTDB_TRUSTED_CA;
368
1.51k
            trustType = trustSSL;
369
1.51k
            break;
370
16
        case certUsageSSLServerWithStepUp:
371
16
            requiredFlags = CERTDB_TRUSTED_CA | CERTDB_GOVT_APPROVED_CA;
372
16
            trustType = trustSSL;
373
16
            break;
374
1.47k
        case certUsageEmailSigner:
375
1.81k
        case certUsageEmailRecipient:
376
1.81k
            requiredFlags = CERTDB_TRUSTED_CA;
377
1.81k
            trustType = trustEmail;
378
1.81k
            break;
379
44
        case certUsageObjectSigner:
380
44
            requiredFlags = CERTDB_TRUSTED_CA;
381
44
            trustType = trustObjectSigning;
382
44
            break;
383
0
        case certUsageVerifyCA:
384
0
        case certUsageAnyCA:
385
213
        case certUsageStatusResponder:
386
213
            requiredFlags = CERTDB_TRUSTED_CA;
387
213
            trustType = trustTypeNone;
388
213
            break;
389
0
        default:
390
0
            PORT_Assert(0);
391
0
            goto loser;
392
8.30k
    }
393
8.30k
    if (retFlags != NULL) {
394
8.30k
        *retFlags = requiredFlags;
395
8.30k
    }
396
8.30k
    if (retTrustType != NULL) {
397
8.30k
        *retTrustType = trustType;
398
8.30k
    }
399
400
8.30k
    return (SECSuccess);
401
0
loser:
402
0
    return (SECFailure);
403
8.30k
}
404
405
void
406
cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, long error,
407
                    unsigned int depth, void *arg)
408
44.8k
{
409
44.8k
    CERTVerifyLogNode *node, *tnode;
410
411
44.8k
    PORT_Assert(log != NULL);
412
413
44.8k
    node = (CERTVerifyLogNode *)PORT_ArenaAlloc(log->arena,
414
44.8k
                                                sizeof(CERTVerifyLogNode));
415
44.8k
    if (node != NULL) {
416
44.8k
        node->cert = CERT_DupCertificate(cert);
417
44.8k
        node->error = error;
418
44.8k
        node->depth = depth;
419
44.8k
        node->arg = arg;
420
421
44.8k
        if (log->tail == NULL) {
422
            /* empty list */
423
4.36k
            log->head = log->tail = node;
424
4.36k
            node->prev = NULL;
425
4.36k
            node->next = NULL;
426
40.4k
        } else if (depth >= log->tail->depth) {
427
            /* add to tail */
428
29.2k
            node->prev = log->tail;
429
29.2k
            log->tail->next = node;
430
29.2k
            log->tail = node;
431
29.2k
            node->next = NULL;
432
29.2k
        } else if (depth < log->head->depth) {
433
            /* add at head */
434
30
            node->prev = NULL;
435
30
            node->next = log->head;
436
30
            log->head->prev = node;
437
30
            log->head = node;
438
11.1k
        } else {
439
            /* add in middle */
440
11.1k
            tnode = log->tail;
441
68.4k
            while (tnode != NULL) {
442
68.4k
                if (depth >= tnode->depth) {
443
                    /* insert after tnode */
444
11.1k
                    node->prev = tnode;
445
11.1k
                    node->next = tnode->next;
446
11.1k
                    tnode->next->prev = node;
447
11.1k
                    tnode->next = node;
448
11.1k
                    break;
449
11.1k
                }
450
451
57.2k
                tnode = tnode->prev;
452
57.2k
            }
453
11.1k
        }
454
455
44.8k
        log->count++;
456
44.8k
    }
457
44.8k
    return;
458
44.8k
}
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
16.9k
    if (log != NULL) {                                         \
467
16.9k
        cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
468
16.9k
                            (void *)(PRWord)arg);              \
469
16.9k
    } else {                                                   \
470
0
        goto loser;                                            \
471
0
    }
472
473
#define LOG_ERROR(log, cert, depth, arg)                       \
474
27.8k
    if (log != NULL) {                                         \
475
27.8k
        cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
476
27.8k
                            (void *)(PRWord)arg);              \
477
27.8k
    }
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
7.15k
{
573
7.15k
    int i;
574
7.15k
    const struct DataAndLength *dn = StartComAndWoSignDNs;
575
576
50.0k
    for (i = 0; i < sizeof(StartComAndWoSignDNs) / sizeof(struct DataAndLength); ++i, dn++) {
577
42.9k
        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
42.9k
    }
582
7.15k
    return PR_FALSE;
583
7.15k
}
584
585
SECStatus
586
isIssuerCertAllowedAtCertIssuanceTime(CERTCertificate *issuerCert,
587
                                      CERTCertificate *referenceCert)
588
7.15k
{
589
7.15k
    if (!issuerCert || !referenceCert) {
590
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
591
0
        return SECFailure;
592
0
    }
593
594
7.15k
    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
7.15k
    return SECSuccess;
613
7.15k
}
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
8.30k
{
621
8.30k
    SECTrustType trustType;
622
8.30k
    CERTBasicConstraints basicConstraint;
623
8.30k
    CERTCertificate *issuerCert = NULL;
624
8.30k
    CERTCertificate *subjectCert = NULL;
625
8.30k
    CERTCertificate *badCert = NULL;
626
8.30k
    PRBool isca;
627
8.30k
    SECStatus rv;
628
8.30k
    SECStatus rvFinal = SECSuccess;
629
8.30k
    int count;
630
8.30k
    int currentPathLen = 0;
631
8.30k
    int pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT;
632
8.30k
    unsigned int caCertType;
633
8.30k
    unsigned int requiredCAKeyUsage;
634
8.30k
    unsigned int requiredFlags;
635
8.30k
    PLArenaPool *arena = NULL;
636
8.30k
    CERTGeneralName *namesList = NULL;
637
8.30k
    CERTCertificate **certsList = NULL;
638
8.30k
    int certsListLen = 16;
639
8.30k
    int namesCount = 0;
640
8.30k
    PRBool subjectCertIsSelfIssued;
641
8.30k
    CERTCertTrust issuerTrust;
642
643
8.30k
    if (revoked) {
644
8.30k
        *revoked = PR_FALSE;
645
8.30k
    }
646
647
8.30k
    if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE,
648
8.30k
                                         &requiredCAKeyUsage,
649
8.30k
                                         &caCertType) !=
650
8.30k
        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
8.30k
    switch (certUsage) {
658
3.94k
        case certUsageSSLClient:
659
4.34k
        case certUsageSSLServer:
660
5.86k
        case certUsageIPsec:
661
6.21k
        case certUsageSSLCA:
662
6.23k
        case certUsageSSLServerWithStepUp:
663
7.70k
        case certUsageEmailSigner:
664
8.04k
        case certUsageEmailRecipient:
665
8.08k
        case certUsageObjectSigner:
666
8.08k
        case certUsageVerifyCA:
667
8.08k
        case certUsageAnyCA:
668
8.30k
        case certUsageStatusResponder:
669
8.30k
            if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
670
8.30k
                                              &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
8.30k
            break;
686
8.30k
        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
8.30k
    }
695
696
8.30k
    subjectCert = CERT_DupCertificate(cert);
697
8.30k
    if (subjectCert == NULL) {
698
0
        goto loser;
699
0
    }
700
701
8.30k
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
702
8.30k
    if (arena == NULL) {
703
0
        goto loser;
704
0
    }
705
706
8.30k
    certsList = PORT_ZNewArray(CERTCertificate *, certsListLen);
707
8.30k
    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
8.30k
    subjectCertIsSelfIssued = PR_FALSE;
715
12.7k
    for (count = 0; count < CERT_MAX_CERT_CHAIN; count++) {
716
12.4k
        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
12.4k
        if (subjectCertIsSelfIssued == PR_FALSE) {
724
8.30k
            CERTGeneralName *subjectNameList;
725
8.30k
            int subjectNameListLen;
726
8.30k
            int i;
727
8.30k
            PRBool getSubjectCN = (!count &&
728
8.30k
                                   (certUsage == certUsageSSLServer || certUsage == certUsageIPsec));
729
8.30k
            subjectNameList =
730
8.30k
                CERT_GetConstrainedCertificateNames(subjectCert, arena,
731
8.30k
                                                    getSubjectCN);
732
8.30k
            if (!subjectNameList)
733
104
                goto loser;
734
8.19k
            subjectNameListLen = CERT_GetNamesLength(subjectNameList);
735
8.19k
            if (!subjectNameListLen)
736
0
                goto loser;
737
8.19k
            if (certsListLen <= namesCount + subjectNameListLen) {
738
335
                CERTCertificate **tmpCertsList;
739
335
                certsListLen = (namesCount + subjectNameListLen) * 2;
740
335
                tmpCertsList =
741
335
                    (CERTCertificate **)PORT_Realloc(certsList,
742
335
                                                     certsListLen *
743
335
                                                         sizeof(CERTCertificate *));
744
335
                if (tmpCertsList == NULL) {
745
0
                    goto loser;
746
0
                }
747
335
                certsList = tmpCertsList;
748
335
            }
749
37.7k
            for (i = 0; i < subjectNameListLen; i++) {
750
29.5k
                certsList[namesCount + i] = CERT_DupCertificate(subjectCert);
751
29.5k
            }
752
8.19k
            namesCount += subjectNameListLen;
753
8.19k
            namesList = cert_CombineNamesLists(namesList, subjectNameList);
754
8.19k
        }
755
756
        /* check if the cert has an unsupported critical extension */
757
12.3k
        if (subjectCert->options.bits.hasUnsupportedCriticalExt) {
758
400
            PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
759
400
            LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
760
400
        }
761
762
        /* check that the signatureAlgorithm field of the certificate
763
         * matches the signature field of the tbsCertificate */
764
12.3k
        if (SECOID_CompareAlgorithmID(
765
12.3k
                &subjectCert->signatureWrap.signatureAlgorithm,
766
12.3k
                &subjectCert->signature)) {
767
3.21k
            PORT_SetError(SEC_ERROR_ALGORITHM_MISMATCH);
768
3.21k
            LOG_ERROR(log, subjectCert, count, 0);
769
3.21k
            goto loser;
770
3.21k
        }
771
772
        /* find the certificate of the issuer */
773
9.16k
        issuerCert = CERT_FindCertIssuer(subjectCert, t, certUsage);
774
9.16k
        if (!issuerCert) {
775
1.97k
            PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
776
1.97k
            LOG_ERROR(log, subjectCert, count, 0);
777
1.97k
            goto loser;
778
1.97k
        }
779
780
        /* verify the signature on the cert */
781
7.18k
        if (checkSig) {
782
7.18k
            rv = CERT_VerifySignedData(&subjectCert->signatureWrap,
783
7.18k
                                       issuerCert, t, wincx);
784
785
7.18k
            if (rv != SECSuccess) {
786
6.93k
                if (sigerror) {
787
6.93k
                    *sigerror = PR_TRUE;
788
6.93k
                }
789
6.93k
                if (PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE) {
790
349
                    PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE);
791
349
                    LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
792
6.58k
                } else {
793
6.58k
                    if (PORT_GetError() !=
794
6.58k
                        SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) {
795
6.53k
                        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
796
6.53k
                    }
797
6.58k
                    LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
798
6.58k
                }
799
6.93k
            }
800
7.18k
        }
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
7.18k
        rv = CERT_FindBasicConstraintExten(issuerCert, &basicConstraint);
812
7.18k
        if (rv != SECSuccess) {
813
6.45k
            if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
814
2.50k
                LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
815
2.50k
            }
816
6.45k
            pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT;
817
            /* no basic constraints found, we aren't (yet) a CA. */
818
6.45k
            isca = PR_FALSE;
819
6.45k
        } else {
820
734
            if (basicConstraint.isCA == PR_FALSE) {
821
346
                PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
822
346
                LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
823
346
            }
824
734
            pathLengthLimit = basicConstraint.pathLenConstraint;
825
734
            isca = PR_TRUE;
826
734
        }
827
        /* make sure that the path len constraint is properly set.*/
828
7.18k
        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
7.18k
        rv = CERT_CompareNameSpace(issuerCert, namesList, certsList,
837
7.18k
                                   arena, &badCert);
838
7.18k
        if (rv != SECSuccess || badCert != NULL) {
839
36
            PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE);
840
36
            LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0);
841
36
            goto loser;
842
36
        }
843
844
7.15k
        rv = isIssuerCertAllowedAtCertIssuanceTime(issuerCert, cert);
845
7.15k
        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
7.15k
        rv = SEC_CheckCRL(handle, subjectCert, issuerCert, t, wincx);
856
7.15k
        if (rv == SECFailure) {
857
1.67k
            if (revoked) {
858
1.67k
                *revoked = PR_TRUE;
859
1.67k
            }
860
1.67k
            LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
861
5.48k
        } 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
7.15k
        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
7.15k
        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
7.15k
            if (!isca || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) {
957
6.81k
                isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE;
958
6.81k
            }
959
960
7.15k
            if (!isca) {
961
2.99k
                PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
962
2.99k
                LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
963
2.99k
            }
964
965
            /* make sure key usage allows cert signing */
966
7.15k
            if (CERT_CheckKeyUsage(issuerCert, requiredCAKeyUsage) != SECSuccess) {
967
344
                PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
968
344
                LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, requiredCAKeyUsage);
969
344
            }
970
7.15k
        }
971
972
        /* make sure that the issuer is not self signed.  If it is, then
973
         * stop here to prevent looping.
974
         */
975
7.15k
        if (issuerCert->isRoot) {
976
2.75k
            PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
977
2.75k
            LOG_ERROR(log, issuerCert, count + 1, 0);
978
2.75k
            goto loser;
979
2.75k
        }
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
4.40k
        subjectCertIsSelfIssued = (PRBool)
985
4.40k
                                      SECITEM_ItemsAreEqual(&issuerCert->derIssuer,
986
4.40k
                                                            &issuerCert->derSubject) &&
987
4.40k
                                  issuerCert->derSubject.len >
988
4.40k
                                      0;
989
4.40k
        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
4.40k
        CERT_DestroyCertificate(subjectCert);
997
4.40k
        subjectCert = issuerCert;
998
4.40k
        issuerCert = NULL;
999
4.40k
    }
1000
1001
220
    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
1002
220
    LOG_ERROR(log, subjectCert, count, 0);
1003
8.30k
loser:
1004
8.30k
    rv = SECFailure;
1005
8.30k
done:
1006
8.30k
    if (certsList != NULL) {
1007
37.8k
        for (int i = 0; i < namesCount; i++) {
1008
29.5k
            if (certsList[i]) {
1009
29.5k
                CERT_DestroyCertificate(certsList[i]);
1010
29.5k
            }
1011
29.5k
        }
1012
8.30k
        PORT_Free(certsList);
1013
8.30k
    }
1014
8.30k
    if (issuerCert) {
1015
2.78k
        CERT_DestroyCertificate(issuerCert);
1016
2.78k
    }
1017
1018
8.30k
    if (subjectCert) {
1019
8.30k
        CERT_DestroyCertificate(subjectCert);
1020
8.30k
    }
1021
1022
8.30k
    if (arena != NULL) {
1023
8.30k
        PORT_FreeArena(arena, PR_FALSE);
1024
8.30k
    }
1025
8.30k
    return rv;
1026
8.30k
}
1027
1028
SECStatus
1029
cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
1030
                     PRBool checkSig, PRBool *sigerror,
1031
                     SECCertUsage certUsage, PRTime t, void *wincx,
1032
                     CERTVerifyLog *log, PRBool *revoked)
1033
8.30k
{
1034
8.30k
    if (CERT_GetUsePKIXForValidation()) {
1035
0
        return cert_VerifyCertChainPkix(cert, checkSig, certUsage, t,
1036
0
                                        wincx, log, sigerror, revoked);
1037
0
    }
1038
8.30k
    return cert_VerifyCertChainOld(handle, cert, checkSig, sigerror,
1039
8.30k
                                   certUsage, t, wincx, log, revoked);
1040
8.30k
}
1041
1042
SECStatus
1043
CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
1044
                     PRBool checkSig, SECCertUsage certUsage, PRTime t,
1045
                     void *wincx, CERTVerifyLog *log)
1046
0
{
1047
0
    return cert_VerifyCertChain(handle, cert, checkSig, NULL, certUsage, t,
1048
0
                                wincx, log, NULL);
1049
0
}
1050
1051
/*
1052
 * verify that a CA can sign a certificate with the requested usage.
1053
 */
1054
SECStatus
1055
CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, CERTCertificate *cert,
1056
                          PRBool checkSig, SECCertUsage certUsage, PRTime t,
1057
                          void *wincx, CERTVerifyLog *log)
1058
0
{
1059
0
    SECTrustType trustType;
1060
0
    CERTBasicConstraints basicConstraint;
1061
0
    PRBool isca;
1062
0
    PRBool validCAOverride = PR_FALSE;
1063
0
    SECStatus rv;
1064
0
    SECStatus rvFinal = SECSuccess;
1065
0
    unsigned int flags;
1066
0
    unsigned int caCertType;
1067
0
    unsigned int requiredCAKeyUsage;
1068
0
    unsigned int requiredFlags;
1069
0
    CERTCertificate *issuerCert;
1070
0
    CERTCertTrust certTrust;
1071
1072
0
    if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE,
1073
0
                                         &requiredCAKeyUsage,
1074
0
                                         &caCertType) != SECSuccess) {
1075
0
        PORT_Assert(0);
1076
0
        EXIT_IF_NOT_LOGGING(log);
1077
0
        requiredCAKeyUsage = 0;
1078
0
        caCertType = 0;
1079
0
    }
1080
1081
0
    switch (certUsage) {
1082
0
        case certUsageSSLClient:
1083
0
        case certUsageSSLServer:
1084
0
        case certUsageIPsec:
1085
0
        case certUsageSSLCA:
1086
0
        case certUsageSSLServerWithStepUp:
1087
0
        case certUsageEmailSigner:
1088
0
        case certUsageEmailRecipient:
1089
0
        case certUsageObjectSigner:
1090
0
        case certUsageVerifyCA:
1091
0
        case certUsageStatusResponder:
1092
0
            if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
1093
0
                                              &trustType) != SECSuccess) {
1094
0
                PORT_Assert(0);
1095
0
                EXIT_IF_NOT_LOGGING(log);
1096
0
                requiredFlags = 0;
1097
0
                trustType = trustSSL;
1098
0
            }
1099
0
            break;
1100
0
        default:
1101
0
            PORT_Assert(0);
1102
0
            EXIT_IF_NOT_LOGGING(log);
1103
0
            requiredFlags = 0;
1104
0
            trustType = trustSSL; /* This used to be 0, but we need something
1105
                                   * that matches the enumeration type.
1106
                                   */
1107
0
            caCertType = 0;
1108
0
    }
1109
1110
    /* If the basicConstraint extension is included in an intermmediate CA
1111
     * certificate, make sure that the isCA flag is on.  If the
1112
     * pathLenConstraint component exists, it must be greater than the
1113
     * number of CA certificates we have seen so far.  If the extension
1114
     * is omitted, we will assume that this is a CA certificate with
1115
     * an unlimited pathLenConstraint (since it already passes the
1116
     * netscape-cert-type extension checking).
1117
     */
1118
1119
0
    rv = CERT_FindBasicConstraintExten(cert, &basicConstraint);
1120
0
    if (rv != SECSuccess) {
1121
0
        if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
1122
0
            LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1123
0
        }
1124
        /* no basic constraints found, we aren't (yet) a CA. */
1125
0
        isca = PR_FALSE;
1126
0
    } else {
1127
0
        if (basicConstraint.isCA == PR_FALSE) {
1128
0
            PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
1129
0
            LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1130
0
        }
1131
1132
        /* can't check path length if we don't know the previous path */
1133
0
        isca = PR_TRUE;
1134
0
    }
1135
1136
0
    if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) {
1137
        /* we have some trust info, but this does NOT imply that this
1138
         * cert is actually trusted for any purpose.  The cert may be
1139
         * explicitly UNtrusted.  We won't know until we examine the
1140
         * trust bits.
1141
         */
1142
0
        if (certUsage == certUsageStatusResponder) {
1143
            /* Check the special case of certUsageStatusResponder */
1144
0
            issuerCert = CERT_FindCertIssuer(cert, t, certUsage);
1145
0
            if (issuerCert) {
1146
0
                if (SEC_CheckCRL(handle, cert, issuerCert, t, wincx) !=
1147
0
                    SECSuccess) {
1148
0
                    PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
1149
0
                    CERT_DestroyCertificate(issuerCert);
1150
0
                    goto loser;
1151
0
                }
1152
0
                CERT_DestroyCertificate(issuerCert);
1153
0
            }
1154
            /* XXX We have NOT determined that this cert is trusted.
1155
             * For years, NSS has treated this as trusted,
1156
             * but it seems incorrect.
1157
             */
1158
0
            rv = rvFinal;
1159
0
            goto done;
1160
0
        }
1161
1162
        /*
1163
         * check the trust params of the issuer
1164
         */
1165
0
        flags = SEC_GET_TRUST_FLAGS(&certTrust, trustType);
1166
0
        if ((flags & requiredFlags) == requiredFlags) {
1167
            /* we found a trusted one, so return */
1168
0
            rv = rvFinal;
1169
0
            goto done;
1170
0
        }
1171
0
        if (flags & CERTDB_VALID_CA) {
1172
0
            validCAOverride = PR_TRUE;
1173
0
        }
1174
        /* is it explicitly distrusted? */
1175
0
        if ((flags & CERTDB_TERMINAL_RECORD) &&
1176
0
            ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
1177
            /* untrusted -- the cert is explicitly untrusted, not
1178
             * just that it doesn't chain to a trusted cert */
1179
0
            PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
1180
0
            LOG_ERROR_OR_EXIT(log, cert, 0, flags);
1181
0
        }
1182
0
    }
1183
0
    if (!validCAOverride) {
1184
        /*
1185
         * Make sure that if this is an intermediate CA in the chain that
1186
         * it was given permission by its signer to be a CA.
1187
         */
1188
        /*
1189
         * if basicConstraints says it is a ca, then we check the
1190
         * nsCertType.  If the nsCertType has any CA bits set, then
1191
         * it must have the right one.
1192
         */
1193
0
        if (!isca || (cert->nsCertType & NS_CERT_TYPE_CA)) {
1194
0
            isca = (cert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE;
1195
0
        }
1196
1197
0
        if (!isca) {
1198
0
            PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
1199
0
            LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1200
0
        }
1201
1202
        /* make sure key usage allows cert signing */
1203
0
        if (CERT_CheckKeyUsage(cert, requiredCAKeyUsage) != SECSuccess) {
1204
0
            PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
1205
0
            LOG_ERROR_OR_EXIT(log, cert, 0, requiredCAKeyUsage);
1206
0
        }
1207
0
    }
1208
    /* make sure that the issuer is not self signed.  If it is, then
1209
     * stop here to prevent looping.
1210
     */
1211
0
    if (cert->isRoot) {
1212
0
        PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
1213
0
        LOG_ERROR(log, cert, 0, 0);
1214
0
        goto loser;
1215
0
    }
1216
1217
0
    return CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t,
1218
0
                                wincx, log);
1219
0
loser:
1220
0
    rv = SECFailure;
1221
0
done:
1222
0
    return rv;
1223
0
}
1224
1225
#define NEXT_USAGE() \
1226
17.4k
    {                \
1227
17.4k
        i *= 2;      \
1228
17.4k
        certUsage++; \
1229
17.4k
        continue;    \
1230
56.6k
    }
1231
1232
#define VALID_USAGE() \
1233
0
    {                 \
1234
0
        NEXT_USAGE(); \
1235
0
    }
1236
1237
#define INVALID_USAGE()                 \
1238
0
    {                                   \
1239
39.2k
        if (returnedUsages) {           \
1240
39.2k
            *returnedUsages &= (~i);    \
1241
39.2k
        }                               \
1242
39.2k
        if (PR_TRUE == requiredUsage) { \
1243
0
            valid = SECFailure;         \
1244
0
        }                               \
1245
39.2k
        NEXT_USAGE();                   \
1246
0
    }
1247
1248
/*
1249
 * check the leaf cert against trust and usage.
1250
 *   returns success if the cert is not distrusted. If the cert is
1251
 *       trusted, then the trusted bool will be true.
1252
 *   returns failure if the cert is distrusted. If failure, flags
1253
 *       will return the flag bits that indicated distrust.
1254
 */
1255
SECStatus
1256
cert_CheckLeafTrust(CERTCertificate *cert, SECCertUsage certUsage,
1257
                    unsigned int *failedFlags, PRBool *trusted)
1258
19.5k
{
1259
19.5k
    unsigned int flags;
1260
19.5k
    CERTCertTrust trust;
1261
1262
19.5k
    *failedFlags = 0;
1263
19.5k
    *trusted = PR_FALSE;
1264
1265
    /* check trust flags to see if this cert is directly trusted */
1266
19.5k
    if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
1267
0
        switch (certUsage) {
1268
0
            case certUsageSSLClient:
1269
0
            case certUsageSSLServer:
1270
0
            case certUsageIPsec:
1271
0
                flags = trust.sslFlags;
1272
1273
                /* is the cert directly trusted or not trusted ? */
1274
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1275
                                                       * authoritative */
1276
0
                    if (flags & CERTDB_TRUSTED) {     /* trust this cert */
1277
0
                        *trusted = PR_TRUE;
1278
0
                        return SECSuccess;
1279
0
                    } else { /* don't trust this cert */
1280
0
                        *failedFlags = flags;
1281
0
                        return SECFailure;
1282
0
                    }
1283
0
                }
1284
0
                break;
1285
0
            case certUsageSSLServerWithStepUp:
1286
                /* XXX - step up certs can't be directly trusted, only distrust */
1287
0
                flags = trust.sslFlags;
1288
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1289
                                                       * authoritative */
1290
0
                    if ((flags & CERTDB_TRUSTED) == 0) {
1291
                        /* don't trust this cert */
1292
0
                        *failedFlags = flags;
1293
0
                        return SECFailure;
1294
0
                    }
1295
0
                }
1296
0
                break;
1297
0
            case certUsageSSLCA:
1298
0
                flags = trust.sslFlags;
1299
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1300
                                                       * authoritative */
1301
0
                    if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
1302
                        /* don't trust this cert */
1303
0
                        *failedFlags = flags;
1304
0
                        return SECFailure;
1305
0
                    }
1306
0
                }
1307
0
                break;
1308
0
            case certUsageEmailSigner:
1309
0
            case certUsageEmailRecipient:
1310
0
                flags = trust.emailFlags;
1311
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1312
                                                       * authoritative */
1313
0
                    if (flags & CERTDB_TRUSTED) {     /* trust this cert */
1314
0
                        *trusted = PR_TRUE;
1315
0
                        return SECSuccess;
1316
0
                    } else { /* don't trust this cert */
1317
0
                        *failedFlags = flags;
1318
0
                        return SECFailure;
1319
0
                    }
1320
0
                }
1321
1322
0
                break;
1323
0
            case certUsageObjectSigner:
1324
0
                flags = trust.objectSigningFlags;
1325
1326
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1327
                                                       * authoritative */
1328
0
                    if (flags & CERTDB_TRUSTED) {     /* trust this cert */
1329
0
                        *trusted = PR_TRUE;
1330
0
                        return SECSuccess;
1331
0
                    } else { /* don't trust this cert */
1332
0
                        *failedFlags = flags;
1333
0
                        return SECFailure;
1334
0
                    }
1335
0
                }
1336
0
                break;
1337
0
            case certUsageVerifyCA:
1338
0
            case certUsageStatusResponder:
1339
0
                flags = trust.sslFlags;
1340
                /* is the cert directly trusted or not trusted ? */
1341
0
                if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
1342
0
                    (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
1343
0
                    *trusted = PR_TRUE;
1344
0
                    return SECSuccess;
1345
0
                }
1346
0
                flags = trust.emailFlags;
1347
                /* is the cert directly trusted or not trusted ? */
1348
0
                if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
1349
0
                    (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
1350
0
                    *trusted = PR_TRUE;
1351
0
                    return SECSuccess;
1352
0
                }
1353
0
                flags = trust.objectSigningFlags;
1354
                /* is the cert directly trusted or not trusted ? */
1355
0
                if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
1356
0
                    (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
1357
0
                    *trusted = PR_TRUE;
1358
0
                    return SECSuccess;
1359
0
                }
1360
            /* fall through to test distrust */
1361
0
            case certUsageAnyCA:
1362
0
            case certUsageUserCertImport:
1363
                /* do we distrust these certs explicitly */
1364
0
                flags = trust.sslFlags;
1365
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1366
                                                       * authoritative */
1367
0
                    if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
1368
0
                        *failedFlags = flags;
1369
0
                        return SECFailure;
1370
0
                    }
1371
0
                }
1372
0
                flags = trust.emailFlags;
1373
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1374
                                                       * authoritative */
1375
0
                    if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
1376
0
                        *failedFlags = flags;
1377
0
                        return SECFailure;
1378
0
                    }
1379
0
                }
1380
            /* fall through */
1381
0
            case certUsageProtectedObjectSigner:
1382
0
                flags = trust.objectSigningFlags;
1383
0
                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
1384
                                                       * authoritative */
1385
0
                    if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
1386
0
                        *failedFlags = flags;
1387
0
                        return SECFailure;
1388
0
                    }
1389
0
                }
1390
0
                break;
1391
0
        }
1392
0
    }
1393
19.5k
    return SECSuccess;
1394
19.5k
}
1395
1396
/*
1397
 * verify a certificate by checking if it's valid and that we
1398
 * trust the issuer.
1399
 *
1400
 * certificateUsage contains a bitfield of all cert usages that are
1401
 * required for verification to succeed
1402
 *
1403
 * a bitfield of cert usages is returned in *returnedUsages
1404
 * if requiredUsages is non-zero, the returned bitmap is only
1405
 * for those required usages, otherwise it is for all usages
1406
 *
1407
 */
1408
SECStatus
1409
CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
1410
                       PRBool checkSig, SECCertificateUsage requiredUsages, PRTime t,
1411
                       void *wincx, CERTVerifyLog *log, SECCertificateUsage *returnedUsages)
1412
4.36k
{
1413
4.36k
    SECStatus rv;
1414
4.36k
    SECStatus valid;
1415
4.36k
    unsigned int requiredKeyUsage;
1416
4.36k
    unsigned int requiredCertType;
1417
4.36k
    unsigned int flags;
1418
4.36k
    unsigned int certType;
1419
4.36k
    PRBool allowOverride;
1420
4.36k
    SECCertTimeValidity validity;
1421
4.36k
    CERTStatusConfig *statusConfig;
1422
4.36k
    PRInt32 i;
1423
4.36k
    SECCertUsage certUsage = 0;
1424
4.36k
    PRBool checkedOCSP = PR_FALSE;
1425
4.36k
    PRBool checkAllUsages = PR_FALSE;
1426
4.36k
    PRBool revoked = PR_FALSE;
1427
4.36k
    PRBool sigerror = PR_FALSE;
1428
4.36k
    PRBool trusted = PR_FALSE;
1429
1430
4.36k
    if (!requiredUsages) {
1431
        /* there are no required usages, so the user probably wants to
1432
           get status for all usages */
1433
4.36k
        checkAllUsages = PR_TRUE;
1434
4.36k
    }
1435
1436
4.36k
    if (returnedUsages) {
1437
4.36k
        *returnedUsages = 0;
1438
4.36k
    } else {
1439
        /* we don't have a place to return status for all usages,
1440
           so we can skip checks for usages that aren't required */
1441
0
        checkAllUsages = PR_FALSE;
1442
0
    }
1443
4.36k
    valid = SECSuccess; /* start off assuming cert is valid */
1444
1445
    /* make sure that the cert is valid at time t */
1446
4.36k
    allowOverride = (PRBool)((requiredUsages & certificateUsageSSLServer) ||
1447
4.36k
                             (requiredUsages & certificateUsageSSLServerWithStepUp) ||
1448
4.36k
                             (requiredUsages & certificateUsageIPsec));
1449
4.36k
    validity = CERT_CheckCertValidTimes(cert, t, allowOverride);
1450
4.36k
    if (validity != secCertTimeValid) {
1451
1.73k
        valid = SECFailure;
1452
1.73k
        LOG_ERROR_OR_EXIT(log, cert, 0, validity);
1453
1.73k
    }
1454
1455
    /* check key usage and netscape cert type */
1456
4.36k
    cert_GetCertType(cert);
1457
4.36k
    certType = cert->nsCertType;
1458
1459
61.0k
    for (i = 1; i <= certificateUsageHighest &&
1460
56.6k
                (SECSuccess == valid || returnedUsages || log);) {
1461
56.6k
        PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE;
1462
56.6k
        if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) {
1463
0
            NEXT_USAGE();
1464
0
        }
1465
56.6k
        if (returnedUsages) {
1466
56.6k
            *returnedUsages |= i; /* start off assuming this usage is valid */
1467
56.6k
        }
1468
56.6k
        switch (certUsage) {
1469
4.36k
            case certUsageSSLClient:
1470
8.72k
            case certUsageSSLServer:
1471
13.0k
            case certUsageSSLServerWithStepUp:
1472
17.4k
            case certUsageSSLCA:
1473
21.8k
            case certUsageEmailSigner:
1474
26.1k
            case certUsageEmailRecipient:
1475
30.5k
            case certUsageObjectSigner:
1476
34.8k
            case certUsageStatusResponder:
1477
39.2k
            case certUsageIPsec:
1478
39.2k
                rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE,
1479
39.2k
                                                      &requiredKeyUsage,
1480
39.2k
                                                      &requiredCertType);
1481
39.2k
                if (rv != SECSuccess) {
1482
0
                    PORT_Assert(0);
1483
                    /* EXIT_IF_NOT_LOGGING(log); XXX ??? */
1484
0
                    requiredKeyUsage = 0;
1485
0
                    requiredCertType = 0;
1486
0
                    INVALID_USAGE();
1487
0
                }
1488
39.2k
                break;
1489
1490
39.2k
            case certUsageAnyCA:
1491
8.72k
            case certUsageProtectedObjectSigner:
1492
13.0k
            case certUsageUserCertImport:
1493
17.4k
            case certUsageVerifyCA:
1494
                /* these usages cannot be verified */
1495
17.4k
                NEXT_USAGE();
1496
1497
0
            default:
1498
0
                PORT_Assert(0);
1499
0
                requiredKeyUsage = 0;
1500
0
                requiredCertType = 0;
1501
0
                INVALID_USAGE();
1502
56.6k
        }
1503
39.2k
        if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) {
1504
7.98k
            if (PR_TRUE == requiredUsage) {
1505
0
                PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
1506
0
            }
1507
7.98k
            LOG_ERROR(log, cert, 0, requiredKeyUsage);
1508
7.98k
            INVALID_USAGE();
1509
0
        }
1510
31.2k
        if (!(certType & requiredCertType)) {
1511
11.6k
            if (PR_TRUE == requiredUsage) {
1512
0
                PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
1513
0
            }
1514
11.6k
            LOG_ERROR(log, cert, 0, requiredCertType);
1515
11.6k
            INVALID_USAGE();
1516
0
        }
1517
1518
19.5k
        rv = cert_CheckLeafTrust(cert, certUsage, &flags, &trusted);
1519
19.5k
        if (rv == SECFailure) {
1520
0
            if (PR_TRUE == requiredUsage) {
1521
0
                PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
1522
0
            }
1523
0
            LOG_ERROR(log, cert, 0, flags);
1524
0
            INVALID_USAGE();
1525
19.5k
        } else if (trusted) {
1526
0
            VALID_USAGE();
1527
0
        }
1528
1529
19.5k
        if (PR_TRUE == revoked || PR_TRUE == sigerror) {
1530
11.2k
            INVALID_USAGE();
1531
0
        }
1532
1533
8.30k
        rv = cert_VerifyCertChain(handle, cert,
1534
8.30k
                                  checkSig, &sigerror,
1535
8.30k
                                  certUsage, t, wincx, log,
1536
8.30k
                                  &revoked);
1537
1538
8.30k
        if (rv != SECSuccess) {
1539
            /* EXIT_IF_NOT_LOGGING(log); XXX ???? */
1540
8.30k
            INVALID_USAGE();
1541
0
        }
1542
1543
        /*
1544
         * Check OCSP revocation status, but only if the cert we are checking
1545
         * is not a status responder itself. We only do this in the case
1546
         * where we checked the cert chain (above); explicit trust "wins"
1547
         * (avoids status checking, just as it avoids CRL checking) by
1548
         * bypassing this code.
1549
         */
1550
1551
0
        if (PR_FALSE == checkedOCSP) {
1552
0
            checkedOCSP = PR_TRUE; /* only check OCSP once */
1553
0
            statusConfig = CERT_GetStatusConfig(handle);
1554
0
            if (requiredUsages != certificateUsageStatusResponder &&
1555
0
                statusConfig != NULL) {
1556
0
                if (statusConfig->statusChecker != NULL) {
1557
0
                    rv = (*statusConfig->statusChecker)(handle, cert,
1558
0
                                                        t, wincx);
1559
0
                    if (rv != SECSuccess) {
1560
0
                        LOG_ERROR(log, cert, 0, 0);
1561
0
                        revoked = PR_TRUE;
1562
0
                        INVALID_USAGE();
1563
0
                    }
1564
0
                }
1565
0
            }
1566
0
        }
1567
1568
0
        NEXT_USAGE();
1569
0
    }
1570
1571
4.36k
loser:
1572
4.36k
    return (valid);
1573
4.36k
}
1574
1575
SECStatus
1576
CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
1577
                PRBool checkSig, SECCertUsage certUsage, PRTime t,
1578
                void *wincx, CERTVerifyLog *log)
1579
0
{
1580
0
    return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t,
1581
0
                                    CERT_VERIFYCERT_USE_DEFAULTS, wincx, log);
1582
0
}
1583
1584
SECStatus
1585
cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
1586
                         PRBool checkSig, SECCertUsage certUsage, PRTime t,
1587
                         PRUint32 flags, void *wincx, CERTVerifyLog *log)
1588
0
{
1589
0
    SECStatus rv;
1590
0
    unsigned int requiredKeyUsage;
1591
0
    unsigned int requiredCertType;
1592
0
    unsigned int failedFlags;
1593
0
    unsigned int certType;
1594
0
    PRBool trusted;
1595
0
    PRBool allowOverride;
1596
0
    SECCertTimeValidity validity;
1597
0
    CERTStatusConfig *statusConfig;
1598
1599
#ifdef notdef
1600
    /* check if this cert is in the Evil list */
1601
    rv = CERT_CheckForEvilCert(cert);
1602
    if (rv != SECSuccess) {
1603
        PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
1604
        LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1605
    }
1606
#endif
1607
1608
    /* make sure that the cert is valid at time t */
1609
0
    allowOverride = (PRBool)((certUsage == certUsageSSLServer) ||
1610
0
                             (certUsage == certUsageSSLServerWithStepUp) ||
1611
0
                             (certUsage == certUsageIPsec));
1612
0
    validity = CERT_CheckCertValidTimes(cert, t, allowOverride);
1613
0
    if (validity != secCertTimeValid) {
1614
0
        LOG_ERROR_OR_EXIT(log, cert, 0, validity);
1615
0
    }
1616
1617
    /* check key usage and netscape cert type */
1618
0
    cert_GetCertType(cert);
1619
0
    certType = cert->nsCertType;
1620
0
    switch (certUsage) {
1621
0
        case certUsageSSLClient:
1622
0
        case certUsageSSLServer:
1623
0
        case certUsageSSLServerWithStepUp:
1624
0
        case certUsageIPsec:
1625
0
        case certUsageSSLCA:
1626
0
        case certUsageEmailSigner:
1627
0
        case certUsageEmailRecipient:
1628
0
        case certUsageObjectSigner:
1629
0
        case certUsageStatusResponder:
1630
0
            rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE,
1631
0
                                                  &requiredKeyUsage,
1632
0
                                                  &requiredCertType);
1633
0
            if (rv != SECSuccess) {
1634
0
                PORT_Assert(0);
1635
0
                EXIT_IF_NOT_LOGGING(log);
1636
0
                requiredKeyUsage = 0;
1637
0
                requiredCertType = 0;
1638
0
            }
1639
0
            break;
1640
0
        case certUsageVerifyCA:
1641
0
        case certUsageAnyCA:
1642
0
            requiredKeyUsage = KU_KEY_CERT_SIGN;
1643
0
            requiredCertType = NS_CERT_TYPE_CA;
1644
0
            if (!(certType & NS_CERT_TYPE_CA)) {
1645
0
                certType |= NS_CERT_TYPE_CA;
1646
0
            }
1647
0
            break;
1648
0
        default:
1649
0
            PORT_Assert(0);
1650
0
            EXIT_IF_NOT_LOGGING(log);
1651
0
            requiredKeyUsage = 0;
1652
0
            requiredCertType = 0;
1653
0
    }
1654
0
    if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) {
1655
0
        PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
1656
0
        LOG_ERROR_OR_EXIT(log, cert, 0, requiredKeyUsage);
1657
0
    }
1658
0
    if (!(certType & requiredCertType)) {
1659
0
        PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
1660
0
        LOG_ERROR_OR_EXIT(log, cert, 0, requiredCertType);
1661
0
    }
1662
1663
0
    rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted);
1664
0
    if (rv == SECFailure) {
1665
0
        PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
1666
0
        LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags);
1667
0
    } else if (trusted) {
1668
0
        goto done;
1669
0
    }
1670
1671
0
    rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage,
1672
0
                              t, wincx, log);
1673
0
    if (rv != SECSuccess) {
1674
0
        EXIT_IF_NOT_LOGGING(log);
1675
0
    }
1676
1677
    /*
1678
     * Check revocation status, but only if the cert we are checking is not a
1679
     * status responder itself and the caller did not ask us to skip the check.
1680
     * We only do this in the case where we checked the cert chain (above);
1681
     * explicit trust "wins" (avoids status checking, just as it avoids CRL
1682
     * checking, which is all done inside VerifyCertChain) by bypassing this
1683
     * code.
1684
     */
1685
0
    if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) &&
1686
0
        certUsage != certUsageStatusResponder) {
1687
0
        statusConfig = CERT_GetStatusConfig(handle);
1688
0
        if (statusConfig && statusConfig->statusChecker) {
1689
0
            rv = (*statusConfig->statusChecker)(handle, cert,
1690
0
                                                t, wincx);
1691
0
            if (rv != SECSuccess) {
1692
0
                LOG_ERROR_OR_EXIT(log, cert, 0, 0);
1693
0
            }
1694
0
        }
1695
0
    }
1696
1697
0
done:
1698
0
    if (log && log->head) {
1699
0
        return SECFailure;
1700
0
    }
1701
0
    return (SECSuccess);
1702
1703
0
loser:
1704
0
    rv = SECFailure;
1705
1706
0
    return (rv);
1707
0
}
1708
1709
/*
1710
 * verify a certificate by checking if its valid and that we
1711
 * trust the issuer.  Verify time against now.
1712
 */
1713
SECStatus
1714
CERT_VerifyCertificateNow(CERTCertDBHandle *handle, CERTCertificate *cert,
1715
                          PRBool checkSig, SECCertificateUsage requiredUsages,
1716
                          void *wincx, SECCertificateUsage *returnedUsages)
1717
0
{
1718
0
    return (CERT_VerifyCertificate(handle, cert, checkSig,
1719
0
                                   requiredUsages, PR_Now(), wincx, NULL, returnedUsages));
1720
0
}
1721
1722
/* obsolete, do not use for new code */
1723
SECStatus
1724
CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert,
1725
                   PRBool checkSig, SECCertUsage certUsage, void *wincx)
1726
0
{
1727
0
    return (CERT_VerifyCert(handle, cert, checkSig,
1728
0
                            certUsage, PR_Now(), wincx, NULL));
1729
0
}
1730
1731
/* [ FROM pcertdb.c ] */
1732
/*
1733
 * Supported usage values and types:
1734
 *  certUsageSSLClient
1735
 *  certUsageSSLServer
1736
 *  certUsageSSLServerWithStepUp
1737
 *  certUsageIPsec
1738
 *  certUsageEmailSigner
1739
 *  certUsageEmailRecipient
1740
 *  certUsageObjectSigner
1741
 */
1742
1743
CERTCertificate *
1744
CERT_FindMatchingCert(CERTCertDBHandle *handle, SECItem *derName,
1745
                      CERTCertOwner owner, SECCertUsage usage,
1746
                      PRBool preferTrusted, PRTime validTime, PRBool validOnly)
1747
0
{
1748
0
    CERTCertList *certList = NULL;
1749
0
    CERTCertificate *cert = NULL;
1750
0
    CERTCertTrust certTrust;
1751
0
    unsigned int requiredTrustFlags;
1752
0
    SECTrustType requiredTrustType;
1753
0
    unsigned int flags;
1754
1755
0
    PRBool lookingForCA = PR_FALSE;
1756
0
    SECStatus rv;
1757
0
    CERTCertListNode *node;
1758
0
    CERTCertificate *saveUntrustedCA = NULL;
1759
1760
    /* if preferTrusted is set, must be a CA cert */
1761
0
    PORT_Assert(!(preferTrusted && (owner != certOwnerCA)));
1762
1763
0
    if (owner == certOwnerCA) {
1764
0
        lookingForCA = PR_TRUE;
1765
0
        if (preferTrusted) {
1766
0
            rv = CERT_TrustFlagsForCACertUsage(usage, &requiredTrustFlags,
1767
0
                                               &requiredTrustType);
1768
0
            if (rv != SECSuccess) {
1769
0
                goto loser;
1770
0
            }
1771
0
            requiredTrustFlags |= CERTDB_VALID_CA;
1772
0
        }
1773
0
    }
1774
1775
0
    certList = CERT_CreateSubjectCertList(NULL, handle, derName, validTime,
1776
0
                                          validOnly);
1777
0
    if (certList != NULL) {
1778
0
        rv = CERT_FilterCertListByUsage(certList, usage, lookingForCA);
1779
0
        if (rv != SECSuccess) {
1780
0
            goto loser;
1781
0
        }
1782
1783
0
        node = CERT_LIST_HEAD(certList);
1784
1785
0
        while (!CERT_LIST_END(node, certList)) {
1786
0
            cert = node->cert;
1787
1788
            /* looking for a trusted CA cert */
1789
0
            if ((owner == certOwnerCA) && preferTrusted &&
1790
0
                (requiredTrustType != trustTypeNone)) {
1791
1792
0
                if (CERT_GetCertTrust(cert, &certTrust) != SECSuccess) {
1793
0
                    flags = 0;
1794
0
                } else {
1795
0
                    flags = SEC_GET_TRUST_FLAGS(&certTrust, requiredTrustType);
1796
0
                }
1797
1798
0
                if ((flags & requiredTrustFlags) != requiredTrustFlags) {
1799
                    /* cert is not trusted */
1800
                    /* if this is the first cert to get this far, then save
1801
                     * it, so we can use it if we can't find a trusted one
1802
                     */
1803
0
                    if (saveUntrustedCA == NULL) {
1804
0
                        saveUntrustedCA = cert;
1805
0
                    }
1806
0
                    goto endloop;
1807
0
                }
1808
0
            }
1809
            /* if we got this far, then this cert meets all criteria */
1810
0
            break;
1811
1812
0
        endloop:
1813
0
            node = CERT_LIST_NEXT(node);
1814
0
            cert = NULL;
1815
0
        }
1816
1817
        /* use the saved one if we have it */
1818
0
        if (cert == NULL) {
1819
0
            cert = saveUntrustedCA;
1820
0
        }
1821
1822
        /* if we found one then bump the ref count before freeing the list */
1823
0
        if (cert != NULL) {
1824
            /* bump the ref count */
1825
0
            cert = CERT_DupCertificate(cert);
1826
0
        }
1827
1828
0
        CERT_DestroyCertList(certList);
1829
0
    }
1830
1831
0
    return (cert);
1832
1833
0
loser:
1834
0
    if (certList != NULL) {
1835
0
        CERT_DestroyCertList(certList);
1836
0
    }
1837
1838
0
    return (NULL);
1839
0
}
1840
1841
/* [ From certdb.c ] */
1842
/*
1843
 * Filter a list of certificates, removing those certs that do not have
1844
 * one of the named CA certs somewhere in their cert chain.
1845
 *
1846
 *  "certList" - the list of certificates to filter
1847
 *  "nCANames" - number of CA names
1848
 *  "caNames" - array of CA names in string(rfc 1485) form
1849
 *  "usage" - what use the certs are for, this is used when
1850
 *      selecting CA certs
1851
 */
1852
SECStatus
1853
CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames,
1854
                             char **caNames, SECCertUsage usage)
1855
0
{
1856
0
    CERTCertificate *issuerCert = NULL;
1857
0
    CERTCertificate *subjectCert;
1858
0
    CERTCertListNode *node, *freenode;
1859
0
    CERTCertificate *cert;
1860
0
    int n;
1861
0
    char **names;
1862
0
    PRBool found;
1863
0
    PRTime time;
1864
1865
0
    if (nCANames <= 0) {
1866
0
        return (SECSuccess);
1867
0
    }
1868
1869
0
    time = PR_Now();
1870
1871
0
    node = CERT_LIST_HEAD(certList);
1872
1873
0
    while (!CERT_LIST_END(node, certList)) {
1874
0
        cert = node->cert;
1875
1876
0
        subjectCert = CERT_DupCertificate(cert);
1877
1878
        /* traverse the CA certs for this cert */
1879
0
        found = PR_FALSE;
1880
0
        while (subjectCert != NULL) {
1881
0
            n = nCANames;
1882
0
            names = caNames;
1883
1884
0
            if (subjectCert->issuerName != NULL) {
1885
0
                while (n > 0) {
1886
0
                    if (PORT_Strcmp(*names, subjectCert->issuerName) == 0) {
1887
0
                        found = PR_TRUE;
1888
0
                        break;
1889
0
                    }
1890
1891
0
                    n--;
1892
0
                    names++;
1893
0
                }
1894
0
            }
1895
1896
0
            if (found) {
1897
0
                break;
1898
0
            }
1899
1900
0
            issuerCert = CERT_FindCertIssuer(subjectCert, time, usage);
1901
0
            if (issuerCert == subjectCert) {
1902
0
                CERT_DestroyCertificate(issuerCert);
1903
0
                issuerCert = NULL;
1904
0
                break;
1905
0
            }
1906
0
            CERT_DestroyCertificate(subjectCert);
1907
0
            subjectCert = issuerCert;
1908
0
        }
1909
0
        CERT_DestroyCertificate(subjectCert);
1910
0
        if (!found) {
1911
            /* CA was not found, so remove this cert from the list */
1912
0
            freenode = node;
1913
0
            node = CERT_LIST_NEXT(node);
1914
0
            CERT_RemoveCertListNode(freenode);
1915
0
        } else {
1916
            /* CA was found, so leave it in the list */
1917
0
            node = CERT_LIST_NEXT(node);
1918
0
        }
1919
0
    }
1920
1921
0
    return (SECSuccess);
1922
0
}
1923
1924
/*
1925
 * Given a certificate, return a string containing the nickname, and possibly
1926
 * one of the validity strings, based on the current validity state of the
1927
 * certificate.
1928
 *
1929
 * "arena" - arena to allocate returned string from.  If NULL, then heap
1930
 *  is used.
1931
 * "cert" - the cert to get nickname from
1932
 * "expiredString" - the string to append to the nickname if the cert is
1933
 *      expired.
1934
 * "notYetGoodString" - the string to append to the nickname if the cert is
1935
 *      not yet good.
1936
 */
1937
char *
1938
CERT_GetCertNicknameWithValidity(PLArenaPool *arena, CERTCertificate *cert,
1939
                                 char *expiredString, char *notYetGoodString)
1940
0
{
1941
0
    SECCertTimeValidity validity;
1942
0
    char *nickname = NULL, *tmpstr = NULL;
1943
0
    const char *srcNickname = cert->nickname;
1944
0
    if (!srcNickname) {
1945
0
        srcNickname = "{???}";
1946
0
    }
1947
1948
0
    validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE);
1949
1950
    /* if the cert is good, then just use the nickname directly */
1951
0
    if (validity == secCertTimeValid) {
1952
0
        if (arena == NULL) {
1953
0
            nickname = PORT_Strdup(srcNickname);
1954
0
        } else {
1955
0
            nickname = PORT_ArenaStrdup(arena, srcNickname);
1956
0
        }
1957
1958
0
        if (nickname == NULL) {
1959
0
            goto loser;
1960
0
        }
1961
0
    } else {
1962
1963
        /* if the cert is not valid, then tack one of the strings on the
1964
         * end
1965
         */
1966
0
        if (validity == secCertTimeExpired) {
1967
0
            tmpstr = PR_smprintf("%s%s", srcNickname,
1968
0
                                 expiredString);
1969
0
        } else if (validity == secCertTimeNotValidYet) {
1970
            /* not yet valid */
1971
0
            tmpstr = PR_smprintf("%s%s", srcNickname,
1972
0
                                 notYetGoodString);
1973
0
        } else {
1974
            /* undetermined */
1975
0
            tmpstr = PR_smprintf("%s",
1976
0
                                 "(NULL) (Validity Unknown)");
1977
0
        }
1978
1979
0
        if (tmpstr == NULL) {
1980
0
            goto loser;
1981
0
        }
1982
1983
0
        if (arena) {
1984
            /* copy the string into the arena and free the malloc'd one */
1985
0
            nickname = PORT_ArenaStrdup(arena, tmpstr);
1986
0
            PORT_Free(tmpstr);
1987
0
        } else {
1988
0
            nickname = tmpstr;
1989
0
        }
1990
0
        if (nickname == NULL) {
1991
0
            goto loser;
1992
0
        }
1993
0
    }
1994
0
    return (nickname);
1995
1996
0
loser:
1997
0
    return (NULL);
1998
0
}
1999
2000
/*
2001
 * Collect the nicknames from all certs in a CertList.  If the cert is not
2002
 * valid, append a string to that nickname.
2003
 *
2004
 * "certList" - the list of certificates
2005
 * "expiredString" - the string to append to the nickname of any expired cert
2006
 * "notYetGoodString" - the string to append to the nickname of any cert
2007
 *      that is not yet valid
2008
 */
2009
CERTCertNicknames *
2010
CERT_NicknameStringsFromCertList(CERTCertList *certList, char *expiredString,
2011
                                 char *notYetGoodString)
2012
0
{
2013
0
    CERTCertNicknames *names;
2014
0
    PLArenaPool *arena;
2015
0
    CERTCertListNode *node;
2016
0
    char **nn;
2017
2018
    /* allocate an arena */
2019
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2020
0
    if (arena == NULL) {
2021
0
        return (NULL);
2022
0
    }
2023
2024
    /* allocate the structure */
2025
0
    names = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
2026
0
    if (names == NULL) {
2027
0
        goto loser;
2028
0
    }
2029
2030
    /* init the structure */
2031
0
    names->arena = arena;
2032
0
    names->head = NULL;
2033
0
    names->numnicknames = 0;
2034
0
    names->nicknames = NULL;
2035
0
    names->totallen = 0;
2036
2037
    /* count the certs in the list */
2038
0
    node = CERT_LIST_HEAD(certList);
2039
0
    while (!CERT_LIST_END(node, certList)) {
2040
0
        names->numnicknames++;
2041
0
        node = CERT_LIST_NEXT(node);
2042
0
    }
2043
2044
    /* allocate nicknames array */
2045
0
    names->nicknames = PORT_ArenaAlloc(arena,
2046
0
                                       sizeof(char *) * names->numnicknames);
2047
0
    if (names->nicknames == NULL) {
2048
0
        goto loser;
2049
0
    }
2050
2051
    /* just in case printf can't deal with null strings */
2052
0
    if (expiredString == NULL) {
2053
0
        expiredString = "";
2054
0
    }
2055
2056
0
    if (notYetGoodString == NULL) {
2057
0
        notYetGoodString = "";
2058
0
    }
2059
2060
    /* traverse the list of certs and collect the nicknames */
2061
0
    nn = names->nicknames;
2062
0
    node = CERT_LIST_HEAD(certList);
2063
0
    while (!CERT_LIST_END(node, certList)) {
2064
0
        *nn = CERT_GetCertNicknameWithValidity(arena, node->cert,
2065
0
                                               expiredString,
2066
0
                                               notYetGoodString);
2067
0
        if (*nn == NULL) {
2068
0
            goto loser;
2069
0
        }
2070
2071
0
        names->totallen += PORT_Strlen(*nn);
2072
2073
0
        nn++;
2074
0
        node = CERT_LIST_NEXT(node);
2075
0
    }
2076
2077
0
    return (names);
2078
2079
0
loser:
2080
0
    PORT_FreeArena(arena, PR_FALSE);
2081
0
    return (NULL);
2082
0
}
2083
2084
/*
2085
 * Extract the nickname from a nickmake string that may have either
2086
 * expiredString or notYetGoodString appended.
2087
 *
2088
 * Args:
2089
 *  "namestring" - the string containing the nickname, and possibly
2090
 *      one of the validity label strings
2091
 *  "expiredString" - the expired validity label string
2092
 *  "notYetGoodString" - the not yet good validity label string
2093
 *
2094
 * Returns the raw nickname
2095
 */
2096
char *
2097
CERT_ExtractNicknameString(char *namestring, char *expiredString,
2098
                           char *notYetGoodString)
2099
0
{
2100
0
    int explen, nyglen, namelen;
2101
0
    int retlen;
2102
0
    char *retstr;
2103
2104
0
    namelen = PORT_Strlen(namestring);
2105
0
    explen = PORT_Strlen(expiredString);
2106
0
    nyglen = PORT_Strlen(notYetGoodString);
2107
2108
0
    if (namelen > explen) {
2109
0
        if (PORT_Strcmp(expiredString, &namestring[namelen - explen]) == 0) {
2110
0
            retlen = namelen - explen;
2111
0
            retstr = (char *)PORT_Alloc(retlen + 1);
2112
0
            if (retstr == NULL) {
2113
0
                goto loser;
2114
0
            }
2115
2116
0
            PORT_Memcpy(retstr, namestring, retlen);
2117
0
            retstr[retlen] = '\0';
2118
0
            goto done;
2119
0
        }
2120
0
    }
2121
2122
0
    if (namelen > nyglen) {
2123
0
        if (PORT_Strcmp(notYetGoodString, &namestring[namelen - nyglen]) == 0) {
2124
0
            retlen = namelen - nyglen;
2125
0
            retstr = (char *)PORT_Alloc(retlen + 1);
2126
0
            if (retstr == NULL) {
2127
0
                goto loser;
2128
0
            }
2129
2130
0
            PORT_Memcpy(retstr, namestring, retlen);
2131
0
            retstr[retlen] = '\0';
2132
0
            goto done;
2133
0
        }
2134
0
    }
2135
2136
    /* if name string is shorter than either invalid string, then it must
2137
     * be a raw nickname
2138
     */
2139
0
    retstr = PORT_Strdup(namestring);
2140
2141
0
done:
2142
0
    return (retstr);
2143
2144
0
loser:
2145
0
    return (NULL);
2146
0
}
2147
2148
CERTCertList *
2149
CERT_GetCertChainFromCert(CERTCertificate *cert, PRTime time, SECCertUsage usage)
2150
4.36k
{
2151
4.36k
    CERTCertList *chain = NULL;
2152
4.36k
    int count = 0;
2153
2154
4.36k
    if (NULL == cert) {
2155
0
        return NULL;
2156
0
    }
2157
2158
4.36k
    cert = CERT_DupCertificate(cert);
2159
4.36k
    if (NULL == cert) {
2160
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
2161
0
        return NULL;
2162
0
    }
2163
2164
4.36k
    chain = CERT_NewCertList();
2165
4.36k
    if (NULL == chain) {
2166
0
        CERT_DestroyCertificate(cert);
2167
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
2168
0
        return NULL;
2169
0
    }
2170
2171
10.9k
    while (cert != NULL && ++count <= CERT_MAX_CERT_CHAIN) {
2172
9.35k
        if (SECSuccess != CERT_AddCertToListTail(chain, cert)) {
2173
            /* return partial chain */
2174
0
            CERT_DestroyCertificate(cert);
2175
0
            PORT_SetError(SEC_ERROR_NO_MEMORY);
2176
0
            return chain;
2177
0
        }
2178
2179
9.35k
        if (cert->isRoot) {
2180
            /* return complete chain */
2181
2.81k
            return chain;
2182
2.81k
        }
2183
2184
6.54k
        cert = CERT_FindCertIssuer(cert, time, usage);
2185
6.54k
    }
2186
2187
    /* return partial chain */
2188
1.55k
    CERT_DestroyCertificate(cert);
2189
1.55k
    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
2190
1.55k
    return chain;
2191
4.36k
}