Coverage Report

Created: 2024-11-21 07:03

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