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(¶llelFnInvocationCount);
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(¶llelFnInvocationCount);
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(¶llelFnInvocationCount);
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 ¶msIn[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(¶llelFnInvocationCount);
2300 usePKIXValidationEngine = savedUsePkixEngFlag;
2301 #endif /* PKIX_OBJECT_LEAK_TEST */
2302
2303 return r;
2304 #endif /* NSS_DISABLE_LIBPKIX */
2305 }
2306