1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/libpkix/pkix/top/pkix_validate.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1451 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * pkix_validate.c 1.9 + * 1.10 + * Top level validateChain function 1.11 + * 1.12 + */ 1.13 + 1.14 +#include "pkix_validate.h" 1.15 +#include "pkix_pl_common.h" 1.16 + 1.17 +/* --Private-Functions-------------------------------------------- */ 1.18 + 1.19 +/* 1.20 + * FUNCTION: pkix_AddToVerifyLog 1.21 + * DESCRIPTION: 1.22 + * 1.23 + * This function returns immediately if the address for the VerifyNode tree 1.24 + * pointed to by "pVerifyTree" is NULL. Otherwise it creates a new VerifyNode 1.25 + * from the Cert pointed to by "cert" and the Error pointed to by "error", 1.26 + * and inserts it at the depth in the VerifyNode tree determined by "depth". A 1.27 + * depth of zero means that this function creates the root node of a new tree. 1.28 + * 1.29 + * Note: this function does not include the means of choosing among branches 1.30 + * of a tree. It is intended for non-branching trees, that is, where each 1.31 + * parent node has only a single child node. 1.32 + * 1.33 + * PARAMETERS: 1.34 + * "cert" 1.35 + * The address of the Cert to be included in the new VerifyNode. Must be 1.36 + * non-NULL. 1.37 + * "depth" 1.38 + * The UInt32 value of the depth. 1.39 + * "error" 1.40 + * The address of the Error to be included in the new VerifyNode. 1.41 + * "pVerifyTree" 1.42 + * The address of the VerifyNode tree into which the created VerifyNode 1.43 + * is to be inserted. The node is not created if VerifyTree is NULL. 1.44 + * "plContext" 1.45 + * Platform-specific context pointer. 1.46 + * THREAD SAFETY: 1.47 + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.48 + * RETURNS: 1.49 + * Returns NULL if the function succeeds. 1.50 + * Returns a Validate Error if the function fails in a non-fatal way. 1.51 + * Returns a Fatal Error if the function fails in an unrecoverable way. 1.52 + */ 1.53 +static PKIX_Error * 1.54 +pkix_AddToVerifyLog( 1.55 + PKIX_PL_Cert *cert, 1.56 + PKIX_UInt32 depth, 1.57 + PKIX_Error *error, 1.58 + PKIX_VerifyNode **pVerifyTree, 1.59 + void *plContext) 1.60 +{ 1.61 + 1.62 + PKIX_VerifyNode *verifyNode = NULL; 1.63 + 1.64 + PKIX_ENTER(VALIDATE, "pkix_AddToVerifyLog"); 1.65 + PKIX_NULLCHECK_ONE(cert); 1.66 + 1.67 + if (pVerifyTree) { /* nothing to do if no address given for log */ 1.68 + 1.69 + PKIX_CHECK(pkix_VerifyNode_Create 1.70 + (cert, depth, error, &verifyNode, plContext), 1.71 + PKIX_VERIFYNODECREATEFAILED); 1.72 + 1.73 + if (depth == 0) { 1.74 + /* We just created the root node */ 1.75 + *pVerifyTree = verifyNode; 1.76 + } else { 1.77 + PKIX_CHECK(pkix_VerifyNode_AddToChain 1.78 + (*pVerifyTree, verifyNode, plContext), 1.79 + PKIX_VERIFYNODEADDTOCHAINFAILED); 1.80 + } 1.81 + } 1.82 + 1.83 +cleanup: 1.84 + 1.85 + PKIX_RETURN(VALIDATE); 1.86 + 1.87 +} 1.88 + 1.89 +/* 1.90 + * FUNCTION: pkix_CheckCert 1.91 + * DESCRIPTION: 1.92 + * 1.93 + * Checks whether the Cert pointed to by "cert" successfully validates 1.94 + * using the List of CertChainCheckers pointed to by "checkers". If the 1.95 + * certificate does not validate, an Error pointer is returned. 1.96 + * 1.97 + * This function should be called initially with the UInt32 pointed to by 1.98 + * "pCheckerIndex" containing zero, and the pointer at "pNBIOContext" 1.99 + * containing NULL. If a checker does non-blocking I/O, this function will 1.100 + * return with the index of that checker stored at "pCheckerIndex" and a 1.101 + * platform-dependent non-blocking I/O context stored at "pNBIOContext". 1.102 + * A subsequent call to this function with those values intact will allow the 1.103 + * checking to resume where it left off. This should be repeated until the 1.104 + * function returns with NULL stored at "pNBIOContext". 1.105 + * 1.106 + * PARAMETERS: 1.107 + * "cert" 1.108 + * Address of Cert to validate. Must be non-NULL. 1.109 + * "checkers" 1.110 + * List of CertChainCheckers which must each validate the certificate. 1.111 + * Must be non-NULL. 1.112 + * "checkedExtOIDs" 1.113 + * List of PKIX_PL_OID that has been processed. If called from building 1.114 + * chain, it is the list of critical extension OIDs that has been 1.115 + * processed prior to validation. May be NULL. 1.116 + * "pCheckerIndex" 1.117 + * Address at which is stored the the index, within the List "checkers", 1.118 + * of a checker whose processing was interrupted by non-blocking I/O. 1.119 + * Must be non-NULL. 1.120 + * "pNBIOContext" 1.121 + * Address at which is stored platform-specific non-blocking I/O context. 1.122 + * Must be non-NULL. 1.123 + * "plContext" 1.124 + * Platform-specific context pointer. 1.125 + * THREAD SAFETY: 1.126 + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.127 + * RETURNS: 1.128 + * Returns NULL if the function succeeds. 1.129 + * Returns a Validate Error if the function fails in a non-fatal way. 1.130 + * Returns a Fatal Error if the function fails in an unrecoverable way. 1.131 + */ 1.132 +static PKIX_Error * 1.133 +pkix_CheckCert( 1.134 + PKIX_PL_Cert *cert, 1.135 + PKIX_List *checkers, 1.136 + PKIX_List *checkedExtOIDsList, 1.137 + PKIX_UInt32 *pCheckerIndex, 1.138 + void **pNBIOContext, 1.139 + void *plContext) 1.140 +{ 1.141 + PKIX_CertChainChecker_CheckCallback checkerCheck = NULL; 1.142 + PKIX_CertChainChecker *checker = NULL; 1.143 + PKIX_List *unresCritExtOIDs = NULL; 1.144 + PKIX_UInt32 numCheckers; 1.145 + PKIX_UInt32 numUnresCritExtOIDs = 0; 1.146 + PKIX_UInt32 checkerIndex = 0; 1.147 + void *nbioContext = NULL; 1.148 + 1.149 + PKIX_ENTER(VALIDATE, "pkix_CheckCert"); 1.150 + PKIX_NULLCHECK_FOUR(cert, checkers, pCheckerIndex, pNBIOContext); 1.151 + 1.152 + nbioContext = *pNBIOContext; 1.153 + *pNBIOContext = NULL; /* prepare for case of error exit */ 1.154 + 1.155 + PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs 1.156 + (cert, &unresCritExtOIDs, plContext), 1.157 + PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED); 1.158 + 1.159 + PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext), 1.160 + PKIX_LISTGETLENGTHFAILED); 1.161 + 1.162 + for (checkerIndex = *pCheckerIndex; 1.163 + checkerIndex < numCheckers; 1.164 + checkerIndex++) { 1.165 + 1.166 + PKIX_CHECK(PKIX_List_GetItem 1.167 + (checkers, 1.168 + checkerIndex, 1.169 + (PKIX_PL_Object **)&checker, 1.170 + plContext), 1.171 + PKIX_LISTGETITEMFAILED); 1.172 + 1.173 + PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback 1.174 + (checker, &checkerCheck, plContext), 1.175 + PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED); 1.176 + 1.177 + PKIX_CHECK(checkerCheck(checker, cert, unresCritExtOIDs, 1.178 + &nbioContext, plContext), 1.179 + PKIX_CERTCHAINCHECKERCHECKFAILED); 1.180 + 1.181 + if (nbioContext != NULL) { 1.182 + *pCheckerIndex = checkerIndex; 1.183 + *pNBIOContext = nbioContext; 1.184 + goto cleanup; 1.185 + } 1.186 + 1.187 + PKIX_DECREF(checker); 1.188 + } 1.189 + 1.190 + if (unresCritExtOIDs){ 1.191 + 1.192 +#ifdef PKIX_VALIDATEDEBUG 1.193 + { 1.194 + PKIX_PL_String *oidString = NULL; 1.195 + PKIX_UInt32 length; 1.196 + char *oidAscii = NULL; 1.197 + PKIX_TOSTRING(unresCritExtOIDs, &oidString, plContext, 1.198 + PKIX_LISTTOSTRINGFAILED); 1.199 + PKIX_CHECK(PKIX_PL_String_GetEncoded 1.200 + (oidString, 1.201 + PKIX_ESCASCII, 1.202 + (void **) &oidAscii, 1.203 + &length, 1.204 + plContext), 1.205 + PKIX_STRINGGETENCODEDFAILED); 1.206 + PKIX_VALIDATE_DEBUG_ARG 1.207 + ("unrecognized critical extension OIDs:" 1.208 + " %s\n", oidAscii); 1.209 + PKIX_DECREF(oidString); 1.210 + PKIX_PL_Free(oidAscii, plContext); 1.211 + } 1.212 +#endif 1.213 + 1.214 + if (checkedExtOIDsList != NULL) { 1.215 + /* Take out OID's that had been processed, if any */ 1.216 + PKIX_CHECK(pkix_List_RemoveItems 1.217 + (unresCritExtOIDs, 1.218 + checkedExtOIDsList, 1.219 + plContext), 1.220 + PKIX_LISTREMOVEITEMSFAILED); 1.221 + } 1.222 + 1.223 + PKIX_CHECK(PKIX_List_GetLength 1.224 + (unresCritExtOIDs, &numUnresCritExtOIDs, plContext), 1.225 + PKIX_LISTGETLENGTHFAILED); 1.226 + 1.227 + if (numUnresCritExtOIDs != 0){ 1.228 + PKIX_ERROR(PKIX_UNRECOGNIZEDCRITICALEXTENSION); 1.229 + } 1.230 + 1.231 + } 1.232 + 1.233 +cleanup: 1.234 + 1.235 + PKIX_DECREF(checker); 1.236 + PKIX_DECREF(unresCritExtOIDs); 1.237 + 1.238 + PKIX_RETURN(VALIDATE); 1.239 + 1.240 +} 1.241 + 1.242 +/* 1.243 + * FUNCTION: pkix_InitializeCheckers 1.244 + * DESCRIPTION: 1.245 + * 1.246 + * Creates several checkers and initializes them with values derived from the 1.247 + * TrustAnchor pointed to by "anchor", the ProcessingParams pointed to by 1.248 + * "procParams", and the number of Certs in the Chain, represented by 1.249 + * "numCerts". The List of checkers is stored at "pCheckers". 1.250 + * 1.251 + * PARAMETERS: 1.252 + * "anchor" 1.253 + * Address of TrustAnchor used to initialize the SignatureChecker and 1.254 + * NameChainingChecker. Must be non-NULL. 1.255 + * "procParams" 1.256 + * Address of ProcessingParams used to initialize the ExpirationChecker 1.257 + * and TargetCertChecker. Must be non-NULL. 1.258 + * "numCerts" 1.259 + * Number of certificates in the CertChain. 1.260 + * "pCheckers" 1.261 + * Address where object pointer will be stored. Must be non-NULL. 1.262 + * "plContext" 1.263 + * Platform-specific context pointer. 1.264 + * THREAD SAFETY: 1.265 + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.266 + * RETURNS: 1.267 + * Returns NULL if the function succeeds. 1.268 + * Returns a Validate Error if the function fails in a non-fatal way. 1.269 + * Returns a Fatal Error if the function fails in an unrecoverable way. 1.270 + */ 1.271 +static PKIX_Error * 1.272 +pkix_InitializeCheckers( 1.273 + PKIX_TrustAnchor *anchor, 1.274 + PKIX_ProcessingParams *procParams, 1.275 + PKIX_UInt32 numCerts, 1.276 + PKIX_List **pCheckers, 1.277 + void *plContext) 1.278 +{ 1.279 + PKIX_CertChainChecker *targetCertChecker = NULL; 1.280 + PKIX_CertChainChecker *expirationChecker = NULL; 1.281 + PKIX_CertChainChecker *nameChainingChecker = NULL; 1.282 + PKIX_CertChainChecker *nameConstraintsChecker = NULL; 1.283 + PKIX_CertChainChecker *basicConstraintsChecker = NULL; 1.284 + PKIX_CertChainChecker *policyChecker = NULL; 1.285 + PKIX_CertChainChecker *sigChecker = NULL; 1.286 + PKIX_CertChainChecker *defaultCrlChecker = NULL; 1.287 + PKIX_CertChainChecker *userChecker = NULL; 1.288 + PKIX_PL_X500Name *trustedCAName = NULL; 1.289 + PKIX_PL_PublicKey *trustedPubKey = NULL; 1.290 + PKIX_List *checkers = NULL; 1.291 + PKIX_PL_Date *testDate = NULL; 1.292 + PKIX_CertSelector *certSelector = NULL; 1.293 + PKIX_PL_Cert *trustedCert = NULL; 1.294 + PKIX_PL_CertNameConstraints *trustedNC = NULL; 1.295 + PKIX_List *initialPolicies = NULL; 1.296 + PKIX_Boolean policyQualifiersRejected = PKIX_FALSE; 1.297 + PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE; 1.298 + PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE; 1.299 + PKIX_Boolean initialExplicitPolicy = PKIX_FALSE; 1.300 + PKIX_List *userCheckersList = NULL; 1.301 + PKIX_List *certStores = NULL; 1.302 + PKIX_UInt32 numCertCheckers = 0; 1.303 + PKIX_UInt32 i; 1.304 + 1.305 + PKIX_ENTER(VALIDATE, "pkix_InitializeCheckers"); 1.306 + PKIX_NULLCHECK_THREE(anchor, procParams, pCheckers); 1.307 + PKIX_CHECK(PKIX_List_Create(&checkers, plContext), 1.308 + PKIX_LISTCREATEFAILED); 1.309 + 1.310 + /* 1.311 + * The TrustAnchor may have been created using CreateWithCert 1.312 + * (in which case GetCAPublicKey and GetCAName will return NULL) 1.313 + * or may have been created using CreateWithNameKeyPair (in which 1.314 + * case GetTrustedCert will return NULL. So we call GetTrustedCert 1.315 + * and populate trustedPubKey and trustedCAName accordingly. 1.316 + */ 1.317 + 1.318 + PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert 1.319 + (anchor, &trustedCert, plContext), 1.320 + PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); 1.321 + 1.322 + if (trustedCert){ 1.323 + PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey 1.324 + (trustedCert, &trustedPubKey, plContext), 1.325 + PKIX_CERTGETSUBJECTPUBLICKEYFAILED); 1.326 + 1.327 + PKIX_CHECK(PKIX_PL_Cert_GetSubject 1.328 + (trustedCert, &trustedCAName, plContext), 1.329 + PKIX_CERTGETSUBJECTFAILED); 1.330 + } else { 1.331 + PKIX_CHECK(PKIX_TrustAnchor_GetCAPublicKey 1.332 + (anchor, &trustedPubKey, plContext), 1.333 + PKIX_TRUSTANCHORGETCAPUBLICKEYFAILED); 1.334 + 1.335 + PKIX_CHECK(PKIX_TrustAnchor_GetCAName 1.336 + (anchor, &trustedCAName, plContext), 1.337 + PKIX_TRUSTANCHORGETCANAMEFAILED); 1.338 + } 1.339 + 1.340 + PKIX_NULLCHECK_TWO(trustedPubKey, trustedCAName); 1.341 + 1.342 + PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints 1.343 + (anchor, &trustedNC, plContext), 1.344 + PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED); 1.345 + 1.346 + PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints 1.347 + (procParams, &certSelector, plContext), 1.348 + PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); 1.349 + 1.350 + PKIX_CHECK(PKIX_ProcessingParams_GetDate 1.351 + (procParams, &testDate, plContext), 1.352 + PKIX_PROCESSINGPARAMSGETDATEFAILED); 1.353 + 1.354 + PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies 1.355 + (procParams, &initialPolicies, plContext), 1.356 + PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED); 1.357 + 1.358 + PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected 1.359 + (procParams, &policyQualifiersRejected, plContext), 1.360 + PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED); 1.361 + 1.362 + PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited 1.363 + (procParams, &initialPolicyMappingInhibit, plContext), 1.364 + PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED); 1.365 + 1.366 + PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited 1.367 + (procParams, &initialAnyPolicyInhibit, plContext), 1.368 + PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED); 1.369 + 1.370 + PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired 1.371 + (procParams, &initialExplicitPolicy, plContext), 1.372 + PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED); 1.373 + 1.374 + PKIX_CHECK(PKIX_ProcessingParams_GetCertStores 1.375 + (procParams, &certStores, plContext), 1.376 + PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED); 1.377 + 1.378 + PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers 1.379 + (procParams, &userCheckersList, plContext), 1.380 + PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); 1.381 + 1.382 + /* now, initialize all the checkers */ 1.383 + PKIX_CHECK(pkix_TargetCertChecker_Initialize 1.384 + (certSelector, numCerts, &targetCertChecker, plContext), 1.385 + PKIX_TARGETCERTCHECKERINITIALIZEFAILED); 1.386 + 1.387 + PKIX_CHECK(pkix_ExpirationChecker_Initialize 1.388 + (testDate, &expirationChecker, plContext), 1.389 + PKIX_EXPIRATIONCHECKERINITIALIZEFAILED); 1.390 + 1.391 + PKIX_CHECK(pkix_NameChainingChecker_Initialize 1.392 + (trustedCAName, &nameChainingChecker, plContext), 1.393 + PKIX_NAMECHAININGCHECKERINITIALIZEFAILED); 1.394 + 1.395 + PKIX_CHECK(pkix_NameConstraintsChecker_Initialize 1.396 + (trustedNC, numCerts, &nameConstraintsChecker, plContext), 1.397 + PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED); 1.398 + 1.399 + PKIX_CHECK(pkix_BasicConstraintsChecker_Initialize 1.400 + (numCerts, &basicConstraintsChecker, plContext), 1.401 + PKIX_BASICCONSTRAINTSCHECKERINITIALIZEFAILED); 1.402 + 1.403 + PKIX_CHECK(pkix_PolicyChecker_Initialize 1.404 + (initialPolicies, 1.405 + policyQualifiersRejected, 1.406 + initialPolicyMappingInhibit, 1.407 + initialExplicitPolicy, 1.408 + initialAnyPolicyInhibit, 1.409 + numCerts, 1.410 + &policyChecker, 1.411 + plContext), 1.412 + PKIX_POLICYCHECKERINITIALIZEFAILED); 1.413 + 1.414 + PKIX_CHECK(pkix_SignatureChecker_Initialize 1.415 + (trustedPubKey, numCerts, &sigChecker, plContext), 1.416 + PKIX_SIGNATURECHECKERINITIALIZEFAILED); 1.417 + 1.418 + if (userCheckersList != NULL) { 1.419 + 1.420 + PKIX_CHECK(PKIX_List_GetLength 1.421 + (userCheckersList, &numCertCheckers, plContext), 1.422 + PKIX_LISTGETLENGTHFAILED); 1.423 + 1.424 + for (i = 0; i < numCertCheckers; i++) { 1.425 + 1.426 + PKIX_CHECK(PKIX_List_GetItem 1.427 + (userCheckersList, 1.428 + i, 1.429 + (PKIX_PL_Object **) &userChecker, 1.430 + plContext), 1.431 + PKIX_LISTGETITEMFAILED); 1.432 + 1.433 + PKIX_CHECK(PKIX_List_AppendItem 1.434 + (checkers, 1.435 + (PKIX_PL_Object *)userChecker, 1.436 + plContext), 1.437 + PKIX_LISTAPPENDITEMFAILED); 1.438 + 1.439 + PKIX_DECREF(userChecker); 1.440 + } 1.441 + } 1.442 + 1.443 + PKIX_CHECK(PKIX_List_AppendItem 1.444 + (checkers, (PKIX_PL_Object *)targetCertChecker, plContext), 1.445 + PKIX_LISTAPPENDITEMFAILED); 1.446 + 1.447 + PKIX_CHECK(PKIX_List_AppendItem 1.448 + (checkers, (PKIX_PL_Object *)expirationChecker, plContext), 1.449 + PKIX_LISTAPPENDITEMFAILED); 1.450 + 1.451 + PKIX_CHECK(PKIX_List_AppendItem 1.452 + (checkers, (PKIX_PL_Object *)nameChainingChecker, plContext), 1.453 + PKIX_LISTAPPENDITEMFAILED); 1.454 + 1.455 + PKIX_CHECK(PKIX_List_AppendItem 1.456 + (checkers, (PKIX_PL_Object *)nameConstraintsChecker, plContext), 1.457 + PKIX_LISTAPPENDITEMFAILED); 1.458 + 1.459 + PKIX_CHECK(PKIX_List_AppendItem 1.460 + (checkers, (PKIX_PL_Object *)basicConstraintsChecker, plContext), 1.461 + PKIX_LISTAPPENDITEMFAILED); 1.462 + 1.463 + PKIX_CHECK(PKIX_List_AppendItem 1.464 + (checkers, (PKIX_PL_Object *)policyChecker, plContext), 1.465 + PKIX_LISTAPPENDITEMFAILED); 1.466 + 1.467 + PKIX_CHECK(PKIX_List_AppendItem 1.468 + (checkers, (PKIX_PL_Object *)sigChecker, plContext), 1.469 + PKIX_LISTAPPENDITEMFAILED); 1.470 + 1.471 + *pCheckers = checkers; 1.472 + 1.473 +cleanup: 1.474 + 1.475 + if (PKIX_ERROR_RECEIVED){ 1.476 + PKIX_DECREF(checkers); 1.477 + } 1.478 + 1.479 + PKIX_DECREF(certSelector); 1.480 + PKIX_DECREF(testDate); 1.481 + PKIX_DECREF(initialPolicies); 1.482 + PKIX_DECREF(targetCertChecker); 1.483 + PKIX_DECREF(expirationChecker); 1.484 + PKIX_DECREF(nameChainingChecker); 1.485 + PKIX_DECREF(nameConstraintsChecker); 1.486 + PKIX_DECREF(basicConstraintsChecker); 1.487 + PKIX_DECREF(policyChecker); 1.488 + PKIX_DECREF(sigChecker); 1.489 + PKIX_DECREF(trustedCAName); 1.490 + PKIX_DECREF(trustedPubKey); 1.491 + PKIX_DECREF(trustedNC); 1.492 + PKIX_DECREF(trustedCert); 1.493 + PKIX_DECREF(defaultCrlChecker); 1.494 + PKIX_DECREF(userCheckersList); 1.495 + PKIX_DECREF(certStores); 1.496 + PKIX_DECREF(userChecker); 1.497 + 1.498 + PKIX_RETURN(VALIDATE); 1.499 +} 1.500 + 1.501 +/* 1.502 + * FUNCTION: pkix_RetrieveOutputs 1.503 + * DESCRIPTION: 1.504 + * 1.505 + * This function queries the respective states of the List of checkers in 1.506 + * "checkers" to to obtain the final public key from the SignatureChecker 1.507 + * and the policy tree from the PolicyChecker, storing those values at 1.508 + * "pFinalSubjPubKey" and "pPolicyTree", respectively. 1.509 + * 1.510 + * PARAMETERS: 1.511 + * "checkers" 1.512 + * Address of List of checkers to be queried. Must be non-NULL. 1.513 + * "pFinalSubjPubKey" 1.514 + * Address where final public key will be stored. Must be non-NULL. 1.515 + * "pPolicyTree" 1.516 + * Address where policy tree will be stored. Must be non-NULL. 1.517 + * "plContext" 1.518 + * Platform-specific context pointer. 1.519 + * THREAD SAFETY: 1.520 + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.521 + * RETURNS: 1.522 + * Returns NULL if the function succeeds. 1.523 + * Returns a Validate Error if the function fails in a non-fatal way. 1.524 + * Returns a Fatal Error if the function fails in an unrecoverable way. 1.525 + */ 1.526 +static PKIX_Error * 1.527 +pkix_RetrieveOutputs( 1.528 + PKIX_List *checkers, 1.529 + PKIX_PL_PublicKey **pFinalSubjPubKey, 1.530 + PKIX_PolicyNode **pPolicyTree, 1.531 + void *plContext) 1.532 +{ 1.533 + PKIX_PL_PublicKey *finalSubjPubKey = NULL; 1.534 + PKIX_PolicyNode *validPolicyTree = NULL; 1.535 + PKIX_CertChainChecker *checker = NULL; 1.536 + PKIX_PL_Object *state = NULL; 1.537 + PKIX_UInt32 numCheckers = 0; 1.538 + PKIX_UInt32 type; 1.539 + PKIX_Int32 j; 1.540 + 1.541 + PKIX_ENTER(VALIDATE, "pkix_RetrieveOutputs"); 1.542 + 1.543 + PKIX_NULLCHECK_TWO(checkers, pPolicyTree); 1.544 + 1.545 + /* 1.546 + * To optimize the search, we guess that the sigChecker is 1.547 + * last in the tree and is preceded by the policyChecker. We 1.548 + * search toward the front of the chain. Remember that List 1.549 + * items are indexed 0..(numItems - 1). 1.550 + */ 1.551 + 1.552 + PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext), 1.553 + PKIX_LISTGETLENGTHFAILED); 1.554 + 1.555 + for (j = numCheckers - 1; j >= 0; j--){ 1.556 + PKIX_CHECK(PKIX_List_GetItem 1.557 + (checkers, j, (PKIX_PL_Object **)&checker, plContext), 1.558 + PKIX_LISTGETITEMFAILED); 1.559 + 1.560 + PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState 1.561 + (checker, &state, plContext), 1.562 + PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); 1.563 + 1.564 + /* user defined checker may have no state */ 1.565 + if (state != NULL) { 1.566 + 1.567 + PKIX_CHECK(PKIX_PL_Object_GetType(state, &type, plContext), 1.568 + PKIX_OBJECTGETTYPEFAILED); 1.569 + 1.570 + if (type == PKIX_SIGNATURECHECKERSTATE_TYPE){ 1.571 + /* final pubKey will include any inherited DSA params */ 1.572 + finalSubjPubKey = 1.573 + ((pkix_SignatureCheckerState *)state)-> 1.574 + prevPublicKey; 1.575 + PKIX_INCREF(finalSubjPubKey); 1.576 + *pFinalSubjPubKey = finalSubjPubKey; 1.577 + } 1.578 + 1.579 + if (type == PKIX_CERTPOLICYCHECKERSTATE_TYPE) { 1.580 + validPolicyTree = 1.581 + ((PKIX_PolicyCheckerState *)state)->validPolicyTree; 1.582 + break; 1.583 + } 1.584 + } 1.585 + 1.586 + PKIX_DECREF(checker); 1.587 + PKIX_DECREF(state); 1.588 + } 1.589 + 1.590 + PKIX_INCREF(validPolicyTree); 1.591 + *pPolicyTree = validPolicyTree; 1.592 + 1.593 +cleanup: 1.594 + 1.595 + PKIX_DECREF(checker); 1.596 + PKIX_DECREF(state); 1.597 + 1.598 + PKIX_RETURN(VALIDATE); 1.599 + 1.600 +} 1.601 + 1.602 +/* 1.603 + * FUNCTION: pkix_CheckChain 1.604 + * DESCRIPTION: 1.605 + * 1.606 + * Checks whether the List of Certs pointed to by "certs", containing 1.607 + * "numCerts" entries, successfully validates using each CertChainChecker in 1.608 + * the List pointed to by "checkers" and has not been revoked, according to any 1.609 + * of the Revocation Checkers in the List pointed to by "revChecker". Checkers 1.610 + * are expected to remove from "removeCheckedExtOIDs" and extensions that they 1.611 + * process. Indices to the certChain and the checkerChain are obtained and 1.612 + * returned in "pCertCheckedIndex" and "pCheckerIndex", respectively. These 1.613 + * should be set to zero prior to the initial call, but may be changed (and 1.614 + * must be supplied on subsequent calls) if processing is suspended for non- 1.615 + * blocking I/O. Each time a Cert passes from being validated by one of the 1.616 + * CertChainCheckers to being checked by a Revocation Checker, the Boolean 1.617 + * stored at "pRevChecking" is changed from FALSE to TRUE. If the Cert is 1.618 + * rejected by a Revocation Checker, its reason code is returned at 1.619 + * "pReasonCode. If the List of Certs successfully validates, the public key i 1.620 + * the final certificate is obtained and stored at "pFinalSubjPubKey" and the 1.621 + * validPolicyTree, which could be NULL, is stored at pPolicyTree. If the List 1.622 + * of Certs fails to validate, an Error pointer is returned. 1.623 + * 1.624 + * If "pVerifyTree" is non-NULL, a chain of VerifyNodes is created which 1.625 + * tracks the results of the validation. That is, either each node in the 1.626 + * chain has a NULL Error component, or the last node contains an Error 1.627 + * which indicates why the validation failed. 1.628 + * 1.629 + * The number of Certs in the List, represented by "numCerts", is used to 1.630 + * determine which Cert is the final Cert. 1.631 + * 1.632 + * PARAMETERS: 1.633 + * "certs" 1.634 + * Address of List of Certs to validate. Must be non-NULL. 1.635 + * "numCerts" 1.636 + * Number of certificates in the List of certificates. 1.637 + * "checkers" 1.638 + * List of CertChainCheckers which must each validate the List of 1.639 + * certificates. Must be non-NULL. 1.640 + * "revChecker" 1.641 + * List of RevocationCheckers which must each not reject the List of 1.642 + * certificates. May be empty, but must be non-NULL. 1.643 + * "removeCheckedExtOIDs" 1.644 + * List of PKIX_PL_OID that has been processed. If called from building 1.645 + * chain, it is the list of critical extension OIDs that has been 1.646 + * processed prior to validation. Extension OIDs that may be processed by 1.647 + * user defined checker processes are also in the list. May be NULL. 1.648 + * "procParams" 1.649 + * Address of ProcessingParams used to initialize various checkers. Must 1.650 + * be non-NULL. 1.651 + * "pCertCheckedIndex" 1.652 + * Address where Int32 index to the Cert chain is obtained and 1.653 + * returned. Must be non-NULL. 1.654 + * "pCheckerIndex" 1.655 + * Address where Int32 index to the CheckerChain is obtained and 1.656 + * returned. Must be non-NULL. 1.657 + * "pRevChecking" 1.658 + * Address where Boolean is obtained and returned, indicating, if FALSE, 1.659 + * that CertChainCheckers are being called; or, if TRUE, that RevChecker 1.660 + * are being called. Must be non-NULL. 1.661 + * "pReasonCode" 1.662 + * Address where UInt32 results of revocation checking are stored. Must be 1.663 + * non-NULL. 1.664 + * "pNBIOContext" 1.665 + * Address where platform-dependent context is stored if checking is 1.666 + * suspended for non-blocking I/O. Must be non-NULL. 1.667 + * "pFinalSubjPubKey" 1.668 + * Address where the final public key will be stored. Must be non-NULL. 1.669 + * "pPolicyTree" 1.670 + * Address where the final validPolicyTree is stored. Must be non-NULL. 1.671 + * "pVerifyTree" 1.672 + * Address where a VerifyTree is stored, if non-NULL. 1.673 + * "plContext" 1.674 + * Platform-specific context pointer. 1.675 + * THREAD SAFETY: 1.676 + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.677 + * RETURNS: 1.678 + * Returns NULL if the function succeeds. 1.679 + * Returns a Validate Error if the function fails in a non-fatal way. 1.680 + * Returns a Fatal Error if the function fails in an unrecoverable way. 1.681 + */ 1.682 +PKIX_Error * 1.683 +pkix_CheckChain( 1.684 + PKIX_List *certs, 1.685 + PKIX_UInt32 numCerts, 1.686 + PKIX_TrustAnchor *anchor, 1.687 + PKIX_List *checkers, 1.688 + PKIX_RevocationChecker *revChecker, 1.689 + PKIX_List *removeCheckedExtOIDs, 1.690 + PKIX_ProcessingParams *procParams, 1.691 + PKIX_UInt32 *pCertCheckedIndex, 1.692 + PKIX_UInt32 *pCheckerIndex, 1.693 + PKIX_Boolean *pRevChecking, 1.694 + PKIX_UInt32 *pReasonCode, 1.695 + void **pNBIOContext, 1.696 + PKIX_PL_PublicKey **pFinalSubjPubKey, 1.697 + PKIX_PolicyNode **pPolicyTree, 1.698 + PKIX_VerifyNode **pVerifyTree, 1.699 + void *plContext) 1.700 +{ 1.701 + PKIX_UInt32 j = 0; 1.702 + PKIX_Boolean revChecking = PKIX_FALSE; 1.703 + PKIX_Error *checkCertError = NULL; 1.704 + void *nbioContext = NULL; 1.705 + PKIX_PL_Cert *cert = NULL; 1.706 + PKIX_PL_Cert *issuer = NULL; 1.707 + PKIX_PL_NssContext *nssContext = NULL; 1.708 + CERTCertList *certList = NULL; 1.709 + const CERTChainVerifyCallback *chainVerifyCallback = NULL; 1.710 + CERTCertificate *nssCert = NULL; 1.711 + 1.712 + PKIX_ENTER(VALIDATE, "pkix_CheckChain"); 1.713 + PKIX_NULLCHECK_FOUR(certs, checkers, revChecker, pCertCheckedIndex); 1.714 + PKIX_NULLCHECK_FOUR(pCheckerIndex, pRevChecking, pReasonCode, anchor); 1.715 + PKIX_NULLCHECK_THREE(pNBIOContext, pFinalSubjPubKey, pPolicyTree); 1.716 + 1.717 + nbioContext = *pNBIOContext; 1.718 + *pNBIOContext = NULL; 1.719 + revChecking = *pRevChecking; 1.720 + nssContext = (PKIX_PL_NssContext *)plContext; 1.721 + chainVerifyCallback = &nssContext->chainVerifyCallback; 1.722 + 1.723 + if (chainVerifyCallback->isChainValid != NULL) { 1.724 + PRBool chainOK = PR_FALSE; /*assume failure*/ 1.725 + SECStatus rv; 1.726 + 1.727 + certList = CERT_NewCertList(); 1.728 + if (certList == NULL) { 1.729 + PKIX_ERROR_ALLOC_ERROR(); 1.730 + } 1.731 + 1.732 + /* Add the trust anchor to the list */ 1.733 + PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert 1.734 + (anchor, &cert, plContext), 1.735 + PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); 1.736 + 1.737 + PKIX_CHECK( 1.738 + PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext), 1.739 + PKIX_CERTGETCERTCERTIFICATEFAILED); 1.740 + 1.741 + rv = CERT_AddCertToListHead(certList, nssCert); 1.742 + if (rv != SECSuccess) { 1.743 + PKIX_ERROR_ALLOC_ERROR(); 1.744 + } 1.745 + /* the certList takes ownership of nssCert on success */ 1.746 + nssCert = NULL; 1.747 + PKIX_DECREF(cert); 1.748 + 1.749 + /* Add the rest of the chain to the list */ 1.750 + for (j = *pCertCheckedIndex; j < numCerts; j++) { 1.751 + PKIX_CHECK(PKIX_List_GetItem( 1.752 + certs, j, (PKIX_PL_Object **)&cert, plContext), 1.753 + PKIX_LISTGETITEMFAILED); 1.754 + 1.755 + PKIX_CHECK( 1.756 + PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext), 1.757 + PKIX_CERTGETCERTCERTIFICATEFAILED); 1.758 + 1.759 + rv = CERT_AddCertToListHead(certList, nssCert); 1.760 + if (rv != SECSuccess) { 1.761 + PKIX_ERROR_ALLOC_ERROR(); 1.762 + } 1.763 + /* the certList takes ownership of nssCert on success */ 1.764 + nssCert = NULL; 1.765 + PKIX_DECREF(cert); 1.766 + } 1.767 + 1.768 + rv = (*chainVerifyCallback->isChainValid) 1.769 + (chainVerifyCallback->isChainValidArg, certList, &chainOK); 1.770 + if (rv != SECSuccess) { 1.771 + PKIX_ERROR_FATAL(PKIX_CHAINVERIFYCALLBACKFAILED); 1.772 + } 1.773 + 1.774 + if (!chainOK) { 1.775 + PKIX_ERROR(PKIX_CHAINVERIFYCALLBACKFAILED); 1.776 + } 1.777 + 1.778 + } 1.779 + 1.780 + PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert 1.781 + (anchor, &cert, plContext), 1.782 + PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); 1.783 + 1.784 + for (j = *pCertCheckedIndex; j < numCerts; j++) { 1.785 + 1.786 + PORT_Assert(cert); 1.787 + PKIX_DECREF(issuer); 1.788 + issuer = cert; 1.789 + cert = NULL; 1.790 + 1.791 + PKIX_CHECK(PKIX_List_GetItem( 1.792 + certs, j, (PKIX_PL_Object **)&cert, plContext), 1.793 + PKIX_LISTGETITEMFAILED); 1.794 + 1.795 + /* check if cert pointer is valid */ 1.796 + PORT_Assert(cert); 1.797 + if (cert == NULL) { 1.798 + continue; 1.799 + } 1.800 + 1.801 + if (revChecking == PKIX_FALSE) { 1.802 + 1.803 + PKIX_CHECK(pkix_CheckCert 1.804 + (cert, 1.805 + checkers, 1.806 + removeCheckedExtOIDs, 1.807 + pCheckerIndex, 1.808 + &nbioContext, 1.809 + plContext), 1.810 + PKIX_CHECKCERTFAILED); 1.811 + 1.812 + if (nbioContext != NULL) { 1.813 + *pCertCheckedIndex = j; 1.814 + *pRevChecking = revChecking; 1.815 + *pNBIOContext = nbioContext; 1.816 + goto cleanup; 1.817 + } 1.818 + 1.819 + revChecking = PKIX_TRUE; 1.820 + *pCheckerIndex = 0; 1.821 + } 1.822 + 1.823 + if (revChecking == PKIX_TRUE) { 1.824 + PKIX_RevocationStatus revStatus; 1.825 + pkixErrorResult = 1.826 + PKIX_RevocationChecker_Check( 1.827 + cert, issuer, revChecker, 1.828 + procParams, PKIX_TRUE, 1.829 + (j == numCerts - 1) ? PKIX_TRUE : PKIX_FALSE, 1.830 + &revStatus, pReasonCode, 1.831 + &nbioContext, plContext); 1.832 + if (nbioContext != NULL) { 1.833 + *pCertCheckedIndex = j; 1.834 + *pRevChecking = revChecking; 1.835 + *pNBIOContext = nbioContext; 1.836 + goto cleanup; 1.837 + } 1.838 + if (revStatus == PKIX_RevStatus_Revoked || 1.839 + pkixErrorResult) { 1.840 + if (!pkixErrorResult) { 1.841 + /* if pkixErrorResult is returned then 1.842 + * use it as it has a detailed revocation 1.843 + * error code. Otherwise create a new error */ 1.844 + PKIX_ERROR_CREATE(VALIDATE, 1.845 + PKIX_CERTIFICATEREVOKED, 1.846 + pkixErrorResult); 1.847 + } 1.848 + goto cleanup; 1.849 + } 1.850 + revChecking = PKIX_FALSE; 1.851 + *pCheckerIndex = 0; 1.852 + } 1.853 + 1.854 + PKIX_CHECK(pkix_AddToVerifyLog 1.855 + (cert, j, NULL, pVerifyTree, plContext), 1.856 + PKIX_ADDTOVERIFYLOGFAILED); 1.857 + } 1.858 + 1.859 + PKIX_CHECK(pkix_RetrieveOutputs 1.860 + (checkers, pFinalSubjPubKey, pPolicyTree, plContext), 1.861 + PKIX_RETRIEVEOUTPUTSFAILED); 1.862 + 1.863 + *pNBIOContext = NULL; 1.864 + 1.865 +cleanup: 1.866 + if (PKIX_ERROR_RECEIVED && cert) { 1.867 + checkCertError = pkixErrorResult; 1.868 + 1.869 + PKIX_CHECK_FATAL( 1.870 + pkix_AddToVerifyLog(cert, j, checkCertError, pVerifyTree, 1.871 + plContext), 1.872 + PKIX_ADDTOVERIFYLOGFAILED); 1.873 + pkixErrorResult = checkCertError; 1.874 + pkixErrorCode = pkixErrorResult->errCode; 1.875 + checkCertError = NULL; 1.876 + } 1.877 + 1.878 +fatal: 1.879 + if (nssCert) { 1.880 + CERT_DestroyCertificate(nssCert); 1.881 + } 1.882 + 1.883 + if (certList) { 1.884 + CERT_DestroyCertList(certList); 1.885 + } 1.886 + 1.887 + PKIX_DECREF(checkCertError); 1.888 + PKIX_DECREF(cert); 1.889 + PKIX_DECREF(issuer); 1.890 + 1.891 + PKIX_RETURN(VALIDATE); 1.892 +} 1.893 + 1.894 +/* 1.895 + * FUNCTION: pkix_ExtractParameters 1.896 + * DESCRIPTION: 1.897 + * 1.898 + * Extracts several parameters from the ValidateParams object pointed to by 1.899 + * "valParams" and stores the CertChain at "pChain", the List of Certs at 1.900 + * "pCerts", the number of Certs in the chain at "pNumCerts", the 1.901 + * ProcessingParams object at "pProcParams", the List of TrustAnchors at 1.902 + * "pAnchors", and the number of TrustAnchors at "pNumAnchors". 1.903 + * 1.904 + * PARAMETERS: 1.905 + * "valParams" 1.906 + * Address of ValidateParams from which the parameters are extracted. 1.907 + * Must be non-NULL. 1.908 + * "pCerts" 1.909 + * Address where object pointer for List of Certs will be stored. 1.910 + * Must be non-NULL. 1.911 + * "pNumCerts" 1.912 + * Address where number of Certs will be stored. Must be non-NULL. 1.913 + * "pProcParams" 1.914 + * Address where object pointer for ProcessingParams will be stored. 1.915 + * Must be non-NULL. 1.916 + * "pAnchors" 1.917 + * Address where object pointer for List of Anchors will be stored. 1.918 + * Must be non-NULL. 1.919 + * "pNumAnchors" 1.920 + * Address where number of Anchors will be stored. Must be non-NULL. 1.921 + * "plContext" 1.922 + * Platform-specific context pointer. 1.923 + * THREAD SAFETY: 1.924 + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.925 + * RETURNS: 1.926 + * Returns NULL if the function succeeds. 1.927 + * Returns a Validate Error if the function fails in a non-fatal way. 1.928 + * Returns a Fatal Error if the function fails in an unrecoverable way. 1.929 + */ 1.930 +static PKIX_Error * 1.931 +pkix_ExtractParameters( 1.932 + PKIX_ValidateParams *valParams, 1.933 + PKIX_List **pCerts, 1.934 + PKIX_UInt32 *pNumCerts, 1.935 + PKIX_ProcessingParams **pProcParams, 1.936 + PKIX_List **pAnchors, 1.937 + PKIX_UInt32 *pNumAnchors, 1.938 + void *plContext) 1.939 +{ 1.940 + PKIX_ENTER(VALIDATE, "pkix_ExtractParameters"); 1.941 + PKIX_NULLCHECK_THREE(valParams, pCerts, pNumCerts); 1.942 + PKIX_NULLCHECK_THREE(pProcParams, pAnchors, pNumAnchors); 1.943 + 1.944 + /* extract relevant parameters from chain */ 1.945 + PKIX_CHECK(PKIX_ValidateParams_GetCertChain 1.946 + (valParams, pCerts, plContext), 1.947 + PKIX_VALIDATEPARAMSGETCERTCHAINFAILED); 1.948 + 1.949 + PKIX_CHECK(PKIX_List_GetLength(*pCerts, pNumCerts, plContext), 1.950 + PKIX_LISTGETLENGTHFAILED); 1.951 + 1.952 + /* extract relevant parameters from procParams */ 1.953 + PKIX_CHECK(PKIX_ValidateParams_GetProcessingParams 1.954 + (valParams, pProcParams, plContext), 1.955 + PKIX_VALIDATEPARAMSGETPROCESSINGPARAMSFAILED); 1.956 + 1.957 + PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors 1.958 + (*pProcParams, pAnchors, plContext), 1.959 + PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED); 1.960 + 1.961 + PKIX_CHECK(PKIX_List_GetLength(*pAnchors, pNumAnchors, plContext), 1.962 + PKIX_LISTGETLENGTHFAILED); 1.963 + 1.964 +cleanup: 1.965 + 1.966 + PKIX_RETURN(VALIDATE); 1.967 +} 1.968 + 1.969 +/* --Public-Functions--------------------------------------------- */ 1.970 + 1.971 +/* 1.972 + * FUNCTION: PKIX_ValidateChain (see comments in pkix.h) 1.973 + */ 1.974 +PKIX_Error * 1.975 +PKIX_ValidateChain( 1.976 + PKIX_ValidateParams *valParams, 1.977 + PKIX_ValidateResult **pResult, 1.978 + PKIX_VerifyNode **pVerifyTree, 1.979 + void *plContext) 1.980 +{ 1.981 + PKIX_Error *chainFailed = NULL; 1.982 + 1.983 + PKIX_ProcessingParams *procParams = NULL; 1.984 + PKIX_CertChainChecker *userChecker = NULL; 1.985 + PKIX_RevocationChecker *revChecker = NULL; 1.986 + PKIX_List *certs = NULL; 1.987 + PKIX_List *checkers = NULL; 1.988 + PKIX_List *anchors = NULL; 1.989 + PKIX_List *userCheckers = NULL; 1.990 + PKIX_List *userCheckerExtOIDs = NULL; 1.991 + PKIX_List *validateCheckedCritExtOIDsList = NULL; 1.992 + PKIX_TrustAnchor *anchor = NULL; 1.993 + PKIX_ValidateResult *valResult = NULL; 1.994 + PKIX_PL_PublicKey *finalPubKey = NULL; 1.995 + PKIX_PolicyNode *validPolicyTree = NULL; 1.996 + PKIX_Boolean supportForwarding = PKIX_FALSE; 1.997 + PKIX_Boolean revChecking = PKIX_FALSE; 1.998 + PKIX_UInt32 i, numCerts, numAnchors; 1.999 + PKIX_UInt32 numUserCheckers = 0; 1.1000 + PKIX_UInt32 certCheckedIndex = 0; 1.1001 + PKIX_UInt32 checkerIndex = 0; 1.1002 + PKIX_UInt32 reasonCode = 0; 1.1003 + void *nbioContext = NULL; 1.1004 + 1.1005 + PKIX_ENTER(VALIDATE, "PKIX_ValidateChain"); 1.1006 + PKIX_NULLCHECK_TWO(valParams, pResult); 1.1007 + 1.1008 + /* extract various parameters from valParams */ 1.1009 + PKIX_CHECK(pkix_ExtractParameters 1.1010 + (valParams, 1.1011 + &certs, 1.1012 + &numCerts, 1.1013 + &procParams, 1.1014 + &anchors, 1.1015 + &numAnchors, 1.1016 + plContext), 1.1017 + PKIX_EXTRACTPARAMETERSFAILED); 1.1018 + 1.1019 + /* 1.1020 + * setup an extension OID list that user had defined for his checker 1.1021 + * processing. User checker is not responsible for taking out OIDs 1.1022 + * from unresolved critical extension list as the libpkix checker 1.1023 + * is doing. Here we add those user checkers' OIDs to the removal 1.1024 + * list to be taken out by CheckChain 1.1025 + */ 1.1026 + PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers 1.1027 + (procParams, &userCheckers, plContext), 1.1028 + PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); 1.1029 + 1.1030 + if (userCheckers != NULL) { 1.1031 + 1.1032 + PKIX_CHECK(PKIX_List_Create 1.1033 + (&validateCheckedCritExtOIDsList, 1.1034 + plContext), 1.1035 + PKIX_LISTCREATEFAILED); 1.1036 + 1.1037 + PKIX_CHECK(PKIX_List_GetLength 1.1038 + (userCheckers, &numUserCheckers, plContext), 1.1039 + PKIX_LISTGETLENGTHFAILED); 1.1040 + 1.1041 + for (i = 0; i < numUserCheckers; i++) { 1.1042 + 1.1043 + PKIX_CHECK(PKIX_List_GetItem 1.1044 + (userCheckers, 1.1045 + i, 1.1046 + (PKIX_PL_Object **) &userChecker, 1.1047 + plContext), 1.1048 + PKIX_LISTGETITEMFAILED); 1.1049 + 1.1050 + PKIX_CHECK 1.1051 + (PKIX_CertChainChecker_IsForwardCheckingSupported 1.1052 + (userChecker, &supportForwarding, plContext), 1.1053 + PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED); 1.1054 + 1.1055 + if (supportForwarding == PKIX_FALSE) { 1.1056 + 1.1057 + PKIX_CHECK 1.1058 + (PKIX_CertChainChecker_GetSupportedExtensions 1.1059 + (userChecker, &userCheckerExtOIDs, plContext), 1.1060 + PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); 1.1061 + 1.1062 + if (userCheckerExtOIDs != NULL) { 1.1063 + PKIX_CHECK(pkix_List_AppendList 1.1064 + (validateCheckedCritExtOIDsList, 1.1065 + userCheckerExtOIDs, 1.1066 + plContext), 1.1067 + PKIX_LISTAPPENDLISTFAILED); 1.1068 + } 1.1069 + } 1.1070 + 1.1071 + PKIX_DECREF(userCheckerExtOIDs); 1.1072 + PKIX_DECREF(userChecker); 1.1073 + } 1.1074 + } 1.1075 + 1.1076 + PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker 1.1077 + (procParams, &revChecker, plContext), 1.1078 + PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED); 1.1079 + 1.1080 + /* try to validate the chain with each anchor */ 1.1081 + for (i = 0; i < numAnchors; i++){ 1.1082 + 1.1083 + /* get trust anchor */ 1.1084 + PKIX_CHECK(PKIX_List_GetItem 1.1085 + (anchors, i, (PKIX_PL_Object **)&anchor, plContext), 1.1086 + PKIX_LISTGETITEMFAILED); 1.1087 + 1.1088 + /* initialize checkers using information from trust anchor */ 1.1089 + PKIX_CHECK(pkix_InitializeCheckers 1.1090 + (anchor, procParams, numCerts, &checkers, plContext), 1.1091 + PKIX_INITIALIZECHECKERSFAILED); 1.1092 + 1.1093 + /* 1.1094 + * Validate the chain using this trust anchor and these 1.1095 + * checkers. (WARNING: checkers that use non-blocking I/O 1.1096 + * are not currently supported.) 1.1097 + */ 1.1098 + certCheckedIndex = 0; 1.1099 + checkerIndex = 0; 1.1100 + revChecking = PKIX_FALSE; 1.1101 + chainFailed = pkix_CheckChain 1.1102 + (certs, 1.1103 + numCerts, 1.1104 + anchor, 1.1105 + checkers, 1.1106 + revChecker, 1.1107 + validateCheckedCritExtOIDsList, 1.1108 + procParams, 1.1109 + &certCheckedIndex, 1.1110 + &checkerIndex, 1.1111 + &revChecking, 1.1112 + &reasonCode, 1.1113 + &nbioContext, 1.1114 + &finalPubKey, 1.1115 + &validPolicyTree, 1.1116 + pVerifyTree, 1.1117 + plContext); 1.1118 + 1.1119 + if (chainFailed) { 1.1120 + 1.1121 + /* cert chain failed to validate */ 1.1122 + 1.1123 + PKIX_DECREF(chainFailed); 1.1124 + PKIX_DECREF(anchor); 1.1125 + PKIX_DECREF(checkers); 1.1126 + PKIX_DECREF(validPolicyTree); 1.1127 + 1.1128 + /* if last anchor, we fail; else, we try next anchor */ 1.1129 + if (i == (numAnchors - 1)) { /* last anchor */ 1.1130 + PKIX_ERROR(PKIX_VALIDATECHAINFAILED); 1.1131 + } 1.1132 + 1.1133 + } else { 1.1134 + 1.1135 + /* XXX Remove this assertion after 2014-12-31. 1.1136 + * See bug 946984. */ 1.1137 + PORT_Assert(reasonCode == 0); 1.1138 + 1.1139 + /* cert chain successfully validated! */ 1.1140 + PKIX_CHECK(pkix_ValidateResult_Create 1.1141 + (finalPubKey, 1.1142 + anchor, 1.1143 + validPolicyTree, 1.1144 + &valResult, 1.1145 + plContext), 1.1146 + PKIX_VALIDATERESULTCREATEFAILED); 1.1147 + 1.1148 + *pResult = valResult; 1.1149 + 1.1150 + /* no need to try any more anchors in the loop */ 1.1151 + goto cleanup; 1.1152 + } 1.1153 + } 1.1154 + 1.1155 +cleanup: 1.1156 + 1.1157 + PKIX_DECREF(finalPubKey); 1.1158 + PKIX_DECREF(certs); 1.1159 + PKIX_DECREF(anchors); 1.1160 + PKIX_DECREF(anchor); 1.1161 + PKIX_DECREF(checkers); 1.1162 + PKIX_DECREF(revChecker); 1.1163 + PKIX_DECREF(validPolicyTree); 1.1164 + PKIX_DECREF(chainFailed); 1.1165 + PKIX_DECREF(procParams); 1.1166 + PKIX_DECREF(userCheckers); 1.1167 + PKIX_DECREF(validateCheckedCritExtOIDsList); 1.1168 + 1.1169 + PKIX_RETURN(VALIDATE); 1.1170 +} 1.1171 + 1.1172 +/* 1.1173 + * FUNCTION: pkix_Validate_BuildUserOIDs 1.1174 + * DESCRIPTION: 1.1175 + * 1.1176 + * This function creates a List of the OIDs that are processed by the user 1.1177 + * checkers in the List pointed to by "userCheckers", storing the resulting 1.1178 + * List at "pUserCritOIDs". If the List of userCheckers is NULL, the output 1.1179 + * List will be NULL. Otherwise the output List will be non-NULL, but may be 1.1180 + * empty. 1.1181 + * 1.1182 + * PARAMETERS: 1.1183 + * "userCheckers" 1.1184 + * The address of the List of userCheckers. 1.1185 + * "pUserCritOIDs" 1.1186 + * The address at which the List is stored. Must be non-NULL. 1.1187 + * "plContext" 1.1188 + * Platform-specific context pointer. 1.1189 + * THREAD SAFETY: 1.1190 + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.1191 + * RETURNS: 1.1192 + * Returns NULL if the function succeeds. 1.1193 + * Returns a VALIDATE Error if the function fails in a non-fatal way. 1.1194 + * Returns a Fatal Error if the function fails in an unrecoverable way. 1.1195 + */ 1.1196 +static PKIX_Error * 1.1197 +pkix_Validate_BuildUserOIDs( 1.1198 + PKIX_List *userCheckers, 1.1199 + PKIX_List **pUserCritOIDs, 1.1200 + void *plContext) 1.1201 +{ 1.1202 + PKIX_UInt32 numUserCheckers = 0; 1.1203 + PKIX_UInt32 i = 0; 1.1204 + PKIX_List *userCritOIDs = NULL; 1.1205 + PKIX_List *userCheckerExtOIDs = NULL; 1.1206 + PKIX_Boolean supportForwarding = PKIX_FALSE; 1.1207 + PKIX_CertChainChecker *userChecker = NULL; 1.1208 + 1.1209 + PKIX_ENTER(VALIDATE, "pkix_Validate_BuildUserOIDs"); 1.1210 + PKIX_NULLCHECK_ONE(pUserCritOIDs); 1.1211 + 1.1212 + if (userCheckers != NULL) { 1.1213 + PKIX_CHECK(PKIX_List_Create(&userCritOIDs, plContext), 1.1214 + PKIX_LISTCREATEFAILED); 1.1215 + 1.1216 + PKIX_CHECK(PKIX_List_GetLength 1.1217 + (userCheckers, &numUserCheckers, plContext), 1.1218 + PKIX_LISTGETLENGTHFAILED); 1.1219 + 1.1220 + for (i = 0; i < numUserCheckers; i++) { 1.1221 + PKIX_CHECK(PKIX_List_GetItem 1.1222 + (userCheckers, 1.1223 + i, 1.1224 + (PKIX_PL_Object **) &userChecker, 1.1225 + plContext), 1.1226 + PKIX_LISTGETITEMFAILED); 1.1227 + 1.1228 + PKIX_CHECK(PKIX_CertChainChecker_IsForwardCheckingSupported 1.1229 + (userChecker, &supportForwarding, plContext), 1.1230 + PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED); 1.1231 + 1.1232 + if (supportForwarding == PKIX_FALSE) { 1.1233 + 1.1234 + PKIX_CHECK(PKIX_CertChainChecker_GetSupportedExtensions 1.1235 + (userChecker, &userCheckerExtOIDs, plContext), 1.1236 + PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); 1.1237 + 1.1238 + if (userCheckerExtOIDs != NULL) { 1.1239 + PKIX_CHECK(pkix_List_AppendList 1.1240 + (userCritOIDs, userCheckerExtOIDs, plContext), 1.1241 + PKIX_LISTAPPENDLISTFAILED); 1.1242 + } 1.1243 + } 1.1244 + 1.1245 + PKIX_DECREF(userCheckerExtOIDs); 1.1246 + PKIX_DECREF(userChecker); 1.1247 + } 1.1248 + } 1.1249 + 1.1250 + *pUserCritOIDs = userCritOIDs; 1.1251 + 1.1252 +cleanup: 1.1253 + 1.1254 + if (PKIX_ERROR_RECEIVED){ 1.1255 + PKIX_DECREF(userCritOIDs); 1.1256 + } 1.1257 + 1.1258 + PKIX_DECREF(userCheckerExtOIDs); 1.1259 + PKIX_DECREF(userChecker); 1.1260 + 1.1261 + PKIX_RETURN(VALIDATE); 1.1262 +} 1.1263 + 1.1264 +/* 1.1265 + * FUNCTION: PKIX_ValidateChain_nb (see comments in pkix.h) 1.1266 + */ 1.1267 +PKIX_Error * 1.1268 +PKIX_ValidateChain_NB( 1.1269 + PKIX_ValidateParams *valParams, 1.1270 + PKIX_UInt32 *pCertIndex, 1.1271 + PKIX_UInt32 *pAnchorIndex, 1.1272 + PKIX_UInt32 *pCheckerIndex, 1.1273 + PKIX_Boolean *pRevChecking, 1.1274 + PKIX_List **pCheckers, 1.1275 + void **pNBIOContext, 1.1276 + PKIX_ValidateResult **pResult, 1.1277 + PKIX_VerifyNode **pVerifyTree, 1.1278 + void *plContext) 1.1279 +{ 1.1280 + PKIX_UInt32 numCerts = 0; 1.1281 + PKIX_UInt32 numAnchors = 0; 1.1282 + PKIX_UInt32 i = 0; 1.1283 + PKIX_UInt32 certIndex = 0; 1.1284 + PKIX_UInt32 anchorIndex = 0; 1.1285 + PKIX_UInt32 checkerIndex = 0; 1.1286 + PKIX_UInt32 reasonCode = 0; 1.1287 + PKIX_Boolean revChecking = PKIX_FALSE; 1.1288 + PKIX_List *certs = NULL; 1.1289 + PKIX_List *anchors = NULL; 1.1290 + PKIX_List *checkers = NULL; 1.1291 + PKIX_List *userCheckers = NULL; 1.1292 + PKIX_List *validateCheckedCritExtOIDsList = NULL; 1.1293 + PKIX_TrustAnchor *anchor = NULL; 1.1294 + PKIX_ValidateResult *valResult = NULL; 1.1295 + PKIX_PL_PublicKey *finalPubKey = NULL; 1.1296 + PKIX_PolicyNode *validPolicyTree = NULL; 1.1297 + PKIX_ProcessingParams *procParams = NULL; 1.1298 + PKIX_RevocationChecker *revChecker = NULL; 1.1299 + PKIX_Error *chainFailed = NULL; 1.1300 + void *nbioContext = NULL; 1.1301 + 1.1302 + PKIX_ENTER(VALIDATE, "PKIX_ValidateChain_NB"); 1.1303 + PKIX_NULLCHECK_FOUR 1.1304 + (valParams, pCertIndex, pAnchorIndex, pCheckerIndex); 1.1305 + PKIX_NULLCHECK_FOUR(pRevChecking, pCheckers, pNBIOContext, pResult); 1.1306 + 1.1307 + nbioContext = *pNBIOContext; 1.1308 + *pNBIOContext = NULL; 1.1309 + 1.1310 + /* extract various parameters from valParams */ 1.1311 + PKIX_CHECK(pkix_ExtractParameters 1.1312 + (valParams, 1.1313 + &certs, 1.1314 + &numCerts, 1.1315 + &procParams, 1.1316 + &anchors, 1.1317 + &numAnchors, 1.1318 + plContext), 1.1319 + PKIX_EXTRACTPARAMETERSFAILED); 1.1320 + 1.1321 + /* 1.1322 + * Create a List of the OIDs that will be processed by the user 1.1323 + * checkers. User checkers are not responsible for removing OIDs from 1.1324 + * the List of unresolved critical extensions, as libpkix checkers are. 1.1325 + * So we add those user checkers' OIDs to the removal list to be taken 1.1326 + * out by CheckChain. 1.1327 + */ 1.1328 + PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers 1.1329 + (procParams, &userCheckers, plContext), 1.1330 + PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); 1.1331 + 1.1332 + PKIX_CHECK(pkix_Validate_BuildUserOIDs 1.1333 + (userCheckers, &validateCheckedCritExtOIDsList, plContext), 1.1334 + PKIX_VALIDATEBUILDUSEROIDSFAILED); 1.1335 + 1.1336 + PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker 1.1337 + (procParams, &revChecker, plContext), 1.1338 + PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED); 1.1339 + 1.1340 + /* Are we resuming after a WOULDBLOCK return, or starting anew ? */ 1.1341 + if (nbioContext != NULL) { 1.1342 + /* Resuming */ 1.1343 + certIndex = *pCertIndex; 1.1344 + anchorIndex = *pAnchorIndex; 1.1345 + checkerIndex = *pCheckerIndex; 1.1346 + revChecking = *pRevChecking; 1.1347 + checkers = *pCheckers; 1.1348 + *pCheckers = NULL; 1.1349 + } 1.1350 + 1.1351 + /* try to validate the chain with each anchor */ 1.1352 + for (i = anchorIndex; i < numAnchors; i++) { 1.1353 + 1.1354 + /* get trust anchor */ 1.1355 + PKIX_CHECK(PKIX_List_GetItem 1.1356 + (anchors, i, (PKIX_PL_Object **)&anchor, plContext), 1.1357 + PKIX_LISTGETITEMFAILED); 1.1358 + 1.1359 + /* initialize checkers using information from trust anchor */ 1.1360 + if (nbioContext == NULL) { 1.1361 + PKIX_CHECK(pkix_InitializeCheckers 1.1362 + (anchor, 1.1363 + procParams, 1.1364 + numCerts, 1.1365 + &checkers, 1.1366 + plContext), 1.1367 + PKIX_INITIALIZECHECKERSFAILED); 1.1368 + } 1.1369 + 1.1370 + /* 1.1371 + * Validate the chain using this trust anchor and these 1.1372 + * checkers. 1.1373 + */ 1.1374 + chainFailed = pkix_CheckChain 1.1375 + (certs, 1.1376 + numCerts, 1.1377 + anchor, 1.1378 + checkers, 1.1379 + revChecker, 1.1380 + validateCheckedCritExtOIDsList, 1.1381 + procParams, 1.1382 + &certIndex, 1.1383 + &checkerIndex, 1.1384 + &revChecking, 1.1385 + &reasonCode, 1.1386 + &nbioContext, 1.1387 + &finalPubKey, 1.1388 + &validPolicyTree, 1.1389 + pVerifyTree, 1.1390 + plContext); 1.1391 + 1.1392 + if (nbioContext != NULL) { 1.1393 + *pCertIndex = certIndex; 1.1394 + *pAnchorIndex = anchorIndex; 1.1395 + *pCheckerIndex = checkerIndex; 1.1396 + *pRevChecking = revChecking; 1.1397 + PKIX_INCREF(checkers); 1.1398 + *pCheckers = checkers; 1.1399 + *pNBIOContext = nbioContext; 1.1400 + goto cleanup; 1.1401 + } 1.1402 + 1.1403 + if (chainFailed) { 1.1404 + 1.1405 + /* cert chain failed to validate */ 1.1406 + 1.1407 + PKIX_DECREF(chainFailed); 1.1408 + PKIX_DECREF(anchor); 1.1409 + PKIX_DECREF(checkers); 1.1410 + PKIX_DECREF(validPolicyTree); 1.1411 + 1.1412 + /* if last anchor, we fail; else, we try next anchor */ 1.1413 + if (i == (numAnchors - 1)) { /* last anchor */ 1.1414 + PKIX_ERROR(PKIX_VALIDATECHAINFAILED); 1.1415 + } 1.1416 + 1.1417 + } else { 1.1418 + 1.1419 + /* XXX Remove this assertion after 2014-12-31. 1.1420 + * See bug 946984. */ 1.1421 + PORT_Assert(reasonCode == 0); 1.1422 + 1.1423 + /* cert chain successfully validated! */ 1.1424 + PKIX_CHECK(pkix_ValidateResult_Create 1.1425 + (finalPubKey, 1.1426 + anchor, 1.1427 + validPolicyTree, 1.1428 + &valResult, 1.1429 + plContext), 1.1430 + PKIX_VALIDATERESULTCREATEFAILED); 1.1431 + 1.1432 + *pResult = valResult; 1.1433 + 1.1434 + /* no need to try any more anchors in the loop */ 1.1435 + goto cleanup; 1.1436 + } 1.1437 + } 1.1438 + 1.1439 +cleanup: 1.1440 + 1.1441 + PKIX_DECREF(finalPubKey); 1.1442 + PKIX_DECREF(certs); 1.1443 + PKIX_DECREF(anchors); 1.1444 + PKIX_DECREF(anchor); 1.1445 + PKIX_DECREF(checkers); 1.1446 + PKIX_DECREF(revChecker); 1.1447 + PKIX_DECREF(validPolicyTree); 1.1448 + PKIX_DECREF(chainFailed); 1.1449 + PKIX_DECREF(procParams); 1.1450 + PKIX_DECREF(userCheckers); 1.1451 + PKIX_DECREF(validateCheckedCritExtOIDsList); 1.1452 + 1.1453 + PKIX_RETURN(VALIDATE); 1.1454 +}