Coverage Report

Created: 2018-09-25 14:53

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