security/nss/lib/certhigh/certvfypkix.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial