Coverage Report

Created: 2024-11-21 07:03

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