Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/nss/lib/certhigh/certvfypkix.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
/*
5
 * nss_pkix_proxy.h
6
 *
7
 * PKIX - NSS proxy functions
8
 *
9
 * NOTE: All structures, functions, data types are parts of library private
10
 * api and are subjects to change in any following releases.
11
 *
12
 */
13
#include "prerror.h"
14
#include "prprf.h"
15
16
#include "nspr.h"
17
#include "pk11func.h"
18
#include "certdb.h"
19
#include "cert.h"
20
#include "secerr.h"
21
#include "nssb64.h"
22
#include "secasn1.h"
23
#include "secder.h"
24
#include "pkit.h"
25
26
#ifndef NSS_DISABLE_LIBPKIX
27
#include "pkix_pl_common.h"
28
29
extern PRLogModuleInfo *pkixLog;
30
31
#ifdef PKIX_OBJECT_LEAK_TEST
32
33
extern PKIX_UInt32
34
pkix_pl_lifecycle_ObjectLeakCheck(int *);
35
36
extern SECStatus
37
pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable);
38
39
PRInt32 parallelFnInvocationCount;
40
#endif /* PKIX_OBJECT_LEAK_TEST */
41
42
static PRBool usePKIXValidationEngine = PR_FALSE;
43
#endif /* NSS_DISABLE_LIBPKIX */
44
45
/*
46
 * FUNCTION: CERT_SetUsePKIXForValidation
47
 * DESCRIPTION:
48
 *
49
 * Enables or disables use of libpkix for certificate validation
50
 *
51
 * PARAMETERS:
52
 *  "enable"
53
 *      PR_TRUE: enables use of libpkix for cert validation.
54
 *      PR_FALSE: disables.
55
 * THREAD SAFETY:
56
 *  NOT Thread Safe.
57
 * RETURNS:
58
 *  Returns SECSuccess if successfully enabled
59
 */
60
SECStatus
61
CERT_SetUsePKIXForValidation(PRBool enable)
62
0
{
63
0
#ifdef NSS_DISABLE_LIBPKIX
64
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
65
0
    return SECFailure;
66
#else
67
    usePKIXValidationEngine = (enable > 0) ? PR_TRUE : PR_FALSE;
68
    return SECSuccess;
69
#endif /* NSS_DISABLE_LIBPKIX */
70
}
71
72
/*
73
 * FUNCTION: CERT_GetUsePKIXForValidation
74
 * DESCRIPTION:
75
 *
76
 * Checks if libpkix building function should be use for certificate
77
 * chain building.
78
 *
79
 * PARAMETERS:
80
 *  NONE
81
 * THREAD SAFETY:
82
 *  NOT Thread Safe
83
 * RETURNS:
84
 *  Returns PR_TRUE if libpkix should be used. PR_FALSE otherwise.
85
 */
86
PRBool
87
CERT_GetUsePKIXForValidation()
88
0
{
89
0
#ifdef NSS_DISABLE_LIBPKIX
90
0
    return PR_FALSE;
91
#else
92
    return usePKIXValidationEngine;
93
#endif /* NSS_DISABLE_LIBPKIX */
94
}
95
96
#ifndef NSS_DISABLE_LIBPKIX
97
#ifdef NOTDEF
98
/*
99
 * FUNCTION: cert_NssKeyUsagesToPkix
100
 * DESCRIPTION:
101
 *
102
 * Converts nss key usage bit field(PRUint32) to pkix key usage
103
 * bit field.
104
 *
105
 * PARAMETERS:
106
 *  "nssKeyUsage"
107
 *      Nss key usage bit field.
108
 *  "pkixKeyUsage"
109
 *      Pkix key usage big field.
110
 *  "plContext"
111
 *      Platform-specific context pointer.
112
 * THREAD SAFETY:
113
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
114
 * RETURNS:
115
 *  Returns NULL if the function succeeds.
116
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
117
 */
118
static PKIX_Error *
119
cert_NssKeyUsagesToPkix(
120
    PRUint32 nssKeyUsage,
121
    PKIX_UInt32 *pPkixKeyUsage,
122
    void *plContext)
123
{
124
    PKIX_UInt32 pkixKeyUsage = 0;
125
126
    PKIX_ENTER(CERTVFYPKIX, "cert_NssKeyUsagesToPkix");
127
    PKIX_NULLCHECK_ONE(pPkixKeyUsage);
128
129
    *pPkixKeyUsage = 0;
130
131
    if (nssKeyUsage & KU_DIGITAL_SIGNATURE) {
132
        pkixKeyUsage |= PKIX_DIGITAL_SIGNATURE;
133
    }
134
135
    if (nssKeyUsage & KU_NON_REPUDIATION) {
136
        pkixKeyUsage |= PKIX_NON_REPUDIATION;
137
    }
138
139
    if (nssKeyUsage & KU_KEY_ENCIPHERMENT) {
140
        pkixKeyUsage |= PKIX_KEY_ENCIPHERMENT;
141
    }
142
143
    if (nssKeyUsage & KU_DATA_ENCIPHERMENT) {
144
        pkixKeyUsage |= PKIX_DATA_ENCIPHERMENT;
145
    }
146
147
    if (nssKeyUsage & KU_KEY_AGREEMENT) {
148
        pkixKeyUsage |= PKIX_KEY_AGREEMENT;
149
    }
150
151
    if (nssKeyUsage & KU_KEY_CERT_SIGN) {
152
        pkixKeyUsage |= PKIX_KEY_CERT_SIGN;
153
    }
154
155
    if (nssKeyUsage & KU_CRL_SIGN) {
156
        pkixKeyUsage |= PKIX_CRL_SIGN;
157
    }
158
159
    if (nssKeyUsage & KU_ENCIPHER_ONLY) {
160
        pkixKeyUsage |= PKIX_ENCIPHER_ONLY;
161
    }
162
163
    /* Not supported. XXX we should support this once it is
164
     * fixed in NSS */
165
    /* pkixKeyUsage |= PKIX_DECIPHER_ONLY; */
166
167
    *pPkixKeyUsage = pkixKeyUsage;
168
169
    PKIX_RETURN(CERTVFYPKIX);
170
}
171
172
extern SECOidTag ekuOidStrings[];
173
174
enum {
175
    ekuIndexSSLServer = 0,
176
    ekuIndexSSLClient,
177
    ekuIndexCodeSigner,
178
    ekuIndexEmail,
179
    ekuIndexTimeStamp,
180
    ekuIndexStatusResponder,
181
    ekuIndexUnknown
182
} ekuIndex;
183
184
typedef struct {
185
    SECCertUsage certUsage;
186
    PRUint32 ekuStringIndex;
187
} SECCertUsageToEku;
188
189
const SECCertUsageToEku certUsageEkuStringMap[] = {
190
    { certUsageSSLClient, ekuIndexSSLClient },
191
    { certUsageSSLServer, ekuIndexSSLServer },
192
    { certUsageSSLCA, ekuIndexSSLServer },
193
    { certUsageEmailSigner, ekuIndexEmail },
194
    { certUsageEmailRecipient, ekuIndexEmail },
195
    { certUsageObjectSigner, ekuIndexCodeSigner },
196
    { certUsageUserCertImport, ekuIndexUnknown },
197
    { certUsageVerifyCA, ekuIndexUnknown },
198
    { certUsageProtectedObjectSigner, ekuIndexUnknown },
199
    { certUsageStatusResponder, ekuIndexStatusResponder },
200
    { certUsageAnyCA, ekuIndexUnknown },
201
};
202
203
/*
204
 * FUNCTION: cert_NssCertificateUsageToPkixKUAndEKU
205
 * DESCRIPTION:
206
 *
207
 * Converts nss CERTCertificateUsage bit field to pkix key and
208
 * extended key usages.
209
 *
210
 * PARAMETERS:
211
 *  "cert"
212
 *      Pointer to CERTCertificate structure of validating cert.
213
 *  "requiredCertUsages"
214
 *      Required usage that will be converted to pkix eku and ku.
215
 *  "requiredKeyUsage",
216
 *      Additional key usages impose to cert.
217
 *  "isCA",
218
 *      it true, convert usages for cert that is a CA cert.
219
 *  "ppkixEKUList"
220
 *      Returned address of a list of pkix extended key usages.
221
 *  "ppkixKU"
222
 *      Returned address of pkix required key usages bit field.
223
 *  "plContext"
224
 *      Platform-specific context pointer.
225
 * THREAD SAFETY:
226
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
227
 * RETURNS:
228
 *  Returns NULL if the function succeeds.
229
 *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
230
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
231
 */
232
static PKIX_Error *
233
cert_NssCertificateUsageToPkixKUAndEKU(
234
    CERTCertificate *cert,
235
    SECCertUsage requiredCertUsage,
236
    PRUint32 requiredKeyUsages,
237
    PRBool isCA,
238
    PKIX_List **ppkixEKUList,
239
    PKIX_UInt32 *ppkixKU,
240
    void *plContext)
241
{
242
    PKIX_List *ekuOidsList = NULL;
243
    PKIX_PL_OID *ekuOid = NULL;
244
    int i = 0;
245
    int ekuIndex = ekuIndexUnknown;
246
247
    PKIX_ENTER(CERTVFYPKIX, "cert_NssCertificateUsageToPkixEku");
248
    PKIX_NULLCHECK_TWO(ppkixEKUList, ppkixKU);
249
250
    PKIX_CHECK(
251
        PKIX_List_Create(&ekuOidsList, plContext),
252
        PKIX_LISTCREATEFAILED);
253
254
    for (; i < PR_ARRAY_SIZE(certUsageEkuStringMap); i++) {
255
        const SECCertUsageToEku *usageToEkuElem =
256
            &certUsageEkuStringMap[i];
257
        if (usageToEkuElem->certUsage == requiredCertUsage) {
258
            ekuIndex = usageToEkuElem->ekuStringIndex;
259
            break;
260
        }
261
    }
262
    if (ekuIndex != ekuIndexUnknown) {
263
        PRUint32 reqKeyUsage = 0;
264
        PRUint32 reqCertType = 0;
265
266
        CERT_KeyUsageAndTypeForCertUsage(requiredCertUsage, isCA,
267
                                         &reqKeyUsage,
268
                                         &reqCertType);
269
270
        requiredKeyUsages |= reqKeyUsage;
271
272
        PKIX_CHECK(
273
            PKIX_PL_OID_Create(ekuOidStrings[ekuIndex], &ekuOid,
274
                               plContext),
275
            PKIX_OIDCREATEFAILED);
276
277
        PKIX_CHECK(
278
            PKIX_List_AppendItem(ekuOidsList, (PKIX_PL_Object *)ekuOid,
279
                                 plContext),
280
            PKIX_LISTAPPENDITEMFAILED);
281
282
        PKIX_DECREF(ekuOid);
283
    }
284
285
    PKIX_CHECK(
286
        cert_NssKeyUsagesToPkix(requiredKeyUsages, ppkixKU, plContext),
287
        PKIX_NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED);
288
289
    *ppkixEKUList = ekuOidsList;
290
    ekuOidsList = NULL;
291
292
cleanup:
293
294
    PKIX_DECREF(ekuOid);
295
    PKIX_DECREF(ekuOidsList);
296
297
    PKIX_RETURN(CERTVFYPKIX);
298
}
299
300
#endif
301
302
/*
303
 * FUNCTION: cert_ProcessingParamsSetKeyAndCertUsage
304
 * DESCRIPTION:
305
 *
306
 * Converts cert usage to pkix KU type and sets
307
 * converted data into PKIX_ProcessingParams object. It also sets
308
 * proper cert usage into nsscontext object.
309
 *
310
 * PARAMETERS:
311
 *  "procParams"
312
 *      Pointer to PKIX_ProcessingParams used during validation.
313
 *  "requiredCertUsage"
314
 *      Required certificate usages the certificate and chain is built and
315
 *      validated for.
316
 *  "requiredKeyUsage"
317
 *      Request additional key usages the certificate should be validated for.
318
 *  "plContext"
319
 *      Platform-specific context pointer.
320
 * THREAD SAFETY:
321
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
322
 * RETURNS:
323
 *  Returns NULL if the function succeeds.
324
 *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
325
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
326
 */
327
static PKIX_Error *
328
cert_ProcessingParamsSetKeyAndCertUsage(
329
    PKIX_ProcessingParams *procParams,
330
    SECCertUsage requiredCertUsage,
331
    PRUint32 requiredKeyUsages,
332
    void *plContext)
333
{
334
    PKIX_CertSelector *certSelector = NULL;
335
    PKIX_ComCertSelParams *certSelParams = NULL;
336
    PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext *)plContext;
337
338
    PKIX_ENTER(CERTVFYPKIX, "cert_ProcessingParamsSetKeyAndCertUsage");
339
    PKIX_NULLCHECK_TWO(procParams, nssContext);
340
341
    PKIX_CHECK(
342
        pkix_pl_NssContext_SetCertUsage(
343
            ((SECCertificateUsage)1) << requiredCertUsage, nssContext),
344
        PKIX_NSSCONTEXTSETCERTUSAGEFAILED);
345
346
    if (requiredKeyUsages) {
347
        PKIX_CHECK(
348
            PKIX_ProcessingParams_GetTargetCertConstraints(procParams,
349
                                                           &certSelector, plContext),
350
            PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
351
352
        PKIX_CHECK(
353
            PKIX_CertSelector_GetCommonCertSelectorParams(certSelector,
354
                                                          &certSelParams, plContext),
355
            PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
356
357
        PKIX_CHECK(
358
            PKIX_ComCertSelParams_SetKeyUsage(certSelParams, requiredKeyUsages,
359
                                              plContext),
360
            PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED);
361
    }
362
cleanup:
363
    PKIX_DECREF(certSelector);
364
    PKIX_DECREF(certSelParams);
365
366
    PKIX_RETURN(CERTVFYPKIX);
367
}
368
369
/*
370
 * Unused parameters:
371
 *
372
 *  CERTCertList *initialChain,
373
 *  CERTCertStores certStores,
374
 *  CERTCertRevCheckers certRevCheckers,
375
 *  CERTCertChainCheckers certChainCheckers,
376
 *  SECItem *initPolicies,
377
 *  PRBool policyQualifierRejected,
378
 *  PRBool anyPolicyInhibited,
379
 *  PRBool reqExplicitPolicy,
380
 *  PRBool policyMappingInhibited,
381
 *  PKIX_CertSelector certConstraints,
382
 */
383
384
/*
385
 * FUNCTION: cert_CreatePkixProcessingParams
386
 * DESCRIPTION:
387
 *
388
 * Creates and fills in PKIX_ProcessingParams structure to be used
389
 * for certificate chain building.
390
 *
391
 * PARAMETERS:
392
 *  "cert"
393
 *      Pointer to the CERTCertificate: the leaf certificate of a chain.
394
 *  "time"
395
 *      Validity time.
396
 *  "wincx"
397
 *      Nss db password token.
398
 *  "useArena"
399
 *      Flags to use arena for data allocation during chain building process.
400
 *  "pprocParams"
401
 *      Address to return created processing parameters.
402
 *  "plContext"
403
 *      Platform-specific context pointer.
404
 * THREAD SAFETY:
405
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
406
 * RETURNS:
407
 *  Returns NULL if the function succeeds.
408
 *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
409
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
410
 */
411
static PKIX_Error *
412
cert_CreatePkixProcessingParams(
413
    CERTCertificate *cert,
414
    PRBool checkSig, /* not used yet. See bug 391476 */
415
    PRTime time,
416
    void *wincx,
417
    PRBool useArena,
418
    PRBool disableOCSPRemoteFetching,
419
    PKIX_ProcessingParams **pprocParams,
420
    void **pplContext)
421
{
422
    PKIX_List *anchors = NULL;
423
    PKIX_PL_Cert *targetCert = NULL;
424
    PKIX_PL_Date *date = NULL;
425
    PKIX_ProcessingParams *procParams = NULL;
426
    PKIX_CertSelector *certSelector = NULL;
427
    PKIX_ComCertSelParams *certSelParams = NULL;
428
    PKIX_CertStore *certStore = NULL;
429
    PKIX_List *certStores = NULL;
430
    PKIX_RevocationChecker *revChecker = NULL;
431
    PKIX_UInt32 methodFlags = 0;
432
    void *plContext = NULL;
433
    CERTStatusConfig *statusConfig = NULL;
434
435
    PKIX_ENTER(CERTVFYPKIX, "cert_CreatePkixProcessingParams");
436
    PKIX_NULLCHECK_TWO(cert, pprocParams);
437
438
    PKIX_CHECK(
439
        PKIX_PL_NssContext_Create(0, useArena, wincx, &plContext),
440
        PKIX_NSSCONTEXTCREATEFAILED);
441
442
    *pplContext = plContext;
443
444
#ifdef PKIX_NOTDEF
445
    /* Functions should be implemented in patch for 390532 */
446
    PKIX_CHECK(
447
        pkix_pl_NssContext_SetCertSignatureCheck(checkSig,
448
                                                 (PKIX_PL_NssContext *)plContext),
449
        PKIX_NSSCONTEXTSETCERTSIGNCHECKFAILED);
450
451
#endif /* PKIX_NOTDEF */
452
453
    PKIX_CHECK(
454
        PKIX_ProcessingParams_Create(&procParams, plContext),
455
        PKIX_PROCESSINGPARAMSCREATEFAILED);
456
457
    PKIX_CHECK(
458
        PKIX_ComCertSelParams_Create(&certSelParams, plContext),
459
        PKIX_COMCERTSELPARAMSCREATEFAILED);
460
461
    PKIX_CHECK(
462
        PKIX_PL_Cert_CreateFromCERTCertificate(cert, &targetCert, plContext),
463
        PKIX_CERTCREATEWITHNSSCERTFAILED);
464
465
    PKIX_CHECK(
466
        PKIX_ComCertSelParams_SetCertificate(certSelParams,
467
                                             targetCert, plContext),
468
        PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED);
469
470
    PKIX_CHECK(
471
        PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext),
472
        PKIX_COULDNOTCREATECERTSELECTOROBJECT);
473
474
    PKIX_CHECK(
475
        PKIX_CertSelector_SetCommonCertSelectorParams(certSelector,
476
                                                      certSelParams, plContext),
477
        PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
478
479
    PKIX_CHECK(
480
        PKIX_ProcessingParams_SetTargetCertConstraints(procParams,
481
                                                       certSelector, plContext),
482
        PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED);
483
484
    /* Turn off quialification of target cert since leaf cert is
485
     * already check for date validity, key usages and extended
486
     * key usages. */
487
    PKIX_CHECK(
488
        PKIX_ProcessingParams_SetQualifyTargetCert(procParams, PKIX_FALSE,
489
                                                   plContext),
490
        PKIX_PROCESSINGPARAMSSETQUALIFYTARGETCERTFLAGFAILED);
491
492
    PKIX_CHECK(
493
        PKIX_PL_Pk11CertStore_Create(&certStore, plContext),
494
        PKIX_PK11CERTSTORECREATEFAILED);
495
496
    PKIX_CHECK(
497
        PKIX_List_Create(&certStores, plContext),
498
        PKIX_UNABLETOCREATELIST);
499
500
    PKIX_CHECK(
501
        PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore,
502
                             plContext),
503
        PKIX_LISTAPPENDITEMFAILED);
504
505
    PKIX_CHECK(
506
        PKIX_ProcessingParams_SetCertStores(procParams, certStores,
507
                                            plContext),
508
        PKIX_PROCESSINGPARAMSADDCERTSTOREFAILED);
509
510
    PKIX_CHECK(
511
        PKIX_PL_Date_CreateFromPRTime(time, &date, plContext),
512
        PKIX_DATECREATEFROMPRTIMEFAILED);
513
514
    PKIX_CHECK(
515
        PKIX_ProcessingParams_SetDate(procParams, date, plContext),
516
        PKIX_PROCESSINGPARAMSSETDATEFAILED);
517
518
    PKIX_CHECK(
519
        PKIX_RevocationChecker_Create(
520
            PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
521
                PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT,
522
            PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
523
                PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT,
524
            &revChecker, plContext),
525
        PKIX_REVOCATIONCHECKERCREATEFAILED);
526
527
    PKIX_CHECK(
528
        PKIX_ProcessingParams_SetRevocationChecker(procParams, revChecker,
529
                                                   plContext),
530
        PKIX_PROCESSINGPARAMSSETREVOCATIONCHECKERFAILED);
531
532
    /* CRL method flags */
533
    methodFlags =
534
        PKIX_REV_M_TEST_USING_THIS_METHOD |
535
        PKIX_REV_M_FORBID_NETWORK_FETCHING |
536
        PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE | /* 0 */
537
        PKIX_REV_M_IGNORE_MISSING_FRESH_INFO |   /* 0 */
538
        PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO;
539
540
    /* add CRL revocation method to check the leaf certificate */
541
    PKIX_CHECK(
542
        PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
543
                                                  PKIX_RevocationMethod_CRL, methodFlags,
544
                                                  0, NULL, PKIX_TRUE, plContext),
545
        PKIX_REVOCATIONCHECKERADDMETHODFAILED);
546
547
    /* add CRL revocation method for other certs in the chain. */
548
    PKIX_CHECK(
549
        PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
550
                                                  PKIX_RevocationMethod_CRL, methodFlags,
551
                                                  0, NULL, PKIX_FALSE, plContext),
552
        PKIX_REVOCATIONCHECKERADDMETHODFAILED);
553
554
    /* For compatibility with the old code, need to check that
555
     * statusConfig is set in the db handle and status checker
556
     * is defined befor allow ocsp status check on the leaf cert.*/
557
    statusConfig = CERT_GetStatusConfig(CERT_GetDefaultCertDB());
558
    if (statusConfig != NULL && statusConfig->statusChecker != NULL) {
559
560
        /* Enable OCSP revocation checking for the leaf cert. */
561
        /* OCSP method flags */
562
        methodFlags =
563
            PKIX_REV_M_TEST_USING_THIS_METHOD |
564
            PKIX_REV_M_ALLOW_NETWORK_FETCHING |        /* 0 */
565
            PKIX_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE | /* 0 */
566
            PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE |   /* 0 */
567
            PKIX_REV_M_IGNORE_MISSING_FRESH_INFO |     /* 0 */
568
            PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO;
569
570
        /* Disabling ocsp fetching when checking the status
571
         * of ocsp response signer. Here and in the next if,
572
         * adjust flags for ocsp signer cert validation case. */
573
        if (disableOCSPRemoteFetching) {
574
            methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING;
575
        }
576
577
        if (ocsp_FetchingFailureIsVerificationFailure() &&
578
            !disableOCSPRemoteFetching) {
579
            methodFlags |=
580
                PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO;
581
        }
582
583
        /* add OCSP revocation method to check only the leaf certificate.*/
584
        PKIX_CHECK(
585
            PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
586
                                                      PKIX_RevocationMethod_OCSP, methodFlags,
587
                                                      1, NULL, PKIX_TRUE, plContext),
588
            PKIX_REVOCATIONCHECKERADDMETHODFAILED);
589
    }
590
591
    PKIX_CHECK(
592
        PKIX_ProcessingParams_SetAnyPolicyInhibited(procParams, PR_FALSE,
593
                                                    plContext),
594
        PKIX_PROCESSINGPARAMSSETANYPOLICYINHIBITED);
595
596
    PKIX_CHECK(
597
        PKIX_ProcessingParams_SetExplicitPolicyRequired(procParams, PR_FALSE,
598
                                                        plContext),
599
        PKIX_PROCESSINGPARAMSSETEXPLICITPOLICYREQUIRED);
600
601
    PKIX_CHECK(
602
        PKIX_ProcessingParams_SetPolicyMappingInhibited(procParams, PR_FALSE,
603
                                                        plContext),
604
        PKIX_PROCESSINGPARAMSSETPOLICYMAPPINGINHIBITED);
605
606
    *pprocParams = procParams;
607
    procParams = NULL;
608
609
cleanup:
610
    PKIX_DECREF(anchors);
611
    PKIX_DECREF(targetCert);
612
    PKIX_DECREF(date);
613
    PKIX_DECREF(certSelector);
614
    PKIX_DECREF(certSelParams);
615
    PKIX_DECREF(certStore);
616
    PKIX_DECREF(certStores);
617
    PKIX_DECREF(procParams);
618
    PKIX_DECREF(revChecker);
619
620
    PKIX_RETURN(CERTVFYPKIX);
621
}
622
623
/*
624
 * FUNCTION: cert_PkixToNssCertsChain
625
 * DESCRIPTION:
626
 *
627
 * Converts pkix cert list into nss cert list.
628
 *
629
 * PARAMETERS:
630
 *  "pkixCertChain"
631
 *      Pkix certificate list.
632
 *  "pvalidChain"
633
 *      An address of returned nss certificate list.
634
 *  "plContext"
635
 *      Platform-specific context pointer.
636
 * THREAD SAFETY:
637
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
638
 * RETURNS:
639
 *  Returns NULL if the function succeeds.
640
 *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
641
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
642
 */
643
static PKIX_Error *
644
cert_PkixToNssCertsChain(
645
    PKIX_List *pkixCertChain,
646
    CERTCertList **pvalidChain,
647
    void *plContext)
648
{
649
    PLArenaPool *arena = NULL;
650
    CERTCertificate *nssCert = NULL;
651
    CERTCertList *validChain = NULL;
652
    PKIX_PL_Object *certItem = NULL;
653
    PKIX_UInt32 length = 0;
654
    PKIX_UInt32 i = 0;
655
656
    PKIX_ENTER(CERTVFYPKIX, "cert_PkixToNssCertsChain");
657
    PKIX_NULLCHECK_ONE(pvalidChain);
658
659
    if (pkixCertChain == NULL) {
660
        goto cleanup;
661
    }
662
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
663
    if (arena == NULL) {
664
        PKIX_ERROR(PKIX_OUTOFMEMORY);
665
    }
666
    validChain = (CERTCertList *)PORT_ArenaZAlloc(arena, sizeof(CERTCertList));
667
    if (validChain == NULL) {
668
        PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
669
    }
670
    PR_INIT_CLIST(&validChain->list);
671
    validChain->arena = arena;
672
    arena = NULL;
673
674
    PKIX_CHECK(
675
        PKIX_List_GetLength(pkixCertChain, &length, plContext),
676
        PKIX_LISTGETLENGTHFAILED);
677
678
    for (i = 0; i < length; i++) {
679
        CERTCertListNode *node = NULL;
680
681
        PKIX_CHECK(
682
            PKIX_List_GetItem(pkixCertChain, i, &certItem, plContext),
683
            PKIX_LISTGETITEMFAILED);
684
685
        PKIX_CHECK(
686
            PKIX_PL_Cert_GetCERTCertificate((PKIX_PL_Cert *)certItem, &nssCert,
687
                                            plContext),
688
            PKIX_CERTGETCERTCERTIFICATEFAILED);
689
690
        node =
691
            (CERTCertListNode *)PORT_ArenaZAlloc(validChain->arena,
692
                                                 sizeof(CERTCertListNode));
693
        if (node == NULL) {
694
            PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
695
        }
696
697
        PR_INSERT_BEFORE(&node->links, &validChain->list);
698
699
        node->cert = nssCert;
700
        nssCert = NULL;
701
702
        PKIX_DECREF(certItem);
703
    }
704
705
    *pvalidChain = validChain;
706
707
cleanup:
708
    if (PKIX_ERROR_RECEIVED) {
709
        if (validChain) {
710
            CERT_DestroyCertList(validChain);
711
        } else if (arena) {
712
            PORT_FreeArena(arena, PR_FALSE);
713
        }
714
        if (nssCert) {
715
            CERT_DestroyCertificate(nssCert);
716
        }
717
    }
718
    PKIX_DECREF(certItem);
719
720
    PKIX_RETURN(CERTVFYPKIX);
721
}
722
723
/*
724
 * FUNCTION: cert_BuildAndValidateChain
725
 * DESCRIPTION:
726
 *
727
 * The function builds and validates a cert chain based on certificate
728
 * selection criterias from procParams. This function call PKIX_BuildChain
729
 * to accomplish chain building. If PKIX_BuildChain returns with incomplete
730
 * IO, the function waits with PR_Poll until the blocking IO is finished and
731
 * return control back to PKIX_BuildChain.
732
 *
733
 * PARAMETERS:
734
 *  "procParams"
735
 *      Processing parameters to be used during chain building.
736
 *  "pResult"
737
 *      Returned build result.
738
 *  "pVerifyNode"
739
 *      Returned pointed to verify node structure: the tree-like structure
740
 *      that reports points of chain building failures.
741
 *  "plContext"
742
 *      Platform-specific context pointer.
743
 * THREAD SAFETY:
744
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
745
 * RETURNS:
746
 *  Returns NULL if the function succeeds.
747
 *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
748
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
749
 */
750
static PKIX_Error *
751
cert_BuildAndValidateChain(
752
    PKIX_ProcessingParams *procParams,
753
    PKIX_BuildResult **pResult,
754
    PKIX_VerifyNode **pVerifyNode,
755
    void *plContext)
756
{
757
    PKIX_BuildResult *result = NULL;
758
    PKIX_VerifyNode *verifyNode = NULL;
759
    void *nbioContext = NULL;
760
    void *state = NULL;
761
762
    PKIX_ENTER(CERTVFYPKIX, "cert_BuildAndVerifyChain");
763
    PKIX_NULLCHECK_TWO(procParams, pResult);
764
765
    do {
766
        if (nbioContext && state) {
767
            /* PKIX-XXX: need to test functionality of NBIO handling in libPkix.
768
             * See bug 391180 */
769
            PRInt32 filesReady = 0;
770
            PRPollDesc *pollDesc = (PRPollDesc *)nbioContext;
771
            filesReady = PR_Poll(pollDesc, 1, PR_INTERVAL_NO_TIMEOUT);
772
            if (filesReady <= 0) {
773
                PKIX_ERROR(PKIX_PRPOLLRETBADFILENUM);
774
            }
775
        }
776
777
        PKIX_CHECK(
778
            PKIX_BuildChain(procParams, &nbioContext, &state,
779
                            &result, &verifyNode, plContext),
780
            PKIX_UNABLETOBUILDCHAIN);
781
782
    } while (nbioContext && state);
783
784
    *pResult = result;
785
786
cleanup:
787
    if (pVerifyNode) {
788
        *pVerifyNode = verifyNode;
789
    }
790
791
    PKIX_RETURN(CERTVFYPKIX);
792
}
793
794
/*
795
 * FUNCTION: cert_PkixErrorToNssCode
796
 * DESCRIPTION:
797
 *
798
 * Converts pkix error(PKIX_Error) structure to PR error codes.
799
 *
800
 * PKIX-XXX to be implemented. See 391183.
801
 *
802
 * PARAMETERS:
803
 *  "error"
804
 *      Pkix error that will be converted.
805
 *  "nssCode"
806
 *      Corresponding nss error code.
807
 *  "plContext"
808
 *      Platform-specific context pointer.
809
 * THREAD SAFETY:
810
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
811
 * RETURNS:
812
 *  Returns NULL if the function succeeds.
813
 *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
814
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
815
 */
816
static PKIX_Error *
817
cert_PkixErrorToNssCode(
818
    PKIX_Error *error,
819
    SECErrorCodes *pNssErr,
820
    void *plContext)
821
{
822
    int errLevel = 0;
823
    PKIX_Int32 nssErr = 0;
824
    PKIX_Error *errPtr = error;
825
826
    PKIX_ENTER(CERTVFYPKIX, "cert_PkixErrorToNssCode");
827
    PKIX_NULLCHECK_TWO(error, pNssErr);
828
829
    /* Loop until we find at least one error with non-null
830
     * plErr code, that is going to be nss error code. */
831
    while (errPtr) {
832
        if (errPtr->plErr && !nssErr) {
833
            nssErr = errPtr->plErr;
834
            if (!pkixLog)
835
                break;
836
        }
837
        if (pkixLog) {
838
#ifdef PKIX_ERROR_DESCRIPTION
839
            PR_LOG(pkixLog, 2, ("Error at level %d: %s\n", errLevel,
840
                                PKIX_ErrorText[errPtr->errCode]));
841
#else
842
            PR_LOG(pkixLog, 2, ("Error at level %d: Error code %d\n", errLevel,
843
                                errPtr->errCode));
844
#endif /* PKIX_ERROR_DESCRIPTION */
845
        }
846
        errPtr = errPtr->cause;
847
        errLevel += 1;
848
    }
849
    PORT_Assert(nssErr);
850
    if (!nssErr) {
851
        *pNssErr = SEC_ERROR_LIBPKIX_INTERNAL;
852
    } else {
853
        *pNssErr = nssErr;
854
    }
855
856
    PKIX_RETURN(CERTVFYPKIX);
857
}
858
859
/*
860
 * FUNCTION: cert_GetLogFromVerifyNode
861
 * DESCRIPTION:
862
 *
863
 * Recursive function that converts verify node tree-like set of structures
864
 * to CERTVerifyLog.
865
 *
866
 * PARAMETERS:
867
 *  "log"
868
 *      Pointed to already allocated CERTVerifyLog structure.
869
 *  "node"
870
 *      A node of PKIX_VerifyNode tree.
871
 *  "plContext"
872
 *      Platform-specific context pointer.
873
 * THREAD SAFETY:
874
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
875
 * RETURNS:
876
 *  Returns NULL if the function succeeds.
877
 *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
878
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
879
 */
880
static PKIX_Error *
881
cert_GetLogFromVerifyNode(
882
    CERTVerifyLog *log,
883
    PKIX_VerifyNode *node,
884
    void *plContext)
885
{
886
    PKIX_List *children = NULL;
887
    PKIX_VerifyNode *childNode = NULL;
888
889
    PKIX_ENTER(CERTVFYPKIX, "cert_GetLogFromVerifyNode");
890
891
    children = node->children;
892
893
    if (children == NULL) {
894
        PKIX_ERRORCODE errCode = PKIX_ANCHORDIDNOTCHAINTOCERT;
895
        if (node->error && node->error->errCode != errCode) {
896
            if (log != NULL) {
897
                SECErrorCodes nssErrorCode = 0;
898
                CERTCertificate *cert = NULL;
899
900
                cert = node->verifyCert->nssCert;
901
902
                PKIX_CHECK(
903
                    cert_PkixErrorToNssCode(node->error, &nssErrorCode,
904
                                            plContext),
905
                    PKIX_GETPKIXERRORCODEFAILED);
906
907
                cert_AddToVerifyLog(log, cert, nssErrorCode, node->depth, NULL);
908
            }
909
        }
910
        PKIX_RETURN(CERTVFYPKIX);
911
    } else {
912
        PRUint32 i = 0;
913
        PKIX_UInt32 length = 0;
914
915
        PKIX_CHECK(
916
            PKIX_List_GetLength(children, &length, plContext),
917
            PKIX_LISTGETLENGTHFAILED);
918
919
        for (i = 0; i < length; i++) {
920
921
            PKIX_CHECK(
922
                PKIX_List_GetItem(children, i, (PKIX_PL_Object **)&childNode,
923
                                  plContext),
924
                PKIX_LISTGETITEMFAILED);
925
926
            PKIX_CHECK(
927
                cert_GetLogFromVerifyNode(log, childNode, plContext),
928
                PKIX_ERRORINRECURSIVEEQUALSCALL);
929
930
            PKIX_DECREF(childNode);
931
        }
932
    }
933
934
cleanup:
935
    PKIX_DECREF(childNode);
936
937
    PKIX_RETURN(CERTVFYPKIX);
938
}
939
940
/*
941
 * FUNCTION: cert_GetBuildResults
942
 * DESCRIPTION:
943
 *
944
 * Converts pkix build results to nss results. This function is called
945
 * regardless of build result.
946
 *
947
 * If it called after chain was successfully constructed, then it will
948
 * convert:
949
 *   * pkix cert list that represent the chain to nss cert list
950
 *   * trusted root the chain was anchored to nss certificate.
951
 *
952
 * In case of failure it will convert:
953
 *   * pkix error to PR error code(will set it with PORT_SetError)
954
 *   * pkix validation log to nss CERTVerifyLog
955
 *
956
 * PARAMETERS:
957
 *  "buildResult"
958
 *      Build results returned by PKIX_BuildChain.
959
 *  "verifyNode"
960
 *      Tree-like structure of chain building/validation failures
961
 *      returned by PKIX_BuildChain. Ignored in case of success.
962
 *  "error"
963
 *      Final error returned by PKIX_BuildChain. Should be NULL in
964
 *      case of success.
965
 *  "log"
966
 *      Address of pre-allocated(if not NULL) CERTVerifyLog structure.
967
 *  "ptrustedRoot"
968
 *      Address of returned trusted root the chain was anchored to.
969
 *  "pvalidChain"
970
 *      Address of returned valid chain.
971
 *  "plContext"
972
 *      Platform-specific context pointer.
973
 * THREAD SAFETY:
974
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
975
 * RETURNS:
976
 *  Returns NULL if the function succeeds.
977
 *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
978
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
979
 */
980
static PKIX_Error *
981
cert_GetBuildResults(
982
    PKIX_BuildResult *buildResult,
983
    PKIX_VerifyNode *verifyNode,
984
    PKIX_Error *error,
985
    CERTVerifyLog *log,
986
    CERTCertificate **ptrustedRoot,
987
    CERTCertList **pvalidChain,
988
    void *plContext)
989
{
990
    PKIX_ValidateResult *validResult = NULL;
991
    CERTCertList *validChain = NULL;
992
    CERTCertificate *trustedRoot = NULL;
993
    PKIX_TrustAnchor *trustAnchor = NULL;
994
    PKIX_PL_Cert *trustedCert = NULL;
995
    PKIX_List *pkixCertChain = NULL;
996
997
    PKIX_ENTER(CERTVFYPKIX, "cert_GetBuildResults");
998
    if (buildResult == NULL && error == NULL) {
999
        PKIX_ERROR(PKIX_NULLARGUMENT);
1000
    }
1001
1002
    if (error) {
1003
        SECErrorCodes nssErrorCode = 0;
1004
        if (verifyNode) {
1005
            PKIX_Error *tmpError =
1006
                cert_GetLogFromVerifyNode(log, verifyNode, plContext);
1007
            if (tmpError) {
1008
                PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext);
1009
            }
1010
        }
1011
        cert_PkixErrorToNssCode(error, &nssErrorCode, plContext);
1012
        PORT_SetError(nssErrorCode);
1013
        goto cleanup;
1014
    }
1015
1016
    if (pvalidChain) {
1017
        PKIX_CHECK(
1018
            PKIX_BuildResult_GetCertChain(buildResult, &pkixCertChain,
1019
                                          plContext),
1020
            PKIX_BUILDRESULTGETCERTCHAINFAILED);
1021
1022
        PKIX_CHECK(
1023
            cert_PkixToNssCertsChain(pkixCertChain, &validChain, plContext),
1024
            PKIX_CERTCHAINTONSSCHAINFAILED);
1025
    }
1026
1027
    if (ptrustedRoot) {
1028
        PKIX_CHECK(
1029
            PKIX_BuildResult_GetValidateResult(buildResult, &validResult,
1030
                                               plContext),
1031
            PKIX_BUILDRESULTGETVALIDATERESULTFAILED);
1032
1033
        PKIX_CHECK(
1034
            PKIX_ValidateResult_GetTrustAnchor(validResult, &trustAnchor,
1035
                                               plContext),
1036
            PKIX_VALIDATERESULTGETTRUSTANCHORFAILED);
1037
1038
        PKIX_CHECK(
1039
            PKIX_TrustAnchor_GetTrustedCert(trustAnchor, &trustedCert,
1040
                                            plContext),
1041
            PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
1042
1043
        PKIX_CHECK(
1044
            PKIX_PL_Cert_GetCERTCertificate(trustedCert, &trustedRoot,
1045
                                            plContext),
1046
            PKIX_CERTGETCERTCERTIFICATEFAILED);
1047
    }
1048
1049
    PORT_Assert(!PKIX_ERROR_RECEIVED);
1050
1051
    if (trustedRoot) {
1052
        *ptrustedRoot = trustedRoot;
1053
    }
1054
    if (validChain) {
1055
        *pvalidChain = validChain;
1056
    }
1057
1058
cleanup:
1059
    if (PKIX_ERROR_RECEIVED) {
1060
        if (trustedRoot) {
1061
            CERT_DestroyCertificate(trustedRoot);
1062
        }
1063
        if (validChain) {
1064
            CERT_DestroyCertList(validChain);
1065
        }
1066
    }
1067
    PKIX_DECREF(trustAnchor);
1068
    PKIX_DECREF(trustedCert);
1069
    PKIX_DECREF(pkixCertChain);
1070
    PKIX_DECREF(validResult);
1071
    PKIX_DECREF(error);
1072
    PKIX_DECREF(verifyNode);
1073
    PKIX_DECREF(buildResult);
1074
1075
    PKIX_RETURN(CERTVFYPKIX);
1076
}
1077
#endif /* NSS_DISABLE_LIBPKIX */
1078
1079
/*
1080
 * FUNCTION: cert_VerifyCertChainPkix
1081
 * DESCRIPTION:
1082
 *
1083
 * The main wrapper function that is called from CERT_VerifyCert and
1084
 * CERT_VerifyCACertForUsage functions to validate cert with libpkix.
1085
 *
1086
 * PARAMETERS:
1087
 *  "cert"
1088
 *      Leaf certificate of a chain we want to build.
1089
 *  "checkSig"
1090
 *      Certificate signatures will not be verified if this
1091
 *      flag is set to PR_FALSE.
1092
 *  "requiredUsage"
1093
 *      Required usage for certificate and chain.
1094
 *  "time"
1095
 *      Validity time.
1096
 *  "wincx"
1097
 *      Nss database password token.
1098
 *  "log"
1099
 *      Address of already allocated CERTVerifyLog structure. Not
1100
 *      used if NULL;
1101
 *  "pSigerror"
1102
 *      Address of PRBool. If not NULL, returns true is cert chain
1103
 *      was invalidated because of bad certificate signature.
1104
 *  "pRevoked"
1105
 *      Address of PRBool. If not NULL, returns true is cert chain
1106
 *      was invalidated because a revoked certificate was found in
1107
 *      the chain.
1108
 * THREAD SAFETY:
1109
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1110
 * RETURNS:
1111
 *  SECFailure is chain building process has failed. SECSuccess otherwise.
1112
 */
1113
SECStatus
1114
cert_VerifyCertChainPkix(
1115
    CERTCertificate *cert,
1116
    PRBool checkSig,
1117
    SECCertUsage requiredUsage,
1118
    PRTime time,
1119
    void *wincx,
1120
    CERTVerifyLog *log,
1121
    PRBool *pSigerror,
1122
    PRBool *pRevoked)
1123
0
{
1124
0
#ifdef NSS_DISABLE_LIBPKIX
1125
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1126
0
    return SECFailure;
1127
#else
1128
    PKIX_ProcessingParams *procParams = NULL;
1129
    PKIX_BuildResult *result = NULL;
1130
    PKIX_VerifyNode *verifyNode = NULL;
1131
    PKIX_Error *error = NULL;
1132
1133
    SECStatus rv = SECFailure;
1134
    void *plContext = NULL;
1135
1136
#ifdef PKIX_OBJECT_LEAK_TEST
1137
    int leakedObjNum = 0;
1138
    int memLeakLoopCount = 0;
1139
    int objCountTable[PKIX_NUMTYPES];
1140
    int fnInvLocalCount = 0;
1141
    PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine;
1142
1143
    if (usePKIXValidationEngine) {
1144
        /* current memory leak testing implementation does not allow
1145
         * to run simultaneous tests one the same or a different threads.
1146
         * Setting the variable to false, to make additional chain
1147
         * validations be handled by old nss. */
1148
        usePKIXValidationEngine = PR_FALSE;
1149
    }
1150
    testStartFnStackPosition = 2;
1151
    fnStackNameArr[0] = "cert_VerifyCertChainPkix";
1152
    fnStackInvCountArr[0] = 0;
1153
    PKIX_Boolean abortOnLeak =
1154
        (PR_GetEnvSecure("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ? PKIX_FALSE
1155
                                                                         : PKIX_TRUE;
1156
    runningLeakTest = PKIX_TRUE;
1157
1158
    /* Prevent multi-threaded run of object leak test */
1159
    fnInvLocalCount = PR_ATOMIC_INCREMENT(&parallelFnInvocationCount);
1160
    PORT_Assert(fnInvLocalCount == 1);
1161
1162
    do {
1163
        rv = SECFailure;
1164
        plContext = NULL;
1165
        procParams = NULL;
1166
        result = NULL;
1167
        verifyNode = NULL;
1168
        error = NULL;
1169
        errorGenerated = PKIX_FALSE;
1170
        stackPosition = 0;
1171
1172
        if (leakedObjNum) {
1173
            pkix_pl_lifecycle_ObjectTableUpdate(objCountTable);
1174
        }
1175
        memLeakLoopCount += 1;
1176
#endif /* PKIX_OBJECT_LEAK_TEST */
1177
1178
        error =
1179
            cert_CreatePkixProcessingParams(cert, checkSig, time, wincx,
1180
                                            PR_FALSE /*use arena*/,
1181
                                            requiredUsage == certUsageStatusResponder,
1182
                                            &procParams, &plContext);
1183
        if (error) {
1184
            goto cleanup;
1185
        }
1186
1187
        error =
1188
            cert_ProcessingParamsSetKeyAndCertUsage(procParams, requiredUsage, 0,
1189
                                                    plContext);
1190
        if (error) {
1191
            goto cleanup;
1192
        }
1193
1194
        error =
1195
            cert_BuildAndValidateChain(procParams, &result, &verifyNode, plContext);
1196
        if (error) {
1197
            goto cleanup;
1198
        }
1199
1200
        if (pRevoked) {
1201
            /* Currently always PR_FALSE. Will be fixed as a part of 394077 */
1202
            *pRevoked = PR_FALSE;
1203
        }
1204
        if (pSigerror) {
1205
            /* Currently always PR_FALSE. Will be fixed as a part of 394077 */
1206
            *pSigerror = PR_FALSE;
1207
        }
1208
        rv = SECSuccess;
1209
1210
    cleanup:
1211
        error = cert_GetBuildResults(result, verifyNode, error, log, NULL, NULL,
1212
                                     plContext);
1213
        if (error) {
1214
            PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1215
        }
1216
        if (procParams) {
1217
            PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext);
1218
        }
1219
        if (plContext) {
1220
            PKIX_PL_NssContext_Destroy(plContext);
1221
        }
1222
1223
#ifdef PKIX_OBJECT_LEAK_TEST
1224
        leakedObjNum =
1225
            pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
1226
1227
        if (pkixLog && leakedObjNum) {
1228
            PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d."
1229
                                "Stack %s\n",
1230
                                memLeakLoopCount, errorFnStackString));
1231
        }
1232
        PR_Free(errorFnStackString);
1233
        errorFnStackString = NULL;
1234
        if (abortOnLeak) {
1235
            PORT_Assert(leakedObjNum == 0);
1236
        }
1237
1238
    } while (errorGenerated);
1239
1240
    runningLeakTest = PKIX_FALSE;
1241
    PR_ATOMIC_DECREMENT(&parallelFnInvocationCount);
1242
    usePKIXValidationEngine = savedUsePkixEngFlag;
1243
#endif /* PKIX_OBJECT_LEAK_TEST */
1244
1245
    return rv;
1246
#endif /* NSS_DISABLE_LIBPKIX */
1247
}
1248
1249
#ifndef NSS_DISABLE_LIBPKIX
1250
PKIX_CertSelector *
1251
cert_GetTargetCertConstraints(CERTCertificate *target, void *plContext)
1252
{
1253
    PKIX_ComCertSelParams *certSelParams = NULL;
1254
    PKIX_CertSelector *certSelector = NULL;
1255
    PKIX_CertSelector *r = NULL;
1256
    PKIX_PL_Cert *eeCert = NULL;
1257
    PKIX_Error *error = NULL;
1258
1259
    error = PKIX_PL_Cert_CreateFromCERTCertificate(target, &eeCert, plContext);
1260
    if (error != NULL)
1261
        goto cleanup;
1262
1263
    error = PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext);
1264
    if (error != NULL)
1265
        goto cleanup;
1266
1267
    error = PKIX_ComCertSelParams_Create(&certSelParams, plContext);
1268
    if (error != NULL)
1269
        goto cleanup;
1270
1271
    error = PKIX_ComCertSelParams_SetCertificate(
1272
        certSelParams, eeCert, plContext);
1273
    if (error != NULL)
1274
        goto cleanup;
1275
1276
    error = PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext);
1277
    if (error != NULL)
1278
        goto cleanup;
1279
1280
    error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certSelector, plContext);
1281
    if (error == NULL)
1282
        r = certSelector;
1283
1284
cleanup:
1285
    if (certSelParams != NULL)
1286
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelParams, plContext);
1287
1288
    if (eeCert != NULL)
1289
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)eeCert, plContext);
1290
1291
    if (certSelector != NULL)
1292
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext);
1293
1294
    if (error != NULL) {
1295
        SECErrorCodes nssErr;
1296
1297
        cert_PkixErrorToNssCode(error, &nssErr, plContext);
1298
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1299
        PORT_SetError(nssErr);
1300
    }
1301
1302
    return r;
1303
}
1304
1305
static PKIX_List *
1306
cert_GetCertStores(void *plContext)
1307
{
1308
    PKIX_CertStore *certStore = NULL;
1309
    PKIX_List *certStores = NULL;
1310
    PKIX_List *r = NULL;
1311
    PKIX_Error *error = NULL;
1312
1313
    error = PKIX_PL_Pk11CertStore_Create(&certStore, plContext);
1314
    if (error != NULL)
1315
        goto cleanup;
1316
1317
    error = PKIX_List_Create(&certStores, plContext);
1318
    if (error != NULL)
1319
        goto cleanup;
1320
1321
    error = PKIX_List_AppendItem(certStores,
1322
                                 (PKIX_PL_Object *)certStore, plContext);
1323
    if (error != NULL)
1324
        goto cleanup;
1325
1326
    error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certStores, plContext);
1327
    if (error == NULL)
1328
        r = certStores;
1329
1330
cleanup:
1331
    if (certStores != NULL)
1332
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext);
1333
1334
    if (certStore != NULL)
1335
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStore, plContext);
1336
1337
    if (error != NULL) {
1338
        SECErrorCodes nssErr;
1339
1340
        cert_PkixErrorToNssCode(error, &nssErr, plContext);
1341
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1342
        PORT_SetError(nssErr);
1343
    }
1344
1345
    return r;
1346
}
1347
1348
struct fake_PKIX_PL_CertStruct {
1349
    CERTCertificate *nssCert;
1350
};
1351
1352
/* This needs to be part of the PKIX_PL_* */
1353
/* This definitely needs to go away, and be replaced with
1354
   a real accessor function in PKIX */
1355
static CERTCertificate *
1356
cert_NSSCertFromPKIXCert(const PKIX_PL_Cert *pkix_cert)
1357
{
1358
    struct fake_PKIX_PL_CertStruct *fcert = NULL;
1359
1360
    fcert = (struct fake_PKIX_PL_CertStruct *)pkix_cert;
1361
1362
    return CERT_DupCertificate(fcert->nssCert);
1363
}
1364
1365
PKIX_List *
1366
cert_PKIXMakeOIDList(const SECOidTag *oids, int oidCount, void *plContext)
1367
{
1368
    PKIX_List *r = NULL;
1369
    PKIX_List *policyList = NULL;
1370
    PKIX_PL_OID *policyOID = NULL;
1371
    PKIX_Error *error = NULL;
1372
    int i;
1373
1374
    error = PKIX_List_Create(&policyList, plContext);
1375
    if (error != NULL) {
1376
        goto cleanup;
1377
    }
1378
1379
    for (i = 0; i < oidCount; i++) {
1380
        error = PKIX_PL_OID_Create(oids[i], &policyOID, plContext);
1381
        if (error) {
1382
            goto cleanup;
1383
        }
1384
        error = PKIX_List_AppendItem(policyList,
1385
                                     (PKIX_PL_Object *)policyOID, plContext);
1386
        if (error != NULL) {
1387
            goto cleanup;
1388
        }
1389
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
1390
        policyOID = NULL;
1391
    }
1392
1393
    error = PKIX_List_SetImmutable(policyList, plContext);
1394
    if (error != NULL)
1395
        goto cleanup;
1396
1397
    error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)policyList, plContext);
1398
    if (error == NULL)
1399
        r = policyList;
1400
1401
cleanup:
1402
    if (policyOID != NULL) {
1403
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
1404
    }
1405
    if (policyList != NULL) {
1406
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyList, plContext);
1407
    }
1408
    if (error != NULL) {
1409
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1410
    }
1411
1412
    return r;
1413
}
1414
1415
CERTValOutParam *
1416
cert_pkix_FindOutputParam(CERTValOutParam *params, const CERTValParamOutType t)
1417
{
1418
    CERTValOutParam *i;
1419
    if (params == NULL) {
1420
        return NULL;
1421
    }
1422
    for (i = params; i->type != cert_po_end; i++) {
1423
        if (i->type == t) {
1424
            return i;
1425
        }
1426
    }
1427
    return NULL;
1428
}
1429
1430
static PKIX_Error *
1431
setRevocationMethod(PKIX_RevocationChecker *revChecker,
1432
                    PKIX_ProcessingParams *procParams,
1433
                    const CERTRevocationTests *revTest,
1434
                    CERTRevocationMethodIndex certRevMethod,
1435
                    PKIX_RevocationMethodType pkixRevMethod,
1436
                    PKIX_Boolean verifyResponderUsages,
1437
                    PKIX_Boolean isLeafTest,
1438
                    void *plContext)
1439
{
1440
    PKIX_UInt32 methodFlags = 0;
1441
    PKIX_Error *error = NULL;
1442
    PKIX_UInt32 priority = 0;
1443
1444
    if (revTest->number_of_defined_methods <= (PRUint32)certRevMethod) {
1445
        return NULL;
1446
    }
1447
    if (revTest->preferred_methods) {
1448
        unsigned int i = 0;
1449
        for (; i < revTest->number_of_preferred_methods; i++) {
1450
            if (revTest->preferred_methods[i] == certRevMethod)
1451
                break;
1452
        }
1453
        priority = i;
1454
    }
1455
    methodFlags = revTest->cert_rev_flags_per_method[certRevMethod];
1456
    if (verifyResponderUsages &&
1457
        pkixRevMethod == PKIX_RevocationMethod_OCSP) {
1458
        methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING;
1459
    }
1460
    error =
1461
        PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
1462
                                                  pkixRevMethod, methodFlags,
1463
                                                  priority, NULL,
1464
                                                  isLeafTest, plContext);
1465
    return error;
1466
}
1467
1468
SECStatus
1469
cert_pkixSetParam(PKIX_ProcessingParams *procParams,
1470
                  const CERTValInParam *param, void *plContext)
1471
{
1472
    PKIX_Error *error = NULL;
1473
    SECStatus r = SECSuccess;
1474
    PKIX_PL_Date *date = NULL;
1475
    PKIX_List *policyOIDList = NULL;
1476
    PKIX_List *certListPkix = NULL;
1477
    const CERTRevocationFlags *flags;
1478
    SECErrorCodes errCode = SEC_ERROR_INVALID_ARGS;
1479
    const CERTCertList *certList = NULL;
1480
    CERTCertListNode *node;
1481
    PKIX_PL_Cert *certPkix = NULL;
1482
    PKIX_TrustAnchor *trustAnchor = NULL;
1483
    PKIX_RevocationChecker *revChecker = NULL;
1484
    PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext *)plContext;
1485
1486
    /* XXX we need a way to map generic PKIX error to generic NSS errors */
1487
1488
    switch (param->type) {
1489
1490
        case cert_pi_policyOID:
1491
1492
            /* needed? */
1493
            error = PKIX_ProcessingParams_SetExplicitPolicyRequired(
1494
                procParams, PKIX_TRUE, plContext);
1495
1496
            if (error != NULL) {
1497
                break;
1498
            }
1499
1500
            policyOIDList = cert_PKIXMakeOIDList(param->value.array.oids,
1501
                                                 param->value.arraySize, plContext);
1502
            if (policyOIDList == NULL) {
1503
                r = SECFailure;
1504
                PORT_SetError(SEC_ERROR_INVALID_ARGS);
1505
                break;
1506
            }
1507
1508
            error = PKIX_ProcessingParams_SetInitialPolicies(
1509
                procParams, policyOIDList, plContext);
1510
            break;
1511
1512
        case cert_pi_date:
1513
            if (param->value.scalar.time == 0) {
1514
                error = PKIX_PL_Date_Create_UTCTime(NULL, &date, plContext);
1515
                if (error != NULL) {
1516
                    errCode = SEC_ERROR_INVALID_TIME;
1517
                    break;
1518
                }
1519
            } else {
1520
                error = pkix_pl_Date_CreateFromPRTime(param->value.scalar.time,
1521
                                                      &date, plContext);
1522
                if (error != NULL) {
1523
                    errCode = SEC_ERROR_INVALID_TIME;
1524
                    break;
1525
                }
1526
            }
1527
1528
            error = PKIX_ProcessingParams_SetDate(procParams, date, plContext);
1529
            if (error != NULL) {
1530
                errCode = SEC_ERROR_INVALID_TIME;
1531
            }
1532
            break;
1533
1534
        case cert_pi_revocationFlags: {
1535
            PKIX_UInt32 leafIMFlags = 0;
1536
            PKIX_UInt32 chainIMFlags = 0;
1537
            PKIX_Boolean validatingResponderCert = PKIX_FALSE;
1538
1539
            flags = param->value.pointer.revocation;
1540
            if (!flags) {
1541
                PORT_SetError(errCode);
1542
                r = SECFailure;
1543
                break;
1544
            }
1545
1546
            leafIMFlags =
1547
                flags->leafTests.cert_rev_method_independent_flags;
1548
            chainIMFlags =
1549
                flags->chainTests.cert_rev_method_independent_flags;
1550
1551
            error =
1552
                PKIX_RevocationChecker_Create(leafIMFlags, chainIMFlags,
1553
                                              &revChecker, plContext);
1554
            if (error) {
1555
                break;
1556
            }
1557
1558
            error =
1559
                PKIX_ProcessingParams_SetRevocationChecker(procParams,
1560
                                                           revChecker, plContext);
1561
            if (error) {
1562
                break;
1563
            }
1564
1565
            if (((PKIX_PL_NssContext *)plContext)->certificateUsage &
1566
                certificateUsageStatusResponder) {
1567
                validatingResponderCert = PKIX_TRUE;
1568
            }
1569
1570
            error = setRevocationMethod(revChecker,
1571
                                        procParams, &flags->leafTests,
1572
                                        cert_revocation_method_crl,
1573
                                        PKIX_RevocationMethod_CRL,
1574
                                        validatingResponderCert,
1575
                                        PKIX_TRUE, plContext);
1576
            if (error) {
1577
                break;
1578
            }
1579
1580
            error = setRevocationMethod(revChecker,
1581
                                        procParams, &flags->leafTests,
1582
                                        cert_revocation_method_ocsp,
1583
                                        PKIX_RevocationMethod_OCSP,
1584
                                        validatingResponderCert,
1585
                                        PKIX_TRUE, plContext);
1586
            if (error) {
1587
                break;
1588
            }
1589
1590
            error = setRevocationMethod(revChecker,
1591
                                        procParams, &flags->chainTests,
1592
                                        cert_revocation_method_crl,
1593
                                        PKIX_RevocationMethod_CRL,
1594
                                        validatingResponderCert,
1595
                                        PKIX_FALSE, plContext);
1596
            if (error) {
1597
                break;
1598
            }
1599
1600
            error = setRevocationMethod(revChecker,
1601
                                        procParams, &flags->chainTests,
1602
                                        cert_revocation_method_ocsp,
1603
                                        PKIX_RevocationMethod_OCSP,
1604
                                        validatingResponderCert,
1605
                                        PKIX_FALSE, plContext);
1606
            if (error) {
1607
                break;
1608
            }
1609
1610
        } break;
1611
1612
        case cert_pi_trustAnchors:
1613
            certList = param->value.pointer.chain;
1614
            if (!certList) {
1615
                PORT_SetError(errCode);
1616
                r = SECFailure;
1617
                break;
1618
            }
1619
            error = PKIX_List_Create(&certListPkix, plContext);
1620
            if (error != NULL) {
1621
                break;
1622
            }
1623
            for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
1624
                 node = CERT_LIST_NEXT(node)) {
1625
                error = PKIX_PL_Cert_CreateFromCERTCertificate(node->cert,
1626
                                                               &certPkix, plContext);
1627
                if (error) {
1628
                    break;
1629
                }
1630
                error = PKIX_TrustAnchor_CreateWithCert(certPkix, &trustAnchor,
1631
                                                        plContext);
1632
                if (error) {
1633
                    break;
1634
                }
1635
                error = PKIX_List_AppendItem(certListPkix,
1636
                                             (PKIX_PL_Object *)trustAnchor, plContext);
1637
                if (error) {
1638
                    break;
1639
                }
1640
                PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
1641
                trustAnchor = NULL;
1642
                PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext);
1643
                certPkix = NULL;
1644
            }
1645
            error =
1646
                PKIX_ProcessingParams_SetTrustAnchors(procParams, certListPkix,
1647
                                                      plContext);
1648
            break;
1649
1650
        case cert_pi_useAIACertFetch:
1651
            error =
1652
                PKIX_ProcessingParams_SetUseAIAForCertFetching(procParams,
1653
                                                               (PRBool)(param->value.scalar.b !=
1654
                                                                        0),
1655
                                                               plContext);
1656
            break;
1657
1658
        case cert_pi_chainVerifyCallback: {
1659
            const CERTChainVerifyCallback *chainVerifyCallback =
1660
                param->value.pointer.chainVerifyCallback;
1661
            if (!chainVerifyCallback || !chainVerifyCallback->isChainValid) {
1662
                PORT_SetError(errCode);
1663
                r = SECFailure;
1664
                break;
1665
            }
1666
1667
            nssContext->chainVerifyCallback = *chainVerifyCallback;
1668
        } break;
1669
1670
        case cert_pi_useOnlyTrustAnchors:
1671
            error =
1672
                PKIX_ProcessingParams_SetUseOnlyTrustAnchors(procParams,
1673
                                                             (PRBool)(param->value.scalar.b !=
1674
                                                                      0),
1675
                                                             plContext);
1676
            break;
1677
1678
        default:
1679
            PORT_SetError(errCode);
1680
            r = SECFailure;
1681
            break;
1682
    }
1683
1684
    if (policyOIDList != NULL)
1685
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOIDList, plContext);
1686
1687
    if (date != NULL)
1688
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)date, plContext);
1689
1690
    if (revChecker != NULL)
1691
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)revChecker, plContext);
1692
1693
    if (certListPkix)
1694
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certListPkix, plContext);
1695
1696
    if (trustAnchor)
1697
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
1698
1699
    if (certPkix)
1700
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext);
1701
1702
    if (error != NULL) {
1703
        PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1704
        PORT_SetError(errCode);
1705
        r = SECFailure;
1706
    }
1707
1708
    return r;
1709
}
1710
1711
void
1712
cert_pkixDestroyValOutParam(CERTValOutParam *params)
1713
{
1714
    CERTValOutParam *i;
1715
1716
    if (params == NULL) {
1717
        return;
1718
    }
1719
    for (i = params; i->type != cert_po_end; i++) {
1720
        switch (i->type) {
1721
            case cert_po_trustAnchor:
1722
                if (i->value.pointer.cert) {
1723
                    CERT_DestroyCertificate(i->value.pointer.cert);
1724
                    i->value.pointer.cert = NULL;
1725
                }
1726
                break;
1727
1728
            case cert_po_certList:
1729
                if (i->value.pointer.chain) {
1730
                    CERT_DestroyCertList(i->value.pointer.chain);
1731
                    i->value.pointer.chain = NULL;
1732
                }
1733
                break;
1734
1735
            default:
1736
                break;
1737
        }
1738
    }
1739
}
1740
1741
static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags[2] = {
1742
    /* crl */
1743
    CERT_REV_M_TEST_USING_THIS_METHOD |
1744
        CERT_REV_M_FORBID_NETWORK_FETCHING |
1745
        CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1746
    /* ocsp */
1747
    CERT_REV_M_TEST_USING_THIS_METHOD
1748
};
1749
1750
static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags[2] = {
1751
    /* crl */
1752
    CERT_REV_M_TEST_USING_THIS_METHOD |
1753
        CERT_REV_M_FORBID_NETWORK_FETCHING |
1754
        CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1755
    /* ocsp */
1756
    0
1757
};
1758
1759
static CERTRevocationMethodIndex
1760
    certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference = {
1761
        cert_revocation_method_crl
1762
    };
1763
1764
static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy = {
1765
    { /* leafTests */
1766
      2,
1767
      certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags,
1768
      1,
1769
      &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference,
1770
      0 },
1771
    { /* chainTests */
1772
      2,
1773
      certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags,
1774
      0,
1775
      0,
1776
      0 }
1777
};
1778
#endif /* NSS_DISABLE_LIBPKIX */
1779
1780
extern const CERTRevocationFlags *
1781
CERT_GetClassicOCSPEnabledSoftFailurePolicy()
1782
0
{
1783
0
#ifdef NSS_DISABLE_LIBPKIX
1784
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1785
0
    return NULL;
1786
#else
1787
    return &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy;
1788
#endif /* NSS_DISABLE_LIBPKIX */
1789
}
1790
1791
#ifndef NSS_DISABLE_LIBPKIX
1792
static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags[2] = {
1793
    /* crl */
1794
    CERT_REV_M_TEST_USING_THIS_METHOD |
1795
        CERT_REV_M_FORBID_NETWORK_FETCHING |
1796
        CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1797
    /* ocsp */
1798
    CERT_REV_M_TEST_USING_THIS_METHOD |
1799
        CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
1800
};
1801
1802
static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags[2] = {
1803
    /* crl */
1804
    CERT_REV_M_TEST_USING_THIS_METHOD |
1805
        CERT_REV_M_FORBID_NETWORK_FETCHING |
1806
        CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1807
    /* ocsp */
1808
    0
1809
};
1810
1811
static CERTRevocationMethodIndex
1812
    certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference = {
1813
        cert_revocation_method_crl
1814
    };
1815
1816
static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy = {
1817
    { /* leafTests */
1818
      2,
1819
      certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags,
1820
      1,
1821
      &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference,
1822
      0 },
1823
    { /* chainTests */
1824
      2,
1825
      certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags,
1826
      0,
1827
      0,
1828
      0 }
1829
};
1830
#endif /* NSS_DISABLE_LIBPKIX */
1831
1832
extern const CERTRevocationFlags *
1833
CERT_GetClassicOCSPEnabledHardFailurePolicy()
1834
0
{
1835
0
#ifdef NSS_DISABLE_LIBPKIX
1836
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1837
0
    return NULL;
1838
#else
1839
    return &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy;
1840
#endif /* NSS_DISABLE_LIBPKIX */
1841
}
1842
1843
#ifndef NSS_DISABLE_LIBPKIX
1844
static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags[2] = {
1845
    /* crl */
1846
    CERT_REV_M_TEST_USING_THIS_METHOD |
1847
        CERT_REV_M_FORBID_NETWORK_FETCHING |
1848
        CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1849
    /* ocsp */
1850
    0
1851
};
1852
1853
static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags[2] = {
1854
    /* crl */
1855
    CERT_REV_M_TEST_USING_THIS_METHOD |
1856
        CERT_REV_M_FORBID_NETWORK_FETCHING |
1857
        CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1858
    /* ocsp */
1859
    0
1860
};
1861
1862
static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Disabled_Policy = {
1863
    { /* leafTests */
1864
      2,
1865
      certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags,
1866
      0,
1867
      0,
1868
      0 },
1869
    { /* chainTests */
1870
      2,
1871
      certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags,
1872
      0,
1873
      0,
1874
      0 }
1875
};
1876
#endif /* NSS_DISABLE_LIBPKIX */
1877
1878
extern const CERTRevocationFlags *
1879
CERT_GetClassicOCSPDisabledPolicy()
1880
0
{
1881
0
#ifdef NSS_DISABLE_LIBPKIX
1882
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1883
0
    return NULL;
1884
#else
1885
    return &certRev_NSS_3_11_Ocsp_Disabled_Policy;
1886
#endif /* NSS_DISABLE_LIBPKIX */
1887
}
1888
1889
#ifndef NSS_DISABLE_LIBPKIX
1890
static PRUint64 certRev_PKIX_Verify_Nist_Policy_LeafFlags[2] = {
1891
    /* crl */
1892
    CERT_REV_M_TEST_USING_THIS_METHOD |
1893
        CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO |
1894
        CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE,
1895
    /* ocsp */
1896
    0
1897
};
1898
1899
static PRUint64 certRev_PKIX_Verify_Nist_Policy_ChainFlags[2] = {
1900
    /* crl */
1901
    CERT_REV_M_TEST_USING_THIS_METHOD |
1902
        CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO |
1903
        CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE,
1904
    /* ocsp */
1905
    0
1906
};
1907
1908
static const CERTRevocationFlags certRev_PKIX_Verify_Nist_Policy = {
1909
    { /* leafTests */
1910
      2,
1911
      certRev_PKIX_Verify_Nist_Policy_LeafFlags,
1912
      0,
1913
      0,
1914
      0 },
1915
    { /* chainTests */
1916
      2,
1917
      certRev_PKIX_Verify_Nist_Policy_ChainFlags,
1918
      0,
1919
      0,
1920
      0 }
1921
};
1922
#endif /* NSS_DISABLE_LIBPKIX */
1923
1924
extern const CERTRevocationFlags *
1925
CERT_GetPKIXVerifyNistRevocationPolicy()
1926
0
{
1927
0
#ifdef NSS_DISABLE_LIBPKIX
1928
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1929
0
    return NULL;
1930
#else
1931
    return &certRev_PKIX_Verify_Nist_Policy;
1932
#endif /* NSS_DISABLE_LIBPKIX */
1933
}
1934
1935
CERTRevocationFlags *
1936
CERT_AllocCERTRevocationFlags(
1937
    PRUint32 number_leaf_methods, PRUint32 number_leaf_pref_methods,
1938
    PRUint32 number_chain_methods, PRUint32 number_chain_pref_methods)
1939
0
{
1940
0
#ifdef NSS_DISABLE_LIBPKIX
1941
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1942
0
    return NULL;
1943
#else
1944
    CERTRevocationFlags *flags;
1945
1946
    flags = PORT_New(CERTRevocationFlags);
1947
    if (!flags)
1948
        return (NULL);
1949
1950
    flags->leafTests.number_of_defined_methods = number_leaf_methods;
1951
    flags->leafTests.cert_rev_flags_per_method =
1952
        PORT_NewArray(PRUint64, number_leaf_methods);
1953
1954
    flags->leafTests.number_of_preferred_methods = number_leaf_pref_methods;
1955
    flags->leafTests.preferred_methods =
1956
        PORT_NewArray(CERTRevocationMethodIndex, number_leaf_pref_methods);
1957
1958
    flags->chainTests.number_of_defined_methods = number_chain_methods;
1959
    flags->chainTests.cert_rev_flags_per_method =
1960
        PORT_NewArray(PRUint64, number_chain_methods);
1961
1962
    flags->chainTests.number_of_preferred_methods = number_chain_pref_methods;
1963
    flags->chainTests.preferred_methods =
1964
        PORT_NewArray(CERTRevocationMethodIndex, number_chain_pref_methods);
1965
1966
    if (!flags->leafTests.cert_rev_flags_per_method ||
1967
        !flags->leafTests.preferred_methods ||
1968
        !flags->chainTests.cert_rev_flags_per_method ||
1969
        !flags->chainTests.preferred_methods) {
1970
        CERT_DestroyCERTRevocationFlags(flags);
1971
        return (NULL);
1972
    }
1973
1974
    return flags;
1975
#endif /* NSS_DISABLE_LIBPKIX */
1976
}
1977
1978
void
1979
CERT_DestroyCERTRevocationFlags(CERTRevocationFlags *flags)
1980
0
{
1981
0
#ifdef NSS_DISABLE_LIBPKIX
1982
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1983
0
    return;
1984
#else
1985
    if (!flags)
1986
        return;
1987
1988
    if (flags->leafTests.cert_rev_flags_per_method)
1989
        PORT_Free(flags->leafTests.cert_rev_flags_per_method);
1990
1991
    if (flags->leafTests.preferred_methods)
1992
        PORT_Free(flags->leafTests.preferred_methods);
1993
1994
    if (flags->chainTests.cert_rev_flags_per_method)
1995
        PORT_Free(flags->chainTests.cert_rev_flags_per_method);
1996
1997
    if (flags->chainTests.preferred_methods)
1998
        PORT_Free(flags->chainTests.preferred_methods);
1999
2000
    PORT_Free(flags);
2001
#endif /* NSS_DISABLE_LIBPKIX */
2002
}
2003
2004
/*
2005
 * CERT_PKIXVerifyCert
2006
 *
2007
 * Verify a Certificate using the PKIX library.
2008
 *
2009
 * Parameters:
2010
 *  cert    - the target certificate to verify. Must be non-null
2011
 *  params  - an array of type/value parameters which can be
2012
 *            used to modify the behavior of the validation
2013
 *            algorithm, or supply additional constraints.
2014
 *
2015
 *  outputTrustAnchor - the trust anchor which the certificate
2016
 *                      chains to. The caller is responsible
2017
 *                      for freeing this.
2018
 *
2019
 * Example Usage:
2020
 *    CERTValParam args[3];
2021
 *    args[0].type = cvpt_policyOID;
2022
 *    args[0].value.si = oid;
2023
 *    args[1].type = revCheckRequired;
2024
 *    args[1].value.b = PR_TRUE;
2025
 *    args[2].type = cvpt_end;
2026
 *
2027
 *    CERT_PKIXVerifyCert(cert, &output, args
2028
 */
2029
SECStatus
2030
CERT_PKIXVerifyCert(
2031
    CERTCertificate *cert,
2032
    SECCertificateUsage usages,
2033
    CERTValInParam *paramsIn,
2034
    CERTValOutParam *paramsOut,
2035
    void *wincx)
2036
0
{
2037
0
#ifdef NSS_DISABLE_LIBPKIX
2038
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
2039
0
    return SECFailure;
2040
#else
2041
    SECStatus r = SECFailure;
2042
    PKIX_Error *error = NULL;
2043
    PKIX_ProcessingParams *procParams = NULL;
2044
    PKIX_BuildResult *buildResult = NULL;
2045
    void *nbioContext = NULL; /* for non-blocking IO */
2046
    void *buildState = NULL;  /* for non-blocking IO */
2047
    PKIX_CertSelector *certSelector = NULL;
2048
    PKIX_List *certStores = NULL;
2049
    PKIX_ValidateResult *valResult = NULL;
2050
    PKIX_VerifyNode *verifyNode = NULL;
2051
    PKIX_TrustAnchor *trustAnchor = NULL;
2052
    PKIX_PL_Cert *trustAnchorCert = NULL;
2053
    PKIX_List *builtCertList = NULL;
2054
    CERTValOutParam *oparam = NULL;
2055
    int i = 0;
2056
2057
    void *plContext = NULL;
2058
2059
#ifdef PKIX_OBJECT_LEAK_TEST
2060
    int leakedObjNum = 0;
2061
    int memLeakLoopCount = 0;
2062
    int objCountTable[PKIX_NUMTYPES];
2063
    int fnInvLocalCount = 0;
2064
    PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine;
2065
2066
    if (usePKIXValidationEngine) {
2067
        /* current memory leak testing implementation does not allow
2068
         * to run simultaneous tests one the same or a different threads.
2069
         * Setting the variable to false, to make additional chain
2070
         * validations be handled by old nss. */
2071
        usePKIXValidationEngine = PR_FALSE;
2072
    }
2073
    testStartFnStackPosition = 1;
2074
    fnStackNameArr[0] = "CERT_PKIXVerifyCert";
2075
    fnStackInvCountArr[0] = 0;
2076
    PKIX_Boolean abortOnLeak =
2077
        (PR_GetEnvSecure("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ? PKIX_FALSE
2078
                                                                         : PKIX_TRUE;
2079
    runningLeakTest = PKIX_TRUE;
2080
2081
    /* Prevent multi-threaded run of object leak test */
2082
    fnInvLocalCount = PR_ATOMIC_INCREMENT(&parallelFnInvocationCount);
2083
    PORT_Assert(fnInvLocalCount == 1);
2084
2085
    do {
2086
        r = SECFailure;
2087
        error = NULL;
2088
        procParams = NULL;
2089
        buildResult = NULL;
2090
        nbioContext = NULL; /* for non-blocking IO */
2091
        buildState = NULL;  /* for non-blocking IO */
2092
        certSelector = NULL;
2093
        certStores = NULL;
2094
        valResult = NULL;
2095
        verifyNode = NULL;
2096
        trustAnchor = NULL;
2097
        trustAnchorCert = NULL;
2098
        builtCertList = NULL;
2099
        oparam = NULL;
2100
        i = 0;
2101
        errorGenerated = PKIX_FALSE;
2102
        stackPosition = 0;
2103
2104
        if (leakedObjNum) {
2105
            pkix_pl_lifecycle_ObjectTableUpdate(objCountTable);
2106
        }
2107
        memLeakLoopCount += 1;
2108
#endif /* PKIX_OBJECT_LEAK_TEST */
2109
2110
        error = PKIX_PL_NssContext_Create(
2111
            0, PR_FALSE /*use arena*/, wincx, &plContext);
2112
        if (error != NULL) { /* need pkix->nss error map */
2113
            PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
2114
            goto cleanup;
2115
        }
2116
2117
        error = pkix_pl_NssContext_SetCertUsage(usages, plContext);
2118
        if (error != NULL) {
2119
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
2120
            goto cleanup;
2121
        }
2122
2123
        error = PKIX_ProcessingParams_Create(&procParams, plContext);
2124
        if (error != NULL) { /* need pkix->nss error map */
2125
            PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
2126
            goto cleanup;
2127
        }
2128
2129
        /* local cert store should be set into procParams before
2130
         * filling in revocation settings. */
2131
        certStores = cert_GetCertStores(plContext);
2132
        if (certStores == NULL) {
2133
            goto cleanup;
2134
        }
2135
        error = PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext);
2136
        if (error != NULL) {
2137
            goto cleanup;
2138
        }
2139
2140
        /* now process the extensible input parameters structure */
2141
        if (paramsIn != NULL) {
2142
            i = 0;
2143
            while (paramsIn[i].type != cert_pi_end) {
2144
                if (paramsIn[i].type >= cert_pi_max) {
2145
                    PORT_SetError(SEC_ERROR_INVALID_ARGS);
2146
                    goto cleanup;
2147
                }
2148
                if (cert_pkixSetParam(procParams,
2149
                                      &paramsIn[i], plContext) !=
2150
                    SECSuccess) {
2151
                    PORT_SetError(SEC_ERROR_INVALID_ARGS);
2152
                    goto cleanup;
2153
                }
2154
                i++;
2155
            }
2156
        }
2157
2158
        certSelector = cert_GetTargetCertConstraints(cert, plContext);
2159
        if (certSelector == NULL) {
2160
            goto cleanup;
2161
        }
2162
        error = PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext);
2163
        if (error != NULL) {
2164
            goto cleanup;
2165
        }
2166
2167
        error = PKIX_BuildChain(procParams, &nbioContext,
2168
                                &buildState, &buildResult, &verifyNode,
2169
                                plContext);
2170
        if (error != NULL) {
2171
            goto cleanup;
2172
        }
2173
2174
        error = PKIX_BuildResult_GetValidateResult(buildResult, &valResult,
2175
                                                   plContext);
2176
        if (error != NULL) {
2177
            goto cleanup;
2178
        }
2179
2180
        error = PKIX_ValidateResult_GetTrustAnchor(valResult, &trustAnchor,
2181
                                                   plContext);
2182
        if (error != NULL) {
2183
            goto cleanup;
2184
        }
2185
2186
        if (trustAnchor != NULL) {
2187
            error = PKIX_TrustAnchor_GetTrustedCert(trustAnchor, &trustAnchorCert,
2188
                                                    plContext);
2189
            if (error != NULL) {
2190
                goto cleanup;
2191
            }
2192
        }
2193
2194
#ifdef PKIX_OBJECT_LEAK_TEST
2195
        /* Can not continue if error was generated but not returned.
2196
         * Jumping to cleanup. */
2197
        if (errorGenerated)
2198
            goto cleanup;
2199
#endif /* PKIX_OBJECT_LEAK_TEST */
2200
2201
        oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_trustAnchor);
2202
        if (oparam != NULL) {
2203
            if (trustAnchorCert != NULL) {
2204
                oparam->value.pointer.cert =
2205
                    cert_NSSCertFromPKIXCert(trustAnchorCert);
2206
            } else {
2207
                oparam->value.pointer.cert = NULL;
2208
            }
2209
        }
2210
2211
        error = PKIX_BuildResult_GetCertChain(buildResult, &builtCertList,
2212
                                              plContext);
2213
        if (error != NULL) {
2214
            goto cleanup;
2215
        }
2216
2217
        oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_certList);
2218
        if (oparam != NULL) {
2219
            error = cert_PkixToNssCertsChain(builtCertList,
2220
                                             &oparam->value.pointer.chain,
2221
                                             plContext);
2222
            if (error)
2223
                goto cleanup;
2224
        }
2225
2226
        r = SECSuccess;
2227
2228
    cleanup:
2229
        if (verifyNode) {
2230
            /* Return validation log only upon error. */
2231
            oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_errorLog);
2232
#ifdef PKIX_OBJECT_LEAK_TEST
2233
            if (!errorGenerated)
2234
#endif /* PKIX_OBJECT_LEAK_TEST */
2235
                if (r && oparam != NULL) {
2236
                    PKIX_Error *tmpError =
2237
                        cert_GetLogFromVerifyNode(oparam->value.pointer.log,
2238
                                                  verifyNode, plContext);
2239
                    if (tmpError) {
2240
                        PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext);
2241
                    }
2242
                }
2243
            PKIX_PL_Object_DecRef((PKIX_PL_Object *)verifyNode, plContext);
2244
        }
2245
2246
        if (procParams != NULL)
2247
            PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext);
2248
2249
        if (trustAnchorCert != NULL)
2250
            PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchorCert, plContext);
2251
2252
        if (trustAnchor != NULL)
2253
            PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
2254
2255
        if (valResult != NULL)
2256
            PKIX_PL_Object_DecRef((PKIX_PL_Object *)valResult, plContext);
2257
2258
        if (buildResult != NULL)
2259
            PKIX_PL_Object_DecRef((PKIX_PL_Object *)buildResult, plContext);
2260
2261
        if (certStores != NULL)
2262
            PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext);
2263
2264
        if (certSelector != NULL)
2265
            PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext);
2266
2267
        if (builtCertList != NULL)
2268
            PKIX_PL_Object_DecRef((PKIX_PL_Object *)builtCertList, plContext);
2269
2270
        if (error != NULL) {
2271
            SECErrorCodes nssErrorCode = 0;
2272
2273
            cert_PkixErrorToNssCode(error, &nssErrorCode, plContext);
2274
            cert_pkixDestroyValOutParam(paramsOut);
2275
            PORT_SetError(nssErrorCode);
2276
            PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
2277
        }
2278
2279
        PKIX_PL_NssContext_Destroy(plContext);
2280
2281
#ifdef PKIX_OBJECT_LEAK_TEST
2282
        leakedObjNum =
2283
            pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
2284
2285
        if (pkixLog && leakedObjNum) {
2286
            PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d."
2287
                                "Stack %s\n",
2288
                                memLeakLoopCount, errorFnStackString));
2289
        }
2290
        PR_Free(errorFnStackString);
2291
        errorFnStackString = NULL;
2292
        if (abortOnLeak) {
2293
            PORT_Assert(leakedObjNum == 0);
2294
        }
2295
2296
    } while (errorGenerated);
2297
2298
    runningLeakTest = PKIX_FALSE;
2299
    PR_ATOMIC_DECREMENT(&parallelFnInvocationCount);
2300
    usePKIXValidationEngine = savedUsePkixEngFlag;
2301
#endif /* PKIX_OBJECT_LEAK_TEST */
2302
2303
    return r;
2304
#endif /* NSS_DISABLE_LIBPKIX */
2305
}