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
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.
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 ***** */
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.
59 #include "pkix_pl_common.h"
60 #include "pkix_pl_ekuchecker.h"
62 extern PRLogModuleInfo
*pkixLog
;
65 /* Temporary declarations of functioins. Will be removed with fix for
68 pkix_Error2ASCII(PKIX_Error
*error
, void *plContext
);
71 cert_PrintCert(PKIX_PL_Cert
*pkixCert
, void *plContext
);
74 cert_PrintCertChain(PKIX_List
*pkixCertChain
, void *plContext
);
78 #ifdef PKIX_OBJECT_LEAK_TEST
81 pkix_pl_lifecycle_ObjectLeakCheck(int *);
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
96 * Enables or disables use of libpkix for certificate validation
100 * PR_TRUE: enables use of libpkix for cert validation.
101 * PR_FALSE: disables.
105 * Returns SECSuccess if successfully enabled
108 CERT_SetUsePKIXForValidation(PRBool enable
)
110 usePKIXValidationEngine
= (enable
> 0) ? PR_TRUE
: PR_FALSE
;
115 * FUNCTION: CERT_GetUsePKIXForValidation
118 * Checks if libpkix building function should be use for certificate
126 * Returns PR_TRUE if libpkix should be used. PR_FALSE otherwise.
129 CERT_GetUsePKIXForValidation()
131 return usePKIXValidationEngine
;
135 * FUNCTION: cert_NssKeyUsagesToPkix
138 * Converts nss key usage bit field(PRUint32) to pkix key usage
143 * Nss key usage bit field.
145 * Pkix key usage big field.
147 * Platform-specific context pointer.
149 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
151 * Returns NULL if the function succeeds.
152 * Returns a Fatal Error if the function fails in an unrecoverable way.
155 cert_NssKeyUsagesToPkix(
156 PRUint32 nssKeyUsage
,
157 PKIX_UInt32
*pPkixKeyUsage
,
160 PKIX_UInt32 pkixKeyUsage
= 0;
162 PKIX_ENTER(CERTVFYPKIX
, "cert_NssKeyUsagesToPkix");
163 PKIX_NULLCHECK_ONE(pPkixKeyUsage
);
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
201 /* pkixKeyUsage |= PKIX_DECIPHER_ONLY; */
203 *pPkixKeyUsage
= pkixKeyUsage
;
205 PKIX_RETURN(CERTVFYPKIX
);
208 extern char* ekuOidStrings
[];
211 ekuIndexSSLServer
= 0,
216 ekuIndexStatusResponder
,
221 SECCertUsage certUsage
;
222 PRUint32 ekuStringIndex
;
225 const SECCertUsageToEku certUsageEkuStringMap
[] = {
226 {certUsageSSLClient
, ekuIndexSSLClient
},
227 {certUsageSSLServer
, ekuIndexSSLServer
},
228 {certUsageSSLServerWithStepUp
, ekuIndexSSLServer
}, /* need to add oids to
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
248 * Converts nss CERTCertificateUsage bit field to pkix key and
249 * extended key usages.
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.
259 * it true, convert usages for cert that is a CA cert.
261 * Returned address of a list of pkix extended key usages.
263 * Returned address of pkix required key usages bit field.
265 * Platform-specific context pointer.
267 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
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.
274 cert_NssCertificateUsageToPkixKUAndEKU(
275 CERTCertificate
*cert
,
276 SECCertUsage requiredCertUsage
,
277 PRUint32 requiredKeyUsages
,
279 PKIX_List
**ppkixEKUList
,
280 PKIX_UInt32
*ppkixKU
,
283 PKIX_List
*ekuOidsList
= NULL
;
284 PKIX_PL_OID
*ekuOid
= NULL
;
286 int ekuIndex
= ekuIndexUnknown
;
288 PKIX_ENTER(CERTVFYPKIX
, "cert_NssCertificateUsageToPkixEku");
289 PKIX_NULLCHECK_TWO(ppkixEKUList
, ppkixKU
);
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
;
303 if (ekuIndex
!= ekuIndexUnknown
) {
304 PRUint32 reqKeyUsage
= 0;
305 PRUint32 reqCertType
= 0;
307 CERT_KeyUsageAndTypeForCertUsage(requiredCertUsage
, isCA
,
311 requiredKeyUsages
|= reqKeyUsage
;
314 PKIX_PL_OID_Create(ekuOidStrings
[ekuIndex
], &ekuOid
,
316 PKIX_OIDCREATEFAILED
);
319 PKIX_List_AppendItem(ekuOidsList
, (PKIX_PL_Object
*)ekuOid
,
321 PKIX_LISTAPPENDITEMFAILED
);
327 cert_NssKeyUsagesToPkix(requiredKeyUsages
, ppkixKU
, plContext
),
328 PKIX_NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED
);
330 *ppkixEKUList
= ekuOidsList
;
336 PKIX_DECREF(ekuOidsList
);
338 PKIX_RETURN(CERTVFYPKIX
);
343 * FUNCTION: cert_ProcessingParamsSetKuAndEku
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.
352 * Pointer to PKIX_ProcessingParams used during validation.
353 * "requiredCertUsage"
354 * Required certificate usages the certificate and chain is built and
357 * Request additional key usages the certificate should be validated for.
359 * Should the cert be verifyed as CA cert for the usages.
361 * Platform-specific context pointer.
363 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
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.
370 cert_ProcessingParamsSetKuAndEku(
371 PKIX_ProcessingParams
*procParams
,
372 CERTCertificate
*cert
,
374 SECCertUsage requiredCertUsage
,
375 PRUint32 requiredKeyUsages
,
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
);
388 pkix_pl_NssContext_SetCertUsage(
389 ((SECCertificateUsage
)1) << requiredCertUsage
, nssContext
),
390 PKIX_NSSCONTEXTSETCERTUSAGEFAILED
);
393 cert_NssCertificateUsageToPkixKUAndEKU(cert
, requiredCertUsage
,
394 requiredKeyUsages
, isCA
,
395 &extKeyUsage
, &keyUsage
,
397 PKIX_CANNOTCONVERTCERTUSAGETOPKIXKEYANDEKUSAGES
);
400 PKIX_ProcessingParams_GetTargetCertConstraints(procParams
,
401 &certSelector
, plContext
),
402 PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED
);
405 PKIX_CertSelector_GetCommonCertSelectorParams(certSelector
,
406 &certSelParams
, plContext
),
407 PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED
);
411 PKIX_ComCertSelParams_SetKeyUsage(certSelParams
, keyUsage
,
413 PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED
);
416 PKIX_ComCertSelParams_SetExtendedKeyUsage(certSelParams
,
419 PKIX_COMCERTSELPARAMSSETEXTKEYUSAGEFAILED
);
422 PKIX_PL_EkuChecker_Create(procParams
, plContext
),
423 PKIX_EKUCHECKERINITIALIZEFAILED
);
426 PKIX_DECREF(extKeyUsage
);
427 PKIX_DECREF(certSelector
);
428 PKIX_DECREF(certSelParams
);
430 PKIX_RETURN(CERTVFYPKIX
);
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
452 * Creates and fills in PKIX_ProcessingParams structure to be used
453 * for certificate chain building.
457 * Pointer to the CERTCertificate: the leaf certificate of a chain.
461 * Nss db password token.
463 * Flags to use arena for data allocation during chain building process.
465 * Address to return created processing parameters.
467 * Platform-specific context pointer.
469 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
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.
476 cert_CreatePkixProcessingParams(
477 CERTCertificate
*cert
,
478 PRBool checkSig
, /* not used yet. See bug 391476 */
483 PRBool checkAllCertsOCSP
,
485 PKIX_ProcessingParams
**pprocParams
,
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
;
497 PKIX_RevocationChecker
*ocspChecker
= NULL
;
499 void *plContext
= NULL
;
501 PKIX_ENTER(CERTVFYPKIX
, "cert_CreatePkixProcessingParams");
502 PKIX_NULLCHECK_TWO(cert
, pprocParams
);
505 PKIX_PL_NssContext_Create(0, useArena
, wincx
, &plContext
),
506 PKIX_NSSCONTEXTCREATEFAILED
);
508 *pplContext
= plContext
;
511 /* Functions should be implemented in patch for 390532 */
513 pkix_pl_NssContext_SetCertSignatureCheck(checkSig
,
514 (PKIX_PL_NssContext
*)plContext
),
515 PKIX_NSSCONTEXTSETCERTSIGNCHECKFAILED
);
517 #endif /* PKIX_NOTDEF */
520 PKIX_ProcessingParams_Create(&procParams
, plContext
),
521 PKIX_PROCESSINGPARAMSCREATEFAILED
);
524 PKIX_ComCertSelParams_Create(&certSelParams
, plContext
),
525 PKIX_COMCERTSELPARAMSCREATEFAILED
);
528 PKIX_PL_Cert_CreateFromCERTCertificate(cert
, &targetCert
, plContext
),
529 PKIX_CERTCREATEWITHNSSCERTFAILED
);
532 PKIX_ComCertSelParams_SetCertificate(certSelParams
,
533 targetCert
, plContext
),
534 PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED
);
537 PKIX_CertSelector_Create(NULL
, NULL
, &certSelector
, plContext
),
538 PKIX_COULDNOTCREATECERTSELECTOROBJECT
);
541 PKIX_CertSelector_SetCommonCertSelectorParams(certSelector
,
542 certSelParams
, plContext
),
543 PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED
);
546 PKIX_ProcessingParams_SetTargetCertConstraints(procParams
,
547 certSelector
, plContext
),
548 PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED
);
551 PKIX_PL_Pk11CertStore_Create(&certStore
, plContext
),
552 PKIX_PK11CERTSTORECREATEFAILED
);
555 PKIX_List_Create(&certStores
, plContext
),
556 PKIX_UNABLETOCREATELIST
);
559 PKIX_List_AppendItem(certStores
, (PKIX_PL_Object
*)certStore
,
561 PKIX_LISTAPPENDITEMFAILED
);
564 PKIX_ProcessingParams_SetCertStores(procParams
, certStores
,
566 PKIX_PROCESSINGPARAMSADDCERTSTOREFAILED
);
569 PKIX_PL_Date_CreateFromPRTime(time
, &date
, plContext
),
570 PKIX_DATECREATEFROMPRTIMEFAILED
);
573 PKIX_ProcessingParams_SetDate(procParams
, date
, plContext
),
574 PKIX_PROCESSINGPARAMSSETDATEFAILED
);
577 PKIX_ProcessingParams_SetNISTRevocationPolicyEnabled(procParams
,
580 PKIX_PROCESSINGPARAMSSETNISTREVOCATIONENABLEDFAILED
);
583 /* Enables ocsp rev checking of the chain cert through pkix OCSP
585 if (checkAllCertsOCSP
) {
587 PKIX_OcspChecker_Initialize(date
, NULL
, NULL
,
588 &ocspChecker
, plContext
),
589 PKIX_PROCESSINGPARAMSSETDATEFAILED
);
592 PKIX_ProcessingParams_AddRevocationChecker(procParams
,
593 ocspChecker
, plContext
),
594 PKIX_PROCESSINGPARAMSSETDATEFAILED
);
599 PKIX_ProcessingParams_SetAnyPolicyInhibited(procParams
, PR_FALSE
,
601 PKIX_PROCESSINGPARAMSSETANYPOLICYINHIBITED
);
604 PKIX_ProcessingParams_SetExplicitPolicyRequired(procParams
, PR_FALSE
,
606 PKIX_PROCESSINGPARAMSSETEXPLICITPOLICYREQUIRED
);
609 PKIX_ProcessingParams_SetPolicyMappingInhibited(procParams
, PR_FALSE
,
611 PKIX_PROCESSINGPARAMSSETPOLICYMAPPINGINHIBITED
);
613 *pprocParams
= procParams
;
617 PKIX_DECREF(anchors
);
618 PKIX_DECREF(targetCert
);
620 PKIX_DECREF(certSelector
);
621 PKIX_DECREF(certSelParams
);
622 PKIX_DECREF(certStore
);
623 PKIX_DECREF(certStores
);
624 PKIX_DECREF(procParams
);
626 PKIX_DECREF(ocspChecker
);
629 PKIX_RETURN(CERTVFYPKIX
);
633 * FUNCTION: cert_PkixToNssCertsChain
636 * Converts pkix cert list into nss cert list.
640 * Pkix certificate list.
642 * An address of returned nss certificate list.
644 * Platform-specific context pointer.
646 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
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.
653 cert_PkixToNssCertsChain(
654 PKIX_List
*pkixCertChain
,
655 CERTCertList
**pvalidChain
,
658 PRArenaPool
*arena
= NULL
;
659 CERTCertificate
*nssCert
= NULL
;
660 CERTCertList
*validChain
= NULL
;
661 PKIX_PL_Object
*certItem
= NULL
;
662 PKIX_UInt32 length
= 0;
665 PKIX_ENTER(CERTVFYPKIX
, "cert_PkixToNssCertsChain");
666 PKIX_NULLCHECK_ONE(pvalidChain
);
668 if (pkixCertChain
== NULL
) {
671 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
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
;
684 PKIX_List_GetLength(pkixCertChain
, &length
, plContext
),
685 PKIX_LISTGETLENGTHFAILED
);
687 for (i
= 0; i
< length
; i
++){
688 CERTCertListNode
*node
= NULL
;
691 PKIX_List_GetItem(pkixCertChain
, i
, &certItem
, plContext
),
692 PKIX_LISTGETITEMFAILED
);
695 PKIX_PL_Cert_GetCERTCertificate((PKIX_PL_Cert
*)certItem
, &nssCert
,
697 PKIX_CERTGETCERTCERTIFICATEFAILED
);
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
;
711 PKIX_DECREF(certItem
);
714 *pvalidChain
= validChain
;
717 if (PKIX_ERROR_RECEIVED
){
719 CERT_DestroyCertList(validChain
);
721 PORT_FreeArena(arena
, PR_FALSE
);
724 CERT_DestroyCertificate(nssCert
);
727 PKIX_DECREF(certItem
);
729 PKIX_RETURN(CERTVFYPKIX
);
734 * FUNCTION: cert_BuildAndValidateChain
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.
745 * Processing parameters to be used during chain building.
747 * Returned build result.
749 * Returned pointed to verify node structure: the tree-like structure
750 * that reports points of chain building failures.
752 * Platform-specific context pointer.
754 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
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.
761 cert_BuildAndValidateChain(
762 PKIX_ProcessingParams
*procParams
,
763 PKIX_BuildResult
**pResult
,
764 PKIX_VerifyNode
**pVerifyNode
,
767 PKIX_BuildResult
*result
= NULL
;
768 PKIX_VerifyNode
*verifyNode
= NULL
;
769 void *nbioContext
= NULL
;
772 PKIX_ENTER(CERTVFYPKIX
, "cert_BuildAndVerifyChain");
773 PKIX_NULLCHECK_TWO(procParams
, pResult
);
776 if (nbioContext
&& state
) {
777 /* PKIX-XXX: need to test functionality of NBIO handling in libPkix.
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
);
788 PKIX_BuildChain(procParams
, &nbioContext
, &state
,
789 &result
, &verifyNode
, plContext
),
790 PKIX_UNABLETOBUILDCHAIN
);
792 } while (nbioContext
&& state
);
798 *pVerifyNode
= verifyNode
;
801 PKIX_RETURN(CERTVFYPKIX
);
806 * FUNCTION: cert_PkixErrorToNssCode
809 * Converts pkix error(PKIX_Error) structure to PR error codes.
811 * PKIX-XXX to be implemented. See 391183.
815 * Pkix error that will be converted.
817 * Corresponding nss error code.
819 * Platform-specific context pointer.
821 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
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.
828 cert_PkixErrorToNssCode(
830 SECErrorCodes
*pNssErr
,
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. */
843 if (errPtr
->plErr
&& !nssErr
) {
844 nssErr
= errPtr
->plErr
;
848 PR_LOG(pkixLog
, 2, ("Error at level %d: %s\n", errLevel
,
849 PKIX_ErrorText
[errPtr
->errCode
]));
851 errPtr
= errPtr
->cause
;
856 *pNssErr
= SEC_ERROR_LIBPKIX_INTERNAL
;
861 PKIX_RETURN(CERTVFYPKIX
);
865 * FUNCTION: cert_GetLogFromVerifyNode
868 * Recursive function that converts verify node tree-like set of structures
873 * Pointed to already allocated CERTVerifyLog structure.
875 * A node of PKIX_VerifyNode tree.
877 * Platform-specific context pointer.
879 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
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.
886 cert_GetLogFromVerifyNode(
888 PKIX_VerifyNode
*node
,
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
) {
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
);
907 SECErrorCodes nssErrorCode
= 0;
908 CERTCertificate
*cert
= NULL
;
910 cert
= node
->verifyCert
->nssCert
;
913 cert_PkixErrorToNssCode(node
->error
, &nssErrorCode
,
915 PKIX_GETPKIXERRORCODEFAILED
);
917 cert_AddToVerifyLog(log
, cert
, nssErrorCode
, node
->depth
, NULL
);
920 PKIX_RETURN(CERTVFYPKIX
);
923 PKIX_UInt32 length
= 0;
926 PKIX_List_GetLength(children
, &length
, plContext
),
927 PKIX_LISTGETLENGTHFAILED
);
929 for (i
= 0; i
< length
; i
++){
932 PKIX_List_GetItem(children
, i
, (PKIX_PL_Object
**)&childNode
,
934 PKIX_LISTGETITEMFAILED
);
937 cert_GetLogFromVerifyNode(log
, childNode
, plContext
),
938 PKIX_ERRORINRECURSIVEEQUALSCALL
);
940 PKIX_DECREF(childNode
);
945 PKIX_DECREF(childNode
);
947 PKIX_RETURN(CERTVFYPKIX
);
951 * FUNCTION: cert_GetBuildResults
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
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
968 * Build results returned by PKIX_BuildChain.
970 * Tree-like structure of chain building/validation failures
971 * returned by PKIX_BuildChain. Ignored in case of success.
973 * Final error returned by PKIX_BuildChain. Should be NULL in
976 * Address of pre-allocated(if not NULL) CERTVerifyLog structure.
978 * Address of returned trusted root the chain was anchored to.
980 * Address of returned valid chain.
982 * Platform-specific context pointer.
984 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
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.
991 cert_GetBuildResults(
992 PKIX_BuildResult
*buildResult
,
993 PKIX_VerifyNode
*verifyNode
,
996 CERTCertificate
**ptrustedRoot
,
997 CERTCertList
**pvalidChain
,
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
;
1007 PKIX_Error
*tmpPkixError
= NULL
;
1010 PKIX_ENTER(CERTVFYPKIX
, "cert_GetBuildResults");
1011 if (buildResult
== NULL
&& error
== NULL
) {
1012 PKIX_ERROR(PKIX_NULLARGUMENT
);
1016 SECErrorCodes nssErrorCode
= 0;
1018 char *temp
= pkix_Error2ASCII(error
, plContext
);
1019 fprintf(stderr
, "BUILD ERROR:\n%s\n", temp
);
1020 PKIX_PL_Free(temp
, NULL
);
1023 PKIX_Error
*tmpError
=
1024 cert_GetLogFromVerifyNode(log
, verifyNode
, plContext
);
1026 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)tmpError
, plContext
);
1029 cert_PkixErrorToNssCode(error
, &nssErrorCode
, plContext
);
1030 PORT_SetError(nssErrorCode
);
1036 PKIX_BuildResult_GetCertChain(buildResult
, &pkixCertChain
,
1038 PKIX_BUILDRESULTGETCERTCHAINFAILED
);
1041 tmpPkixError
= cert_PrintCertChain(pkixCertChain
, plContext
);
1043 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)tmpPkixError
, plContext
);
1048 cert_PkixToNssCertsChain(pkixCertChain
, &validChain
, plContext
),
1049 PKIX_CERTCHAINTONSSCHAINFAILED
);
1054 PKIX_BuildResult_GetValidateResult(buildResult
, &validResult
,
1056 PKIX_BUILDRESULTGETVALIDATERESULTFAILED
);
1059 PKIX_ValidateResult_GetTrustAnchor(validResult
, &trustAnchor
,
1061 PKIX_VALIDATERESULTGETTRUSTANCHORFAILED
);
1064 PKIX_TrustAnchor_GetTrustedCert(trustAnchor
, &trustedCert
,
1066 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED
);
1069 if (pvalidChain
== NULL
) {
1070 cert_PrintCert(trustedCert
, plContext
);
1075 PKIX_PL_Cert_GetCERTCertificate(trustedCert
, &trustedRoot
,
1077 PKIX_CERTGETCERTCERTIFICATEFAILED
);
1080 PORT_Assert(!PKIX_ERROR_RECEIVED
);
1083 *ptrustedRoot
= trustedRoot
;
1086 *pvalidChain
= validChain
;
1090 if (PKIX_ERROR_RECEIVED
) {
1092 CERT_DestroyCertificate(trustedRoot
);
1095 CERT_DestroyCertList(validChain
);
1098 PKIX_DECREF(trustAnchor
);
1099 PKIX_DECREF(trustedCert
);
1100 PKIX_DECREF(pkixCertChain
);
1101 PKIX_DECREF(validResult
);
1103 PKIX_DECREF(verifyNode
);
1104 PKIX_DECREF(buildResult
);
1106 PKIX_RETURN(CERTVFYPKIX
);
1110 * FUNCTION: cert_VerifyCertChainPkix
1113 * The main wrapper function that is called from CERT_VerifyCert and
1114 * CERT_VerifyCACertForUsage functions to validate cert with libpkix.
1118 * Leaf certificate of a chain we want to build.
1120 * Certificate signatures will not be verified if this
1121 * flag is set to PR_FALSE.
1123 * Required usage for certificate and chain.
1127 * Nss database password token.
1129 * Address of already allocated CERTVerifyLog structure. Not
1132 * Address of PRBool. If not NULL, returns true is cert chain
1133 * was invalidated because of bad certificate signature.
1135 * Address of PRBool. If not NULL, returns true is cert chain
1136 * was invalidated because a revoked certificate was found in
1139 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1141 * SECFailure is chain building process has failed. SECSuccess otherwise.
1144 cert_VerifyCertChainPkix(
1145 CERTCertificate
*cert
,
1147 SECCertUsage requiredUsage
,
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
;
1162 CERTCertificate
*trustedRoot
= NULL
;
1163 CERTCertList
*validChain
= NULL
;
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(¶llelFnInvocationCount
);
1182 PORT_Assert(fnInvLocalCount
== 1);
1195 errorGenerated
= PKIX_FALSE
;
1199 pkix_pl_lifecycle_ObjectTableUpdate(objCountTable
);
1202 PR_LOG(pkixLog
, 1, ("Memory leak test: Loop %d\n", memLeakLoopCount
++));
1203 #endif /* PKIX_OBJECT_LEAK_TEST */
1206 cert_CreatePkixProcessingParams(cert
, checkSig
, time
, wincx
,
1207 PR_FALSE
/*use arena*/,
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
,
1215 &procParams
, &plContext
);
1221 cert_ProcessingParamsSetKuAndEku(procParams
, cert
, PR_TRUE
,
1222 requiredUsage
, 0, plContext
);
1228 cert_BuildAndValidateChain(procParams
, &result
, &verifyNode
, plContext
);
1234 /* Currently always PR_FALSE. Will be fixed as a part of 394077 */
1235 *pRevoked
= PR_FALSE
;
1238 /* Currently always PR_FALSE. Will be fixed as a part of 394077 */
1239 *pSigerror
= PR_FALSE
;
1244 error
= cert_GetBuildResults(result
, verifyNode
, error
, log
,
1246 &trustedRoot
, &validChain
,
1253 char *temp
= pkix_Error2ASCII(error
, plContext
);
1254 fprintf(stderr
, "GET BUILD RES ERRORS:\n%s\n", temp
);
1255 PKIX_PL_Free(temp
, NULL
);
1257 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)error
, plContext
);
1261 CERT_DestroyCertificate(trustedRoot
);
1264 CERT_DestroyCertList(validChain
);
1268 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)procParams
, plContext
);
1271 PKIX_PL_NssContext_Destroy(plContext
);
1274 #ifdef PKIX_OBJECT_LEAK_TEST
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
;
1285 PORT_Assert(leakedObjNum
== 0);
1288 } while (errorGenerated
);
1290 runningLeakTest
= PKIX_FALSE
;
1291 PR_AtomicDecrement(¶llelFnInvocationCount
);
1292 #endif /* PKIX_OBJECT_LEAK_TEST */
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
;
1327 if (certSelParams
!= NULL
)
1328 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)certSelParams
, plContext
);
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
);
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
;
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
);
1387 * There is no NSS SECItem -> PKIX OID
1388 * conversion function. For now, I go via the ascii
1390 * this should be in PKIX_PL_*
1394 CERT_PKIXOIDFromNSSOid(SECOidTag tag
, void*plContext
)
1396 char *oidstring
= NULL
;
1397 char *oidstring_adj
= NULL
;
1398 PKIX_PL_OID
*policyOID
= NULL
;
1401 data
= SECOID_FindOIDByTag(tag
);
1403 oidstring
= CERT_GetOidString(&data
->oid
);
1404 if (oidstring
== NULL
) {
1407 oidstring_adj
= oidstring
;
1408 if (PORT_Strncmp("OID.",oidstring_adj
,4) == 0) {
1412 PKIX_PL_OID_Create(oidstring_adj
, &policyOID
, plContext
);
1415 if (oidstring
!= NULL
) PR_smprintf_free(oidstring
);
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 */
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
;
1445 error
= PKIX_List_Create(&policyList
, plContext
);
1446 if (error
!= NULL
) {
1450 for (i
=0; i
<oidCount
; i
++) {
1451 policyOID
= CERT_PKIXOIDFromNSSOid(oids
[i
],plContext
);
1452 if (policyOID
== NULL
) {
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
);
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
;
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
);
1484 cert_pkix_FindOutputParam(CERTValOutParam
*params
, const CERTValParamOutType t
)
1487 if (params
== NULL
) {
1490 for (i
= params
; i
->type
!= cert_po_end
; i
++) {
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
:
1522 error
= PKIX_ProcessingParams_SetExplicitPolicyRequired(
1523 procParams
, PKIX_TRUE
, plContext
);
1525 if (error
!= NULL
) {
1529 policyOIDList
= cert_PKIXMakeOIDList(param
->value
.array
.oids
,
1530 param
->value
.arraySize
,plContext
);
1531 if (policyOIDList
== NULL
) {
1533 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1537 error
= PKIX_ProcessingParams_SetInitialPolicies(
1538 procParams
,policyOIDList
,plContext
);
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
;
1549 error
= pkix_pl_Date_CreateFromPRTime(param
->value
.scalar
.time
,
1551 if (error
!= NULL
) {
1552 errCode
= SEC_ERROR_INVALID_TIME
;
1557 error
= PKIX_ProcessingParams_SetDate(procParams
, date
, plContext
);
1558 if (error
!= NULL
) {
1559 errCode
= SEC_ERROR_INVALID_TIME
;
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
;
1573 PORT_SetError(errCode
);
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
;
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
;
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
;
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
;
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
1648 /* currently OCSP is the only external revocation checker */
1649 error
= PKIX_ProcessingParams_SetRevocationCheckers(procParams
,
1652 /* FIXME: What should be done if !ocspTurnedOnForLeaf ? */
1654 /* OCSP is on for the whole chain */
1656 error
= PKIX_ProcessingParams_GetDate
1657 (procParams
, &date
, plContext
);
1658 if (error
!= NULL
) {
1659 errCode
= SEC_ERROR_INVALID_TIME
;
1663 error
= PKIX_OcspChecker_Initialize(date
, NULL
, NULL
,
1664 &ocspChecker
, plContext
);
1665 if (error
!= NULL
) {
1669 error
= PKIX_ProcessingParams_AddRevocationChecker(procParams
,
1670 ocspChecker
, plContext
);
1671 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)ocspChecker
, plContext
);
1674 /* FIXME: add support for other revocation flags when underlying
1675 * pkix supports it */
1677 if (error
!= NULL
) {
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
1687 /* this function only affects the built-in CRL checker */
1688 error
= PKIX_ProcessingParams_SetRevocationEnabled(procParams
,
1689 PKIX_FALSE
, plContext
);
1690 if (error
!= NULL
) {
1693 /* make sure NIST Revocation Policy is off as well */
1694 error
= PKIX_ProcessingParams_SetNISTRevocationPolicyEnabled
1695 (procParams
, PKIX_FALSE
, plContext
);
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
) {
1705 error
= PKIX_ProcessingParams_SetNISTRevocationPolicyEnabled
1707 crlHardFailure
? PKIX_TRUE
: PKIX_FALSE
,
1713 case cert_pi_trustAnchors
:
1714 certList
= param
->value
.pointer
.chain
;
1716 error
= PKIX_List_Create(&certListPkix
, plContext
);
1717 if (error
!= NULL
) {
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
);
1727 error
= PKIX_TrustAnchor_CreateWithCert(certPkix
, &trustAnchor
,
1732 error
= PKIX_List_AppendItem(certListPkix
,
1733 (PKIX_PL_Object
*)trustAnchor
, plContext
);
1737 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)trustAnchor
, plContext
);
1739 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)certPkix
, plContext
);
1743 PKIX_ProcessingParams_SetTrustAnchors(procParams
, certListPkix
,
1747 case cert_pi_useAIACertFetch
:
1749 PKIX_ProcessingParams_SetUseAIAForCertFetching(procParams
,
1750 (PRBool
)(param
->value
.scalar
.b
!= 0),
1755 PORT_SetError(errCode
);
1759 if (policyOIDList
!= NULL
)
1760 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)policyOIDList
, plContext
);
1763 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)date
, plContext
);
1765 if (ocspChecker
!= NULL
)
1766 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)ocspChecker
, plContext
);
1769 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)certListPkix
, plContext
);
1772 PKIX_PL_Object_DecRef((PKIX_PL_Object
*)trustAnchor
, plContext
);
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
);
1788 cert_pkixDestroyValOutParam(CERTValOutParam
*params
)
1792 if (params
== NULL
) {
1795 for (i
= params
; i
->type
!= cert_po_end
; i
++) {
1797 case cert_po_trustAnchor
:
1798 if (i
->value
.pointer
.cert
) {
1799 CERT_DestroyCertificate(i
->value
.pointer
.cert
);
1800 i
->value
.pointer
.cert
= NULL
;
1804 case cert_po_certList
:
1805 if (i
->value
.pointer
.chain
) {
1806 CERT_DestroyCertList(i
->value
.pointer
.chain
);
1807 i
->value
.pointer
.chain
= NULL
;
1817 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags
[2] = {
1819 CERT_REV_M_TEST_USING_THIS_METHOD
1820 | CERT_REV_M_FORBID_NETWORK_FETCHING
1821 | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO
,
1823 CERT_REV_M_TEST_USING_THIS_METHOD
1826 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags
[2] = {
1828 CERT_REV_M_TEST_USING_THIS_METHOD
1829 | CERT_REV_M_FORBID_NETWORK_FETCHING
1830 | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO
,
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
= {
1844 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags
,
1846 &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference
,
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] = {
1868 CERT_REV_M_TEST_USING_THIS_METHOD
1869 | CERT_REV_M_FORBID_NETWORK_FETCHING
1870 | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO
,
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] = {
1878 CERT_REV_M_TEST_USING_THIS_METHOD
1879 | CERT_REV_M_FORBID_NETWORK_FETCHING
1880 | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO
,
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
= {
1894 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags
,
1896 &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference
,
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] = {
1918 CERT_REV_M_TEST_USING_THIS_METHOD
1919 | CERT_REV_M_FORBID_NETWORK_FETCHING
1920 | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO
,
1925 static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags
[2] = {
1927 CERT_REV_M_TEST_USING_THIS_METHOD
1928 | CERT_REV_M_FORBID_NETWORK_FETCHING
1929 | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO
,
1934 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Disabled_Policy
= {
1938 certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags
,
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] = {
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
,
1969 static PRUint64 certRev_PKIX_Verify_Nist_Policy_ChainFlags
[2] = {
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
,
1978 static const CERTRevocationFlags certRev_PKIX_Verify_Nist_Policy
= {
1982 certRev_PKIX_Verify_Nist_Policy_LeafFlags
,
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.
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
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
,
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
;
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(¶llelFnInvocationCount
);
2069 PORT_Assert(fnInvLocalCount
== 1);
2076 nbioContext
= NULL
; /* for non-blocking IO */
2077 buildState
= NULL
; /* for non-blocking IO */
2078 certSelector
= NULL
;
2083 trustAnchorCert
= NULL
;
2084 builtCertList
= NULL
;
2087 errorGenerated
= PKIX_FALSE
;
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
);
2104 error
= pkix_pl_NssContext_SetCertUsage(usages
, plContext
);
2105 if (error
!= NULL
) {
2106 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
2110 error
= PKIX_ProcessingParams_Create(&procParams
, plContext
);
2111 if (error
!= NULL
) { /* need pkix->nss error map */
2112 PORT_SetError(SEC_ERROR_CERT_NOT_VALID
);
2117 /* now process the extensible input parameters structure */
2118 if (paramsIn
!= NULL
) {
2120 while (paramsIn
[i
].type
!= cert_pi_end
) {
2121 if (paramsIn
[i
].type
>= cert_pi_max
) {
2122 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
2125 if (cert_pkixSetParam(procParams
,
2126 ¶msIn
[i
],plContext
) != SECSuccess
) {
2127 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
2135 certSelector
= cert_GetTargetCertConstraints(cert
, plContext
);
2136 if (certSelector
== NULL
) {
2139 error
= PKIX_ProcessingParams_SetTargetCertConstraints
2140 (procParams
, certSelector
, plContext
);
2141 if (error
!= NULL
) {
2145 certStores
= cert_GetCertStores(plContext
);
2146 if (certStores
== NULL
) {
2149 error
= PKIX_ProcessingParams_SetCertStores
2150 (procParams
, certStores
, plContext
);
2151 if (error
!= NULL
) {
2155 error
= PKIX_BuildChain( procParams
, &nbioContext
,
2156 &buildState
, &buildResult
, &verifyNode
,
2158 if (error
!= NULL
) {
2162 error
= PKIX_BuildResult_GetValidateResult( buildResult
, &valResult
,
2164 if (error
!= NULL
) {
2168 error
= PKIX_ValidateResult_GetTrustAnchor( valResult
, &trustAnchor
,
2170 if (error
!= NULL
) {
2174 error
= PKIX_TrustAnchor_GetTrustedCert( trustAnchor
, &trustAnchorCert
,
2176 if (error
!= NULL
) {
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
,
2192 if (error
!= NULL
) {
2196 oparam
= cert_pkix_FindOutputParam(paramsOut
, cert_po_certList
);
2197 if (oparam
!= NULL
) {
2198 error
= cert_PkixToNssCertsChain(builtCertList
,
2199 &oparam
->value
.pointer
.chain
,
2201 if (error
) goto cleanup
;
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
);
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
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
;
2270 PORT_Assert(leakedObjNum
== 0);
2273 } while (errorGenerated
);
2275 runningLeakTest
= PKIX_FALSE
;
2276 PR_AtomicDecrement(¶llelFnInvocationCount
);
2277 #endif /* PKIX_OBJECT_LEAK_TEST */