| OLD | NEW |
| (Empty) | |
| 1 /* ***** BEGIN LICENSE BLOCK ***** |
| 2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 3 * |
| 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/ |
| 8 * |
| 9 * Software distributed under the License is distributed on an "AS IS" basis, |
| 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 11 * for the specific language governing rights and limitations under the |
| 12 * License. |
| 13 * |
| 14 * The Original Code is the PKIX-C library. |
| 15 * |
| 16 * The Initial Developer of the Original Code is |
| 17 * Sun Microsystems, Inc. |
| 18 * Portions created by the Initial Developer are |
| 19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved. |
| 20 * |
| 21 * Contributor(s): |
| 22 * Sun Microsystems, Inc. |
| 23 * |
| 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. |
| 35 * |
| 36 * ***** END LICENSE BLOCK ***** */ |
| 37 /* |
| 38 * pkix_validate.c |
| 39 * |
| 40 * Top level validateChain function |
| 41 * |
| 42 */ |
| 43 |
| 44 #include "pkix_validate.h" |
| 45 |
| 46 /* --Private-Functions-------------------------------------------- */ |
| 47 |
| 48 /* |
| 49 * FUNCTION: pkix_AddToVerifyLog |
| 50 * DESCRIPTION: |
| 51 * |
| 52 * This function returns immediately if the address for the VerifyNode tree |
| 53 * pointed to by "pVerifyTree" is NULL. Otherwise it creates a new VerifyNode |
| 54 * from the Cert pointed to by "cert" and the Error pointed to by "error", |
| 55 * and inserts it at the depth in the VerifyNode tree determined by "depth". A |
| 56 * depth of zero means that this function creates the root node of a new tree. |
| 57 * |
| 58 * Note: this function does not include the means of choosing among branches |
| 59 * of a tree. It is intended for non-branching trees, that is, where each |
| 60 * parent node has only a single child node. |
| 61 * |
| 62 * PARAMETERS: |
| 63 * "cert" |
| 64 * The address of the Cert to be included in the new VerifyNode. Must be |
| 65 * non-NULL. |
| 66 * "depth" |
| 67 * The UInt32 value of the depth. |
| 68 * "error" |
| 69 * The address of the Error to be included in the new VerifyNode. |
| 70 * "pVerifyTree" |
| 71 * The address of the VerifyNode tree into which the created VerifyNode |
| 72 * is to be inserted. The node is not created if VerifyTree is NULL. |
| 73 * "plContext" |
| 74 * Platform-specific context pointer. |
| 75 * THREAD SAFETY: |
| 76 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| 77 * RETURNS: |
| 78 * Returns NULL if the function succeeds. |
| 79 * Returns a Validate Error if the function fails in a non-fatal way. |
| 80 * Returns a Fatal Error if the function fails in an unrecoverable way. |
| 81 */ |
| 82 static PKIX_Error * |
| 83 pkix_AddToVerifyLog( |
| 84 PKIX_PL_Cert *cert, |
| 85 PKIX_UInt32 depth, |
| 86 PKIX_Error *error, |
| 87 PKIX_VerifyNode **pVerifyTree, |
| 88 void *plContext) |
| 89 { |
| 90 |
| 91 PKIX_VerifyNode *verifyNode = NULL; |
| 92 |
| 93 PKIX_ENTER(VALIDATE, "pkix_AddToVerifyLog"); |
| 94 PKIX_NULLCHECK_ONE(cert); |
| 95 |
| 96 if (pVerifyTree) { /* nothing to do if no address given for log */ |
| 97 |
| 98 PKIX_CHECK(pkix_VerifyNode_Create |
| 99 (cert, depth, error, &verifyNode, plContext), |
| 100 PKIX_VERIFYNODECREATEFAILED); |
| 101 |
| 102 if (depth == 0) { |
| 103 /* We just created the root node */ |
| 104 *pVerifyTree = verifyNode; |
| 105 } else { |
| 106 PKIX_CHECK(pkix_VerifyNode_AddToChain |
| 107 (*pVerifyTree, verifyNode, plContext), |
| 108 PKIX_VERIFYNODEADDTOCHAINFAILED); |
| 109 } |
| 110 } |
| 111 |
| 112 cleanup: |
| 113 |
| 114 PKIX_RETURN(VALIDATE); |
| 115 |
| 116 } |
| 117 |
| 118 /* |
| 119 * FUNCTION: pkix_CheckCert |
| 120 * DESCRIPTION: |
| 121 * |
| 122 * Checks whether the Cert pointed to by "cert" successfully validates |
| 123 * using the List of CertChainCheckers pointed to by "checkers". If the |
| 124 * certificate does not validate, an Error pointer is returned. |
| 125 * |
| 126 * This function should be called initially with the UInt32 pointed to by |
| 127 * "pCheckerIndex" containing zero, and the pointer at "pNBIOContext" |
| 128 * containing NULL. If a checker does non-blocking I/O, this function will |
| 129 * return with the index of that checker stored at "pCheckerIndex" and a |
| 130 * platform-dependent non-blocking I/O context stored at "pNBIOContext". |
| 131 * A subsequent call to this function with those values intact will allow the |
| 132 * checking to resume where it left off. This should be repeated until the |
| 133 * function returns with NULL stored at "pNBIOContext". |
| 134 * |
| 135 * PARAMETERS: |
| 136 * "cert" |
| 137 * Address of Cert to validate. Must be non-NULL. |
| 138 * "checkers" |
| 139 * List of CertChainCheckers which must each validate the certificate. |
| 140 * Must be non-NULL. |
| 141 * "checkedExtOIDs" |
| 142 * List of PKIX_PL_OID that has been processed. If called from building |
| 143 * chain, it is the list of critical extension OIDs that has been |
| 144 * processed prior to validation. May be NULL. |
| 145 * "pCheckerIndex" |
| 146 * Address at which is stored the the index, within the List "checkers", |
| 147 * of a checker whose processing was interrupted by non-blocking I/O. |
| 148 * Must be non-NULL. |
| 149 * "pNBIOContext" |
| 150 * Address at which is stored platform-specific non-blocking I/O context. |
| 151 * Must be non-NULL. |
| 152 * "plContext" |
| 153 * Platform-specific context pointer. |
| 154 * THREAD SAFETY: |
| 155 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| 156 * RETURNS: |
| 157 * Returns NULL if the function succeeds. |
| 158 * Returns a Validate Error if the function fails in a non-fatal way. |
| 159 * Returns a Fatal Error if the function fails in an unrecoverable way. |
| 160 */ |
| 161 static PKIX_Error * |
| 162 pkix_CheckCert( |
| 163 PKIX_PL_Cert *cert, |
| 164 PKIX_List *checkers, |
| 165 PKIX_List *checkedExtOIDsList, |
| 166 PKIX_UInt32 *pCheckerIndex, |
| 167 void **pNBIOContext, |
| 168 void *plContext) |
| 169 { |
| 170 PKIX_CertChainChecker_CheckCallback checkerCheck = NULL; |
| 171 PKIX_CertChainChecker *checker = NULL; |
| 172 PKIX_List *unresCritExtOIDs = NULL; |
| 173 PKIX_UInt32 numCheckers; |
| 174 PKIX_UInt32 numUnresCritExtOIDs = 0; |
| 175 PKIX_UInt32 checkerIndex = 0; |
| 176 void *nbioContext = NULL; |
| 177 |
| 178 PKIX_ENTER(VALIDATE, "pkix_CheckCert"); |
| 179 PKIX_NULLCHECK_FOUR(cert, checkers, pCheckerIndex, pNBIOContext); |
| 180 |
| 181 nbioContext = *pNBIOContext; |
| 182 *pNBIOContext = NULL; /* prepare for case of error exit */ |
| 183 |
| 184 PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs |
| 185 (cert, &unresCritExtOIDs, plContext), |
| 186 PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED); |
| 187 |
| 188 PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext), |
| 189 PKIX_LISTGETLENGTHFAILED); |
| 190 |
| 191 for (checkerIndex = *pCheckerIndex; |
| 192 checkerIndex < numCheckers; |
| 193 checkerIndex++) { |
| 194 |
| 195 PKIX_CHECK(PKIX_List_GetItem |
| 196 (checkers, |
| 197 checkerIndex, |
| 198 (PKIX_PL_Object **)&checker, |
| 199 plContext), |
| 200 PKIX_LISTGETITEMFAILED); |
| 201 |
| 202 PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback |
| 203 (checker, &checkerCheck, plContext), |
| 204 PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED); |
| 205 |
| 206 PKIX_CHECK(checkerCheck(checker, cert, unresCritExtOIDs, |
| 207 &nbioContext, plContext), |
| 208 PKIX_CERTCHAINCHECKERCHECKFAILED); |
| 209 |
| 210 if (nbioContext != NULL) { |
| 211 *pCheckerIndex = checkerIndex; |
| 212 *pNBIOContext = nbioContext; |
| 213 goto cleanup; |
| 214 } |
| 215 |
| 216 PKIX_DECREF(checker); |
| 217 } |
| 218 |
| 219 if (unresCritExtOIDs){ |
| 220 |
| 221 #ifdef PKIX_VALIDATEDEBUG |
| 222 { |
| 223 PKIX_PL_String *oidString = NULL; |
| 224 PKIX_UInt32 length; |
| 225 char *oidAscii = NULL; |
| 226 PKIX_TOSTRING(unresCritExtOIDs, &oidString, plContext, |
| 227 PKIX_LISTTOSTRINGFAILED); |
| 228 PKIX_CHECK(PKIX_PL_String_GetEncoded |
| 229 (oidString, |
| 230 PKIX_ESCASCII, |
| 231 (void **) &oidAscii, |
| 232 &length, |
| 233 plContext), |
| 234 PKIX_STRINGGETENCODEDFAILED); |
| 235 PKIX_VALIDATE_DEBUG_ARG |
| 236 ("unrecognized critical extension OIDs:" |
| 237 " %s\n", oidAscii); |
| 238 PKIX_DECREF(oidString); |
| 239 PKIX_PL_Free(oidAscii, plContext); |
| 240 } |
| 241 #endif |
| 242 |
| 243 if (checkedExtOIDsList != NULL) { |
| 244 /* Take out OID's that had been processed, if any */ |
| 245 PKIX_CHECK(pkix_List_RemoveItems |
| 246 (unresCritExtOIDs, |
| 247 checkedExtOIDsList, |
| 248 plContext), |
| 249 PKIX_LISTREMOVEITEMSFAILED); |
| 250 } |
| 251 |
| 252 PKIX_CHECK(PKIX_List_GetLength |
| 253 (unresCritExtOIDs, &numUnresCritExtOIDs, plContext), |
| 254 PKIX_LISTGETLENGTHFAILED); |
| 255 |
| 256 if (numUnresCritExtOIDs != 0){ |
| 257 PKIX_ERROR(PKIX_UNRECOGNIZEDCRITICALEXTENSION); |
| 258 } |
| 259 |
| 260 } |
| 261 |
| 262 cleanup: |
| 263 |
| 264 PKIX_DECREF(checker); |
| 265 PKIX_DECREF(unresCritExtOIDs); |
| 266 |
| 267 PKIX_RETURN(VALIDATE); |
| 268 |
| 269 } |
| 270 |
| 271 /* |
| 272 * FUNCTION: pkix_InitializeCheckers |
| 273 * DESCRIPTION: |
| 274 * |
| 275 * Creates several checkers and initializes them with values derived from the |
| 276 * TrustAnchor pointed to by "anchor", the ProcessingParams pointed to by |
| 277 * "procParams", and the number of Certs in the Chain, represented by |
| 278 * "numCerts". The List of checkers is stored at "pCheckers". |
| 279 * |
| 280 * PARAMETERS: |
| 281 * "anchor" |
| 282 * Address of TrustAnchor used to initialize the SignatureChecker and |
| 283 * NameChainingChecker. Must be non-NULL. |
| 284 * "procParams" |
| 285 * Address of ProcessingParams used to initialize the ExpirationChecker |
| 286 * and TargetCertChecker. Must be non-NULL. |
| 287 * "numCerts" |
| 288 * Number of certificates in the CertChain. |
| 289 * "pCheckers" |
| 290 * Address where object pointer will be stored. Must be non-NULL. |
| 291 * "plContext" |
| 292 * Platform-specific context pointer. |
| 293 * THREAD SAFETY: |
| 294 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| 295 * RETURNS: |
| 296 * Returns NULL if the function succeeds. |
| 297 * Returns a Validate Error if the function fails in a non-fatal way. |
| 298 * Returns a Fatal Error if the function fails in an unrecoverable way. |
| 299 */ |
| 300 static PKIX_Error * |
| 301 pkix_InitializeCheckers( |
| 302 PKIX_TrustAnchor *anchor, |
| 303 PKIX_ProcessingParams *procParams, |
| 304 PKIX_UInt32 numCerts, |
| 305 PKIX_List **pCheckers, |
| 306 void *plContext) |
| 307 { |
| 308 PKIX_CertChainChecker *targetCertChecker = NULL; |
| 309 PKIX_CertChainChecker *expirationChecker = NULL; |
| 310 PKIX_CertChainChecker *nameChainingChecker = NULL; |
| 311 PKIX_CertChainChecker *nameConstraintsChecker = NULL; |
| 312 PKIX_CertChainChecker *basicConstraintsChecker = NULL; |
| 313 PKIX_CertChainChecker *policyChecker = NULL; |
| 314 PKIX_CertChainChecker *sigChecker = NULL; |
| 315 PKIX_CertChainChecker *defaultCrlChecker = NULL; |
| 316 PKIX_CertChainChecker *userChecker = NULL; |
| 317 PKIX_PL_X500Name *trustedCAName = NULL; |
| 318 PKIX_PL_PublicKey *trustedPubKey = NULL; |
| 319 PKIX_List *checkers = NULL; |
| 320 PKIX_PL_Date *testDate = NULL; |
| 321 PKIX_CertSelector *certSelector = NULL; |
| 322 PKIX_PL_Cert *trustedCert = NULL; |
| 323 PKIX_PL_CertNameConstraints *trustedNC = NULL; |
| 324 PKIX_List *initialPolicies = NULL; |
| 325 PKIX_Boolean policyQualifiersRejected = PKIX_FALSE; |
| 326 PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE; |
| 327 PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE; |
| 328 PKIX_Boolean initialExplicitPolicy = PKIX_FALSE; |
| 329 PKIX_List *userCheckersList = NULL; |
| 330 PKIX_List *certStores = NULL; |
| 331 PKIX_UInt32 numCertCheckers = 0; |
| 332 PKIX_UInt32 i; |
| 333 |
| 334 PKIX_ENTER(VALIDATE, "pkix_InitializeCheckers"); |
| 335 PKIX_NULLCHECK_THREE(anchor, procParams, pCheckers); |
| 336 PKIX_CHECK(PKIX_List_Create(&checkers, plContext), |
| 337 PKIX_LISTCREATEFAILED); |
| 338 |
| 339 /* |
| 340 * The TrustAnchor may have been created using CreateWithCert |
| 341 * (in which case GetCAPublicKey and GetCAName will return NULL) |
| 342 * or may have been created using CreateWithNameKeyPair (in which |
| 343 * case GetTrustedCert will return NULL. So we call GetTrustedCert |
| 344 * and populate trustedPubKey and trustedCAName accordingly. |
| 345 */ |
| 346 |
| 347 PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert |
| 348 (anchor, &trustedCert, plContext), |
| 349 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); |
| 350 |
| 351 if (trustedCert){ |
| 352 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey |
| 353 (trustedCert, &trustedPubKey, plContext), |
| 354 PKIX_CERTGETSUBJECTPUBLICKEYFAILED); |
| 355 |
| 356 PKIX_CHECK(PKIX_PL_Cert_GetSubject |
| 357 (trustedCert, &trustedCAName, plContext), |
| 358 PKIX_CERTGETSUBJECTFAILED); |
| 359 } else { |
| 360 PKIX_CHECK(PKIX_TrustAnchor_GetCAPublicKey |
| 361 (anchor, &trustedPubKey, plContext), |
| 362 PKIX_TRUSTANCHORGETCAPUBLICKEYFAILED); |
| 363 |
| 364 PKIX_CHECK(PKIX_TrustAnchor_GetCAName |
| 365 (anchor, &trustedCAName, plContext), |
| 366 PKIX_TRUSTANCHORGETCANAMEFAILED); |
| 367 } |
| 368 |
| 369 PKIX_NULLCHECK_TWO(trustedPubKey, trustedCAName); |
| 370 |
| 371 PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints |
| 372 (anchor, &trustedNC, plContext), |
| 373 PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED); |
| 374 |
| 375 PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints |
| 376 (procParams, &certSelector, plContext), |
| 377 PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); |
| 378 |
| 379 PKIX_CHECK(PKIX_ProcessingParams_GetDate |
| 380 (procParams, &testDate, plContext), |
| 381 PKIX_PROCESSINGPARAMSGETDATEFAILED); |
| 382 |
| 383 PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies |
| 384 (procParams, &initialPolicies, plContext), |
| 385 PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED); |
| 386 |
| 387 PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected |
| 388 (procParams, &policyQualifiersRejected, plContext), |
| 389 PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED); |
| 390 |
| 391 PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited |
| 392 (procParams, &initialPolicyMappingInhibit, plContext), |
| 393 PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED); |
| 394 |
| 395 PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited |
| 396 (procParams, &initialAnyPolicyInhibit, plContext), |
| 397 PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED); |
| 398 |
| 399 PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired |
| 400 (procParams, &initialExplicitPolicy, plContext), |
| 401 PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED); |
| 402 |
| 403 PKIX_CHECK(PKIX_ProcessingParams_GetCertStores |
| 404 (procParams, &certStores, plContext), |
| 405 PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED); |
| 406 |
| 407 PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers |
| 408 (procParams, &userCheckersList, plContext), |
| 409 PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); |
| 410 |
| 411 /* now, initialize all the checkers */ |
| 412 PKIX_CHECK(pkix_TargetCertChecker_Initialize |
| 413 (certSelector, numCerts, &targetCertChecker, plContext), |
| 414 PKIX_TARGETCERTCHECKERINITIALIZEFAILED); |
| 415 |
| 416 PKIX_CHECK(pkix_ExpirationChecker_Initialize |
| 417 (testDate, &expirationChecker, plContext), |
| 418 PKIX_EXPIRATIONCHECKERINITIALIZEFAILED); |
| 419 |
| 420 PKIX_CHECK(pkix_NameChainingChecker_Initialize |
| 421 (trustedCAName, &nameChainingChecker, plContext), |
| 422 PKIX_NAMECHAININGCHECKERINITIALIZEFAILED); |
| 423 |
| 424 PKIX_CHECK(pkix_NameConstraintsChecker_Initialize |
| 425 (trustedNC, numCerts, &nameConstraintsChecker, plContext), |
| 426 PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED); |
| 427 |
| 428 PKIX_CHECK(pkix_BasicConstraintsChecker_Initialize |
| 429 (numCerts, &basicConstraintsChecker, plContext), |
| 430 PKIX_BASICCONSTRAINTSCHECKERINITIALIZEFAILED); |
| 431 |
| 432 PKIX_CHECK(pkix_PolicyChecker_Initialize |
| 433 (initialPolicies, |
| 434 policyQualifiersRejected, |
| 435 initialPolicyMappingInhibit, |
| 436 initialExplicitPolicy, |
| 437 initialAnyPolicyInhibit, |
| 438 numCerts, |
| 439 &policyChecker, |
| 440 plContext), |
| 441 PKIX_POLICYCHECKERINITIALIZEFAILED); |
| 442 |
| 443 PKIX_CHECK(pkix_SignatureChecker_Initialize |
| 444 (trustedPubKey, numCerts, &sigChecker, plContext), |
| 445 PKIX_SIGNATURECHECKERINITIALIZEFAILED); |
| 446 |
| 447 if (userCheckersList != NULL) { |
| 448 |
| 449 PKIX_CHECK(PKIX_List_GetLength |
| 450 (userCheckersList, &numCertCheckers, plContext), |
| 451 PKIX_LISTGETLENGTHFAILED); |
| 452 |
| 453 for (i = 0; i < numCertCheckers; i++) { |
| 454 |
| 455 PKIX_CHECK(PKIX_List_GetItem |
| 456 (userCheckersList, |
| 457 i, |
| 458 (PKIX_PL_Object **) &userChecker, |
| 459 plContext), |
| 460 PKIX_LISTGETITEMFAILED); |
| 461 |
| 462 PKIX_CHECK(PKIX_List_AppendItem |
| 463 (checkers, |
| 464 (PKIX_PL_Object *)userChecker, |
| 465 plContext), |
| 466 PKIX_LISTAPPENDITEMFAILED); |
| 467 |
| 468 PKIX_DECREF(userChecker); |
| 469 } |
| 470 } |
| 471 |
| 472 PKIX_CHECK(PKIX_List_AppendItem |
| 473 (checkers, (PKIX_PL_Object *)targetCertChecker, plContext), |
| 474 PKIX_LISTAPPENDITEMFAILED); |
| 475 |
| 476 PKIX_CHECK(PKIX_List_AppendItem |
| 477 (checkers, (PKIX_PL_Object *)expirationChecker, plContext), |
| 478 PKIX_LISTAPPENDITEMFAILED); |
| 479 |
| 480 PKIX_CHECK(PKIX_List_AppendItem |
| 481 (checkers, (PKIX_PL_Object *)nameChainingChecker, plContext), |
| 482 PKIX_LISTAPPENDITEMFAILED); |
| 483 |
| 484 PKIX_CHECK(PKIX_List_AppendItem |
| 485 (checkers, (PKIX_PL_Object *)nameConstraintsChecker, plContext), |
| 486 PKIX_LISTAPPENDITEMFAILED); |
| 487 |
| 488 PKIX_CHECK(PKIX_List_AppendItem |
| 489 (checkers, (PKIX_PL_Object *)basicConstraintsChecker, plContext), |
| 490 PKIX_LISTAPPENDITEMFAILED); |
| 491 |
| 492 PKIX_CHECK(PKIX_List_AppendItem |
| 493 (checkers, (PKIX_PL_Object *)policyChecker, plContext), |
| 494 PKIX_LISTAPPENDITEMFAILED); |
| 495 |
| 496 PKIX_CHECK(PKIX_List_AppendItem |
| 497 (checkers, (PKIX_PL_Object *)sigChecker, plContext), |
| 498 PKIX_LISTAPPENDITEMFAILED); |
| 499 |
| 500 *pCheckers = checkers; |
| 501 |
| 502 cleanup: |
| 503 |
| 504 if (PKIX_ERROR_RECEIVED){ |
| 505 PKIX_DECREF(checkers); |
| 506 } |
| 507 |
| 508 PKIX_DECREF(certSelector); |
| 509 PKIX_DECREF(testDate); |
| 510 PKIX_DECREF(initialPolicies); |
| 511 PKIX_DECREF(targetCertChecker); |
| 512 PKIX_DECREF(expirationChecker); |
| 513 PKIX_DECREF(nameChainingChecker); |
| 514 PKIX_DECREF(nameConstraintsChecker); |
| 515 PKIX_DECREF(basicConstraintsChecker); |
| 516 PKIX_DECREF(policyChecker); |
| 517 PKIX_DECREF(sigChecker); |
| 518 PKIX_DECREF(trustedCAName); |
| 519 PKIX_DECREF(trustedPubKey); |
| 520 PKIX_DECREF(trustedNC); |
| 521 PKIX_DECREF(trustedCert); |
| 522 PKIX_DECREF(defaultCrlChecker); |
| 523 PKIX_DECREF(userCheckersList); |
| 524 PKIX_DECREF(certStores); |
| 525 PKIX_DECREF(userChecker); |
| 526 |
| 527 PKIX_RETURN(VALIDATE); |
| 528 } |
| 529 |
| 530 /* |
| 531 * FUNCTION: pkix_RetrieveOutputs |
| 532 * DESCRIPTION: |
| 533 * |
| 534 * This function queries the respective states of the List of checkers in |
| 535 * "checkers" to to obtain the final public key from the SignatureChecker |
| 536 * and the policy tree from the PolicyChecker, storing those values at |
| 537 * "pFinalSubjPubKey" and "pPolicyTree", respectively. |
| 538 * |
| 539 * PARAMETERS: |
| 540 * "checkers" |
| 541 * Address of List of checkers to be queried. Must be non-NULL. |
| 542 * "pFinalSubjPubKey" |
| 543 * Address where final public key will be stored. Must be non-NULL. |
| 544 * "pPolicyTree" |
| 545 * Address where policy tree will be stored. Must be non-NULL. |
| 546 * "plContext" |
| 547 * Platform-specific context pointer. |
| 548 * THREAD SAFETY: |
| 549 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| 550 * RETURNS: |
| 551 * Returns NULL if the function succeeds. |
| 552 * Returns a Validate Error if the function fails in a non-fatal way. |
| 553 * Returns a Fatal Error if the function fails in an unrecoverable way. |
| 554 */ |
| 555 static PKIX_Error * |
| 556 pkix_RetrieveOutputs( |
| 557 PKIX_List *checkers, |
| 558 PKIX_PL_PublicKey **pFinalSubjPubKey, |
| 559 PKIX_PolicyNode **pPolicyTree, |
| 560 void *plContext) |
| 561 { |
| 562 PKIX_PL_PublicKey *finalSubjPubKey = NULL; |
| 563 PKIX_PolicyNode *validPolicyTree = NULL; |
| 564 PKIX_CertChainChecker *checker = NULL; |
| 565 PKIX_PL_Object *state = NULL; |
| 566 PKIX_UInt32 numCheckers = 0; |
| 567 PKIX_UInt32 type; |
| 568 PKIX_Int32 j; |
| 569 |
| 570 PKIX_ENTER(VALIDATE, "pkix_RetrieveOutputs"); |
| 571 |
| 572 PKIX_NULLCHECK_TWO(checkers, pPolicyTree); |
| 573 |
| 574 /* |
| 575 * To optimize the search, we guess that the sigChecker is |
| 576 * last in the tree and is preceded by the policyChecker. We |
| 577 * search toward the front of the chain. Remember that List |
| 578 * items are indexed 0..(numItems - 1). |
| 579 */ |
| 580 |
| 581 PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext), |
| 582 PKIX_LISTGETLENGTHFAILED); |
| 583 |
| 584 for (j = numCheckers - 1; j >= 0; j--){ |
| 585 PKIX_CHECK(PKIX_List_GetItem |
| 586 (checkers, j, (PKIX_PL_Object **)&checker, plContext), |
| 587 PKIX_LISTGETITEMFAILED); |
| 588 |
| 589 PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState |
| 590 (checker, &state, plContext), |
| 591 PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); |
| 592 |
| 593 /* user defined checker may have no state */ |
| 594 if (state != NULL) { |
| 595 |
| 596 PKIX_CHECK(PKIX_PL_Object_GetType(state, &type, plContext), |
| 597 PKIX_OBJECTGETTYPEFAILED); |
| 598 |
| 599 if (type == PKIX_SIGNATURECHECKERSTATE_TYPE){ |
| 600 /* final pubKey will include any inherited DSA params */ |
| 601 finalSubjPubKey = |
| 602 ((pkix_SignatureCheckerState *)state)-> |
| 603 prevPublicKey; |
| 604 PKIX_INCREF(finalSubjPubKey); |
| 605 *pFinalSubjPubKey = finalSubjPubKey; |
| 606 } |
| 607 |
| 608 if (type == PKIX_CERTPOLICYCHECKERSTATE_TYPE) { |
| 609 validPolicyTree = |
| 610 ((PKIX_PolicyCheckerState *)state)->validPolicyTree; |
| 611 break; |
| 612 } |
| 613 } |
| 614 |
| 615 PKIX_DECREF(checker); |
| 616 PKIX_DECREF(state); |
| 617 } |
| 618 |
| 619 PKIX_INCREF(validPolicyTree); |
| 620 *pPolicyTree = validPolicyTree; |
| 621 |
| 622 cleanup: |
| 623 |
| 624 PKIX_DECREF(checker); |
| 625 PKIX_DECREF(state); |
| 626 |
| 627 PKIX_RETURN(VALIDATE); |
| 628 |
| 629 } |
| 630 |
| 631 /* |
| 632 * FUNCTION: pkix_CheckChain |
| 633 * DESCRIPTION: |
| 634 * |
| 635 * Checks whether the List of Certs pointed to by "certs", containing |
| 636 * "numCerts" entries, successfully validates using each CertChainChecker in |
| 637 * the List pointed to by "checkers" and has not been revoked, according to any |
| 638 * of the Revocation Checkers in the List pointed to by "revChecker". Checkers |
| 639 * are expected to remove from "removeCheckedExtOIDs" and extensions that they |
| 640 * process. Indices to the certChain and the checkerChain are obtained and |
| 641 * returned in "pCertCheckedIndex" and "pCheckerIndex", respectively. These |
| 642 * should be set to zero prior to the initial call, but may be changed (and |
| 643 * must be supplied on subsequent calls) if processing is suspended for non- |
| 644 * blocking I/O. Each time a Cert passes from being validated by one of the |
| 645 * CertChainCheckers to being checked by a Revocation Checker, the Boolean |
| 646 * stored at "pRevChecking" is changed from FALSE to TRUE. If the Cert is |
| 647 * rejected by a Revocation Checker, its reason code is returned at |
| 648 * "pReasonCode. If the List of Certs successfully validates, the public key i |
| 649 * the final certificate is obtained and stored at "pFinalSubjPubKey" and the |
| 650 * validPolicyTree, which could be NULL, is stored at pPolicyTree. If the List |
| 651 * of Certs fails to validate, an Error pointer is returned. |
| 652 * |
| 653 * If "pVerifyTree" is non-NULL, a chain of VerifyNodes is created which |
| 654 * tracks the results of the validation. That is, either each node in the |
| 655 * chain has a NULL Error component, or the last node contains an Error |
| 656 * which indicates why the validation failed. |
| 657 * |
| 658 * The number of Certs in the List, represented by "numCerts", is used to |
| 659 * determine which Cert is the final Cert. |
| 660 * |
| 661 * PARAMETERS: |
| 662 * "certs" |
| 663 * Address of List of Certs to validate. Must be non-NULL. |
| 664 * "numCerts" |
| 665 * Number of certificates in the List of certificates. |
| 666 * "checkers" |
| 667 * List of CertChainCheckers which must each validate the List of |
| 668 * certificates. Must be non-NULL. |
| 669 * "revChecker" |
| 670 * List of RevocationCheckers which must each not reject the List of |
| 671 * certificates. May be empty, but must be non-NULL. |
| 672 * "removeCheckedExtOIDs" |
| 673 * List of PKIX_PL_OID that has been processed. If called from building |
| 674 * chain, it is the list of critical extension OIDs that has been |
| 675 * processed prior to validation. Extension OIDs that may be processed by |
| 676 * user defined checker processes are also in the list. May be NULL. |
| 677 * "procParams" |
| 678 * Address of ProcessingParams used to initialize various checkers. Must |
| 679 * be non-NULL. |
| 680 * "pCertCheckedIndex" |
| 681 * Address where Int32 index to the Cert chain is obtained and |
| 682 * returned. Must be non-NULL. |
| 683 * "pCheckerIndex" |
| 684 * Address where Int32 index to the CheckerChain is obtained and |
| 685 * returned. Must be non-NULL. |
| 686 * "pRevChecking" |
| 687 * Address where Boolean is obtained and returned, indicating, if FALSE, |
| 688 * that CertChainCheckers are being called; or, if TRUE, that RevChecker |
| 689 * are being called. Must be non-NULL. |
| 690 * "pReasonCode" |
| 691 * Address where UInt32 results of revocation checking are stored. Must be |
| 692 * non-NULL. |
| 693 * "pNBIOContext" |
| 694 * Address where platform-dependent context is stored if checking is |
| 695 * suspended for non-blocking I/O. Must be non-NULL. |
| 696 * "pFinalSubjPubKey" |
| 697 * Address where the final public key will be stored. Must be non-NULL. |
| 698 * "pPolicyTree" |
| 699 * Address where the final validPolicyTree is stored. Must be non-NULL. |
| 700 * "pVerifyTree" |
| 701 * Address where a VerifyTree is stored, if non-NULL. |
| 702 * "plContext" |
| 703 * Platform-specific context pointer. |
| 704 * THREAD SAFETY: |
| 705 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| 706 * RETURNS: |
| 707 * Returns NULL if the function succeeds. |
| 708 * Returns a Validate Error if the function fails in a non-fatal way. |
| 709 * Returns a Fatal Error if the function fails in an unrecoverable way. |
| 710 */ |
| 711 PKIX_Error * |
| 712 pkix_CheckChain( |
| 713 PKIX_List *certs, |
| 714 PKIX_UInt32 numCerts, |
| 715 PKIX_TrustAnchor *anchor, |
| 716 PKIX_List *checkers, |
| 717 PKIX_RevocationChecker *revChecker, |
| 718 PKIX_List *removeCheckedExtOIDs, |
| 719 PKIX_ProcessingParams *procParams, |
| 720 PKIX_UInt32 *pCertCheckedIndex, |
| 721 PKIX_UInt32 *pCheckerIndex, |
| 722 PKIX_Boolean *pRevChecking, |
| 723 PKIX_UInt32 *pReasonCode, |
| 724 void **pNBIOContext, |
| 725 PKIX_PL_PublicKey **pFinalSubjPubKey, |
| 726 PKIX_PolicyNode **pPolicyTree, |
| 727 PKIX_VerifyNode **pVerifyTree, |
| 728 void *plContext) |
| 729 { |
| 730 PKIX_UInt32 j = 0; |
| 731 PKIX_Boolean revChecking = PKIX_FALSE; |
| 732 PKIX_Error *checkCertError = NULL; |
| 733 void *nbioContext = NULL; |
| 734 PKIX_PL_Cert *cert = NULL; |
| 735 PKIX_PL_Cert *issuer = NULL; |
| 736 |
| 737 PKIX_ENTER(VALIDATE, "pkix_CheckChain"); |
| 738 PKIX_NULLCHECK_FOUR(certs, checkers, revChecker, pCertCheckedIndex); |
| 739 PKIX_NULLCHECK_FOUR(pCheckerIndex, pRevChecking, pReasonCode, anchor); |
| 740 PKIX_NULLCHECK_THREE(pNBIOContext, pFinalSubjPubKey, pPolicyTree); |
| 741 |
| 742 nbioContext = *pNBIOContext; |
| 743 *pNBIOContext = NULL; |
| 744 revChecking = *pRevChecking; |
| 745 |
| 746 PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert |
| 747 (anchor, &cert, plContext), |
| 748 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); |
| 749 |
| 750 for (j = *pCertCheckedIndex; j < numCerts; j++) { |
| 751 |
| 752 PORT_Assert(cert); |
| 753 PKIX_DECREF(issuer); |
| 754 issuer = cert; |
| 755 cert = NULL; |
| 756 |
| 757 PKIX_CHECK(PKIX_List_GetItem( |
| 758 certs, j, (PKIX_PL_Object **)&cert, plContext), |
| 759 PKIX_LISTGETITEMFAILED); |
| 760 |
| 761 /* check if cert pointer is valid */ |
| 762 PORT_Assert(cert); |
| 763 if (cert == NULL) { |
| 764 continue; |
| 765 } |
| 766 |
| 767 if (revChecking == PKIX_FALSE) { |
| 768 |
| 769 PKIX_CHECK(pkix_CheckCert |
| 770 (cert, |
| 771 checkers, |
| 772 removeCheckedExtOIDs, |
| 773 pCheckerIndex, |
| 774 &nbioContext, |
| 775 plContext), |
| 776 PKIX_CHECKCERTFAILED); |
| 777 |
| 778 if (nbioContext != NULL) { |
| 779 *pCertCheckedIndex = j; |
| 780 *pRevChecking = revChecking; |
| 781 *pNBIOContext = nbioContext; |
| 782 goto cleanup; |
| 783 } |
| 784 |
| 785 revChecking = PKIX_TRUE; |
| 786 *pCheckerIndex = 0; |
| 787 } |
| 788 |
| 789 if (revChecking == PKIX_TRUE) { |
| 790 PKIX_RevocationStatus revStatus; |
| 791 pkixErrorResult = |
| 792 PKIX_RevocationChecker_Check( |
| 793 cert, issuer, revChecker, |
| 794 procParams, PKIX_TRUE, |
| 795 (j == numCerts - 1) ? PKIX_TRUE : PKIX_FAL
SE, |
| 796 &revStatus, pReasonCode, |
| 797 &nbioContext, plContext); |
| 798 if (nbioContext != NULL) { |
| 799 *pCertCheckedIndex = j; |
| 800 *pRevChecking = revChecking; |
| 801 *pNBIOContext = nbioContext; |
| 802 goto cleanup; |
| 803 } |
| 804 if (revStatus == PKIX_RevStatus_Revoked || |
| 805 pkixErrorResult) { |
| 806 if (!pkixErrorResult) { |
| 807 /* if pkixErrorResult is returned then |
| 808 * use it as it has a detailed revocation |
| 809 * error code. Otherwise create a new error */ |
| 810 PKIX_ERROR_CREATE(VALIDATE, |
| 811 PKIX_CERTIFICATEREVOKED, |
| 812 pkixErrorResult); |
| 813 } |
| 814 goto cleanup; |
| 815 } |
| 816 revChecking = PKIX_FALSE; |
| 817 *pCheckerIndex = 0; |
| 818 } |
| 819 |
| 820 PKIX_CHECK(pkix_AddToVerifyLog |
| 821 (cert, j, NULL, pVerifyTree, plContext), |
| 822 PKIX_ADDTOVERIFYLOGFAILED); |
| 823 } |
| 824 |
| 825 PKIX_CHECK(pkix_RetrieveOutputs |
| 826 (checkers, pFinalSubjPubKey, pPolicyTree, plContext), |
| 827 PKIX_RETRIEVEOUTPUTSFAILED); |
| 828 |
| 829 *pNBIOContext = NULL; |
| 830 |
| 831 cleanup: |
| 832 if (PKIX_ERROR_RECEIVED && cert) { |
| 833 checkCertError = pkixErrorResult; |
| 834 |
| 835 PKIX_CHECK_FATAL( |
| 836 pkix_AddToVerifyLog(cert, j, checkCertError, pVerifyTree, |
| 837 plContext), |
| 838 PKIX_ADDTOVERIFYLOGFAILED); |
| 839 pkixErrorResult = checkCertError; |
| 840 pkixErrorCode = pkixErrorResult->errCode; |
| 841 checkCertError = NULL; |
| 842 } |
| 843 |
| 844 fatal: |
| 845 PKIX_DECREF(checkCertError); |
| 846 PKIX_DECREF(cert); |
| 847 PKIX_DECREF(issuer); |
| 848 |
| 849 PKIX_RETURN(VALIDATE); |
| 850 } |
| 851 |
| 852 /* |
| 853 * FUNCTION: pkix_ExtractParameters |
| 854 * DESCRIPTION: |
| 855 * |
| 856 * Extracts several parameters from the ValidateParams object pointed to by |
| 857 * "valParams" and stores the CertChain at "pChain", the List of Certs at |
| 858 * "pCerts", the number of Certs in the chain at "pNumCerts", the |
| 859 * ProcessingParams object at "pProcParams", the List of TrustAnchors at |
| 860 * "pAnchors", and the number of TrustAnchors at "pNumAnchors". |
| 861 * |
| 862 * PARAMETERS: |
| 863 * "valParams" |
| 864 * Address of ValidateParams from which the parameters are extracted. |
| 865 * Must be non-NULL. |
| 866 * "pCerts" |
| 867 * Address where object pointer for List of Certs will be stored. |
| 868 * Must be non-NULL. |
| 869 * "pNumCerts" |
| 870 * Address where number of Certs will be stored. Must be non-NULL. |
| 871 * "pProcParams" |
| 872 * Address where object pointer for ProcessingParams will be stored. |
| 873 * Must be non-NULL. |
| 874 * "pAnchors" |
| 875 * Address where object pointer for List of Anchors will be stored. |
| 876 * Must be non-NULL. |
| 877 * "pNumAnchors" |
| 878 * Address where number of Anchors will be stored. Must be non-NULL. |
| 879 * "plContext" |
| 880 * Platform-specific context pointer. |
| 881 * THREAD SAFETY: |
| 882 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| 883 * RETURNS: |
| 884 * Returns NULL if the function succeeds. |
| 885 * Returns a Validate Error if the function fails in a non-fatal way. |
| 886 * Returns a Fatal Error if the function fails in an unrecoverable way. |
| 887 */ |
| 888 static PKIX_Error * |
| 889 pkix_ExtractParameters( |
| 890 PKIX_ValidateParams *valParams, |
| 891 PKIX_List **pCerts, |
| 892 PKIX_UInt32 *pNumCerts, |
| 893 PKIX_ProcessingParams **pProcParams, |
| 894 PKIX_List **pAnchors, |
| 895 PKIX_UInt32 *pNumAnchors, |
| 896 void *plContext) |
| 897 { |
| 898 PKIX_ENTER(VALIDATE, "pkix_ExtractParameters"); |
| 899 PKIX_NULLCHECK_THREE(valParams, pCerts, pNumCerts); |
| 900 PKIX_NULLCHECK_THREE(pProcParams, pAnchors, pNumAnchors); |
| 901 |
| 902 /* extract relevant parameters from chain */ |
| 903 PKIX_CHECK(PKIX_ValidateParams_GetCertChain |
| 904 (valParams, pCerts, plContext), |
| 905 PKIX_VALIDATEPARAMSGETCERTCHAINFAILED); |
| 906 |
| 907 PKIX_CHECK(PKIX_List_GetLength(*pCerts, pNumCerts, plContext), |
| 908 PKIX_LISTGETLENGTHFAILED); |
| 909 |
| 910 /* extract relevant parameters from procParams */ |
| 911 PKIX_CHECK(PKIX_ValidateParams_GetProcessingParams |
| 912 (valParams, pProcParams, plContext), |
| 913 PKIX_VALIDATEPARAMSGETPROCESSINGPARAMSFAILED); |
| 914 |
| 915 PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors |
| 916 (*pProcParams, pAnchors, plContext), |
| 917 PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED); |
| 918 |
| 919 PKIX_CHECK(PKIX_List_GetLength(*pAnchors, pNumAnchors, plContext), |
| 920 PKIX_LISTGETLENGTHFAILED); |
| 921 |
| 922 cleanup: |
| 923 |
| 924 PKIX_RETURN(VALIDATE); |
| 925 } |
| 926 |
| 927 /* --Public-Functions--------------------------------------------- */ |
| 928 |
| 929 /* |
| 930 * FUNCTION: PKIX_ValidateChain (see comments in pkix.h) |
| 931 */ |
| 932 PKIX_Error * |
| 933 PKIX_ValidateChain( |
| 934 PKIX_ValidateParams *valParams, |
| 935 PKIX_ValidateResult **pResult, |
| 936 PKIX_VerifyNode **pVerifyTree, |
| 937 void *plContext) |
| 938 { |
| 939 PKIX_Error *chainFailed = NULL; |
| 940 |
| 941 PKIX_ProcessingParams *procParams = NULL; |
| 942 PKIX_CertChainChecker *userChecker = NULL; |
| 943 PKIX_RevocationChecker *revChecker = NULL; |
| 944 PKIX_List *certs = NULL; |
| 945 PKIX_List *checkers = NULL; |
| 946 PKIX_List *anchors = NULL; |
| 947 PKIX_List *userCheckers = NULL; |
| 948 PKIX_List *userCheckerExtOIDs = NULL; |
| 949 PKIX_List *validateCheckedCritExtOIDsList = NULL; |
| 950 PKIX_TrustAnchor *anchor = NULL; |
| 951 PKIX_ValidateResult *valResult = NULL; |
| 952 PKIX_PL_PublicKey *finalPubKey = NULL; |
| 953 PKIX_PolicyNode *validPolicyTree = NULL; |
| 954 PKIX_Boolean supportForwarding = PKIX_FALSE; |
| 955 PKIX_Boolean revChecking = PKIX_FALSE; |
| 956 PKIX_UInt32 i, numCerts, numAnchors; |
| 957 PKIX_UInt32 numUserCheckers = 0; |
| 958 PKIX_UInt32 certCheckedIndex = 0; |
| 959 PKIX_UInt32 checkerIndex = 0; |
| 960 PKIX_UInt32 reasonCode = 0; |
| 961 void *nbioContext = NULL; |
| 962 |
| 963 PKIX_ENTER(VALIDATE, "PKIX_ValidateChain"); |
| 964 PKIX_NULLCHECK_TWO(valParams, pResult); |
| 965 |
| 966 /* extract various parameters from valParams */ |
| 967 PKIX_CHECK(pkix_ExtractParameters |
| 968 (valParams, |
| 969 &certs, |
| 970 &numCerts, |
| 971 &procParams, |
| 972 &anchors, |
| 973 &numAnchors, |
| 974 plContext), |
| 975 PKIX_EXTRACTPARAMETERSFAILED); |
| 976 |
| 977 /* |
| 978 * setup an extension OID list that user had defined for his checker |
| 979 * processing. User checker is not responsible for taking out OIDs |
| 980 * from unresolved critical extension list as the libpkix checker |
| 981 * is doing. Here we add those user checkers' OIDs to the removal |
| 982 * list to be taken out by CheckChain |
| 983 */ |
| 984 PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers |
| 985 (procParams, &userCheckers, plContext), |
| 986 PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); |
| 987 |
| 988 if (userCheckers != NULL) { |
| 989 |
| 990 PKIX_CHECK(PKIX_List_Create |
| 991 (&validateCheckedCritExtOIDsList, |
| 992 plContext), |
| 993 PKIX_LISTCREATEFAILED); |
| 994 |
| 995 PKIX_CHECK(PKIX_List_GetLength |
| 996 (userCheckers, &numUserCheckers, plContext), |
| 997 PKIX_LISTGETLENGTHFAILED); |
| 998 |
| 999 for (i = 0; i < numUserCheckers; i++) { |
| 1000 |
| 1001 PKIX_CHECK(PKIX_List_GetItem |
| 1002 (userCheckers, |
| 1003 i, |
| 1004 (PKIX_PL_Object **) &userChecker, |
| 1005 plContext), |
| 1006 PKIX_LISTGETITEMFAILED); |
| 1007 |
| 1008 PKIX_CHECK |
| 1009 (PKIX_CertChainChecker_IsForwardCheckingSupported |
| 1010 (userChecker, &supportForwarding, plContext), |
| 1011 PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED); |
| 1012 |
| 1013 if (supportForwarding == PKIX_FALSE) { |
| 1014 |
| 1015 PKIX_CHECK |
| 1016 (PKIX_CertChainChecker_GetSupportedExtensions |
| 1017 (userChecker, &userCheckerExtOIDs, plContext), |
| 1018 PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); |
| 1019 |
| 1020 if (userCheckerExtOIDs != NULL) { |
| 1021 PKIX_CHECK(pkix_List_AppendList |
| 1022 (validateCheckedCritExtOIDsList, |
| 1023 userCheckerExtOIDs, |
| 1024 plContext), |
| 1025 PKIX_LISTAPPENDLISTFAILED); |
| 1026 } |
| 1027 } |
| 1028 |
| 1029 PKIX_DECREF(userCheckerExtOIDs); |
| 1030 PKIX_DECREF(userChecker); |
| 1031 } |
| 1032 } |
| 1033 |
| 1034 PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker |
| 1035 (procParams, &revChecker, plContext), |
| 1036 PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED); |
| 1037 |
| 1038 /* try to validate the chain with each anchor */ |
| 1039 for (i = 0; i < numAnchors; i++){ |
| 1040 |
| 1041 /* get trust anchor */ |
| 1042 PKIX_CHECK(PKIX_List_GetItem |
| 1043 (anchors, i, (PKIX_PL_Object **)&anchor, plContext), |
| 1044 PKIX_LISTGETITEMFAILED); |
| 1045 |
| 1046 /* initialize checkers using information from trust anchor */ |
| 1047 PKIX_CHECK(pkix_InitializeCheckers |
| 1048 (anchor, procParams, numCerts, &checkers, plContext), |
| 1049 PKIX_INITIALIZECHECKERSFAILED); |
| 1050 |
| 1051 /* |
| 1052 * Validate the chain using this trust anchor and these |
| 1053 * checkers. (WARNING: checkers that use non-blocking I/O |
| 1054 * are not currently supported.) |
| 1055 */ |
| 1056 certCheckedIndex = 0; |
| 1057 checkerIndex = 0; |
| 1058 revChecking = PKIX_FALSE; |
| 1059 chainFailed = pkix_CheckChain |
| 1060 (certs, |
| 1061 numCerts, |
| 1062 anchor, |
| 1063 checkers, |
| 1064 revChecker, |
| 1065 validateCheckedCritExtOIDsList, |
| 1066 procParams, |
| 1067 &certCheckedIndex, |
| 1068 &checkerIndex, |
| 1069 &revChecking, |
| 1070 &reasonCode, |
| 1071 &nbioContext, |
| 1072 &finalPubKey, |
| 1073 &validPolicyTree, |
| 1074 pVerifyTree, |
| 1075 plContext); |
| 1076 |
| 1077 if (chainFailed || (reasonCode != 0)) { |
| 1078 |
| 1079 /* cert chain failed to validate */ |
| 1080 |
| 1081 PKIX_DECREF(chainFailed); |
| 1082 PKIX_DECREF(anchor); |
| 1083 PKIX_DECREF(checkers); |
| 1084 PKIX_DECREF(validPolicyTree); |
| 1085 |
| 1086 /* if last anchor, we fail; else, we try next anchor */ |
| 1087 if (i == (numAnchors - 1)) { /* last anchor */ |
| 1088 PKIX_ERROR(PKIX_VALIDATECHAINFAILED); |
| 1089 } |
| 1090 |
| 1091 } else { |
| 1092 |
| 1093 /* cert chain successfully validated! */ |
| 1094 PKIX_CHECK(pkix_ValidateResult_Create |
| 1095 (finalPubKey, |
| 1096 anchor, |
| 1097 validPolicyTree, |
| 1098 &valResult, |
| 1099 plContext), |
| 1100 PKIX_VALIDATERESULTCREATEFAILED); |
| 1101 |
| 1102 *pResult = valResult; |
| 1103 |
| 1104 /* no need to try any more anchors in the loop */ |
| 1105 goto cleanup; |
| 1106 } |
| 1107 } |
| 1108 |
| 1109 cleanup: |
| 1110 |
| 1111 PKIX_DECREF(finalPubKey); |
| 1112 PKIX_DECREF(certs); |
| 1113 PKIX_DECREF(anchors); |
| 1114 PKIX_DECREF(anchor); |
| 1115 PKIX_DECREF(checkers); |
| 1116 PKIX_DECREF(revChecker); |
| 1117 PKIX_DECREF(validPolicyTree); |
| 1118 PKIX_DECREF(chainFailed); |
| 1119 PKIX_DECREF(procParams); |
| 1120 PKIX_DECREF(userCheckers); |
| 1121 PKIX_DECREF(validateCheckedCritExtOIDsList); |
| 1122 |
| 1123 PKIX_RETURN(VALIDATE); |
| 1124 } |
| 1125 |
| 1126 /* |
| 1127 * FUNCTION: pkix_Validate_BuildUserOIDs |
| 1128 * DESCRIPTION: |
| 1129 * |
| 1130 * This function creates a List of the OIDs that are processed by the user |
| 1131 * checkers in the List pointed to by "userCheckers", storing the resulting |
| 1132 * List at "pUserCritOIDs". If the List of userCheckers is NULL, the output |
| 1133 * List will be NULL. Otherwise the output List will be non-NULL, but may be |
| 1134 * empty. |
| 1135 * |
| 1136 * PARAMETERS: |
| 1137 * "userCheckers" |
| 1138 * The address of the List of userCheckers. |
| 1139 * "pUserCritOIDs" |
| 1140 * The address at which the List is stored. Must be non-NULL. |
| 1141 * "plContext" |
| 1142 * Platform-specific context pointer. |
| 1143 * THREAD SAFETY: |
| 1144 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| 1145 * RETURNS: |
| 1146 * Returns NULL if the function succeeds. |
| 1147 * Returns a VALIDATE Error if the function fails in a non-fatal way. |
| 1148 * Returns a Fatal Error if the function fails in an unrecoverable way. |
| 1149 */ |
| 1150 static PKIX_Error * |
| 1151 pkix_Validate_BuildUserOIDs( |
| 1152 PKIX_List *userCheckers, |
| 1153 PKIX_List **pUserCritOIDs, |
| 1154 void *plContext) |
| 1155 { |
| 1156 PKIX_UInt32 numUserCheckers = 0; |
| 1157 PKIX_UInt32 i = 0; |
| 1158 PKIX_List *userCritOIDs = NULL; |
| 1159 PKIX_List *userCheckerExtOIDs = NULL; |
| 1160 PKIX_Boolean supportForwarding = PKIX_FALSE; |
| 1161 PKIX_CertChainChecker *userChecker = NULL; |
| 1162 |
| 1163 PKIX_ENTER(VALIDATE, "pkix_Validate_BuildUserOIDs"); |
| 1164 PKIX_NULLCHECK_ONE(pUserCritOIDs); |
| 1165 |
| 1166 if (userCheckers != NULL) { |
| 1167 PKIX_CHECK(PKIX_List_Create(&userCritOIDs, plContext), |
| 1168 PKIX_LISTCREATEFAILED); |
| 1169 |
| 1170 PKIX_CHECK(PKIX_List_GetLength |
| 1171 (userCheckers, &numUserCheckers, plContext), |
| 1172 PKIX_LISTGETLENGTHFAILED); |
| 1173 |
| 1174 for (i = 0; i < numUserCheckers; i++) { |
| 1175 PKIX_CHECK(PKIX_List_GetItem |
| 1176 (userCheckers, |
| 1177 i, |
| 1178 (PKIX_PL_Object **) &userChecker, |
| 1179 plContext), |
| 1180 PKIX_LISTGETITEMFAILED); |
| 1181 |
| 1182 PKIX_CHECK(PKIX_CertChainChecker_IsForwardCheckingSupported |
| 1183 (userChecker, &supportForwarding, plContext), |
| 1184 PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED); |
| 1185 |
| 1186 if (supportForwarding == PKIX_FALSE) { |
| 1187 |
| 1188 PKIX_CHECK(PKIX_CertChainChecker_GetSupportedExtensions |
| 1189 (userChecker, &userCheckerExtOIDs, plContext), |
| 1190 PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); |
| 1191 |
| 1192 if (userCheckerExtOIDs != NULL) { |
| 1193 PKIX_CHECK(pkix_List_AppendList |
| 1194 (userCritOIDs, userCheckerExtOIDs, plContext), |
| 1195 PKIX_LISTAPPENDLISTFAILED); |
| 1196 } |
| 1197 } |
| 1198 |
| 1199 PKIX_DECREF(userCheckerExtOIDs); |
| 1200 PKIX_DECREF(userChecker); |
| 1201 } |
| 1202 } |
| 1203 |
| 1204 *pUserCritOIDs = userCritOIDs; |
| 1205 |
| 1206 cleanup: |
| 1207 |
| 1208 if (PKIX_ERROR_RECEIVED){ |
| 1209 PKIX_DECREF(userCritOIDs); |
| 1210 } |
| 1211 |
| 1212 PKIX_DECREF(userCheckerExtOIDs); |
| 1213 PKIX_DECREF(userChecker); |
| 1214 |
| 1215 PKIX_RETURN(VALIDATE); |
| 1216 } |
| 1217 |
| 1218 /* |
| 1219 * FUNCTION: PKIX_ValidateChain_nb (see comments in pkix.h) |
| 1220 */ |
| 1221 PKIX_Error * |
| 1222 PKIX_ValidateChain_NB( |
| 1223 PKIX_ValidateParams *valParams, |
| 1224 PKIX_UInt32 *pCertIndex, |
| 1225 PKIX_UInt32 *pAnchorIndex, |
| 1226 PKIX_UInt32 *pCheckerIndex, |
| 1227 PKIX_Boolean *pRevChecking, |
| 1228 PKIX_List **pCheckers, |
| 1229 void **pNBIOContext, |
| 1230 PKIX_ValidateResult **pResult, |
| 1231 PKIX_VerifyNode **pVerifyTree, |
| 1232 void *plContext) |
| 1233 { |
| 1234 PKIX_UInt32 numCerts = 0; |
| 1235 PKIX_UInt32 numAnchors = 0; |
| 1236 PKIX_UInt32 i = 0; |
| 1237 PKIX_UInt32 certIndex = 0; |
| 1238 PKIX_UInt32 anchorIndex = 0; |
| 1239 PKIX_UInt32 checkerIndex = 0; |
| 1240 PKIX_UInt32 reasonCode = 0; |
| 1241 PKIX_Boolean revChecking = PKIX_FALSE; |
| 1242 PKIX_List *certs = NULL; |
| 1243 PKIX_List *anchors = NULL; |
| 1244 PKIX_List *checkers = NULL; |
| 1245 PKIX_List *userCheckers = NULL; |
| 1246 PKIX_List *validateCheckedCritExtOIDsList = NULL; |
| 1247 PKIX_TrustAnchor *anchor = NULL; |
| 1248 PKIX_ValidateResult *valResult = NULL; |
| 1249 PKIX_PL_PublicKey *finalPubKey = NULL; |
| 1250 PKIX_PolicyNode *validPolicyTree = NULL; |
| 1251 PKIX_ProcessingParams *procParams = NULL; |
| 1252 PKIX_RevocationChecker *revChecker = NULL; |
| 1253 PKIX_Error *chainFailed = NULL; |
| 1254 void *nbioContext = NULL; |
| 1255 |
| 1256 PKIX_ENTER(VALIDATE, "PKIX_ValidateChain_NB"); |
| 1257 PKIX_NULLCHECK_FOUR |
| 1258 (valParams, pCertIndex, pAnchorIndex, pCheckerIndex); |
| 1259 PKIX_NULLCHECK_FOUR(pRevChecking, pCheckers, pNBIOContext, pResult); |
| 1260 |
| 1261 nbioContext = *pNBIOContext; |
| 1262 *pNBIOContext = NULL; |
| 1263 |
| 1264 /* extract various parameters from valParams */ |
| 1265 PKIX_CHECK(pkix_ExtractParameters |
| 1266 (valParams, |
| 1267 &certs, |
| 1268 &numCerts, |
| 1269 &procParams, |
| 1270 &anchors, |
| 1271 &numAnchors, |
| 1272 plContext), |
| 1273 PKIX_EXTRACTPARAMETERSFAILED); |
| 1274 |
| 1275 /* |
| 1276 * Create a List of the OIDs that will be processed by the user |
| 1277 * checkers. User checkers are not responsible for removing OIDs from |
| 1278 * the List of unresolved critical extensions, as libpkix checkers are. |
| 1279 * So we add those user checkers' OIDs to the removal list to be taken |
| 1280 * out by CheckChain. |
| 1281 */ |
| 1282 PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers |
| 1283 (procParams, &userCheckers, plContext), |
| 1284 PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); |
| 1285 |
| 1286 PKIX_CHECK(pkix_Validate_BuildUserOIDs |
| 1287 (userCheckers, &validateCheckedCritExtOIDsList, plContext), |
| 1288 PKIX_VALIDATEBUILDUSEROIDSFAILED); |
| 1289 |
| 1290 PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker |
| 1291 (procParams, &revChecker, plContext), |
| 1292 PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED); |
| 1293 |
| 1294 /* Are we resuming after a WOULDBLOCK return, or starting anew ? */ |
| 1295 if (nbioContext != NULL) { |
| 1296 /* Resuming */ |
| 1297 certIndex = *pCertIndex; |
| 1298 anchorIndex = *pAnchorIndex; |
| 1299 checkerIndex = *pCheckerIndex; |
| 1300 revChecking = *pRevChecking; |
| 1301 checkers = *pCheckers; |
| 1302 *pCheckers = NULL; |
| 1303 } |
| 1304 |
| 1305 /* try to validate the chain with each anchor */ |
| 1306 for (i = anchorIndex; i < numAnchors; i++) { |
| 1307 |
| 1308 /* get trust anchor */ |
| 1309 PKIX_CHECK(PKIX_List_GetItem |
| 1310 (anchors, i, (PKIX_PL_Object **)&anchor, plContext), |
| 1311 PKIX_LISTGETITEMFAILED); |
| 1312 |
| 1313 /* initialize checkers using information from trust anchor */ |
| 1314 if (nbioContext == NULL) { |
| 1315 PKIX_CHECK(pkix_InitializeCheckers |
| 1316 (anchor, |
| 1317 procParams, |
| 1318 numCerts, |
| 1319 &checkers, |
| 1320 plContext), |
| 1321 PKIX_INITIALIZECHECKERSFAILED); |
| 1322 } |
| 1323 |
| 1324 /* |
| 1325 * Validate the chain using this trust anchor and these |
| 1326 * checkers. |
| 1327 */ |
| 1328 chainFailed = pkix_CheckChain |
| 1329 (certs, |
| 1330 numCerts, |
| 1331 anchor, |
| 1332 checkers, |
| 1333 revChecker, |
| 1334 validateCheckedCritExtOIDsList, |
| 1335 procParams, |
| 1336 &certIndex, |
| 1337 &checkerIndex, |
| 1338 &revChecking, |
| 1339 &reasonCode, |
| 1340 &nbioContext, |
| 1341 &finalPubKey, |
| 1342 &validPolicyTree, |
| 1343 pVerifyTree, |
| 1344 plContext); |
| 1345 |
| 1346 if (nbioContext != NULL) { |
| 1347 *pCertIndex = certIndex; |
| 1348 *pAnchorIndex = anchorIndex; |
| 1349 *pCheckerIndex = checkerIndex; |
| 1350 *pRevChecking = revChecking; |
| 1351 PKIX_INCREF(checkers); |
| 1352 *pCheckers = checkers; |
| 1353 *pNBIOContext = nbioContext; |
| 1354 goto cleanup; |
| 1355 } |
| 1356 |
| 1357 if (chainFailed || (reasonCode != 0)) { |
| 1358 |
| 1359 /* cert chain failed to validate */ |
| 1360 |
| 1361 PKIX_DECREF(chainFailed); |
| 1362 PKIX_DECREF(anchor); |
| 1363 PKIX_DECREF(checkers); |
| 1364 PKIX_DECREF(validPolicyTree); |
| 1365 |
| 1366 /* if last anchor, we fail; else, we try next anchor */ |
| 1367 if (i == (numAnchors - 1)) { /* last anchor */ |
| 1368 PKIX_ERROR(PKIX_VALIDATECHAINFAILED); |
| 1369 } |
| 1370 |
| 1371 } else { |
| 1372 |
| 1373 /* cert chain successfully validated! */ |
| 1374 PKIX_CHECK(pkix_ValidateResult_Create |
| 1375 (finalPubKey, |
| 1376 anchor, |
| 1377 validPolicyTree, |
| 1378 &valResult, |
| 1379 plContext), |
| 1380 PKIX_VALIDATERESULTCREATEFAILED); |
| 1381 |
| 1382 *pResult = valResult; |
| 1383 |
| 1384 /* no need to try any more anchors in the loop */ |
| 1385 goto cleanup; |
| 1386 } |
| 1387 } |
| 1388 |
| 1389 cleanup: |
| 1390 |
| 1391 PKIX_DECREF(finalPubKey); |
| 1392 PKIX_DECREF(certs); |
| 1393 PKIX_DECREF(anchors); |
| 1394 PKIX_DECREF(anchor); |
| 1395 PKIX_DECREF(checkers); |
| 1396 PKIX_DECREF(revChecker); |
| 1397 PKIX_DECREF(validPolicyTree); |
| 1398 PKIX_DECREF(chainFailed); |
| 1399 PKIX_DECREF(procParams); |
| 1400 PKIX_DECREF(userCheckers); |
| 1401 PKIX_DECREF(validateCheckedCritExtOIDsList); |
| 1402 |
| 1403 PKIX_RETURN(VALIDATE); |
| 1404 } |
| OLD | NEW |