Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / security / nss / lib / certhigh / certvfypkix.c
blob686b87546feff8220733ac7fb4f05c7291c12b74
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Sun Microsystems
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * nss_pkix_proxy.h
40 * PKIX - NSS proxy functions
42 * NOTE: All structures, functions, data types are parts of library private
43 * api and are subjects to change in any following releases.
46 #include "prerror.h"
47 #include "prprf.h"
49 #include "nspr.h"
50 #include "pk11func.h"
51 #include "certdb.h"
52 #include "cert.h"
53 #include "secerr.h"
54 #include "nssb64.h"
55 #include "secasn1.h"
56 #include "secder.h"
57 #include "pkit.h"
59 #include "pkix_pl_common.h"
60 #include "pkix_pl_ekuchecker.h"
62 extern PRLogModuleInfo *pkixLog;
64 #ifdef DEBUG_volkov
65 /* Temporary declarations of functioins. Will be removed with fix for
66 * 391183 */
67 extern char *
68 pkix_Error2ASCII(PKIX_Error *error, void *plContext);
70 extern void
71 cert_PrintCert(PKIX_PL_Cert *pkixCert, void *plContext);
73 extern PKIX_Error *
74 cert_PrintCertChain(PKIX_List *pkixCertChain, void *plContext);
76 #endif /* DEBUG */
78 #ifdef PKIX_OBJECT_LEAK_TEST
80 extern PKIX_UInt32
81 pkix_pl_lifecycle_ObjectLeakCheck(int *);
83 extern SECStatus
84 pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable);
86 PRInt32 parallelFnInvocationCount;
87 #endif /* PKIX_OBJECT_LEAK_TEST */
90 static PRBool usePKIXValidationEngine = PR_FALSE;
93 * FUNCTION: CERT_SetUsePKIXForValidation
94 * DESCRIPTION:
96 * Enables or disables use of libpkix for certificate validation
98 * PARAMETERS:
99 * "enable"
100 * PR_TRUE: enables use of libpkix for cert validation.
101 * PR_FALSE: disables.
102 * THREAD SAFETY:
103 * NOT Thread Safe.
104 * RETURNS:
105 * Returns SECSuccess if successfully enabled
107 SECStatus
108 CERT_SetUsePKIXForValidation(PRBool enable)
110 usePKIXValidationEngine = (enable > 0) ? PR_TRUE : PR_FALSE;
111 return SECSuccess;
115 * FUNCTION: CERT_GetUsePKIXForValidation
116 * DESCRIPTION:
118 * Checks if libpkix building function should be use for certificate
119 * chain building.
121 * PARAMETERS:
122 * NONE
123 * THREAD SAFETY:
124 * NOT Thread Safe
125 * RETURNS:
126 * Returns PR_TRUE if libpkix should be used. PR_FALSE otherwise.
128 PRBool
129 CERT_GetUsePKIXForValidation()
131 return usePKIXValidationEngine;
135 * FUNCTION: cert_NssKeyUsagesToPkix
136 * DESCRIPTION:
138 * Converts nss key usage bit field(PRUint32) to pkix key usage
139 * bit field.
141 * PARAMETERS:
142 * "nssKeyUsage"
143 * Nss key usage bit field.
144 * "pkixKeyUsage"
145 * Pkix key usage big field.
146 * "plContext"
147 * Platform-specific context pointer.
148 * THREAD SAFETY:
149 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
150 * RETURNS:
151 * Returns NULL if the function succeeds.
152 * Returns a Fatal Error if the function fails in an unrecoverable way.
154 static PKIX_Error*
155 cert_NssKeyUsagesToPkix(
156 PRUint32 nssKeyUsage,
157 PKIX_UInt32 *pPkixKeyUsage,
158 void *plContext)
160 PKIX_UInt32 pkixKeyUsage = 0;
162 PKIX_ENTER(CERTVFYPKIX, "cert_NssKeyUsagesToPkix");
163 PKIX_NULLCHECK_ONE(pPkixKeyUsage);
165 *pPkixKeyUsage = 0;
167 if (nssKeyUsage & KU_DIGITAL_SIGNATURE) {
168 pkixKeyUsage |= PKIX_DIGITAL_SIGNATURE;
171 if (nssKeyUsage & KU_NON_REPUDIATION) {
172 pkixKeyUsage |= PKIX_NON_REPUDIATION;
175 if (nssKeyUsage & KU_KEY_ENCIPHERMENT) {
176 pkixKeyUsage |= PKIX_KEY_ENCIPHERMENT;
179 if (nssKeyUsage & KU_DATA_ENCIPHERMENT) {
180 pkixKeyUsage |= PKIX_DATA_ENCIPHERMENT;
183 if (nssKeyUsage & KU_KEY_AGREEMENT) {
184 pkixKeyUsage |= PKIX_KEY_AGREEMENT;
187 if (nssKeyUsage & KU_KEY_CERT_SIGN) {
188 pkixKeyUsage |= PKIX_KEY_CERT_SIGN;
191 if (nssKeyUsage & KU_CRL_SIGN) {
192 pkixKeyUsage |= PKIX_CRL_SIGN;
195 if (nssKeyUsage & KU_ENCIPHER_ONLY) {
196 pkixKeyUsage |= PKIX_ENCIPHER_ONLY;
199 /* Not supported. XXX we should support this once it is
200 * fixed in NSS */
201 /* pkixKeyUsage |= PKIX_DECIPHER_ONLY; */
203 *pPkixKeyUsage = pkixKeyUsage;
205 PKIX_RETURN(CERTVFYPKIX);
208 extern char* ekuOidStrings[];
210 enum {
211 ekuIndexSSLServer = 0,
212 ekuIndexSSLClient,
213 ekuIndexCodeSigner,
214 ekuIndexEmail,
215 ekuIndexTimeStamp,
216 ekuIndexStatusResponder,
217 ekuIndexUnknown
218 } ekuIndex;
220 typedef struct {
221 SECCertUsage certUsage;
222 PRUint32 ekuStringIndex;
223 } SECCertUsageToEku;
225 const SECCertUsageToEku certUsageEkuStringMap[] = {
226 {certUsageSSLClient, ekuIndexSSLClient},
227 {certUsageSSLServer, ekuIndexSSLServer},
228 {certUsageSSLServerWithStepUp, ekuIndexSSLServer}, /* need to add oids to
229 * the list of eku.
230 * see 390381*/
231 {certUsageSSLCA, ekuIndexSSLServer},
232 {certUsageEmailSigner, ekuIndexEmail},
233 {certUsageEmailRecipient, ekuIndexEmail},
234 {certUsageObjectSigner, ekuIndexCodeSigner},
235 {certUsageUserCertImport, ekuIndexUnknown},
236 {certUsageVerifyCA, ekuIndexUnknown},
237 {certUsageProtectedObjectSigner, ekuIndexUnknown},
238 {certUsageStatusResponder, ekuIndexStatusResponder},
239 {certUsageAnyCA, ekuIndexUnknown},
242 #define CERT_USAGE_EKU_STRING_MAPS_TOTAL 12
245 * FUNCTION: cert_NssCertificateUsageToPkixKUAndEKU
246 * DESCRIPTION:
248 * Converts nss CERTCertificateUsage bit field to pkix key and
249 * extended key usages.
251 * PARAMETERS:
252 * "cert"
253 * Pointer to CERTCertificate structure of validating cert.
254 * "requiredCertUsages"
255 * Required usage that will be converted to pkix eku and ku.
256 * "requiredKeyUsage",
257 * Additional key usages impose to cert.
258 * "isCA",
259 * it true, convert usages for cert that is a CA cert.
260 * "ppkixEKUList"
261 * Returned address of a list of pkix extended key usages.
262 * "ppkixKU"
263 * Returned address of pkix required key usages bit field.
264 * "plContext"
265 * Platform-specific context pointer.
266 * THREAD SAFETY:
267 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
268 * RETURNS:
269 * Returns NULL if the function succeeds.
270 * Returns a Cert Verify Error if the function fails in an unrecoverable way.
271 * Returns a Fatal Error if the function fails in an unrecoverable way.
273 static PKIX_Error*
274 cert_NssCertificateUsageToPkixKUAndEKU(
275 CERTCertificate *cert,
276 SECCertUsage requiredCertUsage,
277 PRUint32 requiredKeyUsages,
278 PRBool isCA,
279 PKIX_List **ppkixEKUList,
280 PKIX_UInt32 *ppkixKU,
281 void *plContext)
283 PKIX_List *ekuOidsList = NULL;
284 PKIX_PL_OID *ekuOid = NULL;
285 int i = 0;
286 int ekuIndex = ekuIndexUnknown;
288 PKIX_ENTER(CERTVFYPKIX, "cert_NssCertificateUsageToPkixEku");
289 PKIX_NULLCHECK_TWO(ppkixEKUList, ppkixKU);
291 PKIX_CHECK(
292 PKIX_List_Create(&ekuOidsList, plContext),
293 PKIX_LISTCREATEFAILED);
295 for (;i < CERT_USAGE_EKU_STRING_MAPS_TOTAL;i++) {
296 const SECCertUsageToEku *usageToEkuElem =
297 &certUsageEkuStringMap[i];
298 if (usageToEkuElem->certUsage == requiredCertUsage) {
299 ekuIndex = usageToEkuElem->ekuStringIndex;
300 break;
303 if (ekuIndex != ekuIndexUnknown) {
304 PRUint32 reqKeyUsage = 0;
305 PRUint32 reqCertType = 0;
307 CERT_KeyUsageAndTypeForCertUsage(requiredCertUsage, isCA,
308 &reqKeyUsage,
309 &reqCertType);
311 requiredKeyUsages |= reqKeyUsage;
313 PKIX_CHECK(
314 PKIX_PL_OID_Create(ekuOidStrings[ekuIndex], &ekuOid,
315 plContext),
316 PKIX_OIDCREATEFAILED);
318 PKIX_CHECK(
319 PKIX_List_AppendItem(ekuOidsList, (PKIX_PL_Object *)ekuOid,
320 plContext),
321 PKIX_LISTAPPENDITEMFAILED);
323 PKIX_DECREF(ekuOid);
326 PKIX_CHECK(
327 cert_NssKeyUsagesToPkix(requiredKeyUsages, ppkixKU, plContext),
328 PKIX_NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED);
330 *ppkixEKUList = ekuOidsList;
331 ekuOidsList = NULL;
333 cleanup:
335 PKIX_DECREF(ekuOid);
336 PKIX_DECREF(ekuOidsList);
338 PKIX_RETURN(CERTVFYPKIX);
343 * FUNCTION: cert_ProcessingParamsSetKuAndEku
344 * DESCRIPTION:
346 * Converts cert usage to pkix KU and EKU types and sets
347 * converted data into PKIX_ProcessingParams object. It also sets
348 * proper cert usage into nsscontext object.
350 * PARAMETERS:
351 * "procParams"
352 * Pointer to PKIX_ProcessingParams used during validation.
353 * "requiredCertUsage"
354 * Required certificate usages the certificate and chain is built and
355 * validated for.
356 * "requiredKeyUsage"
357 * Request additional key usages the certificate should be validated for.
358 * "isCA"
359 * Should the cert be verifyed as CA cert for the usages.
360 * "plContext"
361 * Platform-specific context pointer.
362 * THREAD SAFETY:
363 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
364 * RETURNS:
365 * Returns NULL if the function succeeds.
366 * Returns a Cert Verify Error if the function fails in an unrecoverable way.
367 * Returns a Fatal Error if the function fails in an unrecoverable way.
369 static PKIX_Error*
370 cert_ProcessingParamsSetKuAndEku(
371 PKIX_ProcessingParams *procParams,
372 CERTCertificate *cert,
373 PRBool isCA,
374 SECCertUsage requiredCertUsage,
375 PRUint32 requiredKeyUsages,
376 void *plContext)
378 PKIX_List *extKeyUsage = NULL;
379 PKIX_CertSelector *certSelector = NULL;
380 PKIX_ComCertSelParams *certSelParams = NULL;
381 PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext*)plContext;
382 PKIX_UInt32 keyUsage = 0;
384 PKIX_ENTER(CERTVFYPKIX, "cert_ProcessingParamsSetKuAndEku");
385 PKIX_NULLCHECK_TWO(procParams, nssContext);
387 PKIX_CHECK(
388 pkix_pl_NssContext_SetCertUsage(
389 ((SECCertificateUsage)1) << requiredCertUsage, nssContext),
390 PKIX_NSSCONTEXTSETCERTUSAGEFAILED);
392 PKIX_CHECK(
393 cert_NssCertificateUsageToPkixKUAndEKU(cert, requiredCertUsage,
394 requiredKeyUsages, isCA,
395 &extKeyUsage, &keyUsage,
396 plContext),
397 PKIX_CANNOTCONVERTCERTUSAGETOPKIXKEYANDEKUSAGES);
399 PKIX_CHECK(
400 PKIX_ProcessingParams_GetTargetCertConstraints(procParams,
401 &certSelector, plContext),
402 PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
404 PKIX_CHECK(
405 PKIX_CertSelector_GetCommonCertSelectorParams(certSelector,
406 &certSelParams, plContext),
407 PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
410 PKIX_CHECK(
411 PKIX_ComCertSelParams_SetKeyUsage(certSelParams, keyUsage,
412 plContext),
413 PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED);
415 PKIX_CHECK(
416 PKIX_ComCertSelParams_SetExtendedKeyUsage(certSelParams,
417 extKeyUsage,
418 plContext),
419 PKIX_COMCERTSELPARAMSSETEXTKEYUSAGEFAILED);
421 PKIX_CHECK(
422 PKIX_PL_EkuChecker_Create(procParams, plContext),
423 PKIX_EKUCHECKERINITIALIZEFAILED);
425 cleanup:
426 PKIX_DECREF(extKeyUsage);
427 PKIX_DECREF(certSelector);
428 PKIX_DECREF(certSelParams);
430 PKIX_RETURN(CERTVFYPKIX);
434 * Unused parameters:
436 * CERTCertList *initialChain,
437 * CERTCertStores certStores,
438 * CERTCertRevCheckers certRevCheckers,
439 * CERTCertChainCheckers certChainCheckers,
440 * SECItem *initPolicies,
441 * PRBool policyQualifierRejected,
442 * PRBool anyPolicyInhibited,
443 * PRBool reqExplicitPolicy,
444 * PRBool policyMappingInhibited,
445 * PKIX_CertSelector certConstraints,
449 * FUNCTION: cert_CreatePkixProcessingParams
450 * DESCRIPTION:
452 * Creates and fills in PKIX_ProcessingParams structure to be used
453 * for certificate chain building.
455 * PARAMETERS:
456 * "cert"
457 * Pointer to the CERTCertificate: the leaf certificate of a chain.
458 * "time"
459 * Validity time.
460 * "wincx"
461 * Nss db password token.
462 * "useArena"
463 * Flags to use arena for data allocation during chain building process.
464 * "pprocParams"
465 * Address to return created processing parameters.
466 * "plContext"
467 * Platform-specific context pointer.
468 * THREAD SAFETY:
469 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
470 * RETURNS:
471 * Returns NULL if the function succeeds.
472 * Returns a Cert Verify Error if the function fails in an unrecoverable way.
473 * Returns a Fatal Error if the function fails in an unrecoverable way.
475 static PKIX_Error*
476 cert_CreatePkixProcessingParams(
477 CERTCertificate *cert,
478 PRBool checkSig, /* not used yet. See bug 391476 */
479 PRTime time,
480 void *wincx,
481 PRBool useArena,
482 #ifdef DEBUG_volkov
483 PRBool checkAllCertsOCSP,
484 #endif
485 PKIX_ProcessingParams **pprocParams,
486 void **pplContext)
488 PKIX_List *anchors = NULL;
489 PKIX_PL_Cert *targetCert = NULL;
490 PKIX_PL_Date *date = NULL;
491 PKIX_ProcessingParams *procParams = NULL;
492 PKIX_CertSelector *certSelector = NULL;
493 PKIX_ComCertSelParams *certSelParams = NULL;
494 PKIX_CertStore *certStore = NULL;
495 PKIX_List *certStores = NULL;
496 #ifdef DEBUG_volkov
497 PKIX_RevocationChecker *ocspChecker = NULL;
498 #endif
499 void *plContext = NULL;
501 PKIX_ENTER(CERTVFYPKIX, "cert_CreatePkixProcessingParams");
502 PKIX_NULLCHECK_TWO(cert, pprocParams);
504 PKIX_CHECK(
505 PKIX_PL_NssContext_Create(0, useArena, wincx, &plContext),
506 PKIX_NSSCONTEXTCREATEFAILED);
508 *pplContext = plContext;
510 #ifdef PKIX_NOTDEF
511 /* Functions should be implemented in patch for 390532 */
512 PKIX_CHECK(
513 pkix_pl_NssContext_SetCertSignatureCheck(checkSig,
514 (PKIX_PL_NssContext*)plContext),
515 PKIX_NSSCONTEXTSETCERTSIGNCHECKFAILED);
517 #endif /* PKIX_NOTDEF */
519 PKIX_CHECK(
520 PKIX_ProcessingParams_Create(&procParams, plContext),
521 PKIX_PROCESSINGPARAMSCREATEFAILED);
523 PKIX_CHECK(
524 PKIX_ComCertSelParams_Create(&certSelParams, plContext),
525 PKIX_COMCERTSELPARAMSCREATEFAILED);
527 PKIX_CHECK(
528 PKIX_PL_Cert_CreateFromCERTCertificate(cert, &targetCert, plContext),
529 PKIX_CERTCREATEWITHNSSCERTFAILED);
531 PKIX_CHECK(
532 PKIX_ComCertSelParams_SetCertificate(certSelParams,
533 targetCert, plContext),
534 PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED);
536 PKIX_CHECK(
537 PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext),
538 PKIX_COULDNOTCREATECERTSELECTOROBJECT);
540 PKIX_CHECK(
541 PKIX_CertSelector_SetCommonCertSelectorParams(certSelector,
542 certSelParams, plContext),
543 PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
545 PKIX_CHECK(
546 PKIX_ProcessingParams_SetTargetCertConstraints(procParams,
547 certSelector, plContext),
548 PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED);
550 PKIX_CHECK(
551 PKIX_PL_Pk11CertStore_Create(&certStore, plContext),
552 PKIX_PK11CERTSTORECREATEFAILED);
554 PKIX_CHECK(
555 PKIX_List_Create(&certStores, plContext),
556 PKIX_UNABLETOCREATELIST);
558 PKIX_CHECK(
559 PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore,
560 plContext),
561 PKIX_LISTAPPENDITEMFAILED);
563 PKIX_CHECK(
564 PKIX_ProcessingParams_SetCertStores(procParams, certStores,
565 plContext),
566 PKIX_PROCESSINGPARAMSADDCERTSTOREFAILED);
568 PKIX_CHECK(
569 PKIX_PL_Date_CreateFromPRTime(time, &date, plContext),
570 PKIX_DATECREATEFROMPRTIMEFAILED);
572 PKIX_CHECK(
573 PKIX_ProcessingParams_SetDate(procParams, date, plContext),
574 PKIX_PROCESSINGPARAMSSETDATEFAILED);
576 PKIX_CHECK(
577 PKIX_ProcessingParams_SetNISTRevocationPolicyEnabled(procParams,
578 PKIX_FALSE,
579 plContext),
580 PKIX_PROCESSINGPARAMSSETNISTREVOCATIONENABLEDFAILED);
582 #ifdef DEBUG_volkov1
583 /* Enables ocsp rev checking of the chain cert through pkix OCSP
584 * implementation. */
585 if (checkAllCertsOCSP) {
586 PKIX_CHECK(
587 PKIX_OcspChecker_Initialize(date, NULL, NULL,
588 &ocspChecker, plContext),
589 PKIX_PROCESSINGPARAMSSETDATEFAILED);
591 PKIX_CHECK(
592 PKIX_ProcessingParams_AddRevocationChecker(procParams,
593 ocspChecker, plContext),
594 PKIX_PROCESSINGPARAMSSETDATEFAILED);
596 #endif
598 PKIX_CHECK(
599 PKIX_ProcessingParams_SetAnyPolicyInhibited(procParams, PR_FALSE,
600 plContext),
601 PKIX_PROCESSINGPARAMSSETANYPOLICYINHIBITED);
603 PKIX_CHECK(
604 PKIX_ProcessingParams_SetExplicitPolicyRequired(procParams, PR_FALSE,
605 plContext),
606 PKIX_PROCESSINGPARAMSSETEXPLICITPOLICYREQUIRED);
608 PKIX_CHECK(
609 PKIX_ProcessingParams_SetPolicyMappingInhibited(procParams, PR_FALSE,
610 plContext),
611 PKIX_PROCESSINGPARAMSSETPOLICYMAPPINGINHIBITED);
613 *pprocParams = procParams;
614 procParams = NULL;
616 cleanup:
617 PKIX_DECREF(anchors);
618 PKIX_DECREF(targetCert);
619 PKIX_DECREF(date);
620 PKIX_DECREF(certSelector);
621 PKIX_DECREF(certSelParams);
622 PKIX_DECREF(certStore);
623 PKIX_DECREF(certStores);
624 PKIX_DECREF(procParams);
625 #ifdef DEBUG_volkov
626 PKIX_DECREF(ocspChecker);
627 #endif
629 PKIX_RETURN(CERTVFYPKIX);
633 * FUNCTION: cert_PkixToNssCertsChain
634 * DESCRIPTION:
636 * Converts pkix cert list into nss cert list.
638 * PARAMETERS:
639 * "pkixCertChain"
640 * Pkix certificate list.
641 * "pvalidChain"
642 * An address of returned nss certificate list.
643 * "plContext"
644 * Platform-specific context pointer.
645 * THREAD SAFETY:
646 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
647 * RETURNS:
648 * Returns NULL if the function succeeds.
649 * Returns a Cert Verify Error if the function fails in an unrecoverable way.
650 * Returns a Fatal Error if the function fails in an unrecoverable way.
652 static PKIX_Error*
653 cert_PkixToNssCertsChain(
654 PKIX_List *pkixCertChain,
655 CERTCertList **pvalidChain,
656 void *plContext)
658 PRArenaPool *arena = NULL;
659 CERTCertificate *nssCert = NULL;
660 CERTCertList *validChain = NULL;
661 PKIX_PL_Object *certItem = NULL;
662 PKIX_UInt32 length = 0;
663 PKIX_UInt32 i = 0;
665 PKIX_ENTER(CERTVFYPKIX, "cert_PkixToNssCertsChain");
666 PKIX_NULLCHECK_ONE(pvalidChain);
668 if (pkixCertChain == NULL) {
669 goto cleanup;
671 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
672 if (arena == NULL) {
673 PKIX_ERROR(PKIX_OUTOFMEMORY);
675 validChain = (CERTCertList*)PORT_ArenaZAlloc(arena, sizeof(CERTCertList));
676 if (validChain == NULL) {
677 PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
679 PR_INIT_CLIST(&validChain->list);
680 validChain->arena = arena;
681 arena = NULL;
683 PKIX_CHECK(
684 PKIX_List_GetLength(pkixCertChain, &length, plContext),
685 PKIX_LISTGETLENGTHFAILED);
687 for (i = 0; i < length; i++){
688 CERTCertListNode *node = NULL;
690 PKIX_CHECK(
691 PKIX_List_GetItem(pkixCertChain, i, &certItem, plContext),
692 PKIX_LISTGETITEMFAILED);
694 PKIX_CHECK(
695 PKIX_PL_Cert_GetCERTCertificate((PKIX_PL_Cert*)certItem, &nssCert,
696 plContext),
697 PKIX_CERTGETCERTCERTIFICATEFAILED);
699 node =
700 (CERTCertListNode *)PORT_ArenaZAlloc(validChain->arena,
701 sizeof(CERTCertListNode));
702 if ( node == NULL ) {
703 PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
706 PR_INSERT_BEFORE(&node->links, &validChain->list);
708 node->cert = nssCert;
709 nssCert = NULL;
711 PKIX_DECREF(certItem);
714 *pvalidChain = validChain;
716 cleanup:
717 if (PKIX_ERROR_RECEIVED){
718 if (validChain) {
719 CERT_DestroyCertList(validChain);
720 } else if (arena) {
721 PORT_FreeArena(arena, PR_FALSE);
723 if (nssCert) {
724 CERT_DestroyCertificate(nssCert);
727 PKIX_DECREF(certItem);
729 PKIX_RETURN(CERTVFYPKIX);
734 * FUNCTION: cert_BuildAndValidateChain
735 * DESCRIPTION:
737 * The function builds and validates a cert chain based on certificate
738 * selection criterias from procParams. This function call PKIX_BuildChain
739 * to accomplish chain building. If PKIX_BuildChain returns with incomplete
740 * IO, the function waits with PR_Poll until the blocking IO is finished and
741 * return control back to PKIX_BuildChain.
743 * PARAMETERS:
744 * "procParams"
745 * Processing parameters to be used during chain building.
746 * "pResult"
747 * Returned build result.
748 * "pVerifyNode"
749 * Returned pointed to verify node structure: the tree-like structure
750 * that reports points of chain building failures.
751 * "plContext"
752 * Platform-specific context pointer.
753 * THREAD SAFETY:
754 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
755 * RETURNS:
756 * Returns NULL if the function succeeds.
757 * Returns a Cert Verify Error if the function fails in an unrecoverable way.
758 * Returns a Fatal Error if the function fails in an unrecoverable way.
760 static PKIX_Error*
761 cert_BuildAndValidateChain(
762 PKIX_ProcessingParams *procParams,
763 PKIX_BuildResult **pResult,
764 PKIX_VerifyNode **pVerifyNode,
765 void *plContext)
767 PKIX_BuildResult *result = NULL;
768 PKIX_VerifyNode *verifyNode = NULL;
769 void *nbioContext = NULL;
770 void *state = NULL;
772 PKIX_ENTER(CERTVFYPKIX, "cert_BuildAndVerifyChain");
773 PKIX_NULLCHECK_TWO(procParams, pResult);
775 do {
776 if (nbioContext && state) {
777 /* PKIX-XXX: need to test functionality of NBIO handling in libPkix.
778 * See bug 391180 */
779 PRInt32 filesReady = 0;
780 PRPollDesc *pollDesc = (PRPollDesc*)nbioContext;
781 filesReady = PR_Poll(pollDesc, 1, PR_INTERVAL_NO_TIMEOUT);
782 if (filesReady <= 0) {
783 PKIX_ERROR(PKIX_PRPOLLRETBADFILENUM);
787 PKIX_CHECK(
788 PKIX_BuildChain(procParams, &nbioContext, &state,
789 &result, &verifyNode, plContext),
790 PKIX_UNABLETOBUILDCHAIN);
792 } while (nbioContext && state);
794 *pResult = result;
796 cleanup:
797 if (pVerifyNode) {
798 *pVerifyNode = verifyNode;
801 PKIX_RETURN(CERTVFYPKIX);
806 * FUNCTION: cert_PkixErrorToNssCode
807 * DESCRIPTION:
809 * Converts pkix error(PKIX_Error) structure to PR error codes.
811 * PKIX-XXX to be implemented. See 391183.
813 * PARAMETERS:
814 * "error"
815 * Pkix error that will be converted.
816 * "nssCode"
817 * Corresponding nss error code.
818 * "plContext"
819 * Platform-specific context pointer.
820 * THREAD SAFETY:
821 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
822 * RETURNS:
823 * Returns NULL if the function succeeds.
824 * Returns a Cert Verify Error if the function fails in an unrecoverable way.
825 * Returns a Fatal Error if the function fails in an unrecoverable way.
827 static PKIX_Error *
828 cert_PkixErrorToNssCode(
829 PKIX_Error *error,
830 SECErrorCodes *pNssErr,
831 void *plContext)
833 int errLevel = 0;
834 PKIX_UInt32 nssErr = 0;
835 PKIX_Error *errPtr = error;
837 PKIX_ENTER(CERTVFYPKIX, "cert_PkixErrorToNssCode");
838 PKIX_NULLCHECK_TWO(error, pNssErr);
840 /* Loop until we find at least one error with non-null
841 * plErr code, that is going to be nss error code. */
842 while (errPtr) {
843 if (errPtr->plErr && !nssErr) {
844 nssErr = errPtr->plErr;
845 if (!pkixLog) break;
847 if (pkixLog) {
848 PR_LOG(pkixLog, 2, ("Error at level %d: %s\n", errLevel,
849 PKIX_ErrorText[errPtr->errCode]));
851 errPtr = errPtr->cause;
852 errLevel += 1;
854 PORT_Assert(nssErr);
855 if (!nssErr) {
856 *pNssErr = SEC_ERROR_LIBPKIX_INTERNAL;
857 } else {
858 *pNssErr = nssErr;
861 PKIX_RETURN(CERTVFYPKIX);
865 * FUNCTION: cert_GetLogFromVerifyNode
866 * DESCRIPTION:
868 * Recursive function that converts verify node tree-like set of structures
869 * to CERTVerifyLog.
871 * PARAMETERS:
872 * "log"
873 * Pointed to already allocated CERTVerifyLog structure.
874 * "node"
875 * A node of PKIX_VerifyNode tree.
876 * "plContext"
877 * Platform-specific context pointer.
878 * THREAD SAFETY:
879 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
880 * RETURNS:
881 * Returns NULL if the function succeeds.
882 * Returns a Cert Verify Error if the function fails in an unrecoverable way.
883 * Returns a Fatal Error if the function fails in an unrecoverable way.
885 static PKIX_Error *
886 cert_GetLogFromVerifyNode(
887 CERTVerifyLog *log,
888 PKIX_VerifyNode *node,
889 void *plContext)
891 PKIX_List *children = NULL;
892 PKIX_VerifyNode *childNode = NULL;
894 PKIX_ENTER(CERTVFYPKIX, "cert_GetLogFromVerifyNode");
896 children = node->children;
898 if (children == NULL) {
899 PKIX_ERRORCODE errCode = PKIX_ANCHORDIDNOTCHAINTOCERT;
900 if (node->error && node->error->errCode != errCode) {
901 #ifdef DEBUG_volkov
902 char *string = pkix_Error2ASCII(node->error, plContext);
903 fprintf(stderr, "Branch search finished with error: \t%s\n", string);
904 PKIX_PL_Free(string, NULL);
905 #endif
906 if (log != NULL) {
907 SECErrorCodes nssErrorCode = 0;
908 CERTCertificate *cert = NULL;
910 cert = node->verifyCert->nssCert;
912 PKIX_CHECK(
913 cert_PkixErrorToNssCode(node->error, &nssErrorCode,
914 plContext),
915 PKIX_GETPKIXERRORCODEFAILED);
917 cert_AddToVerifyLog(log, cert, nssErrorCode, node->depth, NULL);
920 PKIX_RETURN(CERTVFYPKIX);
921 } else {
922 PRUint32 i = 0;
923 PKIX_UInt32 length = 0;
925 PKIX_CHECK(
926 PKIX_List_GetLength(children, &length, plContext),
927 PKIX_LISTGETLENGTHFAILED);
929 for (i = 0; i < length; i++){
931 PKIX_CHECK(
932 PKIX_List_GetItem(children, i, (PKIX_PL_Object**)&childNode,
933 plContext),
934 PKIX_LISTGETITEMFAILED);
936 PKIX_CHECK(
937 cert_GetLogFromVerifyNode(log, childNode, plContext),
938 PKIX_ERRORINRECURSIVEEQUALSCALL);
940 PKIX_DECREF(childNode);
944 cleanup:
945 PKIX_DECREF(childNode);
947 PKIX_RETURN(CERTVFYPKIX);
951 * FUNCTION: cert_GetBuildResults
952 * DESCRIPTION:
954 * Converts pkix build results to nss results. This function is called
955 * regardless of build result.
957 * If it called after chain was successfully constructed, then it will
958 * convert:
959 * * pkix cert list that represent the chain to nss cert list
960 * * trusted root the chain was anchored to nss certificate.
962 * In case of failure it will convert:
963 * * pkix error to PR error code(will set it with PORT_SetError)
964 * * pkix validation log to nss CERTVerifyLog
966 * PARAMETERS:
967 * "buildResult"
968 * Build results returned by PKIX_BuildChain.
969 * "verifyNode"
970 * Tree-like structure of chain building/validation failures
971 * returned by PKIX_BuildChain. Ignored in case of success.
972 * "error"
973 * Final error returned by PKIX_BuildChain. Should be NULL in
974 * case of success.
975 * "log"
976 * Address of pre-allocated(if not NULL) CERTVerifyLog structure.
977 * "ptrustedRoot"
978 * Address of returned trusted root the chain was anchored to.
979 * "pvalidChain"
980 * Address of returned valid chain.
981 * "plContext"
982 * Platform-specific context pointer.
983 * THREAD SAFETY:
984 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
985 * RETURNS:
986 * Returns NULL if the function succeeds.
987 * Returns a Cert Verify Error if the function fails in an unrecoverable way.
988 * Returns a Fatal Error if the function fails in an unrecoverable way.
990 static PKIX_Error*
991 cert_GetBuildResults(
992 PKIX_BuildResult *buildResult,
993 PKIX_VerifyNode *verifyNode,
994 PKIX_Error *error,
995 CERTVerifyLog *log,
996 CERTCertificate **ptrustedRoot,
997 CERTCertList **pvalidChain,
998 void *plContext)
1000 PKIX_ValidateResult *validResult = NULL;
1001 CERTCertList *validChain = NULL;
1002 CERTCertificate *trustedRoot = NULL;
1003 PKIX_TrustAnchor *trustAnchor = NULL;
1004 PKIX_PL_Cert *trustedCert = NULL;
1005 PKIX_List *pkixCertChain = NULL;
1006 #ifdef DEBUG_volkov
1007 PKIX_Error *tmpPkixError = NULL;
1008 #endif /* DEBUG */
1010 PKIX_ENTER(CERTVFYPKIX, "cert_GetBuildResults");
1011 if (buildResult == NULL && error == NULL) {
1012 PKIX_ERROR(PKIX_NULLARGUMENT);
1015 if (error) {
1016 SECErrorCodes nssErrorCode = 0;
1017 #ifdef DEBUG_volkov
1018 char *temp = pkix_Error2ASCII(error, plContext);
1019 fprintf(stderr, "BUILD ERROR:\n%s\n", temp);
1020 PKIX_PL_Free(temp, NULL);
1021 #endif /* DEBUG */
1022 if (verifyNode) {
1023 PKIX_Error *tmpError =
1024 cert_GetLogFromVerifyNode(log, verifyNode, plContext);
1025 if (tmpError) {
1026 PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext);
1029 cert_PkixErrorToNssCode(error, &nssErrorCode, plContext);
1030 PORT_SetError(nssErrorCode);
1031 goto cleanup;
1034 if (pvalidChain) {
1035 PKIX_CHECK(
1036 PKIX_BuildResult_GetCertChain(buildResult, &pkixCertChain,
1037 plContext),
1038 PKIX_BUILDRESULTGETCERTCHAINFAILED);
1040 #ifdef DEBUG_volkov
1041 tmpPkixError = cert_PrintCertChain(pkixCertChain, plContext);
1042 if (tmpPkixError) {
1043 PKIX_PL_Object_DecRef((PKIX_PL_Object*)tmpPkixError, plContext);
1045 #endif
1047 PKIX_CHECK(
1048 cert_PkixToNssCertsChain(pkixCertChain, &validChain, plContext),
1049 PKIX_CERTCHAINTONSSCHAINFAILED);
1052 if (ptrustedRoot) {
1053 PKIX_CHECK(
1054 PKIX_BuildResult_GetValidateResult(buildResult, &validResult,
1055 plContext),
1056 PKIX_BUILDRESULTGETVALIDATERESULTFAILED);
1058 PKIX_CHECK(
1059 PKIX_ValidateResult_GetTrustAnchor(validResult, &trustAnchor,
1060 plContext),
1061 PKIX_VALIDATERESULTGETTRUSTANCHORFAILED);
1063 PKIX_CHECK(
1064 PKIX_TrustAnchor_GetTrustedCert(trustAnchor, &trustedCert,
1065 plContext),
1066 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
1068 #ifdef DEBUG_volkov
1069 if (pvalidChain == NULL) {
1070 cert_PrintCert(trustedCert, plContext);
1072 #endif
1074 PKIX_CHECK(
1075 PKIX_PL_Cert_GetCERTCertificate(trustedCert, &trustedRoot,
1076 plContext),
1077 PKIX_CERTGETCERTCERTIFICATEFAILED);
1080 PORT_Assert(!PKIX_ERROR_RECEIVED);
1082 if (trustedRoot) {
1083 *ptrustedRoot = trustedRoot;
1085 if (validChain) {
1086 *pvalidChain = validChain;
1089 cleanup:
1090 if (PKIX_ERROR_RECEIVED) {
1091 if (trustedRoot) {
1092 CERT_DestroyCertificate(trustedRoot);
1094 if (validChain) {
1095 CERT_DestroyCertList(validChain);
1098 PKIX_DECREF(trustAnchor);
1099 PKIX_DECREF(trustedCert);
1100 PKIX_DECREF(pkixCertChain);
1101 PKIX_DECREF(validResult);
1102 PKIX_DECREF(error);
1103 PKIX_DECREF(verifyNode);
1104 PKIX_DECREF(buildResult);
1106 PKIX_RETURN(CERTVFYPKIX);
1110 * FUNCTION: cert_VerifyCertChainPkix
1111 * DESCRIPTION:
1113 * The main wrapper function that is called from CERT_VerifyCert and
1114 * CERT_VerifyCACertForUsage functions to validate cert with libpkix.
1116 * PARAMETERS:
1117 * "cert"
1118 * Leaf certificate of a chain we want to build.
1119 * "checkSig"
1120 * Certificate signatures will not be verified if this
1121 * flag is set to PR_FALSE.
1122 * "requiredUsage"
1123 * Required usage for certificate and chain.
1124 * "time"
1125 * Validity time.
1126 * "wincx"
1127 * Nss database password token.
1128 * "log"
1129 * Address of already allocated CERTVerifyLog structure. Not
1130 * used if NULL;
1131 * "pSigerror"
1132 * Address of PRBool. If not NULL, returns true is cert chain
1133 * was invalidated because of bad certificate signature.
1134 * "pRevoked"
1135 * Address of PRBool. If not NULL, returns true is cert chain
1136 * was invalidated because a revoked certificate was found in
1137 * the chain.
1138 * THREAD SAFETY:
1139 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1140 * RETURNS:
1141 * SECFailure is chain building process has failed. SECSuccess otherwise.
1143 SECStatus
1144 cert_VerifyCertChainPkix(
1145 CERTCertificate *cert,
1146 PRBool checkSig,
1147 SECCertUsage requiredUsage,
1148 PRTime time,
1149 void *wincx,
1150 CERTVerifyLog *log,
1151 PRBool *pSigerror,
1152 PRBool *pRevoked)
1154 PKIX_ProcessingParams *procParams = NULL;
1155 PKIX_BuildResult *result = NULL;
1156 PKIX_VerifyNode *verifyNode = NULL;
1157 PKIX_Error *error = NULL;
1159 SECStatus rv = SECFailure;
1160 void *plContext = NULL;
1161 #ifdef DEBUG_volkov
1162 CERTCertificate *trustedRoot = NULL;
1163 CERTCertList *validChain = NULL;
1164 #endif /* DEBUG */
1166 #ifdef PKIX_OBJECT_LEAK_TEST
1167 int leakedObjNum = 0;
1168 int memLeakLoopCount = 0;
1169 int objCountTable[PKIX_NUMTYPES];
1170 int fnInvLocalCount = 0;
1172 testStartFnStackPosition = 2;
1173 fnStackNameArr[0] = "cert_VerifyCertChainPkix";
1174 fnStackInvCountArr[0] = 0;
1175 PKIX_Boolean abortOnLeak =
1176 (PR_GetEnv("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ?
1177 PKIX_FALSE : PKIX_TRUE;
1178 runningLeakTest = PKIX_TRUE;
1180 /* Prevent multi-threaded run of object leak test */
1181 fnInvLocalCount = PR_AtomicIncrement(&parallelFnInvocationCount);
1182 PORT_Assert(fnInvLocalCount == 1);
1184 do {
1185 rv = SECFailure;
1186 plContext = NULL;
1187 procParams = NULL;
1188 result = NULL;
1189 verifyNode = NULL;
1190 error = NULL;
1191 #ifdef DEBUG_volkov
1192 trustedRoot = NULL;
1193 validChain = NULL;
1194 #endif /* DEBUG */
1195 errorGenerated = PKIX_FALSE;
1196 stackPosition = 0;
1198 if (leakedObjNum) {
1199 pkix_pl_lifecycle_ObjectTableUpdate(objCountTable);
1202 PR_LOG(pkixLog, 1, ("Memory leak test: Loop %d\n", memLeakLoopCount++));
1203 #endif /* PKIX_OBJECT_LEAK_TEST */
1205 error =
1206 cert_CreatePkixProcessingParams(cert, checkSig, time, wincx,
1207 PR_FALSE/*use arena*/,
1208 #ifdef DEBUG_volkov
1209 /* If in DEBUG_volkov, then enable OCSP
1210 * check for all certs in the chain
1211 * using libpkix ocsp code.
1212 * (except for certUsageStatusResponder). */
1213 requiredUsage != certUsageStatusResponder,
1214 #endif
1215 &procParams, &plContext);
1216 if (error) {
1217 goto cleanup;
1220 error =
1221 cert_ProcessingParamsSetKuAndEku(procParams, cert, PR_TRUE,
1222 requiredUsage, 0, plContext);
1223 if (error) {
1224 goto cleanup;
1227 error =
1228 cert_BuildAndValidateChain(procParams, &result, &verifyNode, plContext);
1229 if (error) {
1230 goto cleanup;
1233 if (pRevoked) {
1234 /* Currently always PR_FALSE. Will be fixed as a part of 394077 */
1235 *pRevoked = PR_FALSE;
1237 if (pSigerror) {
1238 /* Currently always PR_FALSE. Will be fixed as a part of 394077 */
1239 *pSigerror = PR_FALSE;
1241 rv = SECSuccess;
1243 cleanup:
1244 error = cert_GetBuildResults(result, verifyNode, error, log,
1245 #ifdef DEBUG_volkov
1246 &trustedRoot, &validChain,
1247 #else
1248 NULL, NULL,
1249 #endif /* DEBUG */
1250 plContext);
1251 if (error) {
1252 #ifdef DEBUG_volkov
1253 char *temp = pkix_Error2ASCII(error, plContext);
1254 fprintf(stderr, "GET BUILD RES ERRORS:\n%s\n", temp);
1255 PKIX_PL_Free(temp, NULL);
1256 #endif /* DEBUG */
1257 PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1259 #ifdef DEBUG_volkov
1260 if (trustedRoot) {
1261 CERT_DestroyCertificate(trustedRoot);
1263 if (validChain) {
1264 CERT_DestroyCertList(validChain);
1266 #endif /* DEBUG */
1267 if (procParams) {
1268 PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext);
1270 if (plContext) {
1271 PKIX_PL_NssContext_Destroy(plContext);
1274 #ifdef PKIX_OBJECT_LEAK_TEST
1275 leakedObjNum =
1276 pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
1278 if (pkixLog && leakedObjNum) {
1279 PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. "
1280 "Stack %s\n", errorFnStackString));
1282 PR_Free(errorFnStackString);
1283 errorFnStackString = NULL;
1284 if (abortOnLeak) {
1285 PORT_Assert(leakedObjNum == 0);
1288 } while (errorGenerated);
1290 runningLeakTest = PKIX_FALSE;
1291 PR_AtomicDecrement(&parallelFnInvocationCount);
1292 #endif /* PKIX_OBJECT_LEAK_TEST */
1294 return rv;
1297 PKIX_CertSelector *
1298 cert_GetTargetCertConstraints(CERTCertificate *target, void *plContext)
1300 PKIX_ComCertSelParams *certSelParams = NULL;
1301 PKIX_CertSelector *certSelector = NULL;
1302 PKIX_CertSelector *r= NULL;
1303 PKIX_PL_Cert *eeCert = NULL;
1304 PKIX_Error *error = NULL;
1306 error = PKIX_PL_Cert_CreateFromCERTCertificate(target, &eeCert, plContext);
1307 if (error != NULL) goto cleanup;
1309 error = PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext);
1310 if (error != NULL) goto cleanup;
1312 error = PKIX_ComCertSelParams_Create(&certSelParams, plContext);
1313 if (error != NULL) goto cleanup;
1315 error = PKIX_ComCertSelParams_SetCertificate(
1316 certSelParams, eeCert, plContext);
1317 if (error != NULL) goto cleanup;
1319 error = PKIX_CertSelector_SetCommonCertSelectorParams
1320 (certSelector, certSelParams, plContext);
1321 if (error != NULL) goto cleanup;
1323 error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certSelector, plContext);
1324 if (error == NULL) r = certSelector;
1326 cleanup:
1327 if (certSelParams != NULL)
1328 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelParams, plContext);
1330 if (eeCert != NULL)
1331 PKIX_PL_Object_DecRef((PKIX_PL_Object *)eeCert, plContext);
1333 if (certSelector != NULL)
1334 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext);
1336 if (error != NULL) {
1337 SECErrorCodes nssErr;
1339 cert_PkixErrorToNssCode(error, &nssErr, plContext);
1340 PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1341 PORT_SetError(nssErr);
1344 return r;
1347 static PKIX_List *
1348 cert_GetCertStores(void *plContext)
1350 PKIX_CertStore *certStore = NULL;
1351 PKIX_List *certStores = NULL;
1352 PKIX_List *r = NULL;
1353 PKIX_Error *error = NULL;
1355 error = PKIX_PL_Pk11CertStore_Create(&certStore, plContext);
1356 if (error != NULL) goto cleanup;
1358 error = PKIX_List_Create(&certStores, plContext);
1359 if (error != NULL) goto cleanup;
1361 error = PKIX_List_AppendItem( certStores,
1362 (PKIX_PL_Object *)certStore, plContext);
1363 if (error != NULL) goto cleanup;
1365 error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certStores, plContext);
1366 if (error == NULL) r = certStores;
1368 cleanup:
1369 if (certStores != NULL)
1370 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext);
1372 if (certStore != NULL)
1373 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStore, plContext);
1375 if (error != NULL) {
1376 SECErrorCodes nssErr;
1378 cert_PkixErrorToNssCode(error, &nssErr, plContext);
1379 PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1380 PORT_SetError(nssErr);
1383 return r;
1386 /* XXX
1387 * There is no NSS SECItem -> PKIX OID
1388 * conversion function. For now, I go via the ascii
1389 * representation
1390 * this should be in PKIX_PL_*
1393 PKIX_PL_OID *
1394 CERT_PKIXOIDFromNSSOid(SECOidTag tag, void*plContext)
1396 char *oidstring = NULL;
1397 char *oidstring_adj = NULL;
1398 PKIX_PL_OID *policyOID = NULL;
1399 SECOidData *data;
1401 data = SECOID_FindOIDByTag(tag);
1402 if (data != NULL) {
1403 oidstring = CERT_GetOidString(&data->oid);
1404 if (oidstring == NULL) {
1405 goto cleanup;
1407 oidstring_adj = oidstring;
1408 if (PORT_Strncmp("OID.",oidstring_adj,4) == 0) {
1409 oidstring_adj += 4;
1412 PKIX_PL_OID_Create(oidstring_adj, &policyOID, plContext);
1414 cleanup:
1415 if (oidstring != NULL) PR_smprintf_free(oidstring);
1417 return policyOID;
1420 struct fake_PKIX_PL_CertStruct {
1421 CERTCertificate *nssCert;
1424 /* This needs to be part of the PKIX_PL_* */
1425 /* This definitely needs to go away, and be replaced with
1426 a real accessor function in PKIX */
1427 CERTCertificate *
1428 cert_NSSCertFromPKIXCert(const PKIX_PL_Cert *pkix_cert, void *plContext)
1430 struct fake_PKIX_PL_CertStruct *fcert = NULL;
1432 fcert = (struct fake_PKIX_PL_CertStruct*)pkix_cert;
1434 return CERT_DupCertificate(fcert->nssCert);
1437 PKIX_List *cert_PKIXMakeOIDList(const SECOidTag *oids, int oidCount, void *plContext)
1439 PKIX_List *r = NULL;
1440 PKIX_List *policyList = NULL;
1441 PKIX_PL_OID *policyOID = NULL;
1442 PKIX_Error *error = NULL;
1443 int i;
1445 error = PKIX_List_Create(&policyList, plContext);
1446 if (error != NULL) {
1447 goto cleanup;
1450 for (i=0; i<oidCount; i++) {
1451 policyOID = CERT_PKIXOIDFromNSSOid(oids[i],plContext);
1452 if (policyOID == NULL) {
1453 goto cleanup;
1455 error = PKIX_List_AppendItem(policyList,
1456 (PKIX_PL_Object *)policyOID, plContext);
1457 if (error != NULL) {
1458 PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
1459 goto cleanup;
1463 error = PKIX_List_SetImmutable(policyList, plContext);
1464 if (error != NULL) goto cleanup;
1466 error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)policyList, plContext);
1467 if (error == NULL) r = policyList;
1469 cleanup:
1470 if (policyOID != NULL) {
1471 PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
1473 if (policyList != NULL) {
1474 PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyList, plContext);
1476 if (error != NULL) {
1477 PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1480 return r;
1483 CERTValOutParam *
1484 cert_pkix_FindOutputParam(CERTValOutParam *params, const CERTValParamOutType t)
1486 CERTValOutParam *i;
1487 if (params == NULL) {
1488 return NULL;
1490 for (i = params; i->type != cert_po_end; i++) {
1491 if (i->type == t) {
1492 return i;
1495 return NULL;
1498 SECStatus
1499 cert_pkixSetParam(PKIX_ProcessingParams *procParams,
1500 const CERTValInParam *param, void *plContext)
1502 PKIX_Error * error = NULL;
1503 SECStatus r=SECSuccess;
1504 PKIX_PL_Date *date = NULL;
1505 PKIX_List *policyOIDList = NULL;
1506 PKIX_RevocationChecker *ocspChecker = NULL;
1507 PKIX_List *certListPkix = NULL;
1508 const CERTRevocationFlags *flags;
1509 SECErrorCodes errCode = SEC_ERROR_INVALID_ARGS;
1510 const CERTCertList *certList = NULL;
1511 CERTCertListNode *node;
1512 PKIX_PL_Cert *certPkix = NULL;
1513 PKIX_TrustAnchor *trustAnchor = NULL;
1515 /* XXX we need a way to map generic PKIX error to generic NSS errors */
1517 switch (param->type) {
1519 case cert_pi_policyOID:
1521 /* needed? */
1522 error = PKIX_ProcessingParams_SetExplicitPolicyRequired(
1523 procParams, PKIX_TRUE, plContext);
1525 if (error != NULL) {
1526 break;
1529 policyOIDList = cert_PKIXMakeOIDList(param->value.array.oids,
1530 param->value.arraySize,plContext);
1531 if (policyOIDList == NULL) {
1532 r = SECFailure;
1533 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1534 break;
1537 error = PKIX_ProcessingParams_SetInitialPolicies(
1538 procParams,policyOIDList,plContext);
1539 break;
1541 case cert_pi_date:
1542 if (param->value.scalar.time == 0) {
1543 error = PKIX_PL_Date_Create_UTCTime(NULL, &date, plContext);
1544 if (error != NULL) {
1545 errCode = SEC_ERROR_INVALID_TIME;
1546 break;
1548 } else {
1549 error = pkix_pl_Date_CreateFromPRTime(param->value.scalar.time,
1550 &date, plContext);
1551 if (error != NULL) {
1552 errCode = SEC_ERROR_INVALID_TIME;
1553 break;
1557 error = PKIX_ProcessingParams_SetDate(procParams, date, plContext);
1558 if (error != NULL) {
1559 errCode = SEC_ERROR_INVALID_TIME;
1561 break;
1563 case cert_pi_revocationFlags:
1565 PRBool ocspTurnedOnForLeaf = PR_FALSE;
1566 PRBool ocspTurnedOnForChain = PR_FALSE;
1567 PRBool crlTurnedOnForLeaf = PR_FALSE;
1568 PRBool crlTurnedOnForChain = PR_FALSE;
1569 PRBool crlHardFailure = PR_FALSE;
1571 flags = param->value.pointer.revocation;
1572 if (!flags) {
1573 PORT_SetError(errCode);
1574 r = SECFailure;
1575 break;
1578 if (
1579 /* caller did define OCSP leaf behavior */
1580 (flags->leafTests.number_of_defined_methods >
1581 cert_revocation_method_ocsp)
1583 /* caller allows OCSP testing for the leaf */
1584 (flags->leafTests.cert_rev_flags_per_method
1585 [cert_revocation_method_ocsp]
1586 & CERT_REV_M_TEST_USING_THIS_METHOD)) {
1587 ocspTurnedOnForLeaf = PR_TRUE;
1590 if (
1591 /* caller did define OCSP chain behavior */
1592 (flags->chainTests.number_of_defined_methods >
1593 cert_revocation_method_ocsp)
1595 /* caller allows OCSP testing for the chain */
1596 (flags->chainTests.cert_rev_flags_per_method
1597 [cert_revocation_method_ocsp]
1598 & CERT_REV_M_TEST_USING_THIS_METHOD)) {
1599 ocspTurnedOnForChain = PR_TRUE;
1602 if (
1603 /* caller did define CRL leaf behavior */
1604 (flags->leafTests.number_of_defined_methods >
1605 cert_revocation_method_crl)
1607 /* caller allows CRL testing for the chain */
1608 (flags->leafTests.cert_rev_flags_per_method
1609 [cert_revocation_method_crl]
1610 & CERT_REV_M_TEST_USING_THIS_METHOD)) {
1611 crlTurnedOnForLeaf = PR_TRUE;
1614 if (
1615 /* caller did define CRL chain behavior */
1616 (flags->chainTests.number_of_defined_methods >
1617 cert_revocation_method_crl)
1619 /* caller allows CRL testing for the chain */
1620 (flags->chainTests.cert_rev_flags_per_method
1621 [cert_revocation_method_crl]
1622 & CERT_REV_M_TEST_USING_THIS_METHOD)) {
1623 crlTurnedOnForChain = PR_TRUE;
1626 if (
1627 /* caller did define CRL chain behavior */
1628 (flags->chainTests.number_of_defined_methods >
1629 cert_revocation_method_crl)
1631 /* caller requests hard failure on missing (fresh) CRL */
1632 (flags->chainTests.cert_rev_flags_per_method
1633 [cert_revocation_method_crl]
1634 & CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO)) {
1635 /* FIXME: should also consider flag
1636 * CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE
1638 crlHardFailure = PR_TRUE;
1641 if (!ocspTurnedOnForChain) {
1642 /* OCSP off either because:
1643 * 1) we didn't turn ocsp on, or
1644 * 2) we are only checking ocsp on the leaf cert only.
1645 * The caller needs to handle the leaf case once we add leaf
1646 * checking there */
1648 /* currently OCSP is the only external revocation checker */
1649 error = PKIX_ProcessingParams_SetRevocationCheckers(procParams,
1650 NULL, plContext);
1651 } else {
1652 /* FIXME: What should be done if !ocspTurnedOnForLeaf ? */
1654 /* OCSP is on for the whole chain */
1655 if (date == NULL) {
1656 error = PKIX_ProcessingParams_GetDate
1657 (procParams, &date, plContext );
1658 if (error != NULL) {
1659 errCode = SEC_ERROR_INVALID_TIME;
1660 break;
1663 error = PKIX_OcspChecker_Initialize(date, NULL, NULL,
1664 &ocspChecker, plContext);
1665 if (error != NULL) {
1666 break;
1669 error = PKIX_ProcessingParams_AddRevocationChecker(procParams,
1670 ocspChecker, plContext);
1671 PKIX_PL_Object_DecRef((PKIX_PL_Object *)ocspChecker, plContext);
1672 ocspChecker=NULL;
1674 /* FIXME: add support for other revocation flags when underlying
1675 * pkix supports it */
1677 if (error != NULL) {
1678 break;
1680 if (!crlTurnedOnForChain) {
1681 /* CRL checking is off either because:
1682 * 1) we didn't turn crl checking on, or
1683 * 2) we are only checking crls on the leaf cert only.
1684 * The caller needs to handle the leaf case once we add leaf
1685 * checking there */
1687 /* this function only affects the built-in CRL checker */
1688 error = PKIX_ProcessingParams_SetRevocationEnabled(procParams,
1689 PKIX_FALSE, plContext);
1690 if (error != NULL) {
1691 break;
1693 /* make sure NIST Revocation Policy is off as well */
1694 error = PKIX_ProcessingParams_SetNISTRevocationPolicyEnabled
1695 (procParams, PKIX_FALSE, plContext);
1696 } else {
1697 /* FIXME: What should be done if !crlTurnedOnForLeaf ? */
1699 /* CRL checking is on for the whole chain */
1700 error = PKIX_ProcessingParams_SetRevocationEnabled(procParams,
1701 PKIX_TRUE, plContext);
1702 if (error != NULL) {
1703 break;
1705 error = PKIX_ProcessingParams_SetNISTRevocationPolicyEnabled
1706 (procParams,
1707 crlHardFailure ? PKIX_TRUE : PKIX_FALSE,
1708 plContext);
1711 break;
1713 case cert_pi_trustAnchors:
1714 certList = param->value.pointer.chain;
1716 error = PKIX_List_Create(&certListPkix, plContext);
1717 if (error != NULL) {
1718 break;
1720 for(node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
1721 node = CERT_LIST_NEXT(node) ) {
1722 error = PKIX_PL_Cert_CreateFromCERTCertificate(node->cert,
1723 &certPkix, plContext);
1724 if (error) {
1725 break;
1727 error = PKIX_TrustAnchor_CreateWithCert(certPkix, &trustAnchor,
1728 plContext);
1729 if (error) {
1730 break;
1732 error = PKIX_List_AppendItem(certListPkix,
1733 (PKIX_PL_Object*)trustAnchor, plContext);
1734 if (error) {
1735 break;
1737 PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
1738 trustAnchor = NULL;
1739 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext);
1740 certPkix = NULL;
1742 error =
1743 PKIX_ProcessingParams_SetTrustAnchors(procParams, certListPkix,
1744 plContext);
1745 break;
1747 case cert_pi_useAIACertFetch:
1748 error =
1749 PKIX_ProcessingParams_SetUseAIAForCertFetching(procParams,
1750 (PRBool)(param->value.scalar.b != 0),
1751 plContext);
1752 break;
1754 default:
1755 PORT_SetError(errCode);
1756 r = SECFailure;
1759 if (policyOIDList != NULL)
1760 PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOIDList, plContext);
1762 if (date != NULL)
1763 PKIX_PL_Object_DecRef((PKIX_PL_Object *)date, plContext);
1765 if (ocspChecker != NULL)
1766 PKIX_PL_Object_DecRef((PKIX_PL_Object *)ocspChecker, plContext);
1768 if (certListPkix)
1769 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certListPkix, plContext);
1771 if (trustAnchor)
1772 PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
1774 if (certPkix)
1775 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext);
1777 if (error != NULL) {
1778 PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
1779 PORT_SetError(errCode);
1780 r = SECFailure;
1783 return r;
1787 void
1788 cert_pkixDestroyValOutParam(CERTValOutParam *params)
1790 CERTValOutParam *i;
1792 if (params == NULL) {
1793 return;
1795 for (i = params; i->type != cert_po_end; i++) {
1796 switch (i->type) {
1797 case cert_po_trustAnchor:
1798 if (i->value.pointer.cert) {
1799 CERT_DestroyCertificate(i->value.pointer.cert);
1800 i->value.pointer.cert = NULL;
1802 break;
1804 case cert_po_certList:
1805 if (i->value.pointer.chain) {
1806 CERT_DestroyCertList(i->value.pointer.chain);
1807 i->value.pointer.chain = NULL;
1809 break;
1811 default:
1812 break;
1817 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags[2] = {
1818 /* crl */
1819 CERT_REV_M_TEST_USING_THIS_METHOD
1820 | CERT_REV_M_FORBID_NETWORK_FETCHING
1821 | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1822 /* ocsp */
1823 CERT_REV_M_TEST_USING_THIS_METHOD
1826 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags[2] = {
1827 /* crl */
1828 CERT_REV_M_TEST_USING_THIS_METHOD
1829 | CERT_REV_M_FORBID_NETWORK_FETCHING
1830 | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1831 /* ocsp */
1835 static CERTRevocationMethodIndex
1836 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference = {
1837 cert_revocation_method_crl
1840 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy = {
1842 /* leafTests */
1844 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags,
1846 &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference,
1850 /* chainTests */
1852 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags,
1859 extern const CERTRevocationFlags*
1860 CERT_GetClassicOCSPEnabledSoftFailurePolicy()
1862 return &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy;
1866 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags[2] = {
1867 /* crl */
1868 CERT_REV_M_TEST_USING_THIS_METHOD
1869 | CERT_REV_M_FORBID_NETWORK_FETCHING
1870 | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1871 /* ocsp */
1872 CERT_REV_M_TEST_USING_THIS_METHOD
1873 | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
1876 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags[2] = {
1877 /* crl */
1878 CERT_REV_M_TEST_USING_THIS_METHOD
1879 | CERT_REV_M_FORBID_NETWORK_FETCHING
1880 | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1881 /* ocsp */
1885 static CERTRevocationMethodIndex
1886 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference = {
1887 cert_revocation_method_crl
1890 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy = {
1892 /* leafTests */
1894 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags,
1896 &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference,
1900 /* chainTests */
1902 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags,
1909 extern const CERTRevocationFlags*
1910 CERT_GetClassicOCSPEnabledHardFailurePolicy()
1912 return &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy;
1916 static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags[2] = {
1917 /* crl */
1918 CERT_REV_M_TEST_USING_THIS_METHOD
1919 | CERT_REV_M_FORBID_NETWORK_FETCHING
1920 | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1921 /* ocsp */
1925 static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags[2] = {
1926 /* crl */
1927 CERT_REV_M_TEST_USING_THIS_METHOD
1928 | CERT_REV_M_FORBID_NETWORK_FETCHING
1929 | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
1930 /* ocsp */
1934 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Disabled_Policy = {
1936 /* leafTests */
1938 certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags,
1944 /* chainTests */
1946 certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags,
1953 extern const CERTRevocationFlags*
1954 CERT_GetClassicOCSPDisabledPolicy()
1956 return &certRev_NSS_3_11_Ocsp_Disabled_Policy;
1960 static PRUint64 certRev_PKIX_Verify_Nist_Policy_LeafFlags[2] = {
1961 /* crl */
1962 CERT_REV_M_TEST_USING_THIS_METHOD
1963 | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
1964 | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE,
1965 /* ocsp */
1969 static PRUint64 certRev_PKIX_Verify_Nist_Policy_ChainFlags[2] = {
1970 /* crl */
1971 CERT_REV_M_TEST_USING_THIS_METHOD
1972 | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
1973 | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE,
1974 /* ocsp */
1978 static const CERTRevocationFlags certRev_PKIX_Verify_Nist_Policy = {
1980 /* leafTests */
1982 certRev_PKIX_Verify_Nist_Policy_LeafFlags,
1988 /* chainTests */
1990 certRev_PKIX_Verify_Nist_Policy_ChainFlags,
1997 extern const CERTRevocationFlags*
1998 CERT_GetPKIXVerifyNistRevocationPolicy()
2000 return &certRev_PKIX_Verify_Nist_Policy;
2005 * CERT_PKIXVerifyCert
2007 * Verify a Certificate using the PKIX library.
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.
2015 * outputTrustAnchor - the trust anchor which the certificate
2016 * chains to. The caller is responsible
2017 * for freeing this.
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;
2027 * CERT_PKIXVerifyCert(cert, &output, args
2029 SECStatus CERT_PKIXVerifyCert(
2030 CERTCertificate *cert,
2031 SECCertificateUsage usages,
2032 CERTValInParam *paramsIn,
2033 CERTValOutParam *paramsOut,
2034 void *wincx)
2036 SECStatus r = SECFailure;
2037 PKIX_Error * error = NULL;
2038 PKIX_ProcessingParams *procParams = NULL;
2039 PKIX_BuildResult * buildResult = NULL;
2040 void * nbioContext = NULL; /* for non-blocking IO */
2041 void * buildState = NULL; /* for non-blocking IO */
2042 PKIX_CertSelector * certSelector = NULL;
2043 PKIX_List * certStores = NULL;
2044 PKIX_ValidateResult * valResult = NULL;
2045 PKIX_VerifyNode * verifyNode = NULL;
2046 PKIX_TrustAnchor * trustAnchor = NULL;
2047 PKIX_PL_Cert * trustAnchorCert = NULL;
2048 PKIX_List * builtCertList = NULL;
2049 CERTValOutParam * oparam = NULL;
2050 int i=0;
2052 void *plContext = NULL;
2054 #ifdef PKIX_OBJECT_LEAK_TEST
2055 int leakedObjNum = 0;
2056 int memLeakLoopCount = 0;
2057 int objCountTable[PKIX_NUMTYPES];
2058 int fnInvLocalCount = 0;
2059 testStartFnStackPosition = 1;
2060 fnStackNameArr[0] = "CERT_PKIXVerifyCert";
2061 fnStackInvCountArr[0] = 0;
2062 PKIX_Boolean abortOnLeak =
2063 (PR_GetEnv("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ?
2064 PKIX_FALSE : PKIX_TRUE;
2065 runningLeakTest = PKIX_TRUE;
2067 /* Prevent multi-threaded run of object leak test */
2068 fnInvLocalCount = PR_AtomicIncrement(&parallelFnInvocationCount);
2069 PORT_Assert(fnInvLocalCount == 1);
2071 do {
2072 r = SECFailure;
2073 error = NULL;
2074 procParams = NULL;
2075 buildResult = NULL;
2076 nbioContext = NULL; /* for non-blocking IO */
2077 buildState = NULL; /* for non-blocking IO */
2078 certSelector = NULL;
2079 certStores = NULL;
2080 valResult = NULL;
2081 verifyNode = NULL;
2082 trustAnchor = NULL;
2083 trustAnchorCert = NULL;
2084 builtCertList = NULL;
2085 oparam = NULL;
2086 i=0;
2087 errorGenerated = PKIX_FALSE;
2088 stackPosition = 0;
2090 if (leakedObjNum) {
2091 pkix_pl_lifecycle_ObjectTableUpdate(objCountTable);
2094 PR_LOG(pkixLog, 1, ("Memory leak test: Loop %d\n", memLeakLoopCount++));
2095 #endif /* PKIX_OBJECT_LEAK_TEST */
2097 error = PKIX_PL_NssContext_Create(
2098 0, PR_FALSE /*use arena*/, wincx, &plContext);
2099 if (error != NULL) { /* need pkix->nss error map */
2100 PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
2101 goto cleanup;
2104 error = pkix_pl_NssContext_SetCertUsage(usages, plContext);
2105 if (error != NULL) {
2106 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2107 goto cleanup;
2110 error = PKIX_ProcessingParams_Create(&procParams, plContext);
2111 if (error != NULL) { /* need pkix->nss error map */
2112 PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
2113 goto cleanup;
2117 /* now process the extensible input parameters structure */
2118 if (paramsIn != NULL) {
2119 i=0;
2120 while (paramsIn[i].type != cert_pi_end) {
2121 if (paramsIn[i].type >= cert_pi_max) {
2122 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2123 goto cleanup;
2125 if (cert_pkixSetParam(procParams,
2126 &paramsIn[i],plContext) != SECSuccess) {
2127 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2128 goto cleanup;
2130 i++;
2135 certSelector = cert_GetTargetCertConstraints(cert, plContext);
2136 if (certSelector == NULL) {
2137 goto cleanup;
2139 error = PKIX_ProcessingParams_SetTargetCertConstraints
2140 (procParams, certSelector, plContext);
2141 if (error != NULL) {
2142 goto cleanup;
2145 certStores = cert_GetCertStores(plContext);
2146 if (certStores == NULL) {
2147 goto cleanup;
2149 error = PKIX_ProcessingParams_SetCertStores
2150 (procParams, certStores, plContext);
2151 if (error != NULL) {
2152 goto cleanup;
2155 error = PKIX_BuildChain( procParams, &nbioContext,
2156 &buildState, &buildResult, &verifyNode,
2157 plContext);
2158 if (error != NULL) {
2159 goto cleanup;
2162 error = PKIX_BuildResult_GetValidateResult( buildResult, &valResult,
2163 plContext);
2164 if (error != NULL) {
2165 goto cleanup;
2168 error = PKIX_ValidateResult_GetTrustAnchor( valResult, &trustAnchor,
2169 plContext);
2170 if (error != NULL) {
2171 goto cleanup;
2174 error = PKIX_TrustAnchor_GetTrustedCert( trustAnchor, &trustAnchorCert,
2175 plContext);
2176 if (error != NULL) {
2177 goto cleanup;
2180 #ifdef PKIX_OBJECT_LEAK_TEST
2181 PORT_Assert(!errorGenerated);
2182 #endif /* PKIX_OBJECT_LEAK_TEST */
2184 oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_trustAnchor);
2185 if (oparam != NULL) {
2186 oparam->value.pointer.cert =
2187 cert_NSSCertFromPKIXCert(trustAnchorCert,plContext);
2190 error = PKIX_BuildResult_GetCertChain( buildResult, &builtCertList,
2191 plContext);
2192 if (error != NULL) {
2193 goto cleanup;
2196 oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_certList);
2197 if (oparam != NULL) {
2198 error = cert_PkixToNssCertsChain(builtCertList,
2199 &oparam->value.pointer.chain,
2200 plContext);
2201 if (error) goto cleanup;
2204 r = SECSuccess;
2206 cleanup:
2207 if (verifyNode) {
2208 /* Return validation log only upon error. */
2209 oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_errorLog);
2210 #ifdef PKIX_OBJECT_LEAK_TEST
2211 if (!errorGenerated)
2212 #endif /* PKIX_OBJECT_LEAK_TEST */
2213 if (r && oparam != NULL) {
2214 PKIX_Error *tmpError =
2215 cert_GetLogFromVerifyNode(oparam->value.pointer.log,
2216 verifyNode, plContext);
2217 if (tmpError) {
2218 PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext);
2221 PKIX_PL_Object_DecRef((PKIX_PL_Object *)verifyNode, plContext);
2224 if (procParams != NULL)
2225 PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext);
2227 if (trustAnchorCert != NULL)
2228 PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchorCert, plContext);
2230 if (trustAnchor != NULL)
2231 PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
2233 if (valResult != NULL)
2234 PKIX_PL_Object_DecRef((PKIX_PL_Object *)valResult, plContext);
2236 if (buildResult != NULL)
2237 PKIX_PL_Object_DecRef((PKIX_PL_Object *)buildResult, plContext);
2239 if (certStores != NULL)
2240 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext);
2242 if (certSelector != NULL)
2243 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext);
2245 if (builtCertList != NULL)
2246 PKIX_PL_Object_DecRef((PKIX_PL_Object *)builtCertList, plContext);
2248 if (error != NULL) {
2249 SECErrorCodes nssErrorCode = 0;
2251 cert_PkixErrorToNssCode(error, &nssErrorCode, plContext);
2252 cert_pkixDestroyValOutParam(paramsOut);
2253 PORT_SetError(nssErrorCode);
2254 PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
2257 PKIX_PL_NssContext_Destroy(plContext);
2259 #ifdef PKIX_OBJECT_LEAK_TEST
2260 leakedObjNum =
2261 pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
2263 if (pkixLog && leakedObjNum) {
2264 PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. "
2265 "Stack %s\n", errorFnStackString));
2267 PR_Free(errorFnStackString);
2268 errorFnStackString = NULL;
2269 if (abortOnLeak) {
2270 PORT_Assert(leakedObjNum == 0);
2273 } while (errorGenerated);
2275 runningLeakTest = PKIX_FALSE;
2276 PR_AtomicDecrement(&parallelFnInvocationCount);
2277 #endif /* PKIX_OBJECT_LEAK_TEST */
2279 return r;