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
CERT_SetUsePKIXForValidation(PRBool enable)61 CERT_SetUsePKIXForValidation(PRBool enable)
62 {
63 #ifdef NSS_DISABLE_LIBPKIX
64     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
65     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
CERT_GetUsePKIXForValidation()87 CERT_GetUsePKIXForValidation()
88 {
89 #ifdef NSS_DISABLE_LIBPKIX
90     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 *
cert_NssKeyUsagesToPkix(PRUint32 nssKeyUsage,PKIX_UInt32 * pPkixKeyUsage,void * plContext)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 *
cert_NssCertificateUsageToPkixKUAndEKU(CERTCertificate * cert,SECCertUsage requiredCertUsage,PRUint32 requiredKeyUsages,PRBool isCA,PKIX_List ** ppkixEKUList,PKIX_UInt32 * ppkixKU,void * plContext)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 *
cert_ProcessingParamsSetKeyAndCertUsage(PKIX_ProcessingParams * procParams,SECCertUsage requiredCertUsage,PRUint32 requiredKeyUsages,void * plContext)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 *
cert_CreatePkixProcessingParams(CERTCertificate * cert,PRBool checkSig,PRTime time,void * wincx,PRBool useArena,PRBool disableOCSPRemoteFetching,PKIX_ProcessingParams ** pprocParams,void ** pplContext)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 *
cert_PkixToNssCertsChain(PKIX_List * pkixCertChain,CERTCertList ** pvalidChain,void * plContext)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 *
cert_BuildAndValidateChain(PKIX_ProcessingParams * procParams,PKIX_BuildResult ** pResult,PKIX_VerifyNode ** pVerifyNode,void * plContext)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 *
cert_PkixErrorToNssCode(PKIX_Error * error,SECErrorCodes * pNssErr,void * plContext)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 *
cert_GetLogFromVerifyNode(CERTVerifyLog * log,PKIX_VerifyNode * node,void * plContext)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 *
cert_GetBuildResults(PKIX_BuildResult * buildResult,PKIX_VerifyNode * verifyNode,PKIX_Error * error,CERTVerifyLog * log,CERTCertificate ** ptrustedRoot,CERTCertList ** pvalidChain,void * plContext)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
cert_VerifyCertChainPkix(CERTCertificate * cert,PRBool checkSig,SECCertUsage requiredUsage,PRTime time,void * wincx,CERTVerifyLog * log,PRBool * pSigerror,PRBool * pRevoked)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 {
1124 #ifdef NSS_DISABLE_LIBPKIX
1125     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1126     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 *
cert_GetTargetCertConstraints(CERTCertificate * target,void * plContext)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 *
cert_GetCertStores(void * plContext)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 *
cert_NSSCertFromPKIXCert(const PKIX_PL_Cert * pkix_cert)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 *
cert_PKIXMakeOIDList(const SECOidTag * oids,int oidCount,void * plContext)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 *
cert_pkix_FindOutputParam(CERTValOutParam * params,const CERTValParamOutType t)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 *
setRevocationMethod(PKIX_RevocationChecker * revChecker,PKIX_ProcessingParams * procParams,const CERTRevocationTests * revTest,CERTRevocationMethodIndex certRevMethod,PKIX_RevocationMethodType pkixRevMethod,PKIX_Boolean verifyResponderUsages,PKIX_Boolean isLeafTest,void * plContext)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
cert_pkixSetParam(PKIX_ProcessingParams * procParams,const CERTValInParam * param,void * plContext)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
cert_pkixDestroyValOutParam(CERTValOutParam * params)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 *
CERT_GetClassicOCSPEnabledSoftFailurePolicy()1781 CERT_GetClassicOCSPEnabledSoftFailurePolicy()
1782 {
1783 #ifdef NSS_DISABLE_LIBPKIX
1784     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1785     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 *
CERT_GetClassicOCSPEnabledHardFailurePolicy()1833 CERT_GetClassicOCSPEnabledHardFailurePolicy()
1834 {
1835 #ifdef NSS_DISABLE_LIBPKIX
1836     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1837     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 *
CERT_GetClassicOCSPDisabledPolicy()1879 CERT_GetClassicOCSPDisabledPolicy()
1880 {
1881 #ifdef NSS_DISABLE_LIBPKIX
1882     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1883     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 *
CERT_GetPKIXVerifyNistRevocationPolicy()1925 CERT_GetPKIXVerifyNistRevocationPolicy()
1926 {
1927 #ifdef NSS_DISABLE_LIBPKIX
1928     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1929     return NULL;
1930 #else
1931     return &certRev_PKIX_Verify_Nist_Policy;
1932 #endif /* NSS_DISABLE_LIBPKIX */
1933 }
1934 
1935 CERTRevocationFlags *
CERT_AllocCERTRevocationFlags(PRUint32 number_leaf_methods,PRUint32 number_leaf_pref_methods,PRUint32 number_chain_methods,PRUint32 number_chain_pref_methods)1936 CERT_AllocCERTRevocationFlags(
1937     PRUint32 number_leaf_methods, PRUint32 number_leaf_pref_methods,
1938     PRUint32 number_chain_methods, PRUint32 number_chain_pref_methods)
1939 {
1940 #ifdef NSS_DISABLE_LIBPKIX
1941     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1942     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
CERT_DestroyCERTRevocationFlags(CERTRevocationFlags * flags)1979 CERT_DestroyCERTRevocationFlags(CERTRevocationFlags *flags)
1980 {
1981 #ifdef NSS_DISABLE_LIBPKIX
1982     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1983     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
CERT_PKIXVerifyCert(CERTCertificate * cert,SECCertificateUsage usages,CERTValInParam * paramsIn,CERTValOutParam * paramsOut,void * wincx)2030 CERT_PKIXVerifyCert(
2031     CERTCertificate *cert,
2032     SECCertificateUsage usages,
2033     CERTValInParam *paramsIn,
2034     CERTValOutParam *paramsOut,
2035     void *wincx)
2036 {
2037 #ifdef NSS_DISABLE_LIBPKIX
2038     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
2039     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 }
2306