certvfypkix.c (72061B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* 5 * nss_pkix_proxy.h 6 * 7 * PKIX - NSS proxy functions 8 * 9 * NOTE: All structures, functions, data types are parts of library private 10 * api and are subjects to change in any following releases. 11 * 12 */ 13 #include "prerror.h" 14 #include "prprf.h" 15 16 #include "nspr.h" 17 #include "pk11func.h" 18 #include "certdb.h" 19 #include "cert.h" 20 #include "secerr.h" 21 #include "nssb64.h" 22 #include "secasn1.h" 23 #include "secder.h" 24 #include "pkit.h" 25 26 #ifndef NSS_DISABLE_LIBPKIX 27 #include "pkix_pl_common.h" 28 29 extern PRLogModuleInfo *pkixLog; 30 31 #ifdef PKIX_OBJECT_LEAK_TEST 32 33 extern PKIX_UInt32 34 pkix_pl_lifecycle_ObjectLeakCheck(int *); 35 36 extern SECStatus 37 pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable); 38 39 PRInt32 parallelFnInvocationCount; 40 #endif /* PKIX_OBJECT_LEAK_TEST */ 41 42 static PRBool usePKIXValidationEngine = PR_TRUE; 43 #endif /* NSS_DISABLE_LIBPKIX */ 44 45 /* 46 * FUNCTION: CERT_SetUsePKIXForValidation 47 * DESCRIPTION: 48 * 49 * Enables or disables use of libpkix for certificate validation 50 * 51 * PARAMETERS: 52 * "enable" 53 * PR_TRUE: enables use of libpkix for cert validation. 54 * PR_FALSE: disables. 55 * THREAD SAFETY: 56 * NOT Thread Safe. 57 * RETURNS: 58 * Returns SECSuccess if successfully enabled 59 */ 60 SECStatus 61 CERT_SetUsePKIXForValidation(PRBool enable) 62 { 63 #ifdef NSS_DISABLE_LIBPKIX 64 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 65 return SECFailure; 66 #else 67 usePKIXValidationEngine = (enable > 0) ? PR_TRUE : PR_FALSE; 68 return SECSuccess; 69 #endif /* NSS_DISABLE_LIBPKIX */ 70 } 71 72 /* 73 * FUNCTION: CERT_GetUsePKIXForValidation 74 * DESCRIPTION: 75 * 76 * Checks if libpkix building function should be use for certificate 77 * chain building. 78 * 79 * PARAMETERS: 80 * NONE 81 * THREAD SAFETY: 82 * NOT Thread Safe 83 * RETURNS: 84 * Returns PR_TRUE if libpkix should be used. PR_FALSE otherwise. 85 */ 86 PRBool 87 CERT_GetUsePKIXForValidation() 88 { 89 #ifdef NSS_DISABLE_LIBPKIX 90 return PR_FALSE; 91 #else 92 return usePKIXValidationEngine; 93 #endif /* NSS_DISABLE_LIBPKIX */ 94 } 95 96 #ifndef NSS_DISABLE_LIBPKIX 97 #ifdef NOTDEF 98 /* 99 * FUNCTION: cert_NssKeyUsagesToPkix 100 * DESCRIPTION: 101 * 102 * Converts nss key usage bit field(PRUint32) to pkix key usage 103 * bit field. 104 * 105 * PARAMETERS: 106 * "nssKeyUsage" 107 * Nss key usage bit field. 108 * "pkixKeyUsage" 109 * Pkix key usage big field. 110 * "plContext" 111 * Platform-specific context pointer. 112 * THREAD SAFETY: 113 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 114 * RETURNS: 115 * Returns NULL if the function succeeds. 116 * Returns a Fatal Error if the function fails in an unrecoverable way. 117 */ 118 static PKIX_Error * 119 cert_NssKeyUsagesToPkix( 120 PRUint32 nssKeyUsage, 121 PKIX_UInt32 *pPkixKeyUsage, 122 void *plContext) 123 { 124 PKIX_UInt32 pkixKeyUsage = 0; 125 126 PKIX_ENTER(CERTVFYPKIX, "cert_NssKeyUsagesToPkix"); 127 PKIX_NULLCHECK_ONE(pPkixKeyUsage); 128 129 *pPkixKeyUsage = 0; 130 131 if (nssKeyUsage & KU_DIGITAL_SIGNATURE) { 132 pkixKeyUsage |= PKIX_DIGITAL_SIGNATURE; 133 } 134 135 if (nssKeyUsage & KU_NON_REPUDIATION) { 136 pkixKeyUsage |= PKIX_NON_REPUDIATION; 137 } 138 139 if (nssKeyUsage & KU_KEY_ENCIPHERMENT) { 140 pkixKeyUsage |= PKIX_KEY_ENCIPHERMENT; 141 } 142 143 if (nssKeyUsage & KU_DATA_ENCIPHERMENT) { 144 pkixKeyUsage |= PKIX_DATA_ENCIPHERMENT; 145 } 146 147 if (nssKeyUsage & KU_KEY_AGREEMENT) { 148 pkixKeyUsage |= PKIX_KEY_AGREEMENT; 149 } 150 151 if (nssKeyUsage & KU_KEY_CERT_SIGN) { 152 pkixKeyUsage |= PKIX_KEY_CERT_SIGN; 153 } 154 155 if (nssKeyUsage & KU_CRL_SIGN) { 156 pkixKeyUsage |= PKIX_CRL_SIGN; 157 } 158 159 if (nssKeyUsage & KU_ENCIPHER_ONLY) { 160 pkixKeyUsage |= PKIX_ENCIPHER_ONLY; 161 } 162 163 /* Not supported. XXX we should support this once it is 164 * fixed in NSS */ 165 /* pkixKeyUsage |= PKIX_DECIPHER_ONLY; */ 166 167 *pPkixKeyUsage = pkixKeyUsage; 168 169 PKIX_RETURN(CERTVFYPKIX); 170 } 171 172 extern SECOidTag ekuOidStrings[]; 173 174 enum { 175 ekuIndexSSLServer = 0, 176 ekuIndexSSLClient, 177 ekuIndexCodeSigner, 178 ekuIndexEmail, 179 ekuIndexTimeStamp, 180 ekuIndexStatusResponder, 181 ekuIndexUnknown 182 } ekuIndex; 183 184 typedef struct { 185 SECCertUsage certUsage; 186 PRUint32 ekuStringIndex; 187 } SECCertUsageToEku; 188 189 const SECCertUsageToEku certUsageEkuStringMap[] = { 190 { certUsageSSLClient, ekuIndexSSLClient }, 191 { certUsageSSLServer, ekuIndexSSLServer }, 192 { certUsageSSLCA, ekuIndexSSLServer }, 193 { certUsageEmailSigner, ekuIndexEmail }, 194 { certUsageEmailRecipient, ekuIndexEmail }, 195 { certUsageObjectSigner, ekuIndexCodeSigner }, 196 { certUsageUserCertImport, ekuIndexUnknown }, 197 { certUsageVerifyCA, ekuIndexUnknown }, 198 { certUsageProtectedObjectSigner, ekuIndexUnknown }, 199 { certUsageStatusResponder, ekuIndexStatusResponder }, 200 { certUsageAnyCA, ekuIndexUnknown }, 201 }; 202 203 /* 204 * FUNCTION: cert_NssCertificateUsageToPkixKUAndEKU 205 * DESCRIPTION: 206 * 207 * Converts nss CERTCertificateUsage bit field to pkix key and 208 * extended key usages. 209 * 210 * PARAMETERS: 211 * "cert" 212 * Pointer to CERTCertificate structure of validating cert. 213 * "requiredCertUsages" 214 * Required usage that will be converted to pkix eku and ku. 215 * "requiredKeyUsage", 216 * Additional key usages impose to cert. 217 * "isCA", 218 * it true, convert usages for cert that is a CA cert. 219 * "ppkixEKUList" 220 * Returned address of a list of pkix extended key usages. 221 * "ppkixKU" 222 * Returned address of pkix required key usages bit field. 223 * "plContext" 224 * Platform-specific context pointer. 225 * THREAD SAFETY: 226 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 227 * RETURNS: 228 * Returns NULL if the function succeeds. 229 * Returns a Cert Verify Error if the function fails in an unrecoverable way. 230 * Returns a Fatal Error if the function fails in an unrecoverable way. 231 */ 232 static PKIX_Error * 233 cert_NssCertificateUsageToPkixKUAndEKU( 234 CERTCertificate *cert, 235 SECCertUsage requiredCertUsage, 236 PRUint32 requiredKeyUsages, 237 PRBool isCA, 238 PKIX_List **ppkixEKUList, 239 PKIX_UInt32 *ppkixKU, 240 void *plContext) 241 { 242 PKIX_List *ekuOidsList = NULL; 243 PKIX_PL_OID *ekuOid = NULL; 244 int i = 0; 245 int ekuIndex = ekuIndexUnknown; 246 247 PKIX_ENTER(CERTVFYPKIX, "cert_NssCertificateUsageToPkixEku"); 248 PKIX_NULLCHECK_TWO(ppkixEKUList, ppkixKU); 249 250 PKIX_CHECK( 251 PKIX_List_Create(&ekuOidsList, plContext), 252 PKIX_LISTCREATEFAILED); 253 254 for (; i < PR_ARRAY_SIZE(certUsageEkuStringMap); i++) { 255 const SECCertUsageToEku *usageToEkuElem = 256 &certUsageEkuStringMap[i]; 257 if (usageToEkuElem->certUsage == requiredCertUsage) { 258 ekuIndex = usageToEkuElem->ekuStringIndex; 259 break; 260 } 261 } 262 if (ekuIndex != ekuIndexUnknown) { 263 PRUint32 reqKeyUsage = 0; 264 PRUint32 reqCertType = 0; 265 266 CERT_KeyUsageAndTypeForCertUsage(requiredCertUsage, isCA, 267 &reqKeyUsage, 268 &reqCertType); 269 270 requiredKeyUsages |= reqKeyUsage; 271 272 PKIX_CHECK( 273 PKIX_PL_OID_Create(ekuOidStrings[ekuIndex], &ekuOid, 274 plContext), 275 PKIX_OIDCREATEFAILED); 276 277 PKIX_CHECK( 278 PKIX_List_AppendItem(ekuOidsList, (PKIX_PL_Object *)ekuOid, 279 plContext), 280 PKIX_LISTAPPENDITEMFAILED); 281 282 PKIX_DECREF(ekuOid); 283 } 284 285 PKIX_CHECK( 286 cert_NssKeyUsagesToPkix(requiredKeyUsages, ppkixKU, plContext), 287 PKIX_NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED); 288 289 *ppkixEKUList = ekuOidsList; 290 ekuOidsList = NULL; 291 292 cleanup: 293 294 PKIX_DECREF(ekuOid); 295 PKIX_DECREF(ekuOidsList); 296 297 PKIX_RETURN(CERTVFYPKIX); 298 } 299 300 #endif 301 302 /* 303 * FUNCTION: cert_ProcessingParamsSetKeyAndCertUsage 304 * DESCRIPTION: 305 * 306 * Converts cert usage to pkix KU type and sets 307 * converted data into PKIX_ProcessingParams object. It also sets 308 * proper cert usage into nsscontext object. 309 * 310 * PARAMETERS: 311 * "procParams" 312 * Pointer to PKIX_ProcessingParams used during validation. 313 * "requiredCertUsage" 314 * Required certificate usages the certificate and chain is built and 315 * validated for. 316 * "requiredKeyUsage" 317 * Request additional key usages the certificate should be validated for. 318 * "plContext" 319 * Platform-specific context pointer. 320 * THREAD SAFETY: 321 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 322 * RETURNS: 323 * Returns NULL if the function succeeds. 324 * Returns a Cert Verify Error if the function fails in an unrecoverable way. 325 * Returns a Fatal Error if the function fails in an unrecoverable way. 326 */ 327 static PKIX_Error * 328 cert_ProcessingParamsSetKeyAndCertUsage( 329 PKIX_ProcessingParams *procParams, 330 SECCertUsage requiredCertUsage, 331 PRUint32 requiredKeyUsages, 332 void *plContext) 333 { 334 PKIX_CertSelector *certSelector = NULL; 335 PKIX_ComCertSelParams *certSelParams = NULL; 336 PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext *)plContext; 337 338 PKIX_ENTER(CERTVFYPKIX, "cert_ProcessingParamsSetKeyAndCertUsage"); 339 PKIX_NULLCHECK_TWO(procParams, nssContext); 340 341 PKIX_CHECK( 342 pkix_pl_NssContext_SetCertUsage( 343 ((SECCertificateUsage)1) << requiredCertUsage, nssContext), 344 PKIX_NSSCONTEXTSETCERTUSAGEFAILED); 345 346 if (requiredKeyUsages) { 347 PKIX_CHECK( 348 PKIX_ProcessingParams_GetTargetCertConstraints(procParams, 349 &certSelector, plContext), 350 PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); 351 352 PKIX_CHECK( 353 PKIX_CertSelector_GetCommonCertSelectorParams(certSelector, 354 &certSelParams, plContext), 355 PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); 356 357 PKIX_CHECK( 358 PKIX_ComCertSelParams_SetKeyUsage(certSelParams, requiredKeyUsages, 359 plContext), 360 PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED); 361 } 362 cleanup: 363 PKIX_DECREF(certSelector); 364 PKIX_DECREF(certSelParams); 365 366 PKIX_RETURN(CERTVFYPKIX); 367 } 368 369 /* 370 * Unused parameters: 371 * 372 * CERTCertList *initialChain, 373 * CERTCertStores certStores, 374 * CERTCertRevCheckers certRevCheckers, 375 * CERTCertChainCheckers certChainCheckers, 376 * SECItem *initPolicies, 377 * PRBool policyQualifierRejected, 378 * PRBool anyPolicyInhibited, 379 * PRBool reqExplicitPolicy, 380 * PRBool policyMappingInhibited, 381 * PKIX_CertSelector certConstraints, 382 */ 383 384 /* 385 * FUNCTION: cert_CreatePkixProcessingParams 386 * DESCRIPTION: 387 * 388 * Creates and fills in PKIX_ProcessingParams structure to be used 389 * for certificate chain building. 390 * 391 * PARAMETERS: 392 * "cert" 393 * Pointer to the CERTCertificate: the leaf certificate of a chain. 394 * "time" 395 * Validity time. 396 * "wincx" 397 * Nss db password token. 398 * "useArena" 399 * Flags to use arena for data allocation during chain building process. 400 * "pprocParams" 401 * Address to return created processing parameters. 402 * "plContext" 403 * Platform-specific context pointer. 404 * THREAD SAFETY: 405 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 406 * RETURNS: 407 * Returns NULL if the function succeeds. 408 * Returns a Cert Verify Error if the function fails in an unrecoverable way. 409 * Returns a Fatal Error if the function fails in an unrecoverable way. 410 */ 411 static PKIX_Error * 412 cert_CreatePkixProcessingParams( 413 CERTCertificate *cert, 414 PRBool checkSig, 415 PRTime time, 416 void *wincx, 417 PRBool useArena, 418 PRBool disableOCSPRemoteFetching, 419 PKIX_ProcessingParams **pprocParams, 420 void **pplContext) 421 { 422 PKIX_List *anchors = NULL; 423 PKIX_PL_Cert *targetCert = NULL; 424 PKIX_PL_Date *date = NULL; 425 PKIX_ProcessingParams *procParams = NULL; 426 PKIX_CertSelector *certSelector = NULL; 427 PKIX_ComCertSelParams *certSelParams = NULL; 428 PKIX_CertStore *certStore = NULL; 429 PKIX_List *certStores = NULL; 430 PKIX_RevocationChecker *revChecker = NULL; 431 PKIX_UInt32 methodFlags = 0; 432 void *plContext = NULL; 433 CERTStatusConfig *statusConfig = NULL; 434 435 PKIX_ENTER(CERTVFYPKIX, "cert_CreatePkixProcessingParams"); 436 PKIX_NULLCHECK_TWO(cert, pprocParams); 437 438 PKIX_CHECK( 439 PKIX_PL_NssContext_Create(0, useArena, wincx, &plContext), 440 PKIX_NSSCONTEXTCREATEFAILED); 441 442 *pplContext = plContext; 443 444 /* Functions should be implemented in patch for 390532 */ 445 PKIX_CHECK( 446 pkix_pl_NssContext_SetCertSignatureCheck(checkSig, 447 (PKIX_PL_NssContext *)plContext), 448 PKIX_NSSCONTEXTSETCERTSIGNCHECKFAILED); 449 450 PKIX_CHECK( 451 PKIX_ProcessingParams_Create(&procParams, plContext), 452 PKIX_PROCESSINGPARAMSCREATEFAILED); 453 454 PKIX_CHECK( 455 PKIX_ComCertSelParams_Create(&certSelParams, plContext), 456 PKIX_COMCERTSELPARAMSCREATEFAILED); 457 458 PKIX_CHECK( 459 PKIX_PL_Cert_CreateFromCERTCertificate(cert, &targetCert, plContext), 460 PKIX_CERTCREATEWITHNSSCERTFAILED); 461 462 PKIX_CHECK( 463 PKIX_ComCertSelParams_SetCertificate(certSelParams, 464 targetCert, plContext), 465 PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED); 466 467 PKIX_CHECK( 468 PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext), 469 PKIX_COULDNOTCREATECERTSELECTOROBJECT); 470 471 PKIX_CHECK( 472 PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, 473 certSelParams, plContext), 474 PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED); 475 476 PKIX_CHECK( 477 PKIX_ProcessingParams_SetTargetCertConstraints(procParams, 478 certSelector, plContext), 479 PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED); 480 481 /* Turn off quialification of target cert since leaf cert is 482 * already check for date validity, key usages and extended 483 * key usages. */ 484 PKIX_CHECK( 485 PKIX_ProcessingParams_SetQualifyTargetCert(procParams, PKIX_FALSE, 486 plContext), 487 PKIX_PROCESSINGPARAMSSETQUALIFYTARGETCERTFLAGFAILED); 488 489 PKIX_CHECK( 490 PKIX_PL_Pk11CertStore_Create(&certStore, plContext), 491 PKIX_PK11CERTSTORECREATEFAILED); 492 493 PKIX_CHECK( 494 PKIX_List_Create(&certStores, plContext), 495 PKIX_UNABLETOCREATELIST); 496 497 PKIX_CHECK( 498 PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore, 499 plContext), 500 PKIX_LISTAPPENDITEMFAILED); 501 502 PKIX_CHECK( 503 PKIX_ProcessingParams_SetCertStores(procParams, certStores, 504 plContext), 505 PKIX_PROCESSINGPARAMSADDCERTSTOREFAILED); 506 507 PKIX_CHECK( 508 PKIX_PL_Date_CreateFromPRTime(time, &date, plContext), 509 PKIX_DATECREATEFROMPRTIMEFAILED); 510 511 PKIX_CHECK( 512 PKIX_ProcessingParams_SetDate(procParams, date, plContext), 513 PKIX_PROCESSINGPARAMSSETDATEFAILED); 514 515 PKIX_CHECK( 516 PKIX_RevocationChecker_Create( 517 PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST | 518 PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT, 519 PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST | 520 PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT, 521 &revChecker, plContext), 522 PKIX_REVOCATIONCHECKERCREATEFAILED); 523 524 PKIX_CHECK( 525 PKIX_ProcessingParams_SetRevocationChecker(procParams, revChecker, 526 plContext), 527 PKIX_PROCESSINGPARAMSSETREVOCATIONCHECKERFAILED); 528 529 /* CRL method flags */ 530 methodFlags = 531 PKIX_REV_M_TEST_USING_THIS_METHOD | 532 PKIX_REV_M_FORBID_NETWORK_FETCHING | 533 PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE | /* 0 */ 534 PKIX_REV_M_IGNORE_MISSING_FRESH_INFO | /* 0 */ 535 PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO; 536 537 /* add CRL revocation method to check the leaf certificate */ 538 PKIX_CHECK( 539 PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams, 540 PKIX_RevocationMethod_CRL, methodFlags, 541 0, NULL, PKIX_TRUE, plContext), 542 PKIX_REVOCATIONCHECKERADDMETHODFAILED); 543 544 /* add CRL revocation method for other certs in the chain. */ 545 PKIX_CHECK( 546 PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams, 547 PKIX_RevocationMethod_CRL, methodFlags, 548 0, NULL, PKIX_FALSE, plContext), 549 PKIX_REVOCATIONCHECKERADDMETHODFAILED); 550 551 /* For compatibility with the old code, need to check that 552 * statusConfig is set in the db handle and status checker 553 * is defined befor allow ocsp status check on the leaf cert.*/ 554 statusConfig = CERT_GetStatusConfig(CERT_GetDefaultCertDB()); 555 if (statusConfig != NULL && statusConfig->statusChecker != NULL) { 556 557 /* Enable OCSP revocation checking for the leaf cert. */ 558 /* OCSP method flags */ 559 methodFlags = 560 PKIX_REV_M_TEST_USING_THIS_METHOD | 561 PKIX_REV_M_ALLOW_NETWORK_FETCHING | /* 0 */ 562 PKIX_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE | /* 0 */ 563 PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE | /* 0 */ 564 PKIX_REV_M_IGNORE_MISSING_FRESH_INFO | /* 0 */ 565 PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO; 566 567 /* Disabling ocsp fetching when checking the status 568 * of ocsp response signer. Here and in the next if, 569 * adjust flags for ocsp signer cert validation case. */ 570 if (disableOCSPRemoteFetching) { 571 methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING; 572 } 573 574 if (ocsp_FetchingFailureIsVerificationFailure() && 575 !disableOCSPRemoteFetching) { 576 methodFlags |= 577 PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO; 578 } 579 580 /* add OCSP revocation method to check only the leaf certificate.*/ 581 PKIX_CHECK( 582 PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams, 583 PKIX_RevocationMethod_OCSP, methodFlags, 584 1, NULL, PKIX_TRUE, plContext), 585 PKIX_REVOCATIONCHECKERADDMETHODFAILED); 586 } 587 588 PKIX_CHECK( 589 PKIX_ProcessingParams_SetAnyPolicyInhibited(procParams, PR_FALSE, 590 plContext), 591 PKIX_PROCESSINGPARAMSSETANYPOLICYINHIBITED); 592 593 PKIX_CHECK( 594 PKIX_ProcessingParams_SetExplicitPolicyRequired(procParams, PR_FALSE, 595 plContext), 596 PKIX_PROCESSINGPARAMSSETEXPLICITPOLICYREQUIRED); 597 598 PKIX_CHECK( 599 PKIX_ProcessingParams_SetPolicyMappingInhibited(procParams, PR_FALSE, 600 plContext), 601 PKIX_PROCESSINGPARAMSSETPOLICYMAPPINGINHIBITED); 602 603 *pprocParams = procParams; 604 procParams = NULL; 605 606 cleanup: 607 PKIX_DECREF(anchors); 608 PKIX_DECREF(targetCert); 609 PKIX_DECREF(date); 610 PKIX_DECREF(certSelector); 611 PKIX_DECREF(certSelParams); 612 PKIX_DECREF(certStore); 613 PKIX_DECREF(certStores); 614 PKIX_DECREF(procParams); 615 PKIX_DECREF(revChecker); 616 617 PKIX_RETURN(CERTVFYPKIX); 618 } 619 620 /* 621 * FUNCTION: cert_PkixToNssCertsChain 622 * DESCRIPTION: 623 * 624 * Converts pkix cert list into nss cert list. 625 * 626 * PARAMETERS: 627 * "pkixCertChain" 628 * Pkix certificate list. 629 * "pvalidChain" 630 * An address of returned nss certificate list. 631 * "plContext" 632 * Platform-specific context pointer. 633 * THREAD SAFETY: 634 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 635 * RETURNS: 636 * Returns NULL if the function succeeds. 637 * Returns a Cert Verify Error if the function fails in an unrecoverable way. 638 * Returns a Fatal Error if the function fails in an unrecoverable way. 639 */ 640 static PKIX_Error * 641 cert_PkixToNssCertsChain( 642 PKIX_List *pkixCertChain, 643 CERTCertList **pvalidChain, 644 void *plContext) 645 { 646 PLArenaPool *arena = NULL; 647 CERTCertificate *nssCert = NULL; 648 CERTCertList *validChain = NULL; 649 PKIX_PL_Object *certItem = NULL; 650 PKIX_UInt32 length = 0; 651 PKIX_UInt32 i = 0; 652 653 PKIX_ENTER(CERTVFYPKIX, "cert_PkixToNssCertsChain"); 654 PKIX_NULLCHECK_ONE(pvalidChain); 655 656 if (pkixCertChain == NULL) { 657 goto cleanup; 658 } 659 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 660 if (arena == NULL) { 661 PKIX_ERROR(PKIX_OUTOFMEMORY); 662 } 663 validChain = (CERTCertList *)PORT_ArenaZAlloc(arena, sizeof(CERTCertList)); 664 if (validChain == NULL) { 665 PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); 666 } 667 PR_INIT_CLIST(&validChain->list); 668 validChain->arena = arena; 669 arena = NULL; 670 671 PKIX_CHECK( 672 PKIX_List_GetLength(pkixCertChain, &length, plContext), 673 PKIX_LISTGETLENGTHFAILED); 674 675 for (i = 0; i < length; i++) { 676 CERTCertListNode *node = NULL; 677 678 PKIX_CHECK( 679 PKIX_List_GetItem(pkixCertChain, i, &certItem, plContext), 680 PKIX_LISTGETITEMFAILED); 681 682 PKIX_CHECK( 683 PKIX_PL_Cert_GetCERTCertificate((PKIX_PL_Cert *)certItem, &nssCert, 684 plContext), 685 PKIX_CERTGETCERTCERTIFICATEFAILED); 686 687 node = 688 (CERTCertListNode *)PORT_ArenaZAlloc(validChain->arena, 689 sizeof(CERTCertListNode)); 690 if (node == NULL) { 691 PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); 692 } 693 694 PR_INSERT_BEFORE(&node->links, &validChain->list); 695 696 node->cert = nssCert; 697 nssCert = NULL; 698 699 PKIX_DECREF(certItem); 700 } 701 702 *pvalidChain = validChain; 703 704 cleanup: 705 if (PKIX_ERROR_RECEIVED) { 706 if (validChain) { 707 CERT_DestroyCertList(validChain); 708 } else if (arena) { 709 PORT_FreeArena(arena, PR_FALSE); 710 } 711 if (nssCert) { 712 CERT_DestroyCertificate(nssCert); 713 } 714 } 715 PKIX_DECREF(certItem); 716 717 PKIX_RETURN(CERTVFYPKIX); 718 } 719 720 /* 721 * FUNCTION: cert_BuildAndValidateChain 722 * DESCRIPTION: 723 * 724 * The function builds and validates a cert chain based on certificate 725 * selection criterias from procParams. This function call PKIX_BuildChain 726 * to accomplish chain building. If PKIX_BuildChain returns with incomplete 727 * IO, the function waits with PR_Poll until the blocking IO is finished and 728 * return control back to PKIX_BuildChain. 729 * 730 * PARAMETERS: 731 * "procParams" 732 * Processing parameters to be used during chain building. 733 * "pResult" 734 * Returned build result. 735 * "pVerifyNode" 736 * Returned pointed to verify node structure: the tree-like structure 737 * that reports points of chain building failures. 738 * "plContext" 739 * Platform-specific context pointer. 740 * THREAD SAFETY: 741 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 742 * RETURNS: 743 * Returns NULL if the function succeeds. 744 * Returns a Cert Verify Error if the function fails in an unrecoverable way. 745 * Returns a Fatal Error if the function fails in an unrecoverable way. 746 */ 747 static PKIX_Error * 748 cert_BuildAndValidateChain( 749 PKIX_ProcessingParams *procParams, 750 PKIX_BuildResult **pResult, 751 PKIX_VerifyNode **pVerifyNode, 752 void *plContext) 753 { 754 PKIX_BuildResult *result = NULL; 755 PKIX_VerifyNode *verifyNode = NULL; 756 void *nbioContext = NULL; 757 void *state = NULL; 758 759 PKIX_ENTER(CERTVFYPKIX, "cert_BuildAndVerifyChain"); 760 PKIX_NULLCHECK_TWO(procParams, pResult); 761 762 do { 763 if (nbioContext && state) { 764 /* PKIX-XXX: need to test functionality of NBIO handling in libPkix. 765 * See bug 391180 */ 766 PRInt32 filesReady = 0; 767 PRPollDesc *pollDesc = (PRPollDesc *)nbioContext; 768 filesReady = PR_Poll(pollDesc, 1, PR_INTERVAL_NO_TIMEOUT); 769 if (filesReady <= 0) { 770 PKIX_ERROR(PKIX_PRPOLLRETBADFILENUM); 771 } 772 } 773 774 PKIX_CHECK( 775 PKIX_BuildChain(procParams, &nbioContext, &state, 776 &result, &verifyNode, plContext), 777 PKIX_UNABLETOBUILDCHAIN); 778 779 } while (nbioContext && state); 780 781 *pResult = result; 782 783 cleanup: 784 if (pVerifyNode) { 785 *pVerifyNode = verifyNode; 786 } 787 788 PKIX_RETURN(CERTVFYPKIX); 789 } 790 791 /* 792 * FUNCTION: cert_PkixErrorToNssCode 793 * DESCRIPTION: 794 * 795 * Converts pkix error(PKIX_Error) structure to PR error codes. 796 * 797 * PKIX-XXX to be implemented. See 391183. 798 * 799 * PARAMETERS: 800 * "error" 801 * Pkix error that will be converted. 802 * "nssCode" 803 * Corresponding nss error code. 804 * "plContext" 805 * Platform-specific context pointer. 806 * THREAD SAFETY: 807 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 808 * RETURNS: 809 * Returns NULL if the function succeeds. 810 * Returns a Cert Verify Error if the function fails in an unrecoverable way. 811 * Returns a Fatal Error if the function fails in an unrecoverable way. 812 */ 813 static PKIX_Error * 814 cert_PkixErrorToNssCode( 815 PKIX_Error *error, 816 SECErrorCodes *pNssErr, 817 void *plContext) 818 { 819 int errLevel = 0; 820 (void)errLevel; /* Suppress unused var warning (Bug 1738028) */ 821 822 PKIX_Int32 nssErr = 0; 823 PKIX_Error *errPtr = error; 824 825 PKIX_ENTER(CERTVFYPKIX, "cert_PkixErrorToNssCode"); 826 PKIX_NULLCHECK_TWO(error, pNssErr); 827 828 /* Loop until we find at least one error with non-null 829 * plErr code, that is going to be nss error code. */ 830 while (errPtr) { 831 if (errPtr->plErr && !nssErr) { 832 nssErr = errPtr->plErr; 833 if (!pkixLog) 834 break; 835 } 836 if (pkixLog) { 837 #ifdef PKIX_ERROR_DESCRIPTION 838 PR_LOG(pkixLog, 2, ("Error at level %d: %s\n", errLevel, PKIX_ErrorText[errPtr->errCode])); 839 #else 840 PR_LOG(pkixLog, 2, ("Error at level %d: Error code %d\n", errLevel, errPtr->errCode)); 841 #endif /* PKIX_ERROR_DESCRIPTION */ 842 } 843 errPtr = errPtr->cause; 844 errLevel += 1; 845 } 846 PORT_Assert(nssErr); 847 if (!nssErr) { 848 *pNssErr = SEC_ERROR_LIBPKIX_INTERNAL; 849 } else { 850 *pNssErr = nssErr; 851 } 852 853 PKIX_RETURN(CERTVFYPKIX); 854 } 855 856 /* 857 * FUNCTION: cert_GetLogFromVerifyNode 858 * DESCRIPTION: 859 * 860 * Recursive function that converts verify node tree-like set of structures 861 * to CERTVerifyLog. 862 * 863 * PARAMETERS: 864 * "log" 865 * Pointed to already allocated CERTVerifyLog structure. 866 * "node" 867 * A node of PKIX_VerifyNode tree. 868 * "plContext" 869 * Platform-specific context pointer. 870 * THREAD SAFETY: 871 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 872 * RETURNS: 873 * Returns NULL if the function succeeds. 874 * Returns a Cert Verify Error if the function fails in an unrecoverable way. 875 * Returns a Fatal Error if the function fails in an unrecoverable way. 876 */ 877 static PKIX_Error * 878 cert_GetLogFromVerifyNode( 879 CERTVerifyLog *log, 880 PKIX_VerifyNode *node, 881 void *plContext) 882 { 883 PKIX_List *children = NULL; 884 PKIX_VerifyNode *childNode = NULL; 885 886 PKIX_ENTER(CERTVFYPKIX, "cert_GetLogFromVerifyNode"); 887 888 children = node->children; 889 890 if (children == NULL) { 891 PKIX_ERRORCODE errCode = PKIX_ANCHORDIDNOTCHAINTOCERT; 892 if (node->error && node->error->errCode != errCode) { 893 if (log != NULL) { 894 SECErrorCodes nssErrorCode = 0; 895 CERTCertificate *cert = NULL; 896 897 cert = node->verifyCert->nssCert; 898 899 PKIX_CHECK( 900 cert_PkixErrorToNssCode(node->error, &nssErrorCode, 901 plContext), 902 PKIX_GETPKIXERRORCODEFAILED); 903 904 cert_AddToVerifyLog(log, cert, nssErrorCode, node->depth, NULL); 905 } 906 } 907 PKIX_RETURN(CERTVFYPKIX); 908 } else { 909 PRUint32 i = 0; 910 PKIX_UInt32 length = 0; 911 912 PKIX_CHECK( 913 PKIX_List_GetLength(children, &length, plContext), 914 PKIX_LISTGETLENGTHFAILED); 915 916 for (i = 0; i < length; i++) { 917 918 PKIX_CHECK( 919 PKIX_List_GetItem(children, i, (PKIX_PL_Object **)&childNode, 920 plContext), 921 PKIX_LISTGETITEMFAILED); 922 923 PKIX_CHECK( 924 cert_GetLogFromVerifyNode(log, childNode, plContext), 925 PKIX_ERRORINRECURSIVEEQUALSCALL); 926 927 PKIX_DECREF(childNode); 928 } 929 } 930 931 cleanup: 932 PKIX_DECREF(childNode); 933 934 PKIX_RETURN(CERTVFYPKIX); 935 } 936 937 /* 938 * FUNCTION: cert_GetBuildResults 939 * DESCRIPTION: 940 * 941 * Converts pkix build results to nss results. This function is called 942 * regardless of build result. 943 * 944 * If it called after chain was successfully constructed, then it will 945 * convert: 946 * * pkix cert list that represent the chain to nss cert list 947 * * trusted root the chain was anchored to nss certificate. 948 * 949 * In case of failure it will convert: 950 * * pkix error to PR error code(will set it with PORT_SetError) 951 * * pkix validation log to nss CERTVerifyLog 952 * 953 * PARAMETERS: 954 * "buildResult" 955 * Build results returned by PKIX_BuildChain. 956 * "verifyNode" 957 * Tree-like structure of chain building/validation failures 958 * returned by PKIX_BuildChain. Ignored in case of success. 959 * "error" 960 * Final error returned by PKIX_BuildChain. Should be NULL in 961 * case of success. 962 * "log" 963 * Address of pre-allocated(if not NULL) CERTVerifyLog structure. 964 * "ptrustedRoot" 965 * Address of returned trusted root the chain was anchored to. 966 * "pvalidChain" 967 * Address of returned valid chain. 968 * "plContext" 969 * Platform-specific context pointer. 970 * THREAD SAFETY: 971 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 972 * RETURNS: 973 * Returns NULL if the function succeeds. 974 * Returns a Cert Verify Error if the function fails in an unrecoverable way. 975 * Returns a Fatal Error if the function fails in an unrecoverable way. 976 */ 977 static PKIX_Error * 978 cert_GetBuildResults( 979 PKIX_BuildResult *buildResult, 980 PKIX_VerifyNode *verifyNode, 981 PKIX_Error *error, 982 CERTVerifyLog *log, 983 CERTCertificate **ptrustedRoot, 984 CERTCertList **pvalidChain, 985 void *plContext) 986 { 987 PKIX_ValidateResult *validResult = NULL; 988 CERTCertList *validChain = NULL; 989 CERTCertificate *trustedRoot = NULL; 990 PKIX_TrustAnchor *trustAnchor = NULL; 991 PKIX_PL_Cert *trustedCert = NULL; 992 PKIX_List *pkixCertChain = NULL; 993 994 PKIX_ENTER(CERTVFYPKIX, "cert_GetBuildResults"); 995 if (buildResult == NULL && error == NULL) { 996 PKIX_ERROR(PKIX_NULLARGUMENT); 997 } 998 999 if (error) { 1000 SECErrorCodes nssErrorCode = 0; 1001 if (verifyNode) { 1002 PKIX_Error *tmpError = 1003 cert_GetLogFromVerifyNode(log, verifyNode, plContext); 1004 if (tmpError) { 1005 PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext); 1006 } 1007 } 1008 cert_PkixErrorToNssCode(error, &nssErrorCode, plContext); 1009 PORT_SetError(nssErrorCode); 1010 goto cleanup; 1011 } 1012 1013 if (pvalidChain) { 1014 PKIX_CHECK( 1015 PKIX_BuildResult_GetCertChain(buildResult, &pkixCertChain, 1016 plContext), 1017 PKIX_BUILDRESULTGETCERTCHAINFAILED); 1018 1019 PKIX_CHECK( 1020 cert_PkixToNssCertsChain(pkixCertChain, &validChain, plContext), 1021 PKIX_CERTCHAINTONSSCHAINFAILED); 1022 } 1023 1024 if (ptrustedRoot) { 1025 PKIX_CHECK( 1026 PKIX_BuildResult_GetValidateResult(buildResult, &validResult, 1027 plContext), 1028 PKIX_BUILDRESULTGETVALIDATERESULTFAILED); 1029 1030 PKIX_CHECK( 1031 PKIX_ValidateResult_GetTrustAnchor(validResult, &trustAnchor, 1032 plContext), 1033 PKIX_VALIDATERESULTGETTRUSTANCHORFAILED); 1034 1035 PKIX_CHECK( 1036 PKIX_TrustAnchor_GetTrustedCert(trustAnchor, &trustedCert, 1037 plContext), 1038 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); 1039 1040 PKIX_CHECK( 1041 PKIX_PL_Cert_GetCERTCertificate(trustedCert, &trustedRoot, 1042 plContext), 1043 PKIX_CERTGETCERTCERTIFICATEFAILED); 1044 } 1045 1046 PORT_Assert(!PKIX_ERROR_RECEIVED); 1047 1048 if (trustedRoot) { 1049 *ptrustedRoot = trustedRoot; 1050 } 1051 if (validChain) { 1052 *pvalidChain = validChain; 1053 } 1054 1055 cleanup: 1056 if (PKIX_ERROR_RECEIVED) { 1057 if (trustedRoot) { 1058 CERT_DestroyCertificate(trustedRoot); 1059 } 1060 if (validChain) { 1061 CERT_DestroyCertList(validChain); 1062 } 1063 } 1064 PKIX_DECREF(trustAnchor); 1065 PKIX_DECREF(trustedCert); 1066 PKIX_DECREF(pkixCertChain); 1067 PKIX_DECREF(validResult); 1068 PKIX_DECREF(error); 1069 PKIX_DECREF(verifyNode); 1070 PKIX_DECREF(buildResult); 1071 1072 PKIX_RETURN(CERTVFYPKIX); 1073 } 1074 #endif /* NSS_DISABLE_LIBPKIX */ 1075 1076 /* 1077 * FUNCTION: cert_VerifyCertChainPkix 1078 * DESCRIPTION: 1079 * 1080 * The main wrapper function that is called from CERT_VerifyCert and 1081 * CERT_VerifyCACertForUsage functions to validate cert with libpkix. 1082 * 1083 * PARAMETERS: 1084 * "cert" 1085 * Leaf certificate of a chain we want to build. 1086 * "checkSig" 1087 * Certificate signatures will not be verified if this 1088 * flag is set to PR_FALSE. 1089 * "requiredUsage" 1090 * Required usage for certificate and chain. 1091 * "time" 1092 * Validity time. 1093 * "wincx" 1094 * Nss database password token. 1095 * "log" 1096 * Address of already allocated CERTVerifyLog structure. Not 1097 * used if NULL; 1098 * "pSigerror" 1099 * Address of PRBool. If not NULL, returns true is cert chain 1100 * was invalidated because of bad certificate signature. 1101 * "pRevoked" 1102 * Address of PRBool. If not NULL, returns true is cert chain 1103 * was invalidated because a revoked certificate was found in 1104 * the chain. 1105 * THREAD SAFETY: 1106 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1107 * RETURNS: 1108 * SECFailure is chain building process has failed. SECSuccess otherwise. 1109 */ 1110 SECStatus 1111 cert_VerifyCertChainPkix( 1112 CERTCertificate *cert, 1113 PRBool checkSig, 1114 SECCertUsage requiredUsage, 1115 PRTime time, 1116 void *wincx, 1117 CERTVerifyLog *log, 1118 PRBool *pSigerror, 1119 PRBool *pRevoked) 1120 { 1121 #ifdef NSS_DISABLE_LIBPKIX 1122 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 1123 return SECFailure; 1124 #else 1125 PKIX_ProcessingParams *procParams = NULL; 1126 PKIX_BuildResult *result = NULL; 1127 PKIX_VerifyNode *verifyNode = NULL; 1128 PKIX_Error *error = NULL; 1129 1130 SECStatus rv = SECFailure; 1131 void *plContext = NULL; 1132 1133 #ifdef PKIX_OBJECT_LEAK_TEST 1134 int leakedObjNum = 0; 1135 int memLeakLoopCount = 0; 1136 int objCountTable[PKIX_NUMTYPES]; 1137 int fnInvLocalCount = 0; 1138 PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine; 1139 1140 if (usePKIXValidationEngine) { 1141 /* current memory leak testing implementation does not allow 1142 * to run simultaneous tests one the same or a different threads. 1143 * Setting the variable to false, to make additional chain 1144 * validations be handled by old nss. */ 1145 usePKIXValidationEngine = PR_FALSE; 1146 } 1147 testStartFnStackPosition = 2; 1148 fnStackNameArr[0] = "cert_VerifyCertChainPkix"; 1149 fnStackInvCountArr[0] = 0; 1150 PKIX_Boolean abortOnLeak = 1151 (PR_GetEnvSecure("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ? PKIX_FALSE 1152 : PKIX_TRUE; 1153 runningLeakTest = PKIX_TRUE; 1154 1155 /* Prevent multi-threaded run of object leak test */ 1156 fnInvLocalCount = PR_ATOMIC_INCREMENT(¶llelFnInvocationCount); 1157 PORT_Assert(fnInvLocalCount == 1); 1158 1159 do { 1160 rv = SECFailure; 1161 plContext = NULL; 1162 procParams = NULL; 1163 result = NULL; 1164 verifyNode = NULL; 1165 error = NULL; 1166 errorGenerated = PKIX_FALSE; 1167 stackPosition = 0; 1168 1169 if (leakedObjNum) { 1170 pkix_pl_lifecycle_ObjectTableUpdate(objCountTable); 1171 } 1172 memLeakLoopCount += 1; 1173 #endif /* PKIX_OBJECT_LEAK_TEST */ 1174 1175 error = 1176 cert_CreatePkixProcessingParams(cert, checkSig, time, wincx, 1177 PR_FALSE /*use arena*/, 1178 requiredUsage == certUsageStatusResponder, 1179 &procParams, &plContext); 1180 if (error) { 1181 goto cleanup; 1182 } 1183 1184 error = 1185 cert_ProcessingParamsSetKeyAndCertUsage(procParams, requiredUsage, 0, 1186 plContext); 1187 if (error) { 1188 goto cleanup; 1189 } 1190 1191 error = 1192 cert_BuildAndValidateChain(procParams, &result, &verifyNode, plContext); 1193 if (error) { 1194 goto cleanup; 1195 } 1196 1197 if (pRevoked) { 1198 /* Currently always PR_FALSE. Will be fixed as a part of 394077 */ 1199 *pRevoked = PR_FALSE; 1200 } 1201 if (pSigerror) { 1202 /* Currently always PR_FALSE. Will be fixed as a part of 394077 */ 1203 *pSigerror = PR_FALSE; 1204 } 1205 rv = SECSuccess; 1206 1207 cleanup: 1208 error = cert_GetBuildResults(result, verifyNode, error, log, NULL, NULL, 1209 plContext); 1210 if (error) { 1211 PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext); 1212 } 1213 if (procParams) { 1214 PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext); 1215 } 1216 if (plContext) { 1217 PKIX_PL_NssContext_Destroy(plContext); 1218 } 1219 1220 #ifdef PKIX_OBJECT_LEAK_TEST 1221 leakedObjNum = 1222 pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL); 1223 1224 if (pkixLog && leakedObjNum) { 1225 PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d." 1226 "Stack %s\n", 1227 memLeakLoopCount, errorFnStackString)); 1228 } 1229 PR_Free(errorFnStackString); 1230 errorFnStackString = NULL; 1231 if (abortOnLeak) { 1232 PORT_Assert(leakedObjNum == 0); 1233 } 1234 1235 } while (errorGenerated); 1236 1237 runningLeakTest = PKIX_FALSE; 1238 PR_ATOMIC_DECREMENT(¶llelFnInvocationCount); 1239 usePKIXValidationEngine = savedUsePkixEngFlag; 1240 #endif /* PKIX_OBJECT_LEAK_TEST */ 1241 1242 return rv; 1243 #endif /* NSS_DISABLE_LIBPKIX */ 1244 } 1245 1246 #ifndef NSS_DISABLE_LIBPKIX 1247 PKIX_CertSelector * 1248 cert_GetTargetCertConstraints(CERTCertificate *target, void *plContext) 1249 { 1250 PKIX_ComCertSelParams *certSelParams = NULL; 1251 PKIX_CertSelector *certSelector = NULL; 1252 PKIX_CertSelector *r = NULL; 1253 PKIX_PL_Cert *eeCert = NULL; 1254 PKIX_Error *error = NULL; 1255 1256 error = PKIX_PL_Cert_CreateFromCERTCertificate(target, &eeCert, plContext); 1257 if (error != NULL) 1258 goto cleanup; 1259 1260 error = PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext); 1261 if (error != NULL) 1262 goto cleanup; 1263 1264 error = PKIX_ComCertSelParams_Create(&certSelParams, plContext); 1265 if (error != NULL) 1266 goto cleanup; 1267 1268 error = PKIX_ComCertSelParams_SetCertificate( 1269 certSelParams, eeCert, plContext); 1270 if (error != NULL) 1271 goto cleanup; 1272 1273 error = PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext); 1274 if (error != NULL) 1275 goto cleanup; 1276 1277 error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certSelector, plContext); 1278 if (error == NULL) 1279 r = certSelector; 1280 1281 cleanup: 1282 if (certSelParams != NULL) 1283 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelParams, plContext); 1284 1285 if (eeCert != NULL) 1286 PKIX_PL_Object_DecRef((PKIX_PL_Object *)eeCert, plContext); 1287 1288 if (certSelector != NULL) 1289 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext); 1290 1291 if (error != NULL) { 1292 SECErrorCodes nssErr; 1293 1294 cert_PkixErrorToNssCode(error, &nssErr, plContext); 1295 PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext); 1296 PORT_SetError(nssErr); 1297 } 1298 1299 return r; 1300 } 1301 1302 static PKIX_List * 1303 cert_GetCertStores(void *plContext) 1304 { 1305 PKIX_CertStore *certStore = NULL; 1306 PKIX_List *certStores = NULL; 1307 PKIX_List *r = NULL; 1308 PKIX_Error *error = NULL; 1309 1310 error = PKIX_PL_Pk11CertStore_Create(&certStore, plContext); 1311 if (error != NULL) 1312 goto cleanup; 1313 1314 error = PKIX_List_Create(&certStores, plContext); 1315 if (error != NULL) 1316 goto cleanup; 1317 1318 error = PKIX_List_AppendItem(certStores, 1319 (PKIX_PL_Object *)certStore, plContext); 1320 if (error != NULL) 1321 goto cleanup; 1322 1323 error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certStores, plContext); 1324 if (error == NULL) 1325 r = certStores; 1326 1327 cleanup: 1328 if (certStores != NULL) 1329 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext); 1330 1331 if (certStore != NULL) 1332 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStore, plContext); 1333 1334 if (error != NULL) { 1335 SECErrorCodes nssErr; 1336 1337 cert_PkixErrorToNssCode(error, &nssErr, plContext); 1338 PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext); 1339 PORT_SetError(nssErr); 1340 } 1341 1342 return r; 1343 } 1344 1345 struct fake_PKIX_PL_CertStruct { 1346 CERTCertificate *nssCert; 1347 }; 1348 1349 /* This needs to be part of the PKIX_PL_* */ 1350 /* This definitely needs to go away, and be replaced with 1351 a real accessor function in PKIX */ 1352 static CERTCertificate * 1353 cert_NSSCertFromPKIXCert(const PKIX_PL_Cert *pkix_cert) 1354 { 1355 struct fake_PKIX_PL_CertStruct *fcert = NULL; 1356 1357 fcert = (struct fake_PKIX_PL_CertStruct *)pkix_cert; 1358 1359 return CERT_DupCertificate(fcert->nssCert); 1360 } 1361 1362 PKIX_List * 1363 cert_PKIXMakeOIDList(const SECOidTag *oids, int oidCount, void *plContext) 1364 { 1365 PKIX_List *r = NULL; 1366 PKIX_List *policyList = NULL; 1367 PKIX_PL_OID *policyOID = NULL; 1368 PKIX_Error *error = NULL; 1369 int i; 1370 1371 error = PKIX_List_Create(&policyList, plContext); 1372 if (error != NULL) { 1373 goto cleanup; 1374 } 1375 1376 for (i = 0; i < oidCount; i++) { 1377 error = PKIX_PL_OID_Create(oids[i], &policyOID, plContext); 1378 if (error) { 1379 goto cleanup; 1380 } 1381 error = PKIX_List_AppendItem(policyList, 1382 (PKIX_PL_Object *)policyOID, plContext); 1383 if (error != NULL) { 1384 goto cleanup; 1385 } 1386 PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext); 1387 policyOID = NULL; 1388 } 1389 1390 error = PKIX_List_SetImmutable(policyList, plContext); 1391 if (error != NULL) 1392 goto cleanup; 1393 1394 error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)policyList, plContext); 1395 if (error == NULL) 1396 r = policyList; 1397 1398 cleanup: 1399 if (policyOID != NULL) { 1400 PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext); 1401 } 1402 if (policyList != NULL) { 1403 PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyList, plContext); 1404 } 1405 if (error != NULL) { 1406 PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext); 1407 } 1408 1409 return r; 1410 } 1411 1412 CERTValOutParam * 1413 cert_pkix_FindOutputParam(CERTValOutParam *params, const CERTValParamOutType t) 1414 { 1415 CERTValOutParam *i; 1416 if (params == NULL) { 1417 return NULL; 1418 } 1419 for (i = params; i->type != cert_po_end; i++) { 1420 if (i->type == t) { 1421 return i; 1422 } 1423 } 1424 return NULL; 1425 } 1426 1427 static PKIX_Error * 1428 setRevocationMethod(PKIX_RevocationChecker *revChecker, 1429 PKIX_ProcessingParams *procParams, 1430 const CERTRevocationTests *revTest, 1431 CERTRevocationMethodIndex certRevMethod, 1432 PKIX_RevocationMethodType pkixRevMethod, 1433 PKIX_Boolean verifyResponderUsages, 1434 PKIX_Boolean isLeafTest, 1435 void *plContext) 1436 { 1437 PKIX_UInt32 methodFlags = 0; 1438 PKIX_Error *error = NULL; 1439 PKIX_UInt32 priority = 0; 1440 1441 if (revTest->number_of_defined_methods <= (PRUint32)certRevMethod) { 1442 return NULL; 1443 } 1444 if (revTest->preferred_methods) { 1445 unsigned int i = 0; 1446 for (; i < revTest->number_of_preferred_methods; i++) { 1447 if (revTest->preferred_methods[i] == certRevMethod) 1448 break; 1449 } 1450 priority = i; 1451 } 1452 methodFlags = revTest->cert_rev_flags_per_method[certRevMethod]; 1453 if (verifyResponderUsages && 1454 pkixRevMethod == PKIX_RevocationMethod_OCSP) { 1455 methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING; 1456 } 1457 error = 1458 PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams, 1459 pkixRevMethod, methodFlags, 1460 priority, NULL, 1461 isLeafTest, plContext); 1462 return error; 1463 } 1464 1465 SECStatus 1466 cert_pkixSetParam(PKIX_ProcessingParams *procParams, 1467 const CERTValInParam *param, void *plContext) 1468 { 1469 PKIX_Error *error = NULL; 1470 SECStatus r = SECSuccess; 1471 PKIX_PL_Date *date = NULL; 1472 PKIX_List *policyOIDList = NULL; 1473 PKIX_List *certListPkix = NULL; 1474 const CERTRevocationFlags *flags; 1475 SECErrorCodes errCode = SEC_ERROR_INVALID_ARGS; 1476 const CERTCertList *certList = NULL; 1477 CERTCertListNode *node; 1478 PKIX_PL_Cert *certPkix = NULL; 1479 PKIX_TrustAnchor *trustAnchor = NULL; 1480 PKIX_RevocationChecker *revChecker = NULL; 1481 PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext *)plContext; 1482 1483 /* XXX we need a way to map generic PKIX error to generic NSS errors */ 1484 1485 switch (param->type) { 1486 1487 case cert_pi_policyOID: 1488 1489 /* needed? */ 1490 error = PKIX_ProcessingParams_SetExplicitPolicyRequired( 1491 procParams, PKIX_TRUE, plContext); 1492 1493 if (error != NULL) { 1494 break; 1495 } 1496 1497 policyOIDList = cert_PKIXMakeOIDList(param->value.array.oids, 1498 param->value.arraySize, plContext); 1499 if (policyOIDList == NULL) { 1500 r = SECFailure; 1501 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1502 break; 1503 } 1504 1505 error = PKIX_ProcessingParams_SetInitialPolicies( 1506 procParams, policyOIDList, plContext); 1507 break; 1508 1509 case cert_pi_date: 1510 if (param->value.scalar.time == 0) { 1511 error = PKIX_PL_Date_Create_UTCTime(NULL, &date, plContext); 1512 if (error != NULL) { 1513 errCode = SEC_ERROR_INVALID_TIME; 1514 break; 1515 } 1516 } else { 1517 error = pkix_pl_Date_CreateFromPRTime(param->value.scalar.time, 1518 &date, plContext); 1519 if (error != NULL) { 1520 errCode = SEC_ERROR_INVALID_TIME; 1521 break; 1522 } 1523 } 1524 1525 error = PKIX_ProcessingParams_SetDate(procParams, date, plContext); 1526 if (error != NULL) { 1527 errCode = SEC_ERROR_INVALID_TIME; 1528 } 1529 break; 1530 1531 case cert_pi_revocationFlags: { 1532 PKIX_UInt32 leafIMFlags = 0; 1533 PKIX_UInt32 chainIMFlags = 0; 1534 PKIX_Boolean validatingResponderCert = PKIX_FALSE; 1535 1536 flags = param->value.pointer.revocation; 1537 if (!flags) { 1538 PORT_SetError(errCode); 1539 r = SECFailure; 1540 break; 1541 } 1542 1543 leafIMFlags = 1544 flags->leafTests.cert_rev_method_independent_flags; 1545 chainIMFlags = 1546 flags->chainTests.cert_rev_method_independent_flags; 1547 1548 error = 1549 PKIX_RevocationChecker_Create(leafIMFlags, chainIMFlags, 1550 &revChecker, plContext); 1551 if (error) { 1552 break; 1553 } 1554 1555 error = 1556 PKIX_ProcessingParams_SetRevocationChecker(procParams, 1557 revChecker, plContext); 1558 if (error) { 1559 break; 1560 } 1561 1562 if (((PKIX_PL_NssContext *)plContext)->certificateUsage & 1563 certificateUsageStatusResponder) { 1564 validatingResponderCert = PKIX_TRUE; 1565 } 1566 1567 error = setRevocationMethod(revChecker, 1568 procParams, &flags->leafTests, 1569 cert_revocation_method_crl, 1570 PKIX_RevocationMethod_CRL, 1571 validatingResponderCert, 1572 PKIX_TRUE, plContext); 1573 if (error) { 1574 break; 1575 } 1576 1577 error = setRevocationMethod(revChecker, 1578 procParams, &flags->leafTests, 1579 cert_revocation_method_ocsp, 1580 PKIX_RevocationMethod_OCSP, 1581 validatingResponderCert, 1582 PKIX_TRUE, plContext); 1583 if (error) { 1584 break; 1585 } 1586 1587 error = setRevocationMethod(revChecker, 1588 procParams, &flags->chainTests, 1589 cert_revocation_method_crl, 1590 PKIX_RevocationMethod_CRL, 1591 validatingResponderCert, 1592 PKIX_FALSE, plContext); 1593 if (error) { 1594 break; 1595 } 1596 1597 error = setRevocationMethod(revChecker, 1598 procParams, &flags->chainTests, 1599 cert_revocation_method_ocsp, 1600 PKIX_RevocationMethod_OCSP, 1601 validatingResponderCert, 1602 PKIX_FALSE, plContext); 1603 if (error) { 1604 break; 1605 } 1606 1607 } break; 1608 1609 case cert_pi_trustAnchors: 1610 certList = param->value.pointer.chain; 1611 if (!certList) { 1612 PORT_SetError(errCode); 1613 r = SECFailure; 1614 break; 1615 } 1616 error = PKIX_List_Create(&certListPkix, plContext); 1617 if (error != NULL) { 1618 break; 1619 } 1620 for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList); 1621 node = CERT_LIST_NEXT(node)) { 1622 error = PKIX_PL_Cert_CreateFromCERTCertificate(node->cert, 1623 &certPkix, plContext); 1624 if (error) { 1625 break; 1626 } 1627 error = PKIX_TrustAnchor_CreateWithCert(certPkix, &trustAnchor, 1628 plContext); 1629 if (error) { 1630 break; 1631 } 1632 error = PKIX_List_AppendItem(certListPkix, 1633 (PKIX_PL_Object *)trustAnchor, plContext); 1634 if (error) { 1635 break; 1636 } 1637 PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext); 1638 trustAnchor = NULL; 1639 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext); 1640 certPkix = NULL; 1641 } 1642 error = 1643 PKIX_ProcessingParams_SetTrustAnchors(procParams, certListPkix, 1644 plContext); 1645 break; 1646 1647 case cert_pi_useAIACertFetch: 1648 error = 1649 PKIX_ProcessingParams_SetUseAIAForCertFetching(procParams, 1650 (PRBool)(param->value.scalar.b != 1651 0), 1652 plContext); 1653 break; 1654 1655 case cert_pi_chainVerifyCallback: { 1656 const CERTChainVerifyCallback *chainVerifyCallback = 1657 param->value.pointer.chainVerifyCallback; 1658 if (!chainVerifyCallback || !chainVerifyCallback->isChainValid) { 1659 PORT_SetError(errCode); 1660 r = SECFailure; 1661 break; 1662 } 1663 1664 nssContext->chainVerifyCallback = *chainVerifyCallback; 1665 } break; 1666 1667 case cert_pi_useOnlyTrustAnchors: 1668 error = 1669 PKIX_ProcessingParams_SetUseOnlyTrustAnchors(procParams, 1670 (PRBool)(param->value.scalar.b != 1671 0), 1672 plContext); 1673 break; 1674 1675 default: 1676 PORT_SetError(errCode); 1677 r = SECFailure; 1678 break; 1679 } 1680 1681 if (policyOIDList != NULL) 1682 PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOIDList, plContext); 1683 1684 if (date != NULL) 1685 PKIX_PL_Object_DecRef((PKIX_PL_Object *)date, plContext); 1686 1687 if (revChecker != NULL) 1688 PKIX_PL_Object_DecRef((PKIX_PL_Object *)revChecker, plContext); 1689 1690 if (certListPkix) 1691 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certListPkix, plContext); 1692 1693 if (trustAnchor) 1694 PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext); 1695 1696 if (certPkix) 1697 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext); 1698 1699 if (error != NULL) { 1700 PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext); 1701 PORT_SetError(errCode); 1702 r = SECFailure; 1703 } 1704 1705 return r; 1706 } 1707 1708 void 1709 cert_pkixDestroyValOutParam(CERTValOutParam *params) 1710 { 1711 CERTValOutParam *i; 1712 1713 if (params == NULL) { 1714 return; 1715 } 1716 for (i = params; i->type != cert_po_end; i++) { 1717 switch (i->type) { 1718 case cert_po_trustAnchor: 1719 if (i->value.pointer.cert) { 1720 CERT_DestroyCertificate(i->value.pointer.cert); 1721 i->value.pointer.cert = NULL; 1722 } 1723 break; 1724 1725 case cert_po_certList: 1726 if (i->value.pointer.chain) { 1727 CERT_DestroyCertList(i->value.pointer.chain); 1728 i->value.pointer.chain = NULL; 1729 } 1730 break; 1731 1732 default: 1733 break; 1734 } 1735 } 1736 } 1737 1738 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags[2] = { 1739 /* crl */ 1740 CERT_REV_M_TEST_USING_THIS_METHOD | 1741 CERT_REV_M_FORBID_NETWORK_FETCHING | 1742 CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO, 1743 /* ocsp */ 1744 CERT_REV_M_TEST_USING_THIS_METHOD 1745 }; 1746 1747 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags[2] = { 1748 /* crl */ 1749 CERT_REV_M_TEST_USING_THIS_METHOD | 1750 CERT_REV_M_FORBID_NETWORK_FETCHING | 1751 CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO, 1752 /* ocsp */ 1753 0 1754 }; 1755 1756 static CERTRevocationMethodIndex 1757 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference = { 1758 cert_revocation_method_crl 1759 }; 1760 1761 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy = { 1762 { /* leafTests */ 1763 2, 1764 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags, 1765 1, 1766 &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference, 1767 0 }, 1768 { /* chainTests */ 1769 2, 1770 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags, 1771 0, 1772 0, 1773 0 } 1774 }; 1775 #endif /* NSS_DISABLE_LIBPKIX */ 1776 1777 extern const CERTRevocationFlags * 1778 CERT_GetClassicOCSPEnabledSoftFailurePolicy() 1779 { 1780 #ifdef NSS_DISABLE_LIBPKIX 1781 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 1782 return NULL; 1783 #else 1784 return &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy; 1785 #endif /* NSS_DISABLE_LIBPKIX */ 1786 } 1787 1788 #ifndef NSS_DISABLE_LIBPKIX 1789 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags[2] = { 1790 /* crl */ 1791 CERT_REV_M_TEST_USING_THIS_METHOD | 1792 CERT_REV_M_FORBID_NETWORK_FETCHING | 1793 CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO, 1794 /* ocsp */ 1795 CERT_REV_M_TEST_USING_THIS_METHOD | 1796 CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO 1797 }; 1798 1799 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags[2] = { 1800 /* crl */ 1801 CERT_REV_M_TEST_USING_THIS_METHOD | 1802 CERT_REV_M_FORBID_NETWORK_FETCHING | 1803 CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO, 1804 /* ocsp */ 1805 0 1806 }; 1807 1808 static CERTRevocationMethodIndex 1809 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference = { 1810 cert_revocation_method_crl 1811 }; 1812 1813 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy = { 1814 { /* leafTests */ 1815 2, 1816 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags, 1817 1, 1818 &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference, 1819 0 }, 1820 { /* chainTests */ 1821 2, 1822 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags, 1823 0, 1824 0, 1825 0 } 1826 }; 1827 #endif /* NSS_DISABLE_LIBPKIX */ 1828 1829 extern const CERTRevocationFlags * 1830 CERT_GetClassicOCSPEnabledHardFailurePolicy() 1831 { 1832 #ifdef NSS_DISABLE_LIBPKIX 1833 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 1834 return NULL; 1835 #else 1836 return &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy; 1837 #endif /* NSS_DISABLE_LIBPKIX */ 1838 } 1839 1840 #ifndef NSS_DISABLE_LIBPKIX 1841 static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags[2] = { 1842 /* crl */ 1843 CERT_REV_M_TEST_USING_THIS_METHOD | 1844 CERT_REV_M_FORBID_NETWORK_FETCHING | 1845 CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO, 1846 /* ocsp */ 1847 0 1848 }; 1849 1850 static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags[2] = { 1851 /* crl */ 1852 CERT_REV_M_TEST_USING_THIS_METHOD | 1853 CERT_REV_M_FORBID_NETWORK_FETCHING | 1854 CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO, 1855 /* ocsp */ 1856 0 1857 }; 1858 1859 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Disabled_Policy = { 1860 { /* leafTests */ 1861 2, 1862 certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags, 1863 0, 1864 0, 1865 0 }, 1866 { /* chainTests */ 1867 2, 1868 certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags, 1869 0, 1870 0, 1871 0 } 1872 }; 1873 #endif /* NSS_DISABLE_LIBPKIX */ 1874 1875 extern const CERTRevocationFlags * 1876 CERT_GetClassicOCSPDisabledPolicy() 1877 { 1878 #ifdef NSS_DISABLE_LIBPKIX 1879 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 1880 return NULL; 1881 #else 1882 return &certRev_NSS_3_11_Ocsp_Disabled_Policy; 1883 #endif /* NSS_DISABLE_LIBPKIX */ 1884 } 1885 1886 #ifndef NSS_DISABLE_LIBPKIX 1887 static PRUint64 certRev_PKIX_Verify_Nist_Policy_LeafFlags[2] = { 1888 /* crl */ 1889 CERT_REV_M_TEST_USING_THIS_METHOD | 1890 CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO | 1891 CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE, 1892 /* ocsp */ 1893 0 1894 }; 1895 1896 static PRUint64 certRev_PKIX_Verify_Nist_Policy_ChainFlags[2] = { 1897 /* crl */ 1898 CERT_REV_M_TEST_USING_THIS_METHOD | 1899 CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO | 1900 CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE, 1901 /* ocsp */ 1902 0 1903 }; 1904 1905 static const CERTRevocationFlags certRev_PKIX_Verify_Nist_Policy = { 1906 { /* leafTests */ 1907 2, 1908 certRev_PKIX_Verify_Nist_Policy_LeafFlags, 1909 0, 1910 0, 1911 0 }, 1912 { /* chainTests */ 1913 2, 1914 certRev_PKIX_Verify_Nist_Policy_ChainFlags, 1915 0, 1916 0, 1917 0 } 1918 }; 1919 #endif /* NSS_DISABLE_LIBPKIX */ 1920 1921 extern const CERTRevocationFlags * 1922 CERT_GetPKIXVerifyNistRevocationPolicy() 1923 { 1924 #ifdef NSS_DISABLE_LIBPKIX 1925 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 1926 return NULL; 1927 #else 1928 return &certRev_PKIX_Verify_Nist_Policy; 1929 #endif /* NSS_DISABLE_LIBPKIX */ 1930 } 1931 1932 CERTRevocationFlags * 1933 CERT_AllocCERTRevocationFlags( 1934 PRUint32 number_leaf_methods, PRUint32 number_leaf_pref_methods, 1935 PRUint32 number_chain_methods, PRUint32 number_chain_pref_methods) 1936 { 1937 #ifdef NSS_DISABLE_LIBPKIX 1938 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 1939 return NULL; 1940 #else 1941 CERTRevocationFlags *flags; 1942 1943 flags = PORT_New(CERTRevocationFlags); 1944 if (!flags) 1945 return (NULL); 1946 1947 flags->leafTests.number_of_defined_methods = number_leaf_methods; 1948 flags->leafTests.cert_rev_flags_per_method = 1949 PORT_NewArray(PRUint64, number_leaf_methods); 1950 1951 flags->leafTests.number_of_preferred_methods = number_leaf_pref_methods; 1952 flags->leafTests.preferred_methods = 1953 PORT_NewArray(CERTRevocationMethodIndex, number_leaf_pref_methods); 1954 1955 flags->chainTests.number_of_defined_methods = number_chain_methods; 1956 flags->chainTests.cert_rev_flags_per_method = 1957 PORT_NewArray(PRUint64, number_chain_methods); 1958 1959 flags->chainTests.number_of_preferred_methods = number_chain_pref_methods; 1960 flags->chainTests.preferred_methods = 1961 PORT_NewArray(CERTRevocationMethodIndex, number_chain_pref_methods); 1962 1963 if (!flags->leafTests.cert_rev_flags_per_method || 1964 !flags->leafTests.preferred_methods || 1965 !flags->chainTests.cert_rev_flags_per_method || 1966 !flags->chainTests.preferred_methods) { 1967 CERT_DestroyCERTRevocationFlags(flags); 1968 return (NULL); 1969 } 1970 1971 return flags; 1972 #endif /* NSS_DISABLE_LIBPKIX */ 1973 } 1974 1975 void 1976 CERT_DestroyCERTRevocationFlags(CERTRevocationFlags *flags) 1977 { 1978 #ifdef NSS_DISABLE_LIBPKIX 1979 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 1980 return; 1981 #else 1982 if (!flags) 1983 return; 1984 1985 if (flags->leafTests.cert_rev_flags_per_method) 1986 PORT_Free(flags->leafTests.cert_rev_flags_per_method); 1987 1988 if (flags->leafTests.preferred_methods) 1989 PORT_Free(flags->leafTests.preferred_methods); 1990 1991 if (flags->chainTests.cert_rev_flags_per_method) 1992 PORT_Free(flags->chainTests.cert_rev_flags_per_method); 1993 1994 if (flags->chainTests.preferred_methods) 1995 PORT_Free(flags->chainTests.preferred_methods); 1996 1997 PORT_Free(flags); 1998 #endif /* NSS_DISABLE_LIBPKIX */ 1999 } 2000 2001 /* 2002 * CERT_PKIXVerifyCert 2003 * 2004 * Verify a Certificate using the PKIX library. 2005 * 2006 * Parameters: 2007 * cert - the target certificate to verify. Must be non-null 2008 * params - an array of type/value parameters which can be 2009 * used to modify the behavior of the validation 2010 * algorithm, or supply additional constraints. 2011 * 2012 * outputTrustAnchor - the trust anchor which the certificate 2013 * chains to. The caller is responsible 2014 * for freeing this. 2015 * 2016 * Example Usage: 2017 * CERTValParam args[3]; 2018 * args[0].type = cvpt_policyOID; 2019 * args[0].value.si = oid; 2020 * args[1].type = revCheckRequired; 2021 * args[1].value.b = PR_TRUE; 2022 * args[2].type = cvpt_end; 2023 * 2024 * CERT_PKIXVerifyCert(cert, &output, args 2025 */ 2026 SECStatus 2027 CERT_PKIXVerifyCert( 2028 CERTCertificate *cert, 2029 SECCertificateUsage usages, 2030 CERTValInParam *paramsIn, 2031 CERTValOutParam *paramsOut, 2032 void *wincx) 2033 { 2034 #ifdef NSS_DISABLE_LIBPKIX 2035 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 2036 return SECFailure; 2037 #else 2038 SECStatus r = SECFailure; 2039 PKIX_Error *error = NULL; 2040 PKIX_ProcessingParams *procParams = NULL; 2041 PKIX_BuildResult *buildResult = NULL; 2042 void *nbioContext = NULL; /* for non-blocking IO */ 2043 void *buildState = NULL; /* for non-blocking IO */ 2044 PKIX_CertSelector *certSelector = NULL; 2045 PKIX_List *certStores = NULL; 2046 PKIX_ValidateResult *valResult = NULL; 2047 PKIX_VerifyNode *verifyNode = NULL; 2048 PKIX_TrustAnchor *trustAnchor = NULL; 2049 PKIX_PL_Cert *trustAnchorCert = NULL; 2050 PKIX_List *builtCertList = NULL; 2051 CERTValOutParam *oparam = NULL; 2052 int i = 0; 2053 2054 void *plContext = NULL; 2055 2056 #ifdef PKIX_OBJECT_LEAK_TEST 2057 int leakedObjNum = 0; 2058 int memLeakLoopCount = 0; 2059 int objCountTable[PKIX_NUMTYPES]; 2060 int fnInvLocalCount = 0; 2061 PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine; 2062 2063 if (usePKIXValidationEngine) { 2064 /* current memory leak testing implementation does not allow 2065 * to run simultaneous tests one the same or a different threads. 2066 * Setting the variable to false, to make additional chain 2067 * validations be handled by old nss. */ 2068 usePKIXValidationEngine = PR_FALSE; 2069 } 2070 testStartFnStackPosition = 1; 2071 fnStackNameArr[0] = "CERT_PKIXVerifyCert"; 2072 fnStackInvCountArr[0] = 0; 2073 PKIX_Boolean abortOnLeak = 2074 (PR_GetEnvSecure("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ? PKIX_FALSE 2075 : PKIX_TRUE; 2076 runningLeakTest = PKIX_TRUE; 2077 2078 /* Prevent multi-threaded run of object leak test */ 2079 fnInvLocalCount = PR_ATOMIC_INCREMENT(¶llelFnInvocationCount); 2080 PORT_Assert(fnInvLocalCount == 1); 2081 2082 do { 2083 r = SECFailure; 2084 error = NULL; 2085 procParams = NULL; 2086 buildResult = NULL; 2087 nbioContext = NULL; /* for non-blocking IO */ 2088 buildState = NULL; /* for non-blocking IO */ 2089 certSelector = NULL; 2090 certStores = NULL; 2091 valResult = NULL; 2092 verifyNode = NULL; 2093 trustAnchor = NULL; 2094 trustAnchorCert = NULL; 2095 builtCertList = NULL; 2096 oparam = NULL; 2097 i = 0; 2098 errorGenerated = PKIX_FALSE; 2099 stackPosition = 0; 2100 2101 if (leakedObjNum) { 2102 pkix_pl_lifecycle_ObjectTableUpdate(objCountTable); 2103 } 2104 memLeakLoopCount += 1; 2105 #endif /* PKIX_OBJECT_LEAK_TEST */ 2106 2107 error = PKIX_PL_NssContext_Create( 2108 0, PR_FALSE /*use arena*/, wincx, &plContext); 2109 if (error != NULL) { /* need pkix->nss error map */ 2110 PORT_SetError(SEC_ERROR_CERT_NOT_VALID); 2111 goto cleanup; 2112 } 2113 2114 error = pkix_pl_NssContext_SetCertUsage(usages, plContext); 2115 if (error != NULL) { 2116 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2117 goto cleanup; 2118 } 2119 2120 error = PKIX_ProcessingParams_Create(&procParams, plContext); 2121 if (error != NULL) { /* need pkix->nss error map */ 2122 PORT_SetError(SEC_ERROR_CERT_NOT_VALID); 2123 goto cleanup; 2124 } 2125 2126 /* local cert store should be set into procParams before 2127 * filling in revocation settings. */ 2128 certStores = cert_GetCertStores(plContext); 2129 if (certStores == NULL) { 2130 goto cleanup; 2131 } 2132 error = PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext); 2133 if (error != NULL) { 2134 goto cleanup; 2135 } 2136 2137 /* now process the extensible input parameters structure */ 2138 if (paramsIn != NULL) { 2139 i = 0; 2140 while (paramsIn[i].type != cert_pi_end) { 2141 if (paramsIn[i].type >= cert_pi_max) { 2142 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2143 goto cleanup; 2144 } 2145 if (cert_pkixSetParam(procParams, 2146 ¶msIn[i], plContext) != 2147 SECSuccess) { 2148 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2149 goto cleanup; 2150 } 2151 i++; 2152 } 2153 } 2154 2155 certSelector = cert_GetTargetCertConstraints(cert, plContext); 2156 if (certSelector == NULL) { 2157 goto cleanup; 2158 } 2159 error = PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext); 2160 if (error != NULL) { 2161 goto cleanup; 2162 } 2163 2164 error = PKIX_BuildChain(procParams, &nbioContext, 2165 &buildState, &buildResult, &verifyNode, 2166 plContext); 2167 if (error != NULL) { 2168 goto cleanup; 2169 } 2170 2171 error = PKIX_BuildResult_GetValidateResult(buildResult, &valResult, 2172 plContext); 2173 if (error != NULL) { 2174 goto cleanup; 2175 } 2176 2177 error = PKIX_ValidateResult_GetTrustAnchor(valResult, &trustAnchor, 2178 plContext); 2179 if (error != NULL) { 2180 goto cleanup; 2181 } 2182 2183 if (trustAnchor != NULL) { 2184 error = PKIX_TrustAnchor_GetTrustedCert(trustAnchor, &trustAnchorCert, 2185 plContext); 2186 if (error != NULL) { 2187 goto cleanup; 2188 } 2189 } 2190 2191 #ifdef PKIX_OBJECT_LEAK_TEST 2192 /* Can not continue if error was generated but not returned. 2193 * Jumping to cleanup. */ 2194 if (errorGenerated) 2195 goto cleanup; 2196 #endif /* PKIX_OBJECT_LEAK_TEST */ 2197 2198 oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_trustAnchor); 2199 if (oparam != NULL) { 2200 if (trustAnchorCert != NULL) { 2201 oparam->value.pointer.cert = 2202 cert_NSSCertFromPKIXCert(trustAnchorCert); 2203 } else { 2204 oparam->value.pointer.cert = NULL; 2205 } 2206 } 2207 2208 error = PKIX_BuildResult_GetCertChain(buildResult, &builtCertList, 2209 plContext); 2210 if (error != NULL) { 2211 goto cleanup; 2212 } 2213 2214 oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_certList); 2215 if (oparam != NULL) { 2216 error = cert_PkixToNssCertsChain(builtCertList, 2217 &oparam->value.pointer.chain, 2218 plContext); 2219 if (error) 2220 goto cleanup; 2221 } 2222 2223 r = SECSuccess; 2224 2225 cleanup: 2226 if (verifyNode) { 2227 /* Return validation log only upon error. */ 2228 oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_errorLog); 2229 #ifdef PKIX_OBJECT_LEAK_TEST 2230 if (!errorGenerated) 2231 #endif /* PKIX_OBJECT_LEAK_TEST */ 2232 if (r && oparam != NULL) { 2233 PKIX_Error *tmpError = 2234 cert_GetLogFromVerifyNode(oparam->value.pointer.log, 2235 verifyNode, plContext); 2236 if (tmpError) { 2237 PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext); 2238 } 2239 } 2240 PKIX_PL_Object_DecRef((PKIX_PL_Object *)verifyNode, plContext); 2241 } 2242 2243 if (procParams != NULL) 2244 PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext); 2245 2246 if (trustAnchorCert != NULL) 2247 PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchorCert, plContext); 2248 2249 if (trustAnchor != NULL) 2250 PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext); 2251 2252 if (valResult != NULL) 2253 PKIX_PL_Object_DecRef((PKIX_PL_Object *)valResult, plContext); 2254 2255 if (buildResult != NULL) 2256 PKIX_PL_Object_DecRef((PKIX_PL_Object *)buildResult, plContext); 2257 2258 if (certStores != NULL) 2259 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext); 2260 2261 if (certSelector != NULL) 2262 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext); 2263 2264 if (builtCertList != NULL) 2265 PKIX_PL_Object_DecRef((PKIX_PL_Object *)builtCertList, plContext); 2266 2267 if (error != NULL) { 2268 SECErrorCodes nssErrorCode = 0; 2269 2270 cert_PkixErrorToNssCode(error, &nssErrorCode, plContext); 2271 cert_pkixDestroyValOutParam(paramsOut); 2272 PORT_SetError(nssErrorCode); 2273 PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext); 2274 } 2275 2276 PKIX_PL_NssContext_Destroy(plContext); 2277 2278 #ifdef PKIX_OBJECT_LEAK_TEST 2279 leakedObjNum = 2280 pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL); 2281 2282 if (pkixLog && leakedObjNum) { 2283 PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d." 2284 "Stack %s\n", 2285 memLeakLoopCount, errorFnStackString)); 2286 } 2287 PR_Free(errorFnStackString); 2288 errorFnStackString = NULL; 2289 if (abortOnLeak) { 2290 PORT_Assert(leakedObjNum == 0); 2291 } 2292 2293 } while (errorGenerated); 2294 2295 runningLeakTest = PKIX_FALSE; 2296 PR_ATOMIC_DECREMENT(¶llelFnInvocationCount); 2297 usePKIXValidationEngine = savedUsePkixEngFlag; 2298 #endif /* PKIX_OBJECT_LEAK_TEST */ 2299 2300 return r; 2301 #endif /* NSS_DISABLE_LIBPKIX */ 2302 }