Coverage Report

Created: 2024-05-20 06:23

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