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,
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 *
cert_PkixToNssCertsChain(PKIX_List * pkixCertChain,CERTCertList ** pvalidChain,void * plContext)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 *
cert_BuildAndValidateChain(PKIX_ProcessingParams * procParams,PKIX_BuildResult ** pResult,PKIX_VerifyNode ** pVerifyNode,void * plContext)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 *
cert_PkixErrorToNssCode(PKIX_Error * error,SECErrorCodes * pNssErr,void * plContext)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,
839                                 PKIX_ErrorText[errPtr->errCode]));
840 #else
841             PR_LOG(pkixLog, 2, ("Error at level %d: Error code %d\n", errLevel,
842                                 errPtr->errCode));
843 #endif /* PKIX_ERROR_DESCRIPTION */
844         }
845         errPtr = errPtr->cause;
846         errLevel += 1;
847     }
848     PORT_Assert(nssErr);
849     if (!nssErr) {
850         *pNssErr = SEC_ERROR_LIBPKIX_INTERNAL;
851     } else {
852         *pNssErr = nssErr;
853     }
854 
855     PKIX_RETURN(CERTVFYPKIX);
856 }
857 
858 /*
859  * FUNCTION: cert_GetLogFromVerifyNode
860  * DESCRIPTION:
861  *
862  * Recursive function that converts verify node tree-like set of structures
863  * to CERTVerifyLog.
864  *
865  * PARAMETERS:
866  *  "log"
867  *      Pointed to already allocated CERTVerifyLog structure.
868  *  "node"
869  *      A node of PKIX_VerifyNode tree.
870  *  "plContext"
871  *      Platform-specific context pointer.
872  * THREAD SAFETY:
873  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
874  * RETURNS:
875  *  Returns NULL if the function succeeds.
876  *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
877  *  Returns a Fatal Error if the function fails in an unrecoverable way.
878  */
879 static PKIX_Error *
cert_GetLogFromVerifyNode(CERTVerifyLog * log,PKIX_VerifyNode * node,void * plContext)880 cert_GetLogFromVerifyNode(
881     CERTVerifyLog *log,
882     PKIX_VerifyNode *node,
883     void *plContext)
884 {
885     PKIX_List *children = NULL;
886     PKIX_VerifyNode *childNode = NULL;
887 
888     PKIX_ENTER(CERTVFYPKIX, "cert_GetLogFromVerifyNode");
889 
890     children = node->children;
891 
892     if (children == NULL) {
893         PKIX_ERRORCODE errCode = PKIX_ANCHORDIDNOTCHAINTOCERT;
894         if (node->error && node->error->errCode != errCode) {
895             if (log != NULL) {
896                 SECErrorCodes nssErrorCode = 0;
897                 CERTCertificate *cert = NULL;
898 
899                 cert = node->verifyCert->nssCert;
900 
901                 PKIX_CHECK(
902                     cert_PkixErrorToNssCode(node->error, &nssErrorCode,
903                                             plContext),
904                     PKIX_GETPKIXERRORCODEFAILED);
905 
906                 cert_AddToVerifyLog(log, cert, nssErrorCode, node->depth, NULL);
907             }
908         }
909         PKIX_RETURN(CERTVFYPKIX);
910     } else {
911         PRUint32 i = 0;
912         PKIX_UInt32 length = 0;
913 
914         PKIX_CHECK(
915             PKIX_List_GetLength(children, &length, plContext),
916             PKIX_LISTGETLENGTHFAILED);
917 
918         for (i = 0; i < length; i++) {
919 
920             PKIX_CHECK(
921                 PKIX_List_GetItem(children, i, (PKIX_PL_Object **)&childNode,
922                                   plContext),
923                 PKIX_LISTGETITEMFAILED);
924 
925             PKIX_CHECK(
926                 cert_GetLogFromVerifyNode(log, childNode, plContext),
927                 PKIX_ERRORINRECURSIVEEQUALSCALL);
928 
929             PKIX_DECREF(childNode);
930         }
931     }
932 
933 cleanup:
934     PKIX_DECREF(childNode);
935 
936     PKIX_RETURN(CERTVFYPKIX);
937 }
938 
939 /*
940  * FUNCTION: cert_GetBuildResults
941  * DESCRIPTION:
942  *
943  * Converts pkix build results to nss results. This function is called
944  * regardless of build result.
945  *
946  * If it called after chain was successfully constructed, then it will
947  * convert:
948  *   * pkix cert list that represent the chain to nss cert list
949  *   * trusted root the chain was anchored to nss certificate.
950  *
951  * In case of failure it will convert:
952  *   * pkix error to PR error code(will set it with PORT_SetError)
953  *   * pkix validation log to nss CERTVerifyLog
954  *
955  * PARAMETERS:
956  *  "buildResult"
957  *      Build results returned by PKIX_BuildChain.
958  *  "verifyNode"
959  *      Tree-like structure of chain building/validation failures
960  *      returned by PKIX_BuildChain. Ignored in case of success.
961  *  "error"
962  *      Final error returned by PKIX_BuildChain. Should be NULL in
963  *      case of success.
964  *  "log"
965  *      Address of pre-allocated(if not NULL) CERTVerifyLog structure.
966  *  "ptrustedRoot"
967  *      Address of returned trusted root the chain was anchored to.
968  *  "pvalidChain"
969  *      Address of returned valid chain.
970  *  "plContext"
971  *      Platform-specific context pointer.
972  * THREAD SAFETY:
973  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
974  * RETURNS:
975  *  Returns NULL if the function succeeds.
976  *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
977  *  Returns a Fatal Error if the function fails in an unrecoverable way.
978  */
979 static PKIX_Error *
cert_GetBuildResults(PKIX_BuildResult * buildResult,PKIX_VerifyNode * verifyNode,PKIX_Error * error,CERTVerifyLog * log,CERTCertificate ** ptrustedRoot,CERTCertList ** pvalidChain,void * plContext)980 cert_GetBuildResults(
981     PKIX_BuildResult *buildResult,
982     PKIX_VerifyNode *verifyNode,
983     PKIX_Error *error,
984     CERTVerifyLog *log,
985     CERTCertificate **ptrustedRoot,
986     CERTCertList **pvalidChain,
987     void *plContext)
988 {
989     PKIX_ValidateResult *validResult = NULL;
990     CERTCertList *validChain = NULL;
991     CERTCertificate *trustedRoot = NULL;
992     PKIX_TrustAnchor *trustAnchor = NULL;
993     PKIX_PL_Cert *trustedCert = NULL;
994     PKIX_List *pkixCertChain = NULL;
995 
996     PKIX_ENTER(CERTVFYPKIX, "cert_GetBuildResults");
997     if (buildResult == NULL && error == NULL) {
998         PKIX_ERROR(PKIX_NULLARGUMENT);
999     }
1000 
1001     if (error) {
1002         SECErrorCodes nssErrorCode = 0;
1003         if (verifyNode) {
1004             PKIX_Error *tmpError =
1005                 cert_GetLogFromVerifyNode(log, verifyNode, plContext);
1006             if (tmpError) {
1007                 PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext);
1008             }
1009         }
1010         cert_PkixErrorToNssCode(error, &nssErrorCode, plContext);
1011         PORT_SetError(nssErrorCode);
1012         goto cleanup;
1013     }
1014 
1015     if (pvalidChain) {
1016         PKIX_CHECK(
1017             PKIX_BuildResult_GetCertChain(buildResult, &pkixCertChain,
1018                                           plContext),
1019             PKIX_BUILDRESULTGETCERTCHAINFAILED);
1020 
1021         PKIX_CHECK(
1022             cert_PkixToNssCertsChain(pkixCertChain, &validChain, plContext),
1023             PKIX_CERTCHAINTONSSCHAINFAILED);
1024     }
1025 
1026     if (ptrustedRoot) {
1027         PKIX_CHECK(
1028             PKIX_BuildResult_GetValidateResult(buildResult, &validResult,
1029                                                plContext),
1030             PKIX_BUILDRESULTGETVALIDATERESULTFAILED);
1031 
1032         PKIX_CHECK(
1033             PKIX_ValidateResult_GetTrustAnchor(validResult, &trustAnchor,
1034                                                plContext),
1035             PKIX_VALIDATERESULTGETTRUSTANCHORFAILED);
1036 
1037         PKIX_CHECK(
1038             PKIX_TrustAnchor_GetTrustedCert(trustAnchor, &trustedCert,
1039                                             plContext),
1040             PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
1041 
1042         PKIX_CHECK(
1043             PKIX_PL_Cert_GetCERTCertificate(trustedCert, &trustedRoot,
1044                                             plContext),
1045             PKIX_CERTGETCERTCERTIFICATEFAILED);
1046     }
1047 
1048     PORT_Assert(!PKIX_ERROR_RECEIVED);
1049 
1050     if (trustedRoot) {
1051         *ptrustedRoot = trustedRoot;
1052     }
1053     if (validChain) {
1054         *pvalidChain = validChain;
1055     }
1056 
1057 cleanup:
1058     if (PKIX_ERROR_RECEIVED) {
1059         if (trustedRoot) {
1060             CERT_DestroyCertificate(trustedRoot);
1061         }
1062         if (validChain) {
1063             CERT_DestroyCertList(validChain);
1064         }
1065     }
1066     PKIX_DECREF(trustAnchor);
1067     PKIX_DECREF(trustedCert);
1068     PKIX_DECREF(pkixCertChain);
1069     PKIX_DECREF(validResult);
1070     PKIX_DECREF(error);
1071     PKIX_DECREF(verifyNode);
1072     PKIX_DECREF(buildResult);
1073 
1074     PKIX_RETURN(CERTVFYPKIX);
1075 }
1076 #endif /* NSS_DISABLE_LIBPKIX */
1077 
1078 /*
1079  * FUNCTION: cert_VerifyCertChainPkix
1080  * DESCRIPTION:
1081  *
1082  * The main wrapper function that is called from CERT_VerifyCert and
1083  * CERT_VerifyCACertForUsage functions to validate cert with libpkix.
1084  *
1085  * PARAMETERS:
1086  *  "cert"
1087  *      Leaf certificate of a chain we want to build.
1088  *  "checkSig"
1089  *      Certificate signatures will not be verified if this
1090  *      flag is set to PR_FALSE.
1091  *  "requiredUsage"
1092  *      Required usage for certificate and chain.
1093  *  "time"
1094  *      Validity time.
1095  *  "wincx"
1096  *      Nss database password token.
1097  *  "log"
1098  *      Address of already allocated CERTVerifyLog structure. Not
1099  *      used if NULL;
1100  *  "pSigerror"
1101  *      Address of PRBool. If not NULL, returns true is cert chain
1102  *      was invalidated because of bad certificate signature.
1103  *  "pRevoked"
1104  *      Address of PRBool. If not NULL, returns true is cert chain
1105  *      was invalidated because a revoked certificate was found in
1106  *      the chain.
1107  * THREAD SAFETY:
1108  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1109  * RETURNS:
1110  *  SECFailure is chain building process has failed. SECSuccess otherwise.
1111  */
1112 SECStatus
cert_VerifyCertChainPkix(CERTCertificate * cert,PRBool checkSig,SECCertUsage requiredUsage,PRTime time,void * wincx,CERTVerifyLog * log,PRBool * pSigerror,PRBool * pRevoked)1113 cert_VerifyCertChainPkix(
1114     CERTCertificate *cert,
1115     PRBool checkSig,
1116     SECCertUsage requiredUsage,
1117     PRTime time,
1118     void *wincx,
1119     CERTVerifyLog *log,
1120     PRBool *pSigerror,
1121     PRBool *pRevoked)
1122 {
1123 #ifdef NSS_DISABLE_LIBPKIX
1124     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1125     return SECFailure;
1126 #else
1127     PKIX_ProcessingParams *procParams = NULL;
1128     PKIX_BuildResult *result = NULL;
1129     PKIX_VerifyNode *verifyNode = NULL;
1130     PKIX_Error *error = NULL;
1131 
1132     SECStatus rv = SECFailure;
1133     void *plContext = NULL;
1134 
1135 #ifdef PKIX_OBJECT_LEAK_TEST
1136     int leakedObjNum = 0;
1137     int memLeakLoopCount = 0;
1138     int objCountTable[PKIX_NUMTYPES];
1139     int fnInvLocalCount = 0;
1140     PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine;
1141 
1142     if (usePKIXValidationEngine) {
1143         /* current memory leak testing implementation does not allow
1144          * to run simultaneous tests one the same or a different threads.
1145          * Setting the variable to false, to make additional chain
1146          * validations be handled by old nss. */
1147         usePKIXValidationEngine = PR_FALSE;
1148     }
1149     testStartFnStackPosition = 2;
1150     fnStackNameArr[0] = "cert_VerifyCertChainPkix";
1151     fnStackInvCountArr[0] = 0;
1152     PKIX_Boolean abortOnLeak =
1153         (PR_GetEnvSecure("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ? PKIX_FALSE
1154                                                                          : PKIX_TRUE;
1155     runningLeakTest = PKIX_TRUE;
1156 
1157     /* Prevent multi-threaded run of object leak test */
1158     fnInvLocalCount = PR_ATOMIC_INCREMENT(&parallelFnInvocationCount);
1159     PORT_Assert(fnInvLocalCount == 1);
1160 
1161     do {
1162         rv = SECFailure;
1163         plContext = NULL;
1164         procParams = NULL;
1165         result = NULL;
1166         verifyNode = NULL;
1167         error = NULL;
1168         errorGenerated = PKIX_FALSE;
1169         stackPosition = 0;
1170 
1171         if (leakedObjNum) {
1172             pkix_pl_lifecycle_ObjectTableUpdate(objCountTable);
1173         }
1174         memLeakLoopCount += 1;
1175 #endif /* PKIX_OBJECT_LEAK_TEST */
1176 
1177         error =
1178             cert_CreatePkixProcessingParams(cert, checkSig, time, wincx,
1179                                             PR_FALSE /*use arena*/,
1180                                             requiredUsage == certUsageStatusResponder,
1181                                             &procParams, &plContext);
1182         if (error) {
1183             goto cleanup;
1184         }
1185 
1186         error =
1187             cert_ProcessingParamsSetKeyAndCertUsage(procParams, requiredUsage, 0,
1188                                                     plContext);
1189         if (error) {
1190             goto cleanup;
1191         }
1192 
1193         error =
1194             cert_BuildAndValidateChain(procParams, &result, &verifyNode, plContext);
1195         if (error) {
1196             goto cleanup;
1197         }
1198 
1199         if (pRevoked) {
1200             /* Currently always PR_FALSE. Will be fixed as a part of 394077 */
1201             *pRevoked = PR_FALSE;
1202         }
1203         if (pSigerror) {
1204             /* Currently always PR_FALSE. Will be fixed as a part of 394077 */
1205             *pSigerror = PR_FALSE;
1206         }
1207         rv = SECSuccess;
1208 
1209     cleanup:
1210         error = cert_GetBuildResults(result, verifyNode, error, log, NULL, NULL,
1211                                      plContext);
1212         if (error) {
1213             PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1214         }
1215         if (procParams) {
1216             PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext);
1217         }
1218         if (plContext) {
1219             PKIX_PL_NssContext_Destroy(plContext);
1220         }
1221 
1222 #ifdef PKIX_OBJECT_LEAK_TEST
1223         leakedObjNum =
1224             pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
1225 
1226         if (pkixLog && leakedObjNum) {
1227             PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d."
1228                                 "Stack %s\n",
1229                                 memLeakLoopCount, errorFnStackString));
1230         }
1231         PR_Free(errorFnStackString);
1232         errorFnStackString = NULL;
1233         if (abortOnLeak) {
1234             PORT_Assert(leakedObjNum == 0);
1235         }
1236 
1237     } while (errorGenerated);
1238 
1239     runningLeakTest = PKIX_FALSE;
1240     PR_ATOMIC_DECREMENT(&parallelFnInvocationCount);
1241     usePKIXValidationEngine = savedUsePkixEngFlag;
1242 #endif /* PKIX_OBJECT_LEAK_TEST */
1243 
1244     return rv;
1245 #endif /* NSS_DISABLE_LIBPKIX */
1246 }
1247 
1248 #ifndef NSS_DISABLE_LIBPKIX
1249 PKIX_CertSelector *
cert_GetTargetCertConstraints(CERTCertificate * target,void * plContext)1250 cert_GetTargetCertConstraints(CERTCertificate *target, void *plContext)
1251 {
1252     PKIX_ComCertSelParams *certSelParams = NULL;
1253     PKIX_CertSelector *certSelector = NULL;
1254     PKIX_CertSelector *r = NULL;
1255     PKIX_PL_Cert *eeCert = NULL;
1256     PKIX_Error *error = NULL;
1257 
1258     error = PKIX_PL_Cert_CreateFromCERTCertificate(target, &eeCert, plContext);
1259     if (error != NULL)
1260         goto cleanup;
1261 
1262     error = PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext);
1263     if (error != NULL)
1264         goto cleanup;
1265 
1266     error = PKIX_ComCertSelParams_Create(&certSelParams, plContext);
1267     if (error != NULL)
1268         goto cleanup;
1269 
1270     error = PKIX_ComCertSelParams_SetCertificate(
1271         certSelParams, eeCert, plContext);
1272     if (error != NULL)
1273         goto cleanup;
1274 
1275     error = PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext);
1276     if (error != NULL)
1277         goto cleanup;
1278 
1279     error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certSelector, plContext);
1280     if (error == NULL)
1281         r = certSelector;
1282 
1283 cleanup:
1284     if (certSelParams != NULL)
1285         PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelParams, plContext);
1286 
1287     if (eeCert != NULL)
1288         PKIX_PL_Object_DecRef((PKIX_PL_Object *)eeCert, plContext);
1289 
1290     if (certSelector != NULL)
1291         PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext);
1292 
1293     if (error != NULL) {
1294         SECErrorCodes nssErr;
1295 
1296         cert_PkixErrorToNssCode(error, &nssErr, plContext);
1297         PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1298         PORT_SetError(nssErr);
1299     }
1300 
1301     return r;
1302 }
1303 
1304 static PKIX_List *
cert_GetCertStores(void * plContext)1305 cert_GetCertStores(void *plContext)
1306 {
1307     PKIX_CertStore *certStore = NULL;
1308     PKIX_List *certStores = NULL;
1309     PKIX_List *r = NULL;
1310     PKIX_Error *error = NULL;
1311 
1312     error = PKIX_PL_Pk11CertStore_Create(&certStore, plContext);
1313     if (error != NULL)
1314         goto cleanup;
1315 
1316     error = PKIX_List_Create(&certStores, plContext);
1317     if (error != NULL)
1318         goto cleanup;
1319 
1320     error = PKIX_List_AppendItem(certStores,
1321                                  (PKIX_PL_Object *)certStore, plContext);
1322     if (error != NULL)
1323         goto cleanup;
1324 
1325     error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certStores, plContext);
1326     if (error == NULL)
1327         r = certStores;
1328 
1329 cleanup:
1330     if (certStores != NULL)
1331         PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext);
1332 
1333     if (certStore != NULL)
1334         PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStore, plContext);
1335 
1336     if (error != NULL) {
1337         SECErrorCodes nssErr;
1338 
1339         cert_PkixErrorToNssCode(error, &nssErr, plContext);
1340         PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1341         PORT_SetError(nssErr);
1342     }
1343 
1344     return r;
1345 }
1346 
1347 struct fake_PKIX_PL_CertStruct {
1348     CERTCertificate *nssCert;
1349 };
1350 
1351 /* This needs to be part of the PKIX_PL_* */
1352 /* This definitely needs to go away, and be replaced with
1353    a real accessor function in PKIX */
1354 static CERTCertificate *
cert_NSSCertFromPKIXCert(const PKIX_PL_Cert * pkix_cert)1355 cert_NSSCertFromPKIXCert(const PKIX_PL_Cert *pkix_cert)
1356 {
1357     struct fake_PKIX_PL_CertStruct *fcert = NULL;
1358 
1359     fcert = (struct fake_PKIX_PL_CertStruct *)pkix_cert;
1360 
1361     return CERT_DupCertificate(fcert->nssCert);
1362 }
1363 
1364 PKIX_List *
cert_PKIXMakeOIDList(const SECOidTag * oids,int oidCount,void * plContext)1365 cert_PKIXMakeOIDList(const SECOidTag *oids, int oidCount, void *plContext)
1366 {
1367     PKIX_List *r = NULL;
1368     PKIX_List *policyList = NULL;
1369     PKIX_PL_OID *policyOID = NULL;
1370     PKIX_Error *error = NULL;
1371     int i;
1372 
1373     error = PKIX_List_Create(&policyList, plContext);
1374     if (error != NULL) {
1375         goto cleanup;
1376     }
1377 
1378     for (i = 0; i < oidCount; i++) {
1379         error = PKIX_PL_OID_Create(oids[i], &policyOID, plContext);
1380         if (error) {
1381             goto cleanup;
1382         }
1383         error = PKIX_List_AppendItem(policyList,
1384                                      (PKIX_PL_Object *)policyOID, plContext);
1385         if (error != NULL) {
1386             goto cleanup;
1387         }
1388         PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
1389         policyOID = NULL;
1390     }
1391 
1392     error = PKIX_List_SetImmutable(policyList, plContext);
1393     if (error != NULL)
1394         goto cleanup;
1395 
1396     error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)policyList, plContext);
1397     if (error == NULL)
1398         r = policyList;
1399 
1400 cleanup:
1401     if (policyOID != NULL) {
1402         PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
1403     }
1404     if (policyList != NULL) {
1405         PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyList, plContext);
1406     }
1407     if (error != NULL) {
1408         PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1409     }
1410 
1411     return r;
1412 }
1413 
1414 CERTValOutParam *
cert_pkix_FindOutputParam(CERTValOutParam * params,const CERTValParamOutType t)1415 cert_pkix_FindOutputParam(CERTValOutParam *params, const CERTValParamOutType t)
1416 {
1417     CERTValOutParam *i;
1418     if (params == NULL) {
1419         return NULL;
1420     }
1421     for (i = params; i->type != cert_po_end; i++) {
1422         if (i->type == t) {
1423             return i;
1424         }
1425     }
1426     return NULL;
1427 }
1428 
1429 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)1430 setRevocationMethod(PKIX_RevocationChecker *revChecker,
1431                     PKIX_ProcessingParams *procParams,
1432                     const CERTRevocationTests *revTest,
1433                     CERTRevocationMethodIndex certRevMethod,
1434                     PKIX_RevocationMethodType pkixRevMethod,
1435                     PKIX_Boolean verifyResponderUsages,
1436                     PKIX_Boolean isLeafTest,
1437                     void *plContext)
1438 {
1439     PKIX_UInt32 methodFlags = 0;
1440     PKIX_Error *error = NULL;
1441     PKIX_UInt32 priority = 0;
1442 
1443     if (revTest->number_of_defined_methods <= (PRUint32)certRevMethod) {
1444         return NULL;
1445     }
1446     if (revTest->preferred_methods) {
1447         unsigned int i = 0;
1448         for (; i < revTest->number_of_preferred_methods; i++) {
1449             if (revTest->preferred_methods[i] == certRevMethod)
1450                 break;
1451         }
1452         priority = i;
1453     }
1454     methodFlags = revTest->cert_rev_flags_per_method[certRevMethod];
1455     if (verifyResponderUsages &&
1456         pkixRevMethod == PKIX_RevocationMethod_OCSP) {
1457         methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING;
1458     }
1459     error =
1460         PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
1461                                                   pkixRevMethod, methodFlags,
1462                                                   priority, NULL,
1463                                                   isLeafTest, plContext);
1464     return error;
1465 }
1466 
1467 SECStatus
cert_pkixSetParam(PKIX_ProcessingParams * procParams,const CERTValInParam * param,void * plContext)1468 cert_pkixSetParam(PKIX_ProcessingParams *procParams,
1469                   const CERTValInParam *param, void *plContext)
1470 {
1471     PKIX_Error *error = NULL;
1472     SECStatus r = SECSuccess;
1473     PKIX_PL_Date *date = NULL;
1474     PKIX_List *policyOIDList = NULL;
1475     PKIX_List *certListPkix = NULL;
1476     const CERTRevocationFlags *flags;
1477     SECErrorCodes errCode = SEC_ERROR_INVALID_ARGS;
1478     const CERTCertList *certList = NULL;
1479     CERTCertListNode *node;
1480     PKIX_PL_Cert *certPkix = NULL;
1481     PKIX_TrustAnchor *trustAnchor = NULL;
1482     PKIX_RevocationChecker *revChecker = NULL;
1483     PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext *)plContext;
1484 
1485     /* XXX we need a way to map generic PKIX error to generic NSS errors */
1486 
1487     switch (param->type) {
1488 
1489         case cert_pi_policyOID:
1490 
1491             /* needed? */
1492             error = PKIX_ProcessingParams_SetExplicitPolicyRequired(
1493                 procParams, PKIX_TRUE, plContext);
1494 
1495             if (error != NULL) {
1496                 break;
1497             }
1498 
1499             policyOIDList = cert_PKIXMakeOIDList(param->value.array.oids,
1500                                                  param->value.arraySize, plContext);
1501             if (policyOIDList == NULL) {
1502                 r = SECFailure;
1503                 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1504                 break;
1505             }
1506 
1507             error = PKIX_ProcessingParams_SetInitialPolicies(
1508                 procParams, policyOIDList, plContext);
1509             break;
1510 
1511         case cert_pi_date:
1512             if (param->value.scalar.time == 0) {
1513                 error = PKIX_PL_Date_Create_UTCTime(NULL, &date, plContext);
1514                 if (error != NULL) {
1515                     errCode = SEC_ERROR_INVALID_TIME;
1516                     break;
1517                 }
1518             } else {
1519                 error = pkix_pl_Date_CreateFromPRTime(param->value.scalar.time,
1520                                                       &date, plContext);
1521                 if (error != NULL) {
1522                     errCode = SEC_ERROR_INVALID_TIME;
1523                     break;
1524                 }
1525             }
1526 
1527             error = PKIX_ProcessingParams_SetDate(procParams, date, plContext);
1528             if (error != NULL) {
1529                 errCode = SEC_ERROR_INVALID_TIME;
1530             }
1531             break;
1532 
1533         case cert_pi_revocationFlags: {
1534             PKIX_UInt32 leafIMFlags = 0;
1535             PKIX_UInt32 chainIMFlags = 0;
1536             PKIX_Boolean validatingResponderCert = PKIX_FALSE;
1537 
1538             flags = param->value.pointer.revocation;
1539             if (!flags) {
1540                 PORT_SetError(errCode);
1541                 r = SECFailure;
1542                 break;
1543             }
1544 
1545             leafIMFlags =
1546                 flags->leafTests.cert_rev_method_independent_flags;
1547             chainIMFlags =
1548                 flags->chainTests.cert_rev_method_independent_flags;
1549 
1550             error =
1551                 PKIX_RevocationChecker_Create(leafIMFlags, chainIMFlags,
1552                                               &revChecker, plContext);
1553             if (error) {
1554                 break;
1555             }
1556 
1557             error =
1558                 PKIX_ProcessingParams_SetRevocationChecker(procParams,
1559                                                            revChecker, plContext);
1560             if (error) {
1561                 break;
1562             }
1563 
1564             if (((PKIX_PL_NssContext *)plContext)->certificateUsage &
1565                 certificateUsageStatusResponder) {
1566                 validatingResponderCert = PKIX_TRUE;
1567             }
1568 
1569             error = setRevocationMethod(revChecker,
1570                                         procParams, &flags->leafTests,
1571                                         cert_revocation_method_crl,
1572                                         PKIX_RevocationMethod_CRL,
1573                                         validatingResponderCert,
1574                                         PKIX_TRUE, plContext);
1575             if (error) {
1576                 break;
1577             }
1578 
1579             error = setRevocationMethod(revChecker,
1580                                         procParams, &flags->leafTests,
1581                                         cert_revocation_method_ocsp,
1582                                         PKIX_RevocationMethod_OCSP,
1583                                         validatingResponderCert,
1584                                         PKIX_TRUE, plContext);
1585             if (error) {
1586                 break;
1587             }
1588 
1589             error = setRevocationMethod(revChecker,
1590                                         procParams, &flags->chainTests,
1591                                         cert_revocation_method_crl,
1592                                         PKIX_RevocationMethod_CRL,
1593                                         validatingResponderCert,
1594                                         PKIX_FALSE, plContext);
1595             if (error) {
1596                 break;
1597             }
1598 
1599             error = setRevocationMethod(revChecker,
1600                                         procParams, &flags->chainTests,
1601                                         cert_revocation_method_ocsp,
1602                                         PKIX_RevocationMethod_OCSP,
1603                                         validatingResponderCert,
1604                                         PKIX_FALSE, plContext);
1605             if (error) {
1606                 break;
1607             }
1608 
1609         } break;
1610 
1611         case cert_pi_trustAnchors:
1612             certList = param->value.pointer.chain;
1613             if (!certList) {
1614                 PORT_SetError(errCode);
1615                 r = SECFailure;
1616                 break;
1617             }
1618             error = PKIX_List_Create(&certListPkix, plContext);
1619             if (error != NULL) {
1620                 break;
1621             }
1622             for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
1623                  node = CERT_LIST_NEXT(node)) {
1624                 error = PKIX_PL_Cert_CreateFromCERTCertificate(node->cert,
1625                                                                &certPkix, plContext);
1626                 if (error) {
1627                     break;
1628                 }
1629                 error = PKIX_TrustAnchor_CreateWithCert(certPkix, &trustAnchor,
1630                                                         plContext);
1631                 if (error) {
1632                     break;
1633                 }
1634                 error = PKIX_List_AppendItem(certListPkix,
1635                                              (PKIX_PL_Object *)trustAnchor, plContext);
1636                 if (error) {
1637                     break;
1638                 }
1639                 PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
1640                 trustAnchor = NULL;
1641                 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext);
1642                 certPkix = NULL;
1643             }
1644             error =
1645                 PKIX_ProcessingParams_SetTrustAnchors(procParams, certListPkix,
1646                                                       plContext);
1647             break;
1648 
1649         case cert_pi_useAIACertFetch:
1650             error =
1651                 PKIX_ProcessingParams_SetUseAIAForCertFetching(procParams,
1652                                                                (PRBool)(param->value.scalar.b !=
1653                                                                         0),
1654                                                                plContext);
1655             break;
1656 
1657         case cert_pi_chainVerifyCallback: {
1658             const CERTChainVerifyCallback *chainVerifyCallback =
1659                 param->value.pointer.chainVerifyCallback;
1660             if (!chainVerifyCallback || !chainVerifyCallback->isChainValid) {
1661                 PORT_SetError(errCode);
1662                 r = SECFailure;
1663                 break;
1664             }
1665 
1666             nssContext->chainVerifyCallback = *chainVerifyCallback;
1667         } break;
1668 
1669         case cert_pi_useOnlyTrustAnchors:
1670             error =
1671                 PKIX_ProcessingParams_SetUseOnlyTrustAnchors(procParams,
1672                                                              (PRBool)(param->value.scalar.b !=
1673                                                                       0),
1674                                                              plContext);
1675             break;
1676 
1677         default:
1678             PORT_SetError(errCode);
1679             r = SECFailure;
1680             break;
1681     }
1682 
1683     if (policyOIDList != NULL)
1684         PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOIDList, plContext);
1685 
1686     if (date != NULL)
1687         PKIX_PL_Object_DecRef((PKIX_PL_Object *)date, plContext);
1688 
1689     if (revChecker != NULL)
1690         PKIX_PL_Object_DecRef((PKIX_PL_Object *)revChecker, plContext);
1691 
1692     if (certListPkix)
1693         PKIX_PL_Object_DecRef((PKIX_PL_Object *)certListPkix, plContext);
1694 
1695     if (trustAnchor)
1696         PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
1697 
1698     if (certPkix)
1699         PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext);
1700 
1701     if (error != NULL) {
1702         PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1703         PORT_SetError(errCode);
1704         r = SECFailure;
1705     }
1706 
1707     return r;
1708 }
1709 
1710 void
cert_pkixDestroyValOutParam(CERTValOutParam * params)1711 cert_pkixDestroyValOutParam(CERTValOutParam *params)
1712 {
1713     CERTValOutParam *i;
1714 
1715     if (params == NULL) {
1716         return;
1717     }
1718     for (i = params; i->type != cert_po_end; i++) {
1719         switch (i->type) {
1720             case cert_po_trustAnchor:
1721                 if (i->value.pointer.cert) {
1722                     CERT_DestroyCertificate(i->value.pointer.cert);
1723                     i->value.pointer.cert = NULL;
1724                 }
1725                 break;
1726 
1727             case cert_po_certList:
1728                 if (i->value.pointer.chain) {
1729                     CERT_DestroyCertList(i->value.pointer.chain);
1730                     i->value.pointer.chain = NULL;
1731                 }
1732                 break;
1733 
1734             default:
1735                 break;
1736         }
1737     }
1738 }
1739 
1740 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags[2] = {
1741     /* crl */
1742     CERT_REV_M_TEST_USING_THIS_METHOD |
1743         CERT_REV_M_FORBID_NETWORK_FETCHING |
1744         CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1745     /* ocsp */
1746     CERT_REV_M_TEST_USING_THIS_METHOD
1747 };
1748 
1749 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags[2] = {
1750     /* crl */
1751     CERT_REV_M_TEST_USING_THIS_METHOD |
1752         CERT_REV_M_FORBID_NETWORK_FETCHING |
1753         CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1754     /* ocsp */
1755     0
1756 };
1757 
1758 static CERTRevocationMethodIndex
1759     certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference = {
1760         cert_revocation_method_crl
1761     };
1762 
1763 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy = {
1764     { /* leafTests */
1765       2,
1766       certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags,
1767       1,
1768       &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference,
1769       0 },
1770     { /* chainTests */
1771       2,
1772       certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags,
1773       0,
1774       0,
1775       0 }
1776 };
1777 #endif /* NSS_DISABLE_LIBPKIX */
1778 
1779 extern const CERTRevocationFlags *
CERT_GetClassicOCSPEnabledSoftFailurePolicy()1780 CERT_GetClassicOCSPEnabledSoftFailurePolicy()
1781 {
1782 #ifdef NSS_DISABLE_LIBPKIX
1783     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1784     return NULL;
1785 #else
1786     return &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy;
1787 #endif /* NSS_DISABLE_LIBPKIX */
1788 }
1789 
1790 #ifndef NSS_DISABLE_LIBPKIX
1791 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags[2] = {
1792     /* crl */
1793     CERT_REV_M_TEST_USING_THIS_METHOD |
1794         CERT_REV_M_FORBID_NETWORK_FETCHING |
1795         CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1796     /* ocsp */
1797     CERT_REV_M_TEST_USING_THIS_METHOD |
1798         CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
1799 };
1800 
1801 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags[2] = {
1802     /* crl */
1803     CERT_REV_M_TEST_USING_THIS_METHOD |
1804         CERT_REV_M_FORBID_NETWORK_FETCHING |
1805         CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1806     /* ocsp */
1807     0
1808 };
1809 
1810 static CERTRevocationMethodIndex
1811     certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference = {
1812         cert_revocation_method_crl
1813     };
1814 
1815 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy = {
1816     { /* leafTests */
1817       2,
1818       certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags,
1819       1,
1820       &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference,
1821       0 },
1822     { /* chainTests */
1823       2,
1824       certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags,
1825       0,
1826       0,
1827       0 }
1828 };
1829 #endif /* NSS_DISABLE_LIBPKIX */
1830 
1831 extern const CERTRevocationFlags *
CERT_GetClassicOCSPEnabledHardFailurePolicy()1832 CERT_GetClassicOCSPEnabledHardFailurePolicy()
1833 {
1834 #ifdef NSS_DISABLE_LIBPKIX
1835     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1836     return NULL;
1837 #else
1838     return &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy;
1839 #endif /* NSS_DISABLE_LIBPKIX */
1840 }
1841 
1842 #ifndef NSS_DISABLE_LIBPKIX
1843 static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags[2] = {
1844     /* crl */
1845     CERT_REV_M_TEST_USING_THIS_METHOD |
1846         CERT_REV_M_FORBID_NETWORK_FETCHING |
1847         CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1848     /* ocsp */
1849     0
1850 };
1851 
1852 static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags[2] = {
1853     /* crl */
1854     CERT_REV_M_TEST_USING_THIS_METHOD |
1855         CERT_REV_M_FORBID_NETWORK_FETCHING |
1856         CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1857     /* ocsp */
1858     0
1859 };
1860 
1861 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Disabled_Policy = {
1862     { /* leafTests */
1863       2,
1864       certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags,
1865       0,
1866       0,
1867       0 },
1868     { /* chainTests */
1869       2,
1870       certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags,
1871       0,
1872       0,
1873       0 }
1874 };
1875 #endif /* NSS_DISABLE_LIBPKIX */
1876 
1877 extern const CERTRevocationFlags *
CERT_GetClassicOCSPDisabledPolicy()1878 CERT_GetClassicOCSPDisabledPolicy()
1879 {
1880 #ifdef NSS_DISABLE_LIBPKIX
1881     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1882     return NULL;
1883 #else
1884     return &certRev_NSS_3_11_Ocsp_Disabled_Policy;
1885 #endif /* NSS_DISABLE_LIBPKIX */
1886 }
1887 
1888 #ifndef NSS_DISABLE_LIBPKIX
1889 static PRUint64 certRev_PKIX_Verify_Nist_Policy_LeafFlags[2] = {
1890     /* crl */
1891     CERT_REV_M_TEST_USING_THIS_METHOD |
1892         CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO |
1893         CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE,
1894     /* ocsp */
1895     0
1896 };
1897 
1898 static PRUint64 certRev_PKIX_Verify_Nist_Policy_ChainFlags[2] = {
1899     /* crl */
1900     CERT_REV_M_TEST_USING_THIS_METHOD |
1901         CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO |
1902         CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE,
1903     /* ocsp */
1904     0
1905 };
1906 
1907 static const CERTRevocationFlags certRev_PKIX_Verify_Nist_Policy = {
1908     { /* leafTests */
1909       2,
1910       certRev_PKIX_Verify_Nist_Policy_LeafFlags,
1911       0,
1912       0,
1913       0 },
1914     { /* chainTests */
1915       2,
1916       certRev_PKIX_Verify_Nist_Policy_ChainFlags,
1917       0,
1918       0,
1919       0 }
1920 };
1921 #endif /* NSS_DISABLE_LIBPKIX */
1922 
1923 extern const CERTRevocationFlags *
CERT_GetPKIXVerifyNistRevocationPolicy()1924 CERT_GetPKIXVerifyNistRevocationPolicy()
1925 {
1926 #ifdef NSS_DISABLE_LIBPKIX
1927     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1928     return NULL;
1929 #else
1930     return &certRev_PKIX_Verify_Nist_Policy;
1931 #endif /* NSS_DISABLE_LIBPKIX */
1932 }
1933 
1934 CERTRevocationFlags *
CERT_AllocCERTRevocationFlags(PRUint32 number_leaf_methods,PRUint32 number_leaf_pref_methods,PRUint32 number_chain_methods,PRUint32 number_chain_pref_methods)1935 CERT_AllocCERTRevocationFlags(
1936     PRUint32 number_leaf_methods, PRUint32 number_leaf_pref_methods,
1937     PRUint32 number_chain_methods, PRUint32 number_chain_pref_methods)
1938 {
1939 #ifdef NSS_DISABLE_LIBPKIX
1940     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1941     return NULL;
1942 #else
1943     CERTRevocationFlags *flags;
1944 
1945     flags = PORT_New(CERTRevocationFlags);
1946     if (!flags)
1947         return (NULL);
1948 
1949     flags->leafTests.number_of_defined_methods = number_leaf_methods;
1950     flags->leafTests.cert_rev_flags_per_method =
1951         PORT_NewArray(PRUint64, number_leaf_methods);
1952 
1953     flags->leafTests.number_of_preferred_methods = number_leaf_pref_methods;
1954     flags->leafTests.preferred_methods =
1955         PORT_NewArray(CERTRevocationMethodIndex, number_leaf_pref_methods);
1956 
1957     flags->chainTests.number_of_defined_methods = number_chain_methods;
1958     flags->chainTests.cert_rev_flags_per_method =
1959         PORT_NewArray(PRUint64, number_chain_methods);
1960 
1961     flags->chainTests.number_of_preferred_methods = number_chain_pref_methods;
1962     flags->chainTests.preferred_methods =
1963         PORT_NewArray(CERTRevocationMethodIndex, number_chain_pref_methods);
1964 
1965     if (!flags->leafTests.cert_rev_flags_per_method ||
1966         !flags->leafTests.preferred_methods ||
1967         !flags->chainTests.cert_rev_flags_per_method ||
1968         !flags->chainTests.preferred_methods) {
1969         CERT_DestroyCERTRevocationFlags(flags);
1970         return (NULL);
1971     }
1972 
1973     return flags;
1974 #endif /* NSS_DISABLE_LIBPKIX */
1975 }
1976 
1977 void
CERT_DestroyCERTRevocationFlags(CERTRevocationFlags * flags)1978 CERT_DestroyCERTRevocationFlags(CERTRevocationFlags *flags)
1979 {
1980 #ifdef NSS_DISABLE_LIBPKIX
1981     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1982     return;
1983 #else
1984     if (!flags)
1985         return;
1986 
1987     if (flags->leafTests.cert_rev_flags_per_method)
1988         PORT_Free(flags->leafTests.cert_rev_flags_per_method);
1989 
1990     if (flags->leafTests.preferred_methods)
1991         PORT_Free(flags->leafTests.preferred_methods);
1992 
1993     if (flags->chainTests.cert_rev_flags_per_method)
1994         PORT_Free(flags->chainTests.cert_rev_flags_per_method);
1995 
1996     if (flags->chainTests.preferred_methods)
1997         PORT_Free(flags->chainTests.preferred_methods);
1998 
1999     PORT_Free(flags);
2000 #endif /* NSS_DISABLE_LIBPKIX */
2001 }
2002 
2003 /*
2004  * CERT_PKIXVerifyCert
2005  *
2006  * Verify a Certificate using the PKIX library.
2007  *
2008  * Parameters:
2009  *  cert    - the target certificate to verify. Must be non-null
2010  *  params  - an array of type/value parameters which can be
2011  *            used to modify the behavior of the validation
2012  *            algorithm, or supply additional constraints.
2013  *
2014  *  outputTrustAnchor - the trust anchor which the certificate
2015  *                      chains to. The caller is responsible
2016  *                      for freeing this.
2017  *
2018  * Example Usage:
2019  *    CERTValParam args[3];
2020  *    args[0].type = cvpt_policyOID;
2021  *    args[0].value.si = oid;
2022  *    args[1].type = revCheckRequired;
2023  *    args[1].value.b = PR_TRUE;
2024  *    args[2].type = cvpt_end;
2025  *
2026  *    CERT_PKIXVerifyCert(cert, &output, args
2027  */
2028 SECStatus
CERT_PKIXVerifyCert(CERTCertificate * cert,SECCertificateUsage usages,CERTValInParam * paramsIn,CERTValOutParam * paramsOut,void * wincx)2029 CERT_PKIXVerifyCert(
2030     CERTCertificate *cert,
2031     SECCertificateUsage usages,
2032     CERTValInParam *paramsIn,
2033     CERTValOutParam *paramsOut,
2034     void *wincx)
2035 {
2036 #ifdef NSS_DISABLE_LIBPKIX
2037     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
2038     return SECFailure;
2039 #else
2040     SECStatus r = SECFailure;
2041     PKIX_Error *error = NULL;
2042     PKIX_ProcessingParams *procParams = NULL;
2043     PKIX_BuildResult *buildResult = NULL;
2044     void *nbioContext = NULL; /* for non-blocking IO */
2045     void *buildState = NULL;  /* for non-blocking IO */
2046     PKIX_CertSelector *certSelector = NULL;
2047     PKIX_List *certStores = NULL;
2048     PKIX_ValidateResult *valResult = NULL;
2049     PKIX_VerifyNode *verifyNode = NULL;
2050     PKIX_TrustAnchor *trustAnchor = NULL;
2051     PKIX_PL_Cert *trustAnchorCert = NULL;
2052     PKIX_List *builtCertList = NULL;
2053     CERTValOutParam *oparam = NULL;
2054     int i = 0;
2055 
2056     void *plContext = NULL;
2057 
2058 #ifdef PKIX_OBJECT_LEAK_TEST
2059     int leakedObjNum = 0;
2060     int memLeakLoopCount = 0;
2061     int objCountTable[PKIX_NUMTYPES];
2062     int fnInvLocalCount = 0;
2063     PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine;
2064 
2065     if (usePKIXValidationEngine) {
2066         /* current memory leak testing implementation does not allow
2067          * to run simultaneous tests one the same or a different threads.
2068          * Setting the variable to false, to make additional chain
2069          * validations be handled by old nss. */
2070         usePKIXValidationEngine = PR_FALSE;
2071     }
2072     testStartFnStackPosition = 1;
2073     fnStackNameArr[0] = "CERT_PKIXVerifyCert";
2074     fnStackInvCountArr[0] = 0;
2075     PKIX_Boolean abortOnLeak =
2076         (PR_GetEnvSecure("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ? PKIX_FALSE
2077                                                                          : PKIX_TRUE;
2078     runningLeakTest = PKIX_TRUE;
2079 
2080     /* Prevent multi-threaded run of object leak test */
2081     fnInvLocalCount = PR_ATOMIC_INCREMENT(&parallelFnInvocationCount);
2082     PORT_Assert(fnInvLocalCount == 1);
2083 
2084     do {
2085         r = SECFailure;
2086         error = NULL;
2087         procParams = NULL;
2088         buildResult = NULL;
2089         nbioContext = NULL; /* for non-blocking IO */
2090         buildState = NULL;  /* for non-blocking IO */
2091         certSelector = NULL;
2092         certStores = NULL;
2093         valResult = NULL;
2094         verifyNode = NULL;
2095         trustAnchor = NULL;
2096         trustAnchorCert = NULL;
2097         builtCertList = NULL;
2098         oparam = NULL;
2099         i = 0;
2100         errorGenerated = PKIX_FALSE;
2101         stackPosition = 0;
2102 
2103         if (leakedObjNum) {
2104             pkix_pl_lifecycle_ObjectTableUpdate(objCountTable);
2105         }
2106         memLeakLoopCount += 1;
2107 #endif /* PKIX_OBJECT_LEAK_TEST */
2108 
2109         error = PKIX_PL_NssContext_Create(
2110             0, PR_FALSE /*use arena*/, wincx, &plContext);
2111         if (error != NULL) { /* need pkix->nss error map */
2112             PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
2113             goto cleanup;
2114         }
2115 
2116         error = pkix_pl_NssContext_SetCertUsage(usages, plContext);
2117         if (error != NULL) {
2118             PORT_SetError(SEC_ERROR_INVALID_ARGS);
2119             goto cleanup;
2120         }
2121 
2122         error = PKIX_ProcessingParams_Create(&procParams, plContext);
2123         if (error != NULL) { /* need pkix->nss error map */
2124             PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
2125             goto cleanup;
2126         }
2127 
2128         /* local cert store should be set into procParams before
2129          * filling in revocation settings. */
2130         certStores = cert_GetCertStores(plContext);
2131         if (certStores == NULL) {
2132             goto cleanup;
2133         }
2134         error = PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext);
2135         if (error != NULL) {
2136             goto cleanup;
2137         }
2138 
2139         /* now process the extensible input parameters structure */
2140         if (paramsIn != NULL) {
2141             i = 0;
2142             while (paramsIn[i].type != cert_pi_end) {
2143                 if (paramsIn[i].type >= cert_pi_max) {
2144                     PORT_SetError(SEC_ERROR_INVALID_ARGS);
2145                     goto cleanup;
2146                 }
2147                 if (cert_pkixSetParam(procParams,
2148                                       &paramsIn[i], plContext) !=
2149                     SECSuccess) {
2150                     PORT_SetError(SEC_ERROR_INVALID_ARGS);
2151                     goto cleanup;
2152                 }
2153                 i++;
2154             }
2155         }
2156 
2157         certSelector = cert_GetTargetCertConstraints(cert, plContext);
2158         if (certSelector == NULL) {
2159             goto cleanup;
2160         }
2161         error = PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext);
2162         if (error != NULL) {
2163             goto cleanup;
2164         }
2165 
2166         error = PKIX_BuildChain(procParams, &nbioContext,
2167                                 &buildState, &buildResult, &verifyNode,
2168                                 plContext);
2169         if (error != NULL) {
2170             goto cleanup;
2171         }
2172 
2173         error = PKIX_BuildResult_GetValidateResult(buildResult, &valResult,
2174                                                    plContext);
2175         if (error != NULL) {
2176             goto cleanup;
2177         }
2178 
2179         error = PKIX_ValidateResult_GetTrustAnchor(valResult, &trustAnchor,
2180                                                    plContext);
2181         if (error != NULL) {
2182             goto cleanup;
2183         }
2184 
2185         if (trustAnchor != NULL) {
2186             error = PKIX_TrustAnchor_GetTrustedCert(trustAnchor, &trustAnchorCert,
2187                                                     plContext);
2188             if (error != NULL) {
2189                 goto cleanup;
2190             }
2191         }
2192 
2193 #ifdef PKIX_OBJECT_LEAK_TEST
2194         /* Can not continue if error was generated but not returned.
2195          * Jumping to cleanup. */
2196         if (errorGenerated)
2197             goto cleanup;
2198 #endif /* PKIX_OBJECT_LEAK_TEST */
2199 
2200         oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_trustAnchor);
2201         if (oparam != NULL) {
2202             if (trustAnchorCert != NULL) {
2203                 oparam->value.pointer.cert =
2204                     cert_NSSCertFromPKIXCert(trustAnchorCert);
2205             } else {
2206                 oparam->value.pointer.cert = NULL;
2207             }
2208         }
2209 
2210         error = PKIX_BuildResult_GetCertChain(buildResult, &builtCertList,
2211                                               plContext);
2212         if (error != NULL) {
2213             goto cleanup;
2214         }
2215 
2216         oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_certList);
2217         if (oparam != NULL) {
2218             error = cert_PkixToNssCertsChain(builtCertList,
2219                                              &oparam->value.pointer.chain,
2220                                              plContext);
2221             if (error)
2222                 goto cleanup;
2223         }
2224 
2225         r = SECSuccess;
2226 
2227     cleanup:
2228         if (verifyNode) {
2229             /* Return validation log only upon error. */
2230             oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_errorLog);
2231 #ifdef PKIX_OBJECT_LEAK_TEST
2232             if (!errorGenerated)
2233 #endif /* PKIX_OBJECT_LEAK_TEST */
2234                 if (r && oparam != NULL) {
2235                     PKIX_Error *tmpError =
2236                         cert_GetLogFromVerifyNode(oparam->value.pointer.log,
2237                                                   verifyNode, plContext);
2238                     if (tmpError) {
2239                         PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext);
2240                     }
2241                 }
2242             PKIX_PL_Object_DecRef((PKIX_PL_Object *)verifyNode, plContext);
2243         }
2244 
2245         if (procParams != NULL)
2246             PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext);
2247 
2248         if (trustAnchorCert != NULL)
2249             PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchorCert, plContext);
2250 
2251         if (trustAnchor != NULL)
2252             PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
2253 
2254         if (valResult != NULL)
2255             PKIX_PL_Object_DecRef((PKIX_PL_Object *)valResult, plContext);
2256 
2257         if (buildResult != NULL)
2258             PKIX_PL_Object_DecRef((PKIX_PL_Object *)buildResult, plContext);
2259 
2260         if (certStores != NULL)
2261             PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext);
2262 
2263         if (certSelector != NULL)
2264             PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext);
2265 
2266         if (builtCertList != NULL)
2267             PKIX_PL_Object_DecRef((PKIX_PL_Object *)builtCertList, plContext);
2268 
2269         if (error != NULL) {
2270             SECErrorCodes nssErrorCode = 0;
2271 
2272             cert_PkixErrorToNssCode(error, &nssErrorCode, plContext);
2273             cert_pkixDestroyValOutParam(paramsOut);
2274             PORT_SetError(nssErrorCode);
2275             PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
2276         }
2277 
2278         PKIX_PL_NssContext_Destroy(plContext);
2279 
2280 #ifdef PKIX_OBJECT_LEAK_TEST
2281         leakedObjNum =
2282             pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
2283 
2284         if (pkixLog && leakedObjNum) {
2285             PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d."
2286                                 "Stack %s\n",
2287                                 memLeakLoopCount, errorFnStackString));
2288         }
2289         PR_Free(errorFnStackString);
2290         errorFnStackString = NULL;
2291         if (abortOnLeak) {
2292             PORT_Assert(leakedObjNum == 0);
2293         }
2294 
2295     } while (errorGenerated);
2296 
2297     runningLeakTest = PKIX_FALSE;
2298     PR_ATOMIC_DECREMENT(&parallelFnInvocationCount);
2299     usePKIXValidationEngine = savedUsePkixEngFlag;
2300 #endif /* PKIX_OBJECT_LEAK_TEST */
2301 
2302     return r;
2303 #endif /* NSS_DISABLE_LIBPKIX */
2304 }
2305