pkix_pl_cert.c (125791B)
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 * pkix_pl_cert.c 6 * 7 * Certificate Object Functions 8 * 9 */ 10 11 #include "pkix_pl_cert.h" 12 13 extern PKIX_PL_HashTable *cachedCertSigTable; 14 15 /* --Private-Cert-Functions------------------------------------- */ 16 17 /* 18 * FUNCTION: pkix_pl_Cert_IsExtensionCritical 19 * DESCRIPTION: 20 * 21 * Checks the Cert specified by "cert" to determine whether the extension 22 * whose tag is the UInt32 value given by "tag" is marked as a critical 23 * extension, and stores the result in "pCritical". 24 * 25 * Tags are the index into the table "oids" of SECOidData defined in the 26 * file secoid.c. Constants, such as SEC_OID_X509_CERTIFICATE_POLICIES, are 27 * are defined in secoidt.h for most of the table entries. 28 * 29 * If the specified tag is invalid (not in the list of tags) or if the 30 * extension is not found in the certificate, PKIX_FALSE is stored. 31 * 32 * PARAMETERS 33 * "cert" 34 * Address of Cert whose extensions are to be examined. Must be non-NULL. 35 * "tag" 36 * The UInt32 value of the tag for the extension whose criticality is 37 * to be determined 38 * "pCritical" 39 * Address where the Boolean value will be stored. Must be non-NULL. 40 * "plContext" 41 * Platform-specific context pointer. 42 * THREAD SAFETY: 43 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 44 * RETURNS: 45 * Returns NULL if the function succeeds. 46 * Returns a Fatal Error if the function fails in an unrecoverable way. 47 */ 48 static PKIX_Error * 49 pkix_pl_Cert_IsExtensionCritical( 50 PKIX_PL_Cert *cert, 51 PKIX_UInt32 tag, 52 PKIX_Boolean *pCritical, 53 void *plContext) 54 { 55 PKIX_Boolean criticality = PKIX_FALSE; 56 CERTCertExtension **extensions = NULL; 57 SECStatus rv; 58 59 PKIX_ENTER(CERT, "pkix_pl_Cert_IsExtensionCritical"); 60 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCritical); 61 62 extensions = cert->nssCert->extensions; 63 PKIX_NULLCHECK_ONE(extensions); 64 65 PKIX_CERT_DEBUG("\t\tCalling CERT_GetExtenCriticality).\n"); 66 rv = CERT_GetExtenCriticality(extensions, tag, &criticality); 67 if (SECSuccess == rv) { 68 *pCritical = criticality; 69 } else { 70 *pCritical = PKIX_FALSE; 71 } 72 73 PKIX_RETURN(CERT); 74 } 75 76 /* 77 * FUNCTION: pkix_pl_Cert_DecodePolicyInfo 78 * DESCRIPTION: 79 * 80 * Decodes the contents of the CertificatePolicy extension in the 81 * CERTCertificate pointed to by "nssCert", to create a List of 82 * CertPolicyInfos, which is stored at the address "pCertPolicyInfos". 83 * A CERTCertificate contains the DER representation of the Cert. 84 * If this certificate does not have a CertificatePolicy extension, 85 * NULL will be stored. If a List is returned, it will be immutable. 86 * 87 * PARAMETERS 88 * "nssCert" 89 * Address of the Cert data whose extension is to be examined. Must be 90 * non-NULL. 91 * "pCertPolicyInfos" 92 * Address where the List of CertPolicyInfos will be stored. Must be 93 * non-NULL. 94 * "plContext" 95 * Platform-specific context pointer. 96 * THREAD SAFETY: 97 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 98 * RETURNS: 99 * Returns NULL if the function succeeds. 100 * Returns a Cert Error if the function fails in a non-fatal way. 101 * Returns a Fatal Error if the function fails in an unrecoverable way. 102 */ 103 static PKIX_Error * 104 pkix_pl_Cert_DecodePolicyInfo( 105 CERTCertificate *nssCert, 106 PKIX_List **pCertPolicyInfos, 107 void *plContext) 108 { 109 110 SECStatus rv; 111 SECItem encodedCertPolicyInfo; 112 113 /* Allocated in the arena; freed in CERT_Destroy... */ 114 CERTCertificatePolicies *certPol = NULL; 115 CERTPolicyInfo **policyInfos = NULL; 116 117 /* Holder for the return value */ 118 PKIX_List *infos = NULL; 119 120 PKIX_PL_OID *pkixOID = NULL; 121 PKIX_List *qualifiers = NULL; 122 PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL; 123 PKIX_PL_CertPolicyQualifier *certPolicyQualifier = NULL; 124 PKIX_PL_ByteArray *qualifierArray = NULL; 125 126 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyInfo"); 127 PKIX_NULLCHECK_TWO(nssCert, pCertPolicyInfos); 128 129 /* get PolicyInfo as a SECItem */ 130 PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n"); 131 rv = CERT_FindCertExtension 132 (nssCert, 133 SEC_OID_X509_CERTIFICATE_POLICIES, 134 &encodedCertPolicyInfo); 135 if (SECSuccess != rv) { 136 *pCertPolicyInfos = NULL; 137 goto cleanup; 138 } 139 140 /* translate PolicyInfo to CERTCertificatePolicies */ 141 PKIX_CERT_DEBUG("\t\tCERT_DecodeCertificatePoliciesExtension).\n"); 142 certPol = CERT_DecodeCertificatePoliciesExtension 143 (&encodedCertPolicyInfo); 144 145 PORT_Free(encodedCertPolicyInfo.data); 146 147 if (NULL == certPol) { 148 PKIX_ERROR(PKIX_CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED); 149 } 150 151 /* 152 * Check whether there are any policyInfos, so we can 153 * avoid creating an unnecessary List 154 */ 155 policyInfos = certPol->policyInfos; 156 if (!policyInfos) { 157 *pCertPolicyInfos = NULL; 158 goto cleanup; 159 } 160 161 /* create a List of CertPolicyInfo Objects */ 162 PKIX_CHECK(PKIX_List_Create(&infos, plContext), 163 PKIX_LISTCREATEFAILED); 164 165 /* 166 * Traverse the CERTCertificatePolicies structure, 167 * building each PKIX_PL_CertPolicyInfo object in turn 168 */ 169 while (*policyInfos != NULL) { 170 CERTPolicyInfo *policyInfo = *policyInfos; 171 CERTPolicyQualifier **policyQualifiers = 172 policyInfo->policyQualifiers; 173 if (policyQualifiers) { 174 /* create a PKIX_List of PKIX_PL_CertPolicyQualifiers */ 175 PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext), 176 PKIX_LISTCREATEFAILED); 177 178 while (*policyQualifiers != NULL) { 179 CERTPolicyQualifier *policyQualifier = 180 *policyQualifiers; 181 182 /* create the qualifier's OID object */ 183 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem 184 (&policyQualifier->qualifierID, 185 &pkixOID, plContext), 186 PKIX_OIDCREATEFAILED); 187 188 /* create qualifier's ByteArray object */ 189 190 PKIX_CHECK(PKIX_PL_ByteArray_Create 191 (policyQualifier->qualifierValue.data, 192 policyQualifier->qualifierValue.len, 193 &qualifierArray, 194 plContext), 195 PKIX_BYTEARRAYCREATEFAILED); 196 197 /* create a CertPolicyQualifier object */ 198 199 PKIX_CHECK(pkix_pl_CertPolicyQualifier_Create 200 (pkixOID, 201 qualifierArray, 202 &certPolicyQualifier, 203 plContext), 204 PKIX_CERTPOLICYQUALIFIERCREATEFAILED); 205 206 PKIX_CHECK(PKIX_List_AppendItem 207 (qualifiers, 208 (PKIX_PL_Object *)certPolicyQualifier, 209 plContext), 210 PKIX_LISTAPPENDITEMFAILED); 211 212 PKIX_DECREF(pkixOID); 213 PKIX_DECREF(qualifierArray); 214 PKIX_DECREF(certPolicyQualifier); 215 216 policyQualifiers++; 217 } 218 219 PKIX_CHECK(PKIX_List_SetImmutable 220 (qualifiers, plContext), 221 PKIX_LISTSETIMMUTABLEFAILED); 222 } 223 224 225 /* 226 * Create an OID object pkixOID from policyInfo->policyID. 227 * (The CERTPolicyInfo structure has an oid field, but it 228 * is of type SECOidTag. This function wants a SECItem.) 229 */ 230 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem 231 (&policyInfo->policyID, &pkixOID, plContext), 232 PKIX_OIDCREATEFAILED); 233 234 /* Create a CertPolicyInfo object */ 235 PKIX_CHECK(pkix_pl_CertPolicyInfo_Create 236 (pkixOID, qualifiers, &certPolicyInfo, plContext), 237 PKIX_CERTPOLICYINFOCREATEFAILED); 238 239 /* Append the new CertPolicyInfo object to the list */ 240 PKIX_CHECK(PKIX_List_AppendItem 241 (infos, (PKIX_PL_Object *)certPolicyInfo, plContext), 242 PKIX_LISTAPPENDITEMFAILED); 243 244 PKIX_DECREF(pkixOID); 245 PKIX_DECREF(qualifiers); 246 PKIX_DECREF(certPolicyInfo); 247 248 policyInfos++; 249 } 250 251 /* 252 * If there were no policies, we went straight to 253 * cleanup, so we don't have to NULLCHECK infos. 254 */ 255 PKIX_CHECK(PKIX_List_SetImmutable(infos, plContext), 256 PKIX_LISTSETIMMUTABLEFAILED); 257 258 *pCertPolicyInfos = infos; 259 infos = NULL; 260 261 cleanup: 262 if (certPol) { 263 PKIX_CERT_DEBUG 264 ("\t\tCalling CERT_DestroyCertificatePoliciesExtension).\n"); 265 CERT_DestroyCertificatePoliciesExtension(certPol); 266 } 267 268 PKIX_DECREF(infos); 269 PKIX_DECREF(pkixOID); 270 PKIX_DECREF(qualifiers); 271 PKIX_DECREF(certPolicyInfo); 272 PKIX_DECREF(certPolicyQualifier); 273 PKIX_DECREF(qualifierArray); 274 275 PKIX_RETURN(CERT); 276 } 277 278 /* 279 * FUNCTION: pkix_pl_Cert_DecodePolicyMapping 280 * DESCRIPTION: 281 * 282 * Decodes the contents of the PolicyMapping extension of the CERTCertificate 283 * pointed to by "nssCert", storing the resulting List of CertPolicyMaps at 284 * the address pointed to by "pCertPolicyMaps". If this certificate does not 285 * have a PolicyMapping extension, NULL will be stored. If a List is returned, 286 * it will be immutable. 287 * 288 * PARAMETERS 289 * "nssCert" 290 * Address of the Cert data whose extension is to be examined. Must be 291 * non-NULL. 292 * "pCertPolicyMaps" 293 * Address where the List of CertPolicyMaps will be stored. Must be 294 * non-NULL. 295 * "plContext" 296 * Platform-specific context pointer. 297 * THREAD SAFETY: 298 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 299 * RETURNS: 300 * Returns NULL if the function succeeds. 301 * Returns a Cert Error if the function fails in a non-fatal way. 302 * Returns a Fatal Error if the function fails in an unrecoverable way. 303 */ 304 static PKIX_Error * 305 pkix_pl_Cert_DecodePolicyMapping( 306 CERTCertificate *nssCert, 307 PKIX_List **pCertPolicyMaps, 308 void *plContext) 309 { 310 SECStatus rv; 311 SECItem encodedCertPolicyMaps; 312 313 /* Allocated in the arena; freed in CERT_Destroy... */ 314 CERTCertificatePolicyMappings *certPolMaps = NULL; 315 CERTPolicyMap **policyMaps = NULL; 316 317 /* Holder for the return value */ 318 PKIX_List *maps = NULL; 319 320 PKIX_PL_OID *issuerDomainOID = NULL; 321 PKIX_PL_OID *subjectDomainOID = NULL; 322 PKIX_PL_CertPolicyMap *certPolicyMap = NULL; 323 324 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyMapping"); 325 PKIX_NULLCHECK_TWO(nssCert, pCertPolicyMaps); 326 327 /* get PolicyMappings as a SECItem */ 328 PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n"); 329 rv = CERT_FindCertExtension 330 (nssCert, SEC_OID_X509_POLICY_MAPPINGS, &encodedCertPolicyMaps); 331 if (SECSuccess != rv) { 332 *pCertPolicyMaps = NULL; 333 goto cleanup; 334 } 335 336 /* translate PolicyMaps to CERTCertificatePolicyMappings */ 337 certPolMaps = CERT_DecodePolicyMappingsExtension 338 (&encodedCertPolicyMaps); 339 340 PORT_Free(encodedCertPolicyMaps.data); 341 342 if (!certPolMaps) { 343 PKIX_ERROR(PKIX_CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED); 344 } 345 346 PKIX_NULLCHECK_ONE(certPolMaps->policyMaps); 347 348 policyMaps = certPolMaps->policyMaps; 349 350 /* create a List of CertPolicyMap Objects */ 351 PKIX_CHECK(PKIX_List_Create(&maps, plContext), 352 PKIX_LISTCREATEFAILED); 353 354 /* 355 * Traverse the CERTCertificatePolicyMappings structure, 356 * building each CertPolicyMap object in turn 357 */ 358 do { 359 CERTPolicyMap *policyMap = *policyMaps; 360 361 /* create the OID for the issuer Domain Policy */ 362 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem 363 (&policyMap->issuerDomainPolicy, 364 &issuerDomainOID, plContext), 365 PKIX_OIDCREATEFAILED); 366 367 /* create the OID for the subject Domain Policy */ 368 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem 369 (&policyMap->subjectDomainPolicy, 370 &subjectDomainOID, plContext), 371 PKIX_OIDCREATEFAILED); 372 373 /* create the CertPolicyMap */ 374 375 PKIX_CHECK(pkix_pl_CertPolicyMap_Create 376 (issuerDomainOID, 377 subjectDomainOID, 378 &certPolicyMap, 379 plContext), 380 PKIX_CERTPOLICYMAPCREATEFAILED); 381 382 PKIX_CHECK(PKIX_List_AppendItem 383 (maps, (PKIX_PL_Object *)certPolicyMap, plContext), 384 PKIX_LISTAPPENDITEMFAILED); 385 386 PKIX_DECREF(issuerDomainOID); 387 PKIX_DECREF(subjectDomainOID); 388 PKIX_DECREF(certPolicyMap); 389 390 policyMaps++; 391 } while (*policyMaps != NULL); 392 393 PKIX_CHECK(PKIX_List_SetImmutable(maps, plContext), 394 PKIX_LISTSETIMMUTABLEFAILED); 395 396 *pCertPolicyMaps = maps; 397 maps = NULL; 398 399 cleanup: 400 if (certPolMaps) { 401 PKIX_CERT_DEBUG 402 ("\t\tCalling CERT_DestroyPolicyMappingsExtension).\n"); 403 CERT_DestroyPolicyMappingsExtension(certPolMaps); 404 } 405 406 PKIX_DECREF(maps); 407 PKIX_DECREF(issuerDomainOID); 408 PKIX_DECREF(subjectDomainOID); 409 PKIX_DECREF(certPolicyMap); 410 411 PKIX_RETURN(CERT); 412 } 413 414 /* 415 * FUNCTION: pkix_pl_Cert_DecodePolicyConstraints 416 * DESCRIPTION: 417 * 418 * Decodes the contents of the PolicyConstraints extension in the 419 * CERTCertificate pointed to by "nssCert", to obtain SkipCerts values 420 * which are stored at the addresses "pExplicitPolicySkipCerts" and 421 * "pInhibitMappingSkipCerts", respectively. If this certificate does 422 * not have an PolicyConstraints extension, or if either of the optional 423 * components is not supplied, this function stores a value of -1 for any 424 * missing component. 425 * 426 * PARAMETERS 427 * "nssCert" 428 * Address of the Cert data whose extension is to be examined. Must be 429 * non-NULL. 430 * "pExplicitPolicySkipCerts" 431 * Address where the SkipCert value for the requireExplicitPolicy 432 * component will be stored. Must be non-NULL. 433 * "pInhibitMappingSkipCerts" 434 * Address where the SkipCert value for the inhibitPolicyMapping 435 * component will be stored. Must be non-NULL. 436 * "plContext" 437 * Platform-specific context pointer. 438 * THREAD SAFETY: 439 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 440 * RETURNS: 441 * Returns NULL if the function succeeds. 442 * Returns a Cert Error if the function fails in a non-fatal way. 443 * Returns a Fatal Error if the function fails in an unrecoverable way. 444 */ 445 static PKIX_Error * 446 pkix_pl_Cert_DecodePolicyConstraints( 447 CERTCertificate *nssCert, 448 PKIX_Int32 *pExplicitPolicySkipCerts, 449 PKIX_Int32 *pInhibitMappingSkipCerts, 450 void *plContext) 451 { 452 CERTCertificatePolicyConstraints policyConstraints; 453 SECStatus rv; 454 SECItem encodedCertPolicyConstraints; 455 PKIX_Int32 explicitPolicySkipCerts = -1; 456 PKIX_Int32 inhibitMappingSkipCerts = -1; 457 458 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyConstraints"); 459 PKIX_NULLCHECK_THREE 460 (nssCert, pExplicitPolicySkipCerts, pInhibitMappingSkipCerts); 461 462 /* get the two skipCert values as SECItems */ 463 PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n"); 464 rv = CERT_FindCertExtension 465 (nssCert, 466 SEC_OID_X509_POLICY_CONSTRAINTS, 467 &encodedCertPolicyConstraints); 468 469 if (rv == SECSuccess) { 470 471 policyConstraints.explicitPolicySkipCerts.data = 472 (unsigned char *)&explicitPolicySkipCerts; 473 policyConstraints.inhibitMappingSkipCerts.data = 474 (unsigned char *)&inhibitMappingSkipCerts; 475 476 /* translate DER to CERTCertificatePolicyConstraints */ 477 rv = CERT_DecodePolicyConstraintsExtension 478 (&policyConstraints, &encodedCertPolicyConstraints); 479 480 PORT_Free(encodedCertPolicyConstraints.data); 481 482 if (rv != SECSuccess) { 483 PKIX_ERROR 484 (PKIX_CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED); 485 } 486 } 487 488 *pExplicitPolicySkipCerts = explicitPolicySkipCerts; 489 *pInhibitMappingSkipCerts = inhibitMappingSkipCerts; 490 491 cleanup: 492 PKIX_RETURN(CERT); 493 } 494 495 /* 496 * FUNCTION: pkix_pl_Cert_DecodeInhibitAnyPolicy 497 * DESCRIPTION: 498 * 499 * Decodes the contents of the InhibitAnyPolicy extension in the 500 * CERTCertificate pointed to by "nssCert", to obtain a SkipCerts value, 501 * which is stored at the address "pSkipCerts". If this certificate does 502 * not have an InhibitAnyPolicy extension, -1 will be stored. 503 * 504 * PARAMETERS 505 * "nssCert" 506 * Address of the Cert data whose InhibitAnyPolicy extension is to be 507 * processed. Must be non-NULL. 508 * "pSkipCerts" 509 * Address where the SkipCert value from the InhibitAnyPolicy extension 510 * will be stored. Must be non-NULL. 511 * "plContext" 512 * Platform-specific context pointer. 513 * THREAD SAFETY: 514 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 515 * RETURNS: 516 * Returns NULL if the function succeeds. 517 * Returns a Cert Error if the function fails in a non-fatal way. 518 * Returns a Fatal Error if the function fails in an unrecoverable way. 519 */ 520 PKIX_Error * 521 pkix_pl_Cert_DecodeInhibitAnyPolicy( 522 CERTCertificate *nssCert, 523 PKIX_Int32 *pSkipCerts, 524 void *plContext) 525 { 526 CERTCertificateInhibitAny inhibitAny; 527 SECStatus rv; 528 SECItem encodedCertInhibitAny; 529 PKIX_Int32 skipCerts = -1; 530 531 PKIX_ENTER(CERT, "pkix_pl_Cert_DecodeInhibitAnyPolicy"); 532 PKIX_NULLCHECK_TWO(nssCert, pSkipCerts); 533 534 /* get InhibitAny as a SECItem */ 535 PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n"); 536 rv = CERT_FindCertExtension 537 (nssCert, SEC_OID_X509_INHIBIT_ANY_POLICY, &encodedCertInhibitAny); 538 539 if (rv == SECSuccess) { 540 inhibitAny.inhibitAnySkipCerts.data = 541 (unsigned char *)&skipCerts; 542 543 /* translate DER to CERTCertificateInhibitAny */ 544 rv = CERT_DecodeInhibitAnyExtension 545 (&inhibitAny, &encodedCertInhibitAny); 546 547 PORT_Free(encodedCertInhibitAny.data); 548 549 if (rv != SECSuccess) { 550 PKIX_ERROR(PKIX_CERTDECODEINHIBITANYEXTENSIONFAILED); 551 } 552 } 553 554 *pSkipCerts = skipCerts; 555 556 cleanup: 557 PKIX_RETURN(CERT); 558 } 559 560 /* 561 * FUNCTION: pkix_pl_Cert_GetNssSubjectAltNames 562 * DESCRIPTION: 563 * 564 * Retrieves the Subject Alternative Names of the certificate specified by 565 * "cert" and stores it at "pNssSubjAltNames". If the Subject Alternative 566 * Name extension is not present, NULL is returned at "pNssSubjAltNames". 567 * If the Subject Alternative Names has not been previously decoded, it is 568 * decoded here with lock on the "cert" unless the flag "hasLock" indicates 569 * the lock had been obtained at a higher call level. 570 * 571 * PARAMETERS 572 * "cert" 573 * Address of the certificate whose Subject Alternative Names extensions 574 * is retrieved. Must be non-NULL. 575 * "hasLock" 576 * Boolean indicates caller has acquired a lock. 577 * Must be non-NULL. 578 * "pNssSubjAltNames" 579 * Address where the returned Subject Alternative Names will be stored. 580 * Must be non-NULL. 581 * "plContext" 582 * Platform-specific context pointer. 583 * THREAD SAFETY: 584 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 585 * RETURNS: 586 * Returns NULL if the function succeeds. 587 * Returns a Cert Error if the function fails in a non-fatal way. 588 * Returns a Fatal Error if the function fails in an unrecoverable way. 589 */ 590 static PKIX_Error * 591 pkix_pl_Cert_GetNssSubjectAltNames( 592 PKIX_PL_Cert *cert, 593 PKIX_Boolean hasLock, 594 CERTGeneralName **pNssSubjAltNames, 595 void *plContext) 596 { 597 CERTCertificate *nssCert = NULL; 598 CERTGeneralName *nssOriginalAltName = NULL; 599 PLArenaPool *arena = NULL; 600 SECItem altNameExtension = {siBuffer, NULL, 0}; 601 SECStatus rv = SECFailure; 602 603 PKIX_ENTER(CERT, "pkix_pl_Cert_GetNssSubjectAltNames"); 604 PKIX_NULLCHECK_THREE(cert, pNssSubjAltNames, cert->nssCert); 605 606 nssCert = cert->nssCert; 607 608 if ((cert->nssSubjAltNames == NULL) && (!cert->subjAltNamesAbsent)){ 609 610 if (!hasLock) { 611 PKIX_OBJECT_LOCK(cert); 612 } 613 614 if ((cert->nssSubjAltNames == NULL) && 615 (!cert->subjAltNamesAbsent)){ 616 617 PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension, 618 (nssCert, 619 SEC_OID_X509_SUBJECT_ALT_NAME, 620 &altNameExtension)); 621 622 if (rv != SECSuccess) { 623 *pNssSubjAltNames = NULL; 624 cert->subjAltNamesAbsent = PKIX_TRUE; 625 goto cleanup; 626 } 627 628 if (cert->arenaNameConstraints == NULL) { 629 PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena, 630 (DER_DEFAULT_CHUNKSIZE)); 631 632 if (arena == NULL) { 633 PKIX_ERROR(PKIX_OUTOFMEMORY); 634 } 635 cert->arenaNameConstraints = arena; 636 } 637 638 PKIX_PL_NSSCALLRV 639 (CERT, 640 nssOriginalAltName, 641 (CERTGeneralName *) CERT_DecodeAltNameExtension, 642 (cert->arenaNameConstraints, &altNameExtension)); 643 644 PKIX_PL_NSSCALL(CERT, PORT_Free, (altNameExtension.data)); 645 646 if (nssOriginalAltName == NULL) { 647 PKIX_ERROR(PKIX_CERTDECODEALTNAMEEXTENSIONFAILED); 648 } 649 cert->nssSubjAltNames = nssOriginalAltName; 650 651 } 652 653 if (!hasLock) { 654 PKIX_OBJECT_UNLOCK(cert); 655 } 656 } 657 658 *pNssSubjAltNames = cert->nssSubjAltNames; 659 660 cleanup: 661 PKIX_OBJECT_UNLOCK(lockedObject); 662 PKIX_RETURN(CERT); 663 } 664 665 /* 666 * FUNCTION: pkix_pl_Cert_CheckExtendKeyUsage 667 * DESCRIPTION: 668 * 669 * For each of the ON bit in "requiredExtendedKeyUsages" that represents its 670 * SECCertUsageEnum type, this function checks "cert"'s certType (extended 671 * key usage) and key usage with what is required for SECCertUsageEnum type. 672 * 673 * PARAMETERS 674 * "cert" 675 * Address of the certificate whose Extended Key Usage extensions 676 * is retrieved. Must be non-NULL. 677 * "requiredExtendedKeyUsages" 678 * An unsigned integer, its bit location is ON based on the required key 679 * usage value representing in SECCertUsageEnum. 680 * "pPass" 681 * Address where the return value, indicating key usage check passed, is 682 * stored. Must be non-NULL. 683 * "plContext" 684 * Platform-specific context pointer. 685 * THREAD SAFETY: 686 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 687 * RETURNS: 688 * Returns NULL if the function succeeds. 689 * Returns a Cert Error if the function fails in a non-fatal way. 690 * Returns a Fatal Error if the function fails in an unrecoverable way. 691 */ 692 PKIX_Error * 693 pkix_pl_Cert_CheckExtendedKeyUsage( 694 PKIX_PL_Cert *cert, 695 PKIX_UInt32 requiredExtendedKeyUsages, 696 PKIX_Boolean *pPass, 697 void *plContext) 698 { 699 PKIX_PL_CertBasicConstraints *basicConstraints = NULL; 700 PKIX_UInt32 certType = 0; 701 PKIX_UInt32 requiredKeyUsage = 0; 702 PKIX_UInt32 requiredCertType = 0; 703 PKIX_UInt32 requiredExtendedKeyUsage = 0; 704 PKIX_UInt32 i; 705 PKIX_Boolean isCA = PKIX_FALSE; 706 SECStatus rv = SECFailure; 707 708 PKIX_ENTER(CERT, "pkix_pl_Cert_CheckExtendKeyUsage"); 709 PKIX_NULLCHECK_THREE(cert, pPass, cert->nssCert); 710 711 *pPass = PKIX_FALSE; 712 713 PKIX_CERT_DEBUG("\t\tCalling cert_GetCertType).\n"); 714 cert_GetCertType(cert->nssCert); 715 certType = cert->nssCert->nsCertType; 716 717 PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints 718 (cert, 719 &basicConstraints, 720 plContext), 721 PKIX_CERTGETBASICCONSTRAINTFAILED); 722 723 if (basicConstraints != NULL) { 724 PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag 725 (basicConstraints, &isCA, plContext), 726 PKIX_BASICCONSTRAINTSGETCAFLAGFAILED); 727 } 728 729 i = 0; 730 while (requiredExtendedKeyUsages != 0) { 731 732 /* Find the bit location of the right-most non-zero bit */ 733 while (requiredExtendedKeyUsages != 0) { 734 if (((1 << i) & requiredExtendedKeyUsages) != 0) { 735 requiredExtendedKeyUsage = 1 << i; 736 break; 737 } 738 i++; 739 } 740 requiredExtendedKeyUsages ^= requiredExtendedKeyUsage; 741 742 requiredExtendedKeyUsage = i; 743 744 PKIX_PL_NSSCALLRV(CERT, rv, CERT_KeyUsageAndTypeForCertUsage, 745 (requiredExtendedKeyUsage, 746 isCA, 747 &requiredKeyUsage, 748 &requiredCertType)); 749 750 if (!(certType & requiredCertType)) { 751 goto cleanup; 752 } 753 754 PKIX_PL_NSSCALLRV(CERT, rv, CERT_CheckKeyUsage, 755 (cert->nssCert, requiredKeyUsage)); 756 if (rv != SECSuccess) { 757 goto cleanup; 758 } 759 i++; 760 761 } 762 763 *pPass = PKIX_TRUE; 764 765 cleanup: 766 PKIX_DECREF(basicConstraints); 767 PKIX_RETURN(CERT); 768 } 769 770 /* 771 * FUNCTION: pkix_pl_Cert_ToString_Helper 772 * DESCRIPTION: 773 * 774 * Helper function that creates a string representation of the Cert pointed 775 * to by "cert" and stores it at "pString", where the value of 776 * "partialString" determines whether a full or partial representation of 777 * the Cert is stored. 778 * 779 * PARAMETERS 780 * "cert" 781 * Address of Cert whose string representation is desired. 782 * Must be non-NULL. 783 * "partialString" 784 * Boolean indicating whether a partial Cert representation is desired. 785 * "pString" 786 * Address where object pointer will be stored. Must be non-NULL. 787 * "plContext" 788 * Platform-specific context pointer. 789 * THREAD SAFETY: 790 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 791 * RETURNS: 792 * Returns NULL if the function succeeds. 793 * Returns a Cert Error if the function fails in a non-fatal way. 794 * Returns a Fatal Error if the function fails in an unrecoverable way. 795 */ 796 PKIX_Error * 797 pkix_pl_Cert_ToString_Helper( 798 PKIX_PL_Cert *cert, 799 PKIX_Boolean partialString, 800 PKIX_PL_String **pString, 801 void *plContext) 802 { 803 PKIX_PL_String *certString = NULL; 804 char *asciiFormat = NULL; 805 PKIX_PL_String *formatString = NULL; 806 PKIX_UInt32 certVersion; 807 PKIX_PL_BigInt *certSN = NULL; 808 PKIX_PL_String *certSNString = NULL; 809 PKIX_PL_X500Name *certIssuer = NULL; 810 PKIX_PL_String *certIssuerString = NULL; 811 PKIX_PL_X500Name *certSubject = NULL; 812 PKIX_PL_String *certSubjectString = NULL; 813 PKIX_PL_String *notBeforeString = NULL; 814 PKIX_PL_String *notAfterString = NULL; 815 PKIX_List *subjAltNames = NULL; 816 PKIX_PL_String *subjAltNamesString = NULL; 817 PKIX_PL_ByteArray *authKeyId = NULL; 818 PKIX_PL_String *authKeyIdString = NULL; 819 PKIX_PL_ByteArray *subjKeyId = NULL; 820 PKIX_PL_String *subjKeyIdString = NULL; 821 PKIX_PL_PublicKey *nssPubKey = NULL; 822 PKIX_PL_String *nssPubKeyString = NULL; 823 PKIX_List *critExtOIDs = NULL; 824 PKIX_PL_String *critExtOIDsString = NULL; 825 PKIX_List *extKeyUsages = NULL; 826 PKIX_PL_String *extKeyUsagesString = NULL; 827 PKIX_PL_CertBasicConstraints *basicConstraint = NULL; 828 PKIX_PL_String *certBasicConstraintsString = NULL; 829 PKIX_List *policyInfo = NULL; 830 PKIX_PL_String *certPolicyInfoString = NULL; 831 PKIX_List *certPolicyMappings = NULL; 832 PKIX_PL_String *certPolicyMappingsString = NULL; 833 PKIX_Int32 certExplicitPolicy = 0; 834 PKIX_Int32 certInhibitMapping = 0; 835 PKIX_Int32 certInhibitAnyPolicy = 0; 836 PKIX_PL_CertNameConstraints *nameConstraints = NULL; 837 PKIX_PL_String *nameConstraintsString = NULL; 838 PKIX_List *authorityInfoAccess = NULL; 839 PKIX_PL_String *authorityInfoAccessString = NULL; 840 PKIX_List *subjectInfoAccess = NULL; 841 PKIX_PL_String *subjectInfoAccessString = NULL; 842 843 PKIX_ENTER(CERT, "pkix_pl_Cert_ToString_Helper"); 844 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pString); 845 846 /* 847 * XXX Add to this format as certificate components are developed. 848 */ 849 850 if (partialString){ 851 asciiFormat = 852 "\t[Issuer: %s\n" 853 "\t Subject: %s]"; 854 } else { 855 asciiFormat = 856 "[\n" 857 "\tVersion: v%d\n" 858 "\tSerialNumber: %s\n" 859 "\tIssuer: %s\n" 860 "\tSubject: %s\n" 861 "\tValidity: [From: %s\n" 862 "\t To: %s]\n" 863 "\tSubjectAltNames: %s\n" 864 "\tAuthorityKeyId: %s\n" 865 "\tSubjectKeyId: %s\n" 866 "\tSubjPubKeyAlgId: %s\n" 867 "\tCritExtOIDs: %s\n" 868 "\tExtKeyUsages: %s\n" 869 "\tBasicConstraint: %s\n" 870 "\tCertPolicyInfo: %s\n" 871 "\tPolicyMappings: %s\n" 872 "\tExplicitPolicy: %d\n" 873 "\tInhibitMapping: %d\n" 874 "\tInhibitAnyPolicy:%d\n" 875 "\tNameConstraints: %s\n" 876 "\tAuthorityInfoAccess: %s\n" 877 "\tSubjectInfoAccess: %s\n" 878 "\tCacheFlag: %d\n" 879 "]\n"; 880 } 881 882 883 884 PKIX_CHECK(PKIX_PL_String_Create 885 (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), 886 PKIX_STRINGCREATEFAILED); 887 888 /* Issuer */ 889 PKIX_CHECK(PKIX_PL_Cert_GetIssuer 890 (cert, &certIssuer, plContext), 891 PKIX_CERTGETISSUERFAILED); 892 893 PKIX_CHECK(PKIX_PL_Object_ToString 894 ((PKIX_PL_Object *)certIssuer, &certIssuerString, plContext), 895 PKIX_X500NAMETOSTRINGFAILED); 896 897 /* Subject */ 898 PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &certSubject, plContext), 899 PKIX_CERTGETSUBJECTFAILED); 900 901 PKIX_TOSTRING(certSubject, &certSubjectString, plContext, 902 PKIX_X500NAMETOSTRINGFAILED); 903 904 if (partialString){ 905 PKIX_CHECK(PKIX_PL_Sprintf 906 (&certString, 907 plContext, 908 formatString, 909 certIssuerString, 910 certSubjectString), 911 PKIX_SPRINTFFAILED); 912 913 *pString = certString; 914 goto cleanup; 915 } 916 917 /* Version */ 918 PKIX_CHECK(PKIX_PL_Cert_GetVersion(cert, &certVersion, plContext), 919 PKIX_CERTGETVERSIONFAILED); 920 921 /* SerialNumber */ 922 PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber(cert, &certSN, plContext), 923 PKIX_CERTGETSERIALNUMBERFAILED); 924 925 PKIX_CHECK(PKIX_PL_Object_ToString 926 ((PKIX_PL_Object *)certSN, &certSNString, plContext), 927 PKIX_BIGINTTOSTRINGFAILED); 928 929 /* Validity: NotBefore */ 930 PKIX_CHECK(pkix_pl_Date_ToString_Helper 931 (&(cert->nssCert->validity.notBefore), 932 ¬BeforeString, 933 plContext), 934 PKIX_DATETOSTRINGHELPERFAILED); 935 936 /* Validity: NotAfter */ 937 PKIX_CHECK(pkix_pl_Date_ToString_Helper 938 (&(cert->nssCert->validity.notAfter), 939 ¬AfterString, 940 plContext), 941 PKIX_DATETOSTRINGHELPERFAILED); 942 943 /* SubjectAltNames */ 944 PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames 945 (cert, &subjAltNames, plContext), 946 PKIX_CERTGETSUBJECTALTNAMESFAILED); 947 948 PKIX_TOSTRING(subjAltNames, &subjAltNamesString, plContext, 949 PKIX_LISTTOSTRINGFAILED); 950 951 /* AuthorityKeyIdentifier */ 952 PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier 953 (cert, &authKeyId, plContext), 954 PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED); 955 956 PKIX_TOSTRING(authKeyId, &authKeyIdString, plContext, 957 PKIX_BYTEARRAYTOSTRINGFAILED); 958 959 /* SubjectKeyIdentifier */ 960 PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier 961 (cert, &subjKeyId, plContext), 962 PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED); 963 964 PKIX_TOSTRING(subjKeyId, &subjKeyIdString, plContext, 965 PKIX_BYTEARRAYTOSTRINGFAILED); 966 967 /* SubjectPublicKey */ 968 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey 969 (cert, &nssPubKey, plContext), 970 PKIX_CERTGETSUBJECTPUBLICKEYFAILED); 971 972 PKIX_CHECK(PKIX_PL_Object_ToString 973 ((PKIX_PL_Object *)nssPubKey, &nssPubKeyString, plContext), 974 PKIX_PUBLICKEYTOSTRINGFAILED); 975 976 /* CriticalExtensionOIDs */ 977 PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs 978 (cert, &critExtOIDs, plContext), 979 PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED); 980 981 PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext, 982 PKIX_LISTTOSTRINGFAILED); 983 984 /* ExtendedKeyUsages */ 985 PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage 986 (cert, &extKeyUsages, plContext), 987 PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); 988 989 PKIX_TOSTRING(extKeyUsages, &extKeyUsagesString, plContext, 990 PKIX_LISTTOSTRINGFAILED); 991 992 /* CertBasicConstraints */ 993 PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints 994 (cert, &basicConstraint, plContext), 995 PKIX_CERTGETBASICCONSTRAINTSFAILED); 996 997 PKIX_TOSTRING(basicConstraint, &certBasicConstraintsString, plContext, 998 PKIX_CERTBASICCONSTRAINTSTOSTRINGFAILED); 999 1000 /* CertPolicyInfo */ 1001 PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation 1002 (cert, &policyInfo, plContext), 1003 PKIX_CERTGETPOLICYINFORMATIONFAILED); 1004 1005 PKIX_TOSTRING(policyInfo, &certPolicyInfoString, plContext, 1006 PKIX_LISTTOSTRINGFAILED); 1007 1008 /* Advanced Policies */ 1009 PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings 1010 (cert, &certPolicyMappings, plContext), 1011 PKIX_CERTGETPOLICYMAPPINGSFAILED); 1012 1013 PKIX_TOSTRING(certPolicyMappings, &certPolicyMappingsString, plContext, 1014 PKIX_LISTTOSTRINGFAILED); 1015 1016 PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy 1017 (cert, &certExplicitPolicy, plContext), 1018 PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED); 1019 1020 PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited 1021 (cert, &certInhibitMapping, plContext), 1022 PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED); 1023 1024 PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy 1025 (cert, &certInhibitAnyPolicy, plContext), 1026 PKIX_CERTGETINHIBITANYPOLICYFAILED); 1027 1028 /* Name Constraints */ 1029 PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints 1030 (cert, &nameConstraints, plContext), 1031 PKIX_CERTGETNAMECONSTRAINTSFAILED); 1032 1033 PKIX_TOSTRING(nameConstraints, &nameConstraintsString, plContext, 1034 PKIX_LISTTOSTRINGFAILED); 1035 1036 /* Authority Information Access */ 1037 PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess 1038 (cert, &authorityInfoAccess, plContext), 1039 PKIX_CERTGETAUTHORITYINFOACCESSFAILED); 1040 1041 PKIX_TOSTRING(authorityInfoAccess, &authorityInfoAccessString, plContext, 1042 PKIX_LISTTOSTRINGFAILED); 1043 1044 /* Subject Information Access */ 1045 PKIX_CHECK(PKIX_PL_Cert_GetSubjectInfoAccess 1046 (cert, &subjectInfoAccess, plContext), 1047 PKIX_CERTGETSUBJECTINFOACCESSFAILED); 1048 1049 PKIX_TOSTRING(subjectInfoAccess, &subjectInfoAccessString, plContext, 1050 PKIX_LISTTOSTRINGFAILED); 1051 1052 PKIX_CHECK(PKIX_PL_Sprintf 1053 (&certString, 1054 plContext, 1055 formatString, 1056 certVersion + 1, 1057 certSNString, 1058 certIssuerString, 1059 certSubjectString, 1060 notBeforeString, 1061 notAfterString, 1062 subjAltNamesString, 1063 authKeyIdString, 1064 subjKeyIdString, 1065 nssPubKeyString, 1066 critExtOIDsString, 1067 extKeyUsagesString, 1068 certBasicConstraintsString, 1069 certPolicyInfoString, 1070 certPolicyMappingsString, 1071 certExplicitPolicy, /* an Int32, not a String */ 1072 certInhibitMapping, /* an Int32, not a String */ 1073 certInhibitAnyPolicy, /* an Int32, not a String */ 1074 nameConstraintsString, 1075 authorityInfoAccessString, 1076 subjectInfoAccessString, 1077 cert->cacheFlag), /* a boolean */ 1078 PKIX_SPRINTFFAILED); 1079 1080 *pString = certString; 1081 1082 cleanup: 1083 PKIX_DECREF(certSN); 1084 PKIX_DECREF(certSNString); 1085 PKIX_DECREF(certIssuer); 1086 PKIX_DECREF(certIssuerString); 1087 PKIX_DECREF(certSubject); 1088 PKIX_DECREF(certSubjectString); 1089 PKIX_DECREF(notBeforeString); 1090 PKIX_DECREF(notAfterString); 1091 PKIX_DECREF(subjAltNames); 1092 PKIX_DECREF(subjAltNamesString); 1093 PKIX_DECREF(authKeyId); 1094 PKIX_DECREF(authKeyIdString); 1095 PKIX_DECREF(subjKeyId); 1096 PKIX_DECREF(subjKeyIdString); 1097 PKIX_DECREF(nssPubKey); 1098 PKIX_DECREF(nssPubKeyString); 1099 PKIX_DECREF(critExtOIDs); 1100 PKIX_DECREF(critExtOIDsString); 1101 PKIX_DECREF(extKeyUsages); 1102 PKIX_DECREF(extKeyUsagesString); 1103 PKIX_DECREF(basicConstraint); 1104 PKIX_DECREF(certBasicConstraintsString); 1105 PKIX_DECREF(policyInfo); 1106 PKIX_DECREF(certPolicyInfoString); 1107 PKIX_DECREF(certPolicyMappings); 1108 PKIX_DECREF(certPolicyMappingsString); 1109 PKIX_DECREF(nameConstraints); 1110 PKIX_DECREF(nameConstraintsString); 1111 PKIX_DECREF(authorityInfoAccess); 1112 PKIX_DECREF(authorityInfoAccessString); 1113 PKIX_DECREF(subjectInfoAccess); 1114 PKIX_DECREF(subjectInfoAccessString); 1115 PKIX_DECREF(formatString); 1116 1117 PKIX_RETURN(CERT); 1118 } 1119 1120 /* 1121 * FUNCTION: pkix_pl_Cert_Destroy 1122 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) 1123 */ 1124 static PKIX_Error * 1125 pkix_pl_Cert_Destroy( 1126 PKIX_PL_Object *object, 1127 void *plContext) 1128 { 1129 PKIX_PL_Cert *cert = NULL; 1130 1131 PKIX_ENTER(CERT, "pkix_pl_Cert_Destroy"); 1132 PKIX_NULLCHECK_ONE(object); 1133 1134 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), 1135 PKIX_OBJECTNOTCERT); 1136 1137 cert = (PKIX_PL_Cert*)object; 1138 1139 PKIX_DECREF(cert->subject); 1140 PKIX_DECREF(cert->issuer); 1141 PKIX_DECREF(cert->subjAltNames); 1142 PKIX_DECREF(cert->publicKeyAlgId); 1143 PKIX_DECREF(cert->publicKey); 1144 PKIX_DECREF(cert->serialNumber); 1145 PKIX_DECREF(cert->critExtOids); 1146 PKIX_DECREF(cert->authKeyId); 1147 PKIX_DECREF(cert->subjKeyId); 1148 PKIX_DECREF(cert->extKeyUsages); 1149 PKIX_DECREF(cert->certBasicConstraints); 1150 PKIX_DECREF(cert->certPolicyInfos); 1151 PKIX_DECREF(cert->certPolicyMappings); 1152 PKIX_DECREF(cert->nameConstraints); 1153 PKIX_DECREF(cert->store); 1154 PKIX_DECREF(cert->authorityInfoAccess); 1155 PKIX_DECREF(cert->subjectInfoAccess); 1156 PKIX_DECREF(cert->crldpList); 1157 1158 if (cert->arenaNameConstraints){ 1159 /* This arena was allocated for SubjectAltNames */ 1160 PKIX_PL_NSSCALL(CERT, PORT_FreeArena, 1161 (cert->arenaNameConstraints, PR_FALSE)); 1162 1163 cert->arenaNameConstraints = NULL; 1164 cert->nssSubjAltNames = NULL; 1165 } 1166 1167 CERT_DestroyCertificate(cert->nssCert); 1168 cert->nssCert = NULL; 1169 1170 cleanup: 1171 PKIX_RETURN(CERT); 1172 } 1173 1174 /* 1175 * FUNCTION: pkix_pl_Cert_ToString 1176 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) 1177 */ 1178 static PKIX_Error * 1179 pkix_pl_Cert_ToString( 1180 PKIX_PL_Object *object, 1181 PKIX_PL_String **pString, 1182 void *plContext) 1183 { 1184 PKIX_PL_String *certString = NULL; 1185 PKIX_PL_Cert *pkixCert = NULL; 1186 1187 PKIX_ENTER(CERT, "pkix_pl_Cert_toString"); 1188 PKIX_NULLCHECK_TWO(object, pString); 1189 1190 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), 1191 PKIX_OBJECTNOTCERT); 1192 1193 pkixCert = (PKIX_PL_Cert *)object; 1194 1195 PKIX_CHECK(pkix_pl_Cert_ToString_Helper 1196 (pkixCert, PKIX_FALSE, &certString, plContext), 1197 PKIX_CERTTOSTRINGHELPERFAILED); 1198 1199 *pString = certString; 1200 1201 cleanup: 1202 PKIX_RETURN(CERT); 1203 } 1204 1205 /* 1206 * FUNCTION: pkix_pl_Cert_Hashcode 1207 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) 1208 */ 1209 static PKIX_Error * 1210 pkix_pl_Cert_Hashcode( 1211 PKIX_PL_Object *object, 1212 PKIX_UInt32 *pHashcode, 1213 void *plContext) 1214 { 1215 PKIX_PL_Cert *pkixCert = NULL; 1216 CERTCertificate *nssCert = NULL; 1217 unsigned char *derBytes = NULL; 1218 PKIX_UInt32 derLength; 1219 PKIX_UInt32 certHash; 1220 1221 PKIX_ENTER(CERT, "pkix_pl_Cert_Hashcode"); 1222 PKIX_NULLCHECK_TWO(object, pHashcode); 1223 1224 PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), 1225 PKIX_OBJECTNOTCERT); 1226 1227 pkixCert = (PKIX_PL_Cert *)object; 1228 1229 nssCert = pkixCert->nssCert; 1230 derBytes = (nssCert->derCert).data; 1231 derLength = (nssCert->derCert).len; 1232 1233 PKIX_CHECK(pkix_hash(derBytes, derLength, &certHash, plContext), 1234 PKIX_HASHFAILED); 1235 1236 *pHashcode = certHash; 1237 1238 cleanup: 1239 PKIX_RETURN(CERT); 1240 } 1241 1242 1243 /* 1244 * FUNCTION: pkix_pl_Cert_Equals 1245 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) 1246 */ 1247 static PKIX_Error * 1248 pkix_pl_Cert_Equals( 1249 PKIX_PL_Object *firstObject, 1250 PKIX_PL_Object *secondObject, 1251 PKIX_Boolean *pResult, 1252 void *plContext) 1253 { 1254 CERTCertificate *firstCert = NULL; 1255 CERTCertificate *secondCert = NULL; 1256 PKIX_UInt32 secondType; 1257 PKIX_Boolean cmpResult; 1258 1259 PKIX_ENTER(CERT, "pkix_pl_Cert_Equals"); 1260 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); 1261 1262 /* test that firstObject is a Cert */ 1263 PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CERT_TYPE, plContext), 1264 PKIX_FIRSTOBJECTNOTCERT); 1265 1266 /* 1267 * Since we know firstObject is a Cert, if both references are 1268 * identical, they must be equal 1269 */ 1270 if (firstObject == secondObject){ 1271 *pResult = PKIX_TRUE; 1272 goto cleanup; 1273 } 1274 1275 /* 1276 * If secondObject isn't a Cert, we don't throw an error. 1277 * We simply return a Boolean result of FALSE 1278 */ 1279 *pResult = PKIX_FALSE; 1280 PKIX_CHECK(PKIX_PL_Object_GetType 1281 (secondObject, &secondType, plContext), 1282 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); 1283 if (secondType != PKIX_CERT_TYPE) goto cleanup; 1284 1285 firstCert = ((PKIX_PL_Cert *)firstObject)->nssCert; 1286 secondCert = ((PKIX_PL_Cert *)secondObject)->nssCert; 1287 1288 PKIX_NULLCHECK_TWO(firstCert, secondCert); 1289 1290 /* CERT_CompareCerts does byte comparison on DER encodings of certs */ 1291 PKIX_CERT_DEBUG("\t\tCalling CERT_CompareCerts).\n"); 1292 cmpResult = CERT_CompareCerts(firstCert, secondCert); 1293 1294 *pResult = cmpResult; 1295 1296 cleanup: 1297 PKIX_RETURN(CERT); 1298 } 1299 1300 /* 1301 * FUNCTION: pkix_pl_Cert_RegisterSelf 1302 * DESCRIPTION: 1303 * Registers PKIX_CERT_TYPE and its related functions with systemClasses[] 1304 * THREAD SAFETY: 1305 * Not Thread Safe - for performance and complexity reasons 1306 * 1307 * Since this function is only called by PKIX_PL_Initialize, which should 1308 * only be called once, it is acceptable that this function is not 1309 * thread-safe. 1310 */ 1311 PKIX_Error * 1312 pkix_pl_Cert_RegisterSelf(void *plContext) 1313 { 1314 1315 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; 1316 pkix_ClassTable_Entry entry; 1317 1318 PKIX_ENTER(CERT, "pkix_pl_Cert_RegisterSelf"); 1319 1320 entry.description = "Cert"; 1321 entry.objCounter = 0; 1322 entry.typeObjectSize = sizeof(PKIX_PL_Cert); 1323 entry.destructor = pkix_pl_Cert_Destroy; 1324 entry.equalsFunction = pkix_pl_Cert_Equals; 1325 entry.hashcodeFunction = pkix_pl_Cert_Hashcode; 1326 entry.toStringFunction = pkix_pl_Cert_ToString; 1327 entry.comparator = NULL; 1328 entry.duplicateFunction = pkix_duplicateImmutable; 1329 1330 systemClasses[PKIX_CERT_TYPE] = entry; 1331 1332 PKIX_RETURN(CERT); 1333 } 1334 1335 /* 1336 * FUNCTION: pkix_pl_Cert_CreateWithNSSCert 1337 * DESCRIPTION: 1338 * 1339 * Creates a new certificate using the CERTCertificate pointed to by "nssCert" 1340 * and stores it at "pCert". Once created, a Cert is immutable. 1341 * 1342 * This function is primarily used as a convenience function for the 1343 * performance tests that have easy access to a CERTCertificate. 1344 * 1345 * PARAMETERS: 1346 * "nssCert" 1347 * Address of CERTCertificate representing the NSS certificate. 1348 * Must be non-NULL. 1349 * "pCert" 1350 * Address where object pointer will be stored. Must be non-NULL. 1351 * "plContext" 1352 * Platform-specific context pointer. 1353 * THREAD SAFETY: 1354 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1355 * RETURNS: 1356 * Returns NULL if the function succeeds. 1357 * Returns a Cert Error if the function fails in a non-fatal way. 1358 * Returns a Fatal Error if the function fails in an unrecoverable way. 1359 */ 1360 PKIX_Error * 1361 pkix_pl_Cert_CreateWithNSSCert( 1362 CERTCertificate *nssCert, 1363 PKIX_PL_Cert **pCert, 1364 void *plContext) 1365 { 1366 PKIX_PL_Cert *cert = NULL; 1367 1368 PKIX_ENTER(CERT, "pkix_pl_Cert_CreateWithNSSCert"); 1369 PKIX_NULLCHECK_TWO(pCert, nssCert); 1370 1371 /* create a PKIX_PL_Cert object */ 1372 PKIX_CHECK(PKIX_PL_Object_Alloc 1373 (PKIX_CERT_TYPE, 1374 sizeof (PKIX_PL_Cert), 1375 (PKIX_PL_Object **)&cert, 1376 plContext), 1377 PKIX_COULDNOTCREATEOBJECT); 1378 1379 /* populate the nssCert field */ 1380 cert->nssCert = nssCert; 1381 1382 /* initialize remaining fields */ 1383 /* 1384 * Fields ending with Absent are initialized to PKIX_FALSE so that the 1385 * first time we need the value we will look for it. If we find it is 1386 * actually absent, the flag will at that time be set to PKIX_TRUE to 1387 * prevent searching for it later. 1388 * Fields ending with Processed are those where a value is defined 1389 * for the Absent case, and a value of zero is possible. When the 1390 * flag is still true we have to look for the field, set the default 1391 * value if necessary, and set the Processed flag to PKIX_TRUE. 1392 */ 1393 cert->subject = NULL; 1394 cert->issuer = NULL; 1395 cert->subjAltNames = NULL; 1396 cert->subjAltNamesAbsent = PKIX_FALSE; 1397 cert->publicKeyAlgId = NULL; 1398 cert->publicKey = NULL; 1399 cert->serialNumber = NULL; 1400 cert->critExtOids = NULL; 1401 cert->subjKeyId = NULL; 1402 cert->subjKeyIdAbsent = PKIX_FALSE; 1403 cert->authKeyId = NULL; 1404 cert->authKeyIdAbsent = PKIX_FALSE; 1405 cert->extKeyUsages = NULL; 1406 cert->extKeyUsagesAbsent = PKIX_FALSE; 1407 cert->certBasicConstraints = NULL; 1408 cert->basicConstraintsAbsent = PKIX_FALSE; 1409 cert->certPolicyInfos = NULL; 1410 cert->policyInfoAbsent = PKIX_FALSE; 1411 cert->policyMappingsAbsent = PKIX_FALSE; 1412 cert->certPolicyMappings = NULL; 1413 cert->policyConstraintsProcessed = PKIX_FALSE; 1414 cert->policyConstraintsExplicitPolicySkipCerts = 0; 1415 cert->policyConstraintsInhibitMappingSkipCerts = 0; 1416 cert->inhibitAnyPolicyProcessed = PKIX_FALSE; 1417 cert->inhibitAnySkipCerts = 0; 1418 cert->nameConstraints = NULL; 1419 cert->nameConstraintsAbsent = PKIX_FALSE; 1420 cert->arenaNameConstraints = NULL; 1421 cert->nssSubjAltNames = NULL; 1422 cert->cacheFlag = PKIX_FALSE; 1423 cert->store = NULL; 1424 cert->authorityInfoAccess = NULL; 1425 cert->subjectInfoAccess = NULL; 1426 cert->isUserTrustAnchor = PKIX_FALSE; 1427 cert->crldpList = NULL; 1428 1429 *pCert = cert; 1430 1431 cleanup: 1432 PKIX_RETURN(CERT); 1433 } 1434 1435 /* 1436 * FUNCTION: pkix_pl_Cert_CreateToList 1437 * DESCRIPTION: 1438 * 1439 * Creates a new certificate using the DER-encoding pointed to by "derCertItem" 1440 * and appends it to the list pointed to by "certList". If Cert creation fails, 1441 * the function returns with certList unchanged, but any decoding Error is 1442 * discarded. 1443 * 1444 * PARAMETERS: 1445 * "derCertItem" 1446 * Address of SECItem containing the DER representation of a certificate. 1447 * Must be non-NULL. 1448 * "certList" 1449 * Address of List to which the Cert will be appended, if successfully 1450 * created. May be empty, but must be non-NULL. 1451 * "plContext" 1452 * Platform-specific context pointer. 1453 * THREAD SAFETY: 1454 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1455 * RETURNS: 1456 * Returns NULL if the function succeeds. 1457 * Returns a Cert Error if the function fails in a non-fatal way. 1458 * Returns a Fatal Error if the function fails in an unrecoverable way. 1459 */ 1460 PKIX_Error * 1461 pkix_pl_Cert_CreateToList( 1462 SECItem *derCertItem, 1463 PKIX_List *certList, 1464 void *plContext) 1465 { 1466 CERTCertificate *nssCert = NULL; 1467 PKIX_PL_Cert *cert = NULL; 1468 CERTCertDBHandle *handle; 1469 1470 PKIX_ENTER(CERT, "pkix_pl_Cert_CreateToList"); 1471 PKIX_NULLCHECK_TWO(derCertItem, certList); 1472 1473 handle = CERT_GetDefaultCertDB(); 1474 nssCert = CERT_NewTempCertificate(handle, derCertItem, 1475 /* nickname */ NULL, 1476 /* isPerm */ PR_FALSE, 1477 /* copyDer */ PR_TRUE); 1478 if (!nssCert) { 1479 goto cleanup; 1480 } 1481 1482 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert 1483 (nssCert, &cert, plContext), 1484 PKIX_CERTCREATEWITHNSSCERTFAILED); 1485 1486 nssCert = NULL; 1487 1488 PKIX_CHECK(PKIX_List_AppendItem 1489 (certList, (PKIX_PL_Object *) cert, plContext), 1490 PKIX_LISTAPPENDITEMFAILED); 1491 1492 cleanup: 1493 if (nssCert) { 1494 CERT_DestroyCertificate(nssCert); 1495 } 1496 1497 PKIX_DECREF(cert); 1498 PKIX_RETURN(CERT); 1499 } 1500 1501 /* --Public-Functions------------------------------------------------------- */ 1502 1503 /* 1504 * FUNCTION: PKIX_PL_Cert_Create (see comments in pkix_pl_pki.h) 1505 * XXX We may want to cache the cert after parsing it, so it can be reused 1506 * XXX Are the NSS/NSPR functions thread safe 1507 */ 1508 PKIX_Error * 1509 PKIX_PL_Cert_Create( 1510 PKIX_PL_ByteArray *byteArray, 1511 PKIX_PL_Cert **pCert, 1512 void *plContext) 1513 { 1514 CERTCertificate *nssCert = NULL; 1515 SECItem *derCertItem = NULL; 1516 void *derBytes = NULL; 1517 PKIX_UInt32 derLength; 1518 PKIX_PL_Cert *cert = NULL; 1519 CERTCertDBHandle *handle; 1520 1521 PKIX_ENTER(CERT, "PKIX_PL_Cert_Create"); 1522 PKIX_NULLCHECK_TWO(pCert, byteArray); 1523 1524 PKIX_CHECK(PKIX_PL_ByteArray_GetPointer 1525 (byteArray, &derBytes, plContext), 1526 PKIX_BYTEARRAYGETPOINTERFAILED); 1527 1528 PKIX_CHECK(PKIX_PL_ByteArray_GetLength 1529 (byteArray, &derLength, plContext), 1530 PKIX_BYTEARRAYGETLENGTHFAILED); 1531 1532 derCertItem = SECITEM_AllocItem(NULL, NULL, derLength); 1533 if (derCertItem == NULL){ 1534 PKIX_ERROR(PKIX_OUTOFMEMORY); 1535 } 1536 1537 (void) PORT_Memcpy(derCertItem->data, derBytes, derLength); 1538 1539 /* 1540 * setting copyDER to true forces NSS to make its own copy of the DER, 1541 * allowing us to free our copy without worrying about whether NSS 1542 * is still using it 1543 */ 1544 handle = CERT_GetDefaultCertDB(); 1545 nssCert = CERT_NewTempCertificate(handle, derCertItem, 1546 /* nickname */ NULL, 1547 /* isPerm */ PR_FALSE, 1548 /* copyDer */ PR_TRUE); 1549 if (!nssCert){ 1550 PKIX_ERROR(PKIX_CERTDECODEDERCERTIFICATEFAILED); 1551 } 1552 1553 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert 1554 (nssCert, &cert, plContext), 1555 PKIX_CERTCREATEWITHNSSCERTFAILED); 1556 1557 *pCert = cert; 1558 1559 cleanup: 1560 if (derCertItem){ 1561 SECITEM_FreeItem(derCertItem, PKIX_TRUE); 1562 } 1563 1564 if (nssCert && PKIX_ERROR_RECEIVED){ 1565 PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n"); 1566 CERT_DestroyCertificate(nssCert); 1567 nssCert = NULL; 1568 } 1569 1570 PKIX_FREE(derBytes); 1571 PKIX_RETURN(CERT); 1572 } 1573 1574 1575 /* 1576 * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate 1577 * (see comments in pkix_pl_pki.h) 1578 */ 1579 PKIX_Error * 1580 PKIX_PL_Cert_CreateFromCERTCertificate( 1581 const CERTCertificate *nssCert, 1582 PKIX_PL_Cert **pCert, 1583 void *plContext) 1584 { 1585 void *buf = NULL; 1586 PKIX_UInt32 len; 1587 PKIX_PL_ByteArray *byteArray = NULL; 1588 1589 PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNssCert"); 1590 PKIX_NULLCHECK_TWO(pCert, nssCert); 1591 1592 buf = (void*)nssCert->derCert.data; 1593 len = nssCert->derCert.len; 1594 1595 PKIX_CHECK( 1596 PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext), 1597 PKIX_BYTEARRAYCREATEFAILED); 1598 1599 PKIX_CHECK( 1600 PKIX_PL_Cert_Create(byteArray, pCert, plContext), 1601 PKIX_CERTCREATEWITHNSSCERTFAILED); 1602 1603 #ifdef PKIX_UNDEF 1604 /* will be tested and used as a patch for bug 391612 */ 1605 nssCert = CERT_DupCertificate(nssInCert); 1606 1607 PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert 1608 (nssCert, &cert, plContext), 1609 PKIX_CERTCREATEWITHNSSCERTFAILED); 1610 #endif /* PKIX_UNDEF */ 1611 1612 cleanup: 1613 1614 #ifdef PKIX_UNDEF 1615 if (nssCert && PKIX_ERROR_RECEIVED){ 1616 PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n"); 1617 CERT_DestroyCertificate(nssCert); 1618 nssCert = NULL; 1619 } 1620 #endif /* PKIX_UNDEF */ 1621 1622 PKIX_DECREF(byteArray); 1623 PKIX_RETURN(CERT); 1624 } 1625 1626 1627 /* 1628 * FUNCTION: PKIX_PL_Cert_GetVersion (see comments in pkix_pl_pki.h) 1629 */ 1630 PKIX_Error * 1631 PKIX_PL_Cert_GetVersion( 1632 PKIX_PL_Cert *cert, 1633 PKIX_UInt32 *pVersion, 1634 void *plContext) 1635 { 1636 CERTCertificate *nssCert = NULL; 1637 PKIX_UInt32 myVersion = 0; /* v1 */ 1638 1639 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetVersion"); 1640 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pVersion); 1641 1642 nssCert = cert->nssCert; 1643 if (nssCert->version.len != 0) { 1644 myVersion = *(nssCert->version.data); 1645 } 1646 1647 if (myVersion > 2){ 1648 PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1V2ORV3); 1649 } 1650 1651 *pVersion = myVersion; 1652 1653 cleanup: 1654 PKIX_RETURN(CERT); 1655 } 1656 1657 /* 1658 * FUNCTION: PKIX_PL_Cert_GetSerialNumber (see comments in pkix_pl_pki.h) 1659 */ 1660 PKIX_Error * 1661 PKIX_PL_Cert_GetSerialNumber( 1662 PKIX_PL_Cert *cert, 1663 PKIX_PL_BigInt **pSerialNumber, 1664 void *plContext) 1665 { 1666 CERTCertificate *nssCert = NULL; 1667 SECItem serialNumItem; 1668 PKIX_PL_BigInt *serialNumber = NULL; 1669 char *bytes = NULL; 1670 PKIX_UInt32 length; 1671 1672 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSerialNumber"); 1673 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSerialNumber); 1674 1675 if (cert->serialNumber == NULL){ 1676 1677 PKIX_OBJECT_LOCK(cert); 1678 1679 if (cert->serialNumber == NULL){ 1680 1681 nssCert = cert->nssCert; 1682 serialNumItem = nssCert->serialNumber; 1683 1684 length = serialNumItem.len; 1685 bytes = (char *)serialNumItem.data; 1686 1687 PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes 1688 (bytes, length, &serialNumber, plContext), 1689 PKIX_BIGINTCREATEWITHBYTESFAILED); 1690 1691 /* save a cached copy in case it is asked for again */ 1692 cert->serialNumber = serialNumber; 1693 } 1694 1695 PKIX_OBJECT_UNLOCK(cert); 1696 } 1697 1698 PKIX_INCREF(cert->serialNumber); 1699 *pSerialNumber = cert->serialNumber; 1700 1701 cleanup: 1702 PKIX_OBJECT_UNLOCK(lockedObject); 1703 PKIX_RETURN(CERT); 1704 } 1705 1706 /* 1707 * FUNCTION: PKIX_PL_Cert_GetSubject (see comments in pkix_pl_pki.h) 1708 */ 1709 PKIX_Error * 1710 PKIX_PL_Cert_GetSubject( 1711 PKIX_PL_Cert *cert, 1712 PKIX_PL_X500Name **pCertSubject, 1713 void *plContext) 1714 { 1715 PKIX_PL_X500Name *pkixSubject = NULL; 1716 CERTName *subjName = NULL; 1717 SECItem *derSubjName = NULL; 1718 1719 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubject"); 1720 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertSubject); 1721 1722 /* if we don't have a cached copy from before, we create one */ 1723 if (cert->subject == NULL){ 1724 1725 PKIX_OBJECT_LOCK(cert); 1726 1727 if (cert->subject == NULL){ 1728 1729 subjName = &cert->nssCert->subject; 1730 derSubjName = &cert->nssCert->derSubject; 1731 1732 /* if there is no subject name */ 1733 if (derSubjName->data == NULL) { 1734 1735 pkixSubject = NULL; 1736 1737 } else { 1738 PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName 1739 (derSubjName, subjName, &pkixSubject, 1740 plContext), 1741 PKIX_X500NAMECREATEFROMCERTNAMEFAILED); 1742 1743 } 1744 /* save a cached copy in case it is asked for again */ 1745 cert->subject = pkixSubject; 1746 } 1747 1748 PKIX_OBJECT_UNLOCK(cert); 1749 } 1750 1751 PKIX_INCREF(cert->subject); 1752 *pCertSubject = cert->subject; 1753 1754 cleanup: 1755 PKIX_OBJECT_UNLOCK(lockedObject); 1756 PKIX_RETURN(CERT); 1757 } 1758 1759 /* 1760 * FUNCTION: PKIX_PL_Cert_GetIssuer (see comments in pkix_pl_pki.h) 1761 */ 1762 PKIX_Error * 1763 PKIX_PL_Cert_GetIssuer( 1764 PKIX_PL_Cert *cert, 1765 PKIX_PL_X500Name **pCertIssuer, 1766 void *plContext) 1767 { 1768 PKIX_PL_X500Name *pkixIssuer = NULL; 1769 SECItem *derIssuerName = NULL; 1770 CERTName *issuerName = NULL; 1771 1772 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetIssuer"); 1773 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertIssuer); 1774 1775 /* if we don't have a cached copy from before, we create one */ 1776 if (cert->issuer == NULL){ 1777 1778 PKIX_OBJECT_LOCK(cert); 1779 1780 if (cert->issuer == NULL){ 1781 1782 issuerName = &cert->nssCert->issuer; 1783 derIssuerName = &cert->nssCert->derIssuer; 1784 1785 /* if there is no subject name */ 1786 PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName 1787 (derIssuerName, issuerName, 1788 &pkixIssuer, plContext), 1789 PKIX_X500NAMECREATEFROMCERTNAMEFAILED); 1790 1791 /* save a cached copy in case it is asked for again */ 1792 cert->issuer = pkixIssuer; 1793 } 1794 1795 PKIX_OBJECT_UNLOCK(cert); 1796 } 1797 1798 PKIX_INCREF(cert->issuer); 1799 *pCertIssuer = cert->issuer; 1800 1801 cleanup: 1802 PKIX_RETURN(CERT); 1803 } 1804 1805 /* 1806 * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames (see comments in pkix_pl_pki.h) 1807 */ 1808 PKIX_Error * 1809 PKIX_PL_Cert_GetSubjectAltNames( 1810 PKIX_PL_Cert *cert, 1811 PKIX_List **pSubjectAltNames, /* list of PKIX_PL_GeneralName */ 1812 void *plContext) 1813 { 1814 PKIX_PL_GeneralName *pkixAltName = NULL; 1815 PKIX_List *altNamesList = NULL; 1816 1817 CERTGeneralName *nssOriginalAltName = NULL; 1818 CERTGeneralName *nssTempAltName = NULL; 1819 1820 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectAltNames"); 1821 PKIX_NULLCHECK_TWO(cert, pSubjectAltNames); 1822 1823 /* if we don't have a cached copy from before, we create one */ 1824 if ((cert->subjAltNames == NULL) && (!cert->subjAltNamesAbsent)){ 1825 1826 PKIX_OBJECT_LOCK(cert); 1827 1828 if ((cert->subjAltNames == NULL) && 1829 (!cert->subjAltNamesAbsent)){ 1830 1831 PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames 1832 (cert, 1833 PKIX_TRUE, 1834 &nssOriginalAltName, 1835 plContext), 1836 PKIX_CERTGETNSSSUBJECTALTNAMESFAILED); 1837 1838 if (nssOriginalAltName == NULL) { 1839 cert->subjAltNamesAbsent = PKIX_TRUE; 1840 pSubjectAltNames = NULL; 1841 goto cleanup; 1842 } 1843 1844 nssTempAltName = nssOriginalAltName; 1845 1846 PKIX_CHECK(PKIX_List_Create(&altNamesList, plContext), 1847 PKIX_LISTCREATEFAILED); 1848 1849 do { 1850 PKIX_CHECK(pkix_pl_GeneralName_Create 1851 (nssTempAltName, &pkixAltName, plContext), 1852 PKIX_GENERALNAMECREATEFAILED); 1853 1854 PKIX_CHECK(PKIX_List_AppendItem 1855 (altNamesList, 1856 (PKIX_PL_Object *)pkixAltName, 1857 plContext), 1858 PKIX_LISTAPPENDITEMFAILED); 1859 1860 PKIX_DECREF(pkixAltName); 1861 1862 PKIX_CERT_DEBUG 1863 ("\t\tCalling CERT_GetNextGeneralName).\n"); 1864 nssTempAltName = CERT_GetNextGeneralName 1865 (nssTempAltName); 1866 1867 } while (nssTempAltName != nssOriginalAltName); 1868 1869 /* save a cached copy in case it is asked for again */ 1870 cert->subjAltNames = altNamesList; 1871 PKIX_CHECK(PKIX_List_SetImmutable 1872 (cert->subjAltNames, plContext), 1873 PKIX_LISTSETIMMUTABLEFAILED); 1874 1875 } 1876 1877 PKIX_OBJECT_UNLOCK(cert); 1878 } 1879 1880 PKIX_INCREF(cert->subjAltNames); 1881 1882 *pSubjectAltNames = cert->subjAltNames; 1883 1884 cleanup: 1885 PKIX_DECREF(pkixAltName); 1886 if (PKIX_ERROR_RECEIVED){ 1887 PKIX_DECREF(altNamesList); 1888 } 1889 PKIX_RETURN(CERT); 1890 } 1891 1892 /* 1893 * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames (see comments in pkix_pl_pki.h) 1894 */ 1895 PKIX_Error * 1896 PKIX_PL_Cert_GetAllSubjectNames( 1897 PKIX_PL_Cert *cert, 1898 PKIX_List **pAllSubjectNames, /* list of PKIX_PL_GeneralName */ 1899 void *plContext) 1900 { 1901 CERTGeneralName *nssOriginalSubjectName = NULL; 1902 CERTGeneralName *nssTempSubjectName = NULL; 1903 PKIX_List *allSubjectNames = NULL; 1904 PKIX_PL_GeneralName *pkixSubjectName = NULL; 1905 PLArenaPool *arena = NULL; 1906 1907 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAllSubjectNames"); 1908 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAllSubjectNames); 1909 1910 1911 if (cert->nssCert->subjectName == NULL){ 1912 /* if there is no subject DN, just get altnames */ 1913 1914 PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames 1915 (cert, 1916 PKIX_FALSE, /* hasLock */ 1917 &nssOriginalSubjectName, 1918 plContext), 1919 PKIX_CERTGETNSSSUBJECTALTNAMESFAILED); 1920 1921 } else { /* get subject DN and altnames */ 1922 1923 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1924 if (arena == NULL) { 1925 PKIX_ERROR(PKIX_OUTOFMEMORY); 1926 } 1927 1928 /* This NSS call returns both Subject and Subject Alt Names */ 1929 PKIX_CERT_DEBUG("\t\tCalling CERT_GetCertificateNames\n"); 1930 nssOriginalSubjectName = 1931 CERT_GetCertificateNames(cert->nssCert, arena); 1932 } 1933 1934 if (nssOriginalSubjectName == NULL) { 1935 pAllSubjectNames = NULL; 1936 goto cleanup; 1937 } 1938 1939 nssTempSubjectName = nssOriginalSubjectName; 1940 1941 PKIX_CHECK(PKIX_List_Create(&allSubjectNames, plContext), 1942 PKIX_LISTCREATEFAILED); 1943 1944 do { 1945 PKIX_CHECK(pkix_pl_GeneralName_Create 1946 (nssTempSubjectName, &pkixSubjectName, plContext), 1947 PKIX_GENERALNAMECREATEFAILED); 1948 1949 PKIX_CHECK(PKIX_List_AppendItem 1950 (allSubjectNames, 1951 (PKIX_PL_Object *)pkixSubjectName, 1952 plContext), 1953 PKIX_LISTAPPENDITEMFAILED); 1954 1955 PKIX_DECREF(pkixSubjectName); 1956 1957 PKIX_CERT_DEBUG 1958 ("\t\tCalling CERT_GetNextGeneralName).\n"); 1959 nssTempSubjectName = CERT_GetNextGeneralName 1960 (nssTempSubjectName); 1961 } while (nssTempSubjectName != nssOriginalSubjectName); 1962 1963 *pAllSubjectNames = allSubjectNames; 1964 1965 cleanup: 1966 if (PKIX_ERROR_RECEIVED){ 1967 PKIX_DECREF(allSubjectNames); 1968 } 1969 1970 if (arena){ 1971 PORT_FreeArena(arena, PR_FALSE); 1972 } 1973 PKIX_DECREF(pkixSubjectName); 1974 PKIX_RETURN(CERT); 1975 } 1976 1977 /* 1978 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId 1979 * (see comments in pkix_pl_pki.h) 1980 */ 1981 PKIX_Error * 1982 PKIX_PL_Cert_GetSubjectPublicKeyAlgId( 1983 PKIX_PL_Cert *cert, 1984 PKIX_PL_OID **pSubjKeyAlgId, 1985 void *plContext) 1986 { 1987 PKIX_PL_OID *pubKeyAlgId = NULL; 1988 1989 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKeyAlgId"); 1990 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyAlgId); 1991 1992 /* if we don't have a cached copy from before, we create one */ 1993 if (cert->publicKeyAlgId == NULL){ 1994 PKIX_OBJECT_LOCK(cert); 1995 if (cert->publicKeyAlgId == NULL){ 1996 CERTCertificate *nssCert = cert->nssCert; 1997 SECAlgorithmID *algorithm; 1998 SECItem *algBytes; 1999 2000 algorithm = &nssCert->subjectPublicKeyInfo.algorithm; 2001 algBytes = &algorithm->algorithm; 2002 if (!algBytes->data || !algBytes->len) { 2003 PKIX_ERROR_FATAL(PKIX_ALGORITHMBYTESLENGTH0); 2004 } 2005 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem 2006 (algBytes, &pubKeyAlgId, plContext), 2007 PKIX_OIDCREATEFAILED); 2008 2009 /* save a cached copy in case it is asked for again */ 2010 cert->publicKeyAlgId = pubKeyAlgId; 2011 pubKeyAlgId = NULL; 2012 } 2013 PKIX_OBJECT_UNLOCK(cert); 2014 } 2015 2016 PKIX_INCREF(cert->publicKeyAlgId); 2017 *pSubjKeyAlgId = cert->publicKeyAlgId; 2018 2019 cleanup: 2020 PKIX_DECREF(pubKeyAlgId); 2021 PKIX_RETURN(CERT); 2022 } 2023 2024 /* 2025 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey (see comments in pkix_pl_pki.h) 2026 */ 2027 PKIX_Error * 2028 PKIX_PL_Cert_GetSubjectPublicKey( 2029 PKIX_PL_Cert *cert, 2030 PKIX_PL_PublicKey **pPublicKey, 2031 void *plContext) 2032 { 2033 PKIX_PL_PublicKey *pkixPubKey = NULL; 2034 SECStatus rv; 2035 2036 CERTSubjectPublicKeyInfo *from = NULL; 2037 CERTSubjectPublicKeyInfo *to = NULL; 2038 SECItem *fromItem = NULL; 2039 SECItem *toItem = NULL; 2040 2041 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKey"); 2042 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPublicKey); 2043 2044 /* if we don't have a cached copy from before, we create one */ 2045 if (cert->publicKey == NULL){ 2046 2047 PKIX_OBJECT_LOCK(cert); 2048 2049 if (cert->publicKey == NULL){ 2050 2051 /* create a PKIX_PL_PublicKey object */ 2052 PKIX_CHECK(PKIX_PL_Object_Alloc 2053 (PKIX_PUBLICKEY_TYPE, 2054 sizeof (PKIX_PL_PublicKey), 2055 (PKIX_PL_Object **)&pkixPubKey, 2056 plContext), 2057 PKIX_COULDNOTCREATEOBJECT); 2058 2059 /* initialize fields */ 2060 pkixPubKey->nssSPKI = NULL; 2061 2062 /* populate the SPKI field */ 2063 PKIX_CHECK(PKIX_PL_Malloc 2064 (sizeof (CERTSubjectPublicKeyInfo), 2065 (void **)&pkixPubKey->nssSPKI, 2066 plContext), 2067 PKIX_MALLOCFAILED); 2068 2069 to = pkixPubKey->nssSPKI; 2070 from = &cert->nssCert->subjectPublicKeyInfo; 2071 2072 PKIX_NULLCHECK_TWO(to, from); 2073 2074 PKIX_CERT_DEBUG 2075 ("\t\tCalling SECOID_CopyAlgorithmID).\n"); 2076 rv = SECOID_CopyAlgorithmID 2077 (NULL, &to->algorithm, &from->algorithm); 2078 if (rv != SECSuccess) { 2079 PKIX_ERROR(PKIX_SECOIDCOPYALGORITHMIDFAILED); 2080 } 2081 2082 /* 2083 * NSS stores the length of subjectPublicKey in bits. 2084 * Therefore, we use that length converted to bytes 2085 * using ((length+7)>>3) before calling PORT_Memcpy 2086 * in order to avoid "read from uninitialized memory" 2087 * errors. 2088 */ 2089 2090 toItem = &to->subjectPublicKey; 2091 fromItem = &from->subjectPublicKey; 2092 2093 PKIX_NULLCHECK_TWO(toItem, fromItem); 2094 2095 toItem->type = fromItem->type; 2096 2097 toItem->data = 2098 (unsigned char*) PORT_ZAlloc(fromItem->len); 2099 if (!toItem->data){ 2100 PKIX_ERROR(PKIX_OUTOFMEMORY); 2101 } 2102 2103 (void) PORT_Memcpy(toItem->data, 2104 fromItem->data, 2105 (fromItem->len + 7)>>3); 2106 toItem->len = fromItem->len; 2107 2108 /* save a cached copy in case it is asked for again */ 2109 cert->publicKey = pkixPubKey; 2110 } 2111 2112 PKIX_OBJECT_UNLOCK(cert); 2113 } 2114 2115 PKIX_INCREF(cert->publicKey); 2116 *pPublicKey = cert->publicKey; 2117 2118 cleanup: 2119 2120 if (PKIX_ERROR_RECEIVED && pkixPubKey){ 2121 PKIX_DECREF(pkixPubKey); 2122 cert->publicKey = NULL; 2123 } 2124 PKIX_RETURN(CERT); 2125 } 2126 2127 /* 2128 * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs 2129 * (see comments in pkix_pl_pki.h) 2130 */ 2131 PKIX_Error * 2132 PKIX_PL_Cert_GetCriticalExtensionOIDs( 2133 PKIX_PL_Cert *cert, 2134 PKIX_List **pList, /* list of PKIX_PL_OID */ 2135 void *plContext) 2136 { 2137 PKIX_List *oidsList = NULL; 2138 CERTCertExtension **extensions = NULL; 2139 CERTCertificate *nssCert = NULL; 2140 2141 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCriticalExtensionOIDs"); 2142 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pList); 2143 2144 /* if we don't have a cached copy from before, we create one */ 2145 if (cert->critExtOids == NULL) { 2146 2147 PKIX_OBJECT_LOCK(cert); 2148 2149 if (cert->critExtOids == NULL) { 2150 2151 nssCert = cert->nssCert; 2152 2153 /* 2154 * ASN.1 for Extension 2155 * 2156 * Extension ::= SEQUENCE { 2157 * extnID OBJECT IDENTIFIER, 2158 * critical BOOLEAN DEFAULT FALSE, 2159 * extnValue OCTET STRING } 2160 * 2161 */ 2162 2163 extensions = nssCert->extensions; 2164 2165 PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs 2166 (extensions, &oidsList, plContext), 2167 PKIX_GETCRITICALEXTENSIONOIDSFAILED); 2168 2169 /* save a cached copy in case it is asked for again */ 2170 cert->critExtOids = oidsList; 2171 } 2172 2173 PKIX_OBJECT_UNLOCK(cert); 2174 } 2175 2176 /* We should return a copy of the List since this list changes */ 2177 PKIX_DUPLICATE(cert->critExtOids, pList, plContext, 2178 PKIX_OBJECTDUPLICATELISTFAILED); 2179 2180 cleanup: 2181 PKIX_OBJECT_UNLOCK(lockedObject); 2182 PKIX_RETURN(CERT); 2183 } 2184 2185 /* 2186 * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier 2187 * (see comments in pkix_pl_pki.h) 2188 */ 2189 PKIX_Error * 2190 PKIX_PL_Cert_GetAuthorityKeyIdentifier( 2191 PKIX_PL_Cert *cert, 2192 PKIX_PL_ByteArray **pAuthKeyId, 2193 void *plContext) 2194 { 2195 PKIX_PL_ByteArray *authKeyId = NULL; 2196 CERTCertificate *nssCert = NULL; 2197 CERTAuthKeyID *authKeyIdExtension = NULL; 2198 PLArenaPool *arena = NULL; 2199 SECItem retItem; 2200 2201 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityKeyIdentifier"); 2202 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAuthKeyId); 2203 2204 /* if we don't have a cached copy from before, we create one */ 2205 if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){ 2206 2207 PKIX_OBJECT_LOCK(cert); 2208 2209 if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){ 2210 2211 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 2212 if (arena == NULL) { 2213 PKIX_ERROR(PKIX_OUTOFMEMORY); 2214 } 2215 2216 nssCert = cert->nssCert; 2217 2218 authKeyIdExtension = 2219 CERT_FindAuthKeyIDExten(arena, nssCert); 2220 if (authKeyIdExtension == NULL){ 2221 cert->authKeyIdAbsent = PKIX_TRUE; 2222 *pAuthKeyId = NULL; 2223 goto cleanup; 2224 } 2225 2226 retItem = authKeyIdExtension->keyID; 2227 2228 if (retItem.len == 0){ 2229 cert->authKeyIdAbsent = PKIX_TRUE; 2230 *pAuthKeyId = NULL; 2231 goto cleanup; 2232 } 2233 2234 PKIX_CHECK(PKIX_PL_ByteArray_Create 2235 (retItem.data, 2236 retItem.len, 2237 &authKeyId, 2238 plContext), 2239 PKIX_BYTEARRAYCREATEFAILED); 2240 2241 /* save a cached copy in case it is asked for again */ 2242 cert->authKeyId = authKeyId; 2243 } 2244 2245 PKIX_OBJECT_UNLOCK(cert); 2246 } 2247 2248 PKIX_INCREF(cert->authKeyId); 2249 *pAuthKeyId = cert->authKeyId; 2250 2251 cleanup: 2252 PKIX_OBJECT_UNLOCK(lockedObject); 2253 if (arena){ 2254 PORT_FreeArena(arena, PR_FALSE); 2255 } 2256 PKIX_RETURN(CERT); 2257 } 2258 2259 /* 2260 * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier 2261 * (see comments in pkix_pl_pki.h) 2262 */ 2263 PKIX_Error * 2264 PKIX_PL_Cert_GetSubjectKeyIdentifier( 2265 PKIX_PL_Cert *cert, 2266 PKIX_PL_ByteArray **pSubjKeyId, 2267 void *plContext) 2268 { 2269 PKIX_PL_ByteArray *subjKeyId = NULL; 2270 CERTCertificate *nssCert = NULL; 2271 SECItem *retItem = NULL; 2272 SECStatus status; 2273 2274 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectKeyIdentifier"); 2275 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyId); 2276 2277 /* if we don't have a cached copy from before, we create one */ 2278 if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){ 2279 2280 PKIX_OBJECT_LOCK(cert); 2281 2282 if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){ 2283 2284 retItem = SECITEM_AllocItem(NULL, NULL, 0); 2285 if (retItem == NULL){ 2286 PKIX_ERROR(PKIX_OUTOFMEMORY); 2287 } 2288 2289 nssCert = cert->nssCert; 2290 2291 status = CERT_FindSubjectKeyIDExtension 2292 (nssCert, retItem); 2293 if (status != SECSuccess) { 2294 cert->subjKeyIdAbsent = PKIX_TRUE; 2295 *pSubjKeyId = NULL; 2296 goto cleanup; 2297 } 2298 2299 PKIX_CHECK(PKIX_PL_ByteArray_Create 2300 (retItem->data, 2301 retItem->len, 2302 &subjKeyId, 2303 plContext), 2304 PKIX_BYTEARRAYCREATEFAILED); 2305 2306 /* save a cached copy in case it is asked for again */ 2307 cert->subjKeyId = subjKeyId; 2308 } 2309 2310 PKIX_OBJECT_UNLOCK(cert); 2311 } 2312 2313 PKIX_INCREF(cert->subjKeyId); 2314 *pSubjKeyId = cert->subjKeyId; 2315 2316 cleanup: 2317 PKIX_OBJECT_UNLOCK(lockedObject); 2318 if (retItem){ 2319 SECITEM_FreeItem(retItem, PKIX_TRUE); 2320 } 2321 PKIX_RETURN(CERT); 2322 } 2323 2324 /* 2325 * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage (see comments in pkix_pl_pki.h) 2326 */ 2327 PKIX_Error * 2328 PKIX_PL_Cert_GetExtendedKeyUsage( 2329 PKIX_PL_Cert *cert, 2330 PKIX_List **pKeyUsage, /* list of PKIX_PL_OID */ 2331 void *plContext) 2332 { 2333 CERTOidSequence *extKeyUsage = NULL; 2334 CERTCertificate *nssCert = NULL; 2335 PKIX_PL_OID *pkixOID = NULL; 2336 PKIX_List *oidsList = NULL; 2337 SECItem **oids = NULL; 2338 SECItem encodedExtKeyUsage; 2339 SECStatus rv; 2340 2341 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetExtendedKeyUsage"); 2342 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pKeyUsage); 2343 2344 /* if we don't have a cached copy from before, we create one */ 2345 if ((cert->extKeyUsages == NULL) && (!cert->extKeyUsagesAbsent)){ 2346 2347 PKIX_OBJECT_LOCK(cert); 2348 2349 if ((cert->extKeyUsages == NULL) && 2350 (!cert->extKeyUsagesAbsent)){ 2351 2352 nssCert = cert->nssCert; 2353 2354 rv = CERT_FindCertExtension 2355 (nssCert, SEC_OID_X509_EXT_KEY_USAGE, 2356 &encodedExtKeyUsage); 2357 if (rv != SECSuccess){ 2358 cert->extKeyUsagesAbsent = PKIX_TRUE; 2359 *pKeyUsage = NULL; 2360 goto cleanup; 2361 } 2362 2363 extKeyUsage = 2364 CERT_DecodeOidSequence(&encodedExtKeyUsage); 2365 if (extKeyUsage == NULL){ 2366 PKIX_ERROR(PKIX_CERTDECODEOIDSEQUENCEFAILED); 2367 } 2368 2369 PORT_Free(encodedExtKeyUsage.data); 2370 2371 oids = extKeyUsage->oids; 2372 2373 if (!oids){ 2374 /* no extended key usage extensions found */ 2375 cert->extKeyUsagesAbsent = PKIX_TRUE; 2376 *pKeyUsage = NULL; 2377 goto cleanup; 2378 } 2379 2380 PKIX_CHECK(PKIX_List_Create(&oidsList, plContext), 2381 PKIX_LISTCREATEFAILED); 2382 2383 while (*oids){ 2384 SECItem *oid = *oids++; 2385 2386 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem 2387 (oid, &pkixOID, plContext), 2388 PKIX_OIDCREATEFAILED); 2389 2390 PKIX_CHECK(PKIX_List_AppendItem 2391 (oidsList, 2392 (PKIX_PL_Object *)pkixOID, 2393 plContext), 2394 PKIX_LISTAPPENDITEMFAILED); 2395 PKIX_DECREF(pkixOID); 2396 } 2397 2398 PKIX_CHECK(PKIX_List_SetImmutable 2399 (oidsList, plContext), 2400 PKIX_LISTSETIMMUTABLEFAILED); 2401 2402 /* save a cached copy in case it is asked for again */ 2403 cert->extKeyUsages = oidsList; 2404 oidsList = NULL; 2405 } 2406 2407 PKIX_OBJECT_UNLOCK(cert); 2408 } 2409 2410 PKIX_INCREF(cert->extKeyUsages); 2411 *pKeyUsage = cert->extKeyUsages; 2412 2413 cleanup: 2414 PKIX_OBJECT_UNLOCK(lockedObject); 2415 2416 PKIX_DECREF(pkixOID); 2417 PKIX_DECREF(oidsList); 2418 CERT_DestroyOidSequence(extKeyUsage); 2419 2420 PKIX_RETURN(CERT); 2421 } 2422 2423 /* 2424 * FUNCTION: PKIX_PL_Cert_GetBasicConstraints 2425 * (see comments in pkix_pl_pki.h) 2426 */ 2427 PKIX_Error * 2428 PKIX_PL_Cert_GetBasicConstraints( 2429 PKIX_PL_Cert *cert, 2430 PKIX_PL_CertBasicConstraints **pBasicConstraints, 2431 void *plContext) 2432 { 2433 CERTCertificate *nssCert = NULL; 2434 CERTBasicConstraints nssBasicConstraint; 2435 SECStatus rv; 2436 PKIX_PL_CertBasicConstraints *basic; 2437 PKIX_Int32 pathLen = 0; 2438 PKIX_Boolean isCA = PKIX_FALSE; 2439 enum { 2440 realBC, synthBC, absentBC 2441 } constraintSource = absentBC; 2442 2443 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetBasicConstraints"); 2444 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pBasicConstraints); 2445 2446 /* if we don't have a cached copy from before, we create one */ 2447 if ((cert->certBasicConstraints == NULL) && 2448 (!cert->basicConstraintsAbsent)) { 2449 2450 PKIX_OBJECT_LOCK(cert); 2451 2452 if ((cert->certBasicConstraints == NULL) && 2453 (!cert->basicConstraintsAbsent)) { 2454 2455 nssCert = cert->nssCert; 2456 2457 PKIX_CERT_DEBUG( 2458 "\t\tCalling Cert_FindBasicConstraintExten\n"); 2459 rv = CERT_FindBasicConstraintExten 2460 (nssCert, &nssBasicConstraint); 2461 if (rv == SECSuccess) { 2462 constraintSource = realBC; 2463 } 2464 2465 if (constraintSource == absentBC) { 2466 /* can we deduce it's a CA and create a 2467 synthetic constraint? 2468 */ 2469 CERTCertTrust trust; 2470 rv = CERT_GetCertTrust(nssCert, &trust); 2471 if (rv == SECSuccess) { 2472 int anyWantedFlag = CERTDB_TRUSTED_CA | CERTDB_VALID_CA; 2473 if ((trust.sslFlags & anyWantedFlag) 2474 || (trust.emailFlags & anyWantedFlag) 2475 || (trust.objectSigningFlags & anyWantedFlag)) { 2476 2477 constraintSource = synthBC; 2478 } 2479 } 2480 } 2481 2482 if (constraintSource == absentBC) { 2483 cert->basicConstraintsAbsent = PKIX_TRUE; 2484 *pBasicConstraints = NULL; 2485 goto cleanup; 2486 } 2487 } 2488 2489 if (constraintSource == synthBC) { 2490 isCA = PKIX_TRUE; 2491 pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT; 2492 } else { 2493 isCA = (nssBasicConstraint.isCA)?PKIX_TRUE:PKIX_FALSE; 2494 2495 /* The pathLen has meaning only for CAs */ 2496 if (isCA) { 2497 if (CERT_UNLIMITED_PATH_CONSTRAINT == 2498 nssBasicConstraint.pathLenConstraint) { 2499 pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT; 2500 } else { 2501 pathLen = nssBasicConstraint.pathLenConstraint; 2502 } 2503 } 2504 } 2505 2506 PKIX_CHECK(pkix_pl_CertBasicConstraints_Create 2507 (isCA, pathLen, &basic, plContext), 2508 PKIX_CERTBASICCONSTRAINTSCREATEFAILED); 2509 2510 /* save a cached copy in case it is asked for again */ 2511 cert->certBasicConstraints = basic; 2512 } 2513 2514 PKIX_INCREF(cert->certBasicConstraints); 2515 *pBasicConstraints = cert->certBasicConstraints; 2516 2517 cleanup: 2518 PKIX_OBJECT_UNLOCK(lockedObject); 2519 PKIX_RETURN(CERT); 2520 } 2521 2522 /* 2523 * FUNCTION: PKIX_PL_Cert_GetPolicyInformation 2524 * (see comments in pkix_pl_pki.h) 2525 */ 2526 PKIX_Error * 2527 PKIX_PL_Cert_GetPolicyInformation( 2528 PKIX_PL_Cert *cert, 2529 PKIX_List **pPolicyInfo, 2530 void *plContext) 2531 { 2532 PKIX_List *policyList = NULL; 2533 2534 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyInformation"); 2535 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyInfo); 2536 2537 /* if we don't have a cached copy from before, we create one */ 2538 if ((cert->certPolicyInfos == NULL) && 2539 (!cert->policyInfoAbsent)) { 2540 2541 PKIX_OBJECT_LOCK(cert); 2542 2543 if ((cert->certPolicyInfos == NULL) && 2544 (!cert->policyInfoAbsent)) { 2545 2546 PKIX_CHECK(pkix_pl_Cert_DecodePolicyInfo 2547 (cert->nssCert, &policyList, plContext), 2548 PKIX_CERTDECODEPOLICYINFOFAILED); 2549 2550 if (!policyList) { 2551 cert->policyInfoAbsent = PKIX_TRUE; 2552 *pPolicyInfo = NULL; 2553 goto cleanup; 2554 } 2555 } 2556 2557 PKIX_OBJECT_UNLOCK(cert); 2558 2559 /* save a cached copy in case it is asked for again */ 2560 cert->certPolicyInfos = policyList; 2561 policyList = NULL; 2562 } 2563 2564 PKIX_INCREF(cert->certPolicyInfos); 2565 *pPolicyInfo = cert->certPolicyInfos; 2566 2567 cleanup: 2568 PKIX_OBJECT_UNLOCK(lockedObject); 2569 2570 PKIX_DECREF(policyList); 2571 PKIX_RETURN(CERT); 2572 } 2573 2574 /* 2575 * FUNCTION: PKIX_PL_Cert_GetPolicyMappings (see comments in pkix_pl_pki.h) 2576 */ 2577 PKIX_Error * 2578 PKIX_PL_Cert_GetPolicyMappings( 2579 PKIX_PL_Cert *cert, 2580 PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */ 2581 void *plContext) 2582 { 2583 PKIX_List *policyMappings = NULL; /* list of PKIX_PL_CertPolicyMap */ 2584 2585 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappings"); 2586 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyMappings); 2587 2588 /* if we don't have a cached copy from before, we create one */ 2589 if (!(cert->certPolicyMappings) && !(cert->policyMappingsAbsent)) { 2590 2591 PKIX_OBJECT_LOCK(cert); 2592 2593 if (!(cert->certPolicyMappings) && 2594 !(cert->policyMappingsAbsent)) { 2595 2596 PKIX_CHECK(pkix_pl_Cert_DecodePolicyMapping 2597 (cert->nssCert, &policyMappings, plContext), 2598 PKIX_CERTDECODEPOLICYMAPPINGFAILED); 2599 2600 if (!policyMappings) { 2601 cert->policyMappingsAbsent = PKIX_TRUE; 2602 *pPolicyMappings = NULL; 2603 goto cleanup; 2604 } 2605 } 2606 2607 PKIX_OBJECT_UNLOCK(cert); 2608 2609 /* save a cached copy in case it is asked for again */ 2610 cert->certPolicyMappings = policyMappings; 2611 policyMappings = NULL; 2612 } 2613 2614 PKIX_INCREF(cert->certPolicyMappings); 2615 *pPolicyMappings = cert->certPolicyMappings; 2616 2617 cleanup: 2618 PKIX_OBJECT_UNLOCK(lockedObject); 2619 2620 PKIX_DECREF(policyMappings); 2621 PKIX_RETURN(CERT); 2622 } 2623 2624 /* 2625 * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy 2626 * (see comments in pkix_pl_pki.h) 2627 */ 2628 PKIX_Error * 2629 PKIX_PL_Cert_GetRequireExplicitPolicy( 2630 PKIX_PL_Cert *cert, 2631 PKIX_Int32 *pSkipCerts, 2632 void *plContext) 2633 { 2634 PKIX_Int32 explicitPolicySkipCerts = 0; 2635 PKIX_Int32 inhibitMappingSkipCerts = 0; 2636 2637 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetRequireExplicitPolicy"); 2638 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); 2639 2640 if (!(cert->policyConstraintsProcessed)) { 2641 PKIX_OBJECT_LOCK(cert); 2642 2643 if (!(cert->policyConstraintsProcessed)) { 2644 2645 /* 2646 * If we can't process it now, we probably will be 2647 * unable to process it later. Set the default value. 2648 */ 2649 cert->policyConstraintsProcessed = PKIX_TRUE; 2650 cert->policyConstraintsExplicitPolicySkipCerts = -1; 2651 cert->policyConstraintsInhibitMappingSkipCerts = -1; 2652 2653 PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints 2654 (cert->nssCert, 2655 &explicitPolicySkipCerts, 2656 &inhibitMappingSkipCerts, 2657 plContext), 2658 PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED); 2659 2660 cert->policyConstraintsExplicitPolicySkipCerts = 2661 explicitPolicySkipCerts; 2662 cert->policyConstraintsInhibitMappingSkipCerts = 2663 inhibitMappingSkipCerts; 2664 } 2665 2666 PKIX_OBJECT_UNLOCK(cert); 2667 } 2668 2669 *pSkipCerts = cert->policyConstraintsExplicitPolicySkipCerts; 2670 2671 cleanup: 2672 PKIX_OBJECT_UNLOCK(lockedObject); 2673 PKIX_RETURN(CERT); 2674 } 2675 2676 /* 2677 * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited 2678 * (see comments in pkix_pl_pki.h) 2679 */ 2680 PKIX_Error * 2681 PKIX_PL_Cert_GetPolicyMappingInhibited( 2682 PKIX_PL_Cert *cert, 2683 PKIX_Int32 *pSkipCerts, 2684 void *plContext) 2685 { 2686 PKIX_Int32 explicitPolicySkipCerts = 0; 2687 PKIX_Int32 inhibitMappingSkipCerts = 0; 2688 2689 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappingInhibited"); 2690 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); 2691 2692 if (!(cert->policyConstraintsProcessed)) { 2693 PKIX_OBJECT_LOCK(cert); 2694 2695 if (!(cert->policyConstraintsProcessed)) { 2696 2697 /* 2698 * If we can't process it now, we probably will be 2699 * unable to process it later. Set the default value. 2700 */ 2701 cert->policyConstraintsProcessed = PKIX_TRUE; 2702 cert->policyConstraintsExplicitPolicySkipCerts = -1; 2703 cert->policyConstraintsInhibitMappingSkipCerts = -1; 2704 2705 PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints 2706 (cert->nssCert, 2707 &explicitPolicySkipCerts, 2708 &inhibitMappingSkipCerts, 2709 plContext), 2710 PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED); 2711 2712 cert->policyConstraintsExplicitPolicySkipCerts = 2713 explicitPolicySkipCerts; 2714 cert->policyConstraintsInhibitMappingSkipCerts = 2715 inhibitMappingSkipCerts; 2716 } 2717 2718 PKIX_OBJECT_UNLOCK(cert); 2719 } 2720 2721 *pSkipCerts = cert->policyConstraintsInhibitMappingSkipCerts; 2722 2723 cleanup: 2724 PKIX_OBJECT_UNLOCK(lockedObject); 2725 PKIX_RETURN(CERT); 2726 } 2727 2728 /* 2729 * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy (see comments in pkix_pl_pki.h) 2730 */ 2731 PKIX_Error * 2732 PKIX_PL_Cert_GetInhibitAnyPolicy( 2733 PKIX_PL_Cert *cert, 2734 PKIX_Int32 *pSkipCerts, 2735 void *plContext) 2736 { 2737 PKIX_Int32 skipCerts = 0; 2738 2739 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetInhibitAnyPolicy"); 2740 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); 2741 2742 if (!(cert->inhibitAnyPolicyProcessed)) { 2743 2744 PKIX_OBJECT_LOCK(cert); 2745 2746 if (!(cert->inhibitAnyPolicyProcessed)) { 2747 2748 /* 2749 * If we can't process it now, we probably will be 2750 * unable to process it later. Set the default value. 2751 */ 2752 cert->inhibitAnyPolicyProcessed = PKIX_TRUE; 2753 cert->inhibitAnySkipCerts = -1; 2754 2755 PKIX_CHECK(pkix_pl_Cert_DecodeInhibitAnyPolicy 2756 (cert->nssCert, &skipCerts, plContext), 2757 PKIX_CERTDECODEINHIBITANYPOLICYFAILED); 2758 2759 cert->inhibitAnySkipCerts = skipCerts; 2760 } 2761 2762 PKIX_OBJECT_UNLOCK(cert); 2763 } 2764 2765 cleanup: 2766 PKIX_OBJECT_UNLOCK(lockedObject); 2767 *pSkipCerts = cert->inhibitAnySkipCerts; 2768 PKIX_RETURN(CERT); 2769 } 2770 2771 /* 2772 * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical 2773 * (see comments in pkix_pl_pki.h) 2774 */ 2775 PKIX_Error * 2776 PKIX_PL_Cert_AreCertPoliciesCritical( 2777 PKIX_PL_Cert *cert, 2778 PKIX_Boolean *pCritical, 2779 void *plContext) 2780 { 2781 PKIX_Boolean criticality = PKIX_FALSE; 2782 2783 PKIX_ENTER(CERT, "PKIX_PL_Cert_AreCertPoliciesCritical"); 2784 PKIX_NULLCHECK_TWO(cert, pCritical); 2785 2786 PKIX_CHECK(pkix_pl_Cert_IsExtensionCritical( 2787 cert, 2788 SEC_OID_X509_CERTIFICATE_POLICIES, 2789 &criticality, 2790 plContext), 2791 PKIX_CERTISEXTENSIONCRITICALFAILED); 2792 2793 *pCritical = criticality; 2794 2795 cleanup: 2796 PKIX_RETURN(CERT); 2797 } 2798 2799 /* 2800 * FUNCTION: PKIX_PL_Cert_VerifySignature (see comments in pkix_pl_pki.h) 2801 */ 2802 PKIX_Error * 2803 PKIX_PL_Cert_VerifySignature( 2804 PKIX_PL_Cert *cert, 2805 PKIX_PL_PublicKey *pubKey, 2806 void *plContext) 2807 { 2808 CERTCertificate *nssCert = NULL; 2809 SECKEYPublicKey *nssPubKey = NULL; 2810 CERTSignedData *tbsCert = NULL; 2811 PKIX_PL_Cert *cachedCert = NULL; 2812 PKIX_Error *verifySig = NULL; 2813 PKIX_Error *cachedSig = NULL; 2814 PKIX_Error *checkSig = NULL; 2815 SECStatus status; 2816 PKIX_Boolean certEqual = PKIX_FALSE; 2817 PKIX_Boolean certInHash = PKIX_FALSE; 2818 PKIX_Boolean checkCertSig = PKIX_TRUE; 2819 void* wincx = NULL; 2820 2821 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifySignature"); 2822 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pubKey); 2823 2824 /* if the cert check flag is off, skip the check */ 2825 checkSig = pkix_pl_NssContext_GetCertSignatureCheck( 2826 (PKIX_PL_NssContext *)plContext, &checkCertSig); 2827 if ((checkCertSig == PKIX_FALSE) && (checkSig == NULL)) { 2828 goto cleanup; 2829 } 2830 2831 verifySig = PKIX_PL_HashTable_Lookup 2832 (cachedCertSigTable, 2833 (PKIX_PL_Object *) pubKey, 2834 (PKIX_PL_Object **) &cachedCert, 2835 plContext); 2836 2837 if (cachedCert != NULL && verifySig == NULL) { 2838 /* Cached Signature Table lookup succeed */ 2839 PKIX_EQUALS(cert, cachedCert, &certEqual, plContext, 2840 PKIX_OBJECTEQUALSFAILED); 2841 if (certEqual == PKIX_TRUE) { 2842 goto cleanup; 2843 } 2844 /* Different PubKey may hash to same value, skip add */ 2845 certInHash = PKIX_TRUE; 2846 } 2847 2848 nssCert = cert->nssCert; 2849 tbsCert = &nssCert->signatureWrap; 2850 2851 PKIX_CERT_DEBUG("\t\tCalling SECKEY_ExtractPublicKey).\n"); 2852 nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI); 2853 if (!nssPubKey){ 2854 PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED); 2855 } 2856 2857 PKIX_CERT_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey).\n"); 2858 2859 PKIX_CHECK(pkix_pl_NssContext_GetWincx 2860 ((PKIX_PL_NssContext *)plContext, &wincx), 2861 PKIX_NSSCONTEXTGETWINCXFAILED); 2862 2863 status = CERT_VerifySignedDataWithPublicKey(tbsCert, nssPubKey, wincx); 2864 2865 if (status != SECSuccess) { 2866 if (PORT_GetError() != SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) { 2867 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 2868 } 2869 PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY); 2870 } 2871 2872 if (certInHash == PKIX_FALSE) { 2873 cachedSig = PKIX_PL_HashTable_Add 2874 (cachedCertSigTable, 2875 (PKIX_PL_Object *) pubKey, 2876 (PKIX_PL_Object *) cert, 2877 plContext); 2878 2879 if (cachedSig != NULL) { 2880 PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n"); 2881 } 2882 } 2883 2884 cleanup: 2885 if (nssPubKey){ 2886 PKIX_CERT_DEBUG("\t\tCalling SECKEY_DestroyPublicKey).\n"); 2887 SECKEY_DestroyPublicKey(nssPubKey); 2888 } 2889 2890 PKIX_DECREF(cachedCert); 2891 PKIX_DECREF(checkSig); 2892 PKIX_DECREF(verifySig); 2893 PKIX_DECREF(cachedSig); 2894 2895 PKIX_RETURN(CERT); 2896 } 2897 2898 /* 2899 * FUNCTION: PKIX_PL_Cert_CheckValidity (see comments in pkix_pl_pki.h) 2900 */ 2901 PKIX_Error * 2902 PKIX_PL_Cert_CheckValidity( 2903 PKIX_PL_Cert *cert, 2904 PKIX_PL_Date *date, 2905 void *plContext) 2906 { 2907 SECCertTimeValidity val; 2908 PRTime timeToCheck; 2909 PKIX_Boolean allowOverride; 2910 SECCertificateUsage requiredUsages; 2911 2912 PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckValidity"); 2913 PKIX_NULLCHECK_ONE(cert); 2914 2915 /* if the caller supplies a date, we use it; else, use current time */ 2916 if (date != NULL){ 2917 PKIX_CHECK(pkix_pl_Date_GetPRTime 2918 (date, &timeToCheck, plContext), 2919 PKIX_DATEGETPRTIMEFAILED); 2920 } else { 2921 timeToCheck = PR_Now(); 2922 } 2923 2924 requiredUsages = ((PKIX_PL_NssContext*)plContext)->certificateUsage; 2925 allowOverride = 2926 (PRBool)((requiredUsages & certificateUsageSSLServer) || 2927 (requiredUsages & certificateUsageSSLServerWithStepUp) || 2928 (requiredUsages & certificateUsageIPsec)); 2929 val = CERT_CheckCertValidTimes(cert->nssCert, timeToCheck, allowOverride); 2930 if (val != secCertTimeValid){ 2931 PKIX_ERROR(PKIX_CERTCHECKCERTVALIDTIMESFAILED); 2932 } 2933 2934 cleanup: 2935 PKIX_RETURN(CERT); 2936 } 2937 2938 /* 2939 * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter (see comments in pkix_pl_pki.h) 2940 */ 2941 PKIX_Error * 2942 PKIX_PL_Cert_GetValidityNotAfter( 2943 PKIX_PL_Cert *cert, 2944 PKIX_PL_Date **pDate, 2945 void *plContext) 2946 { 2947 PRTime prtime; 2948 SECStatus rv = SECFailure; 2949 2950 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetValidityNotAfter"); 2951 PKIX_NULLCHECK_TWO(cert, pDate); 2952 2953 PKIX_DATE_DEBUG("\t\tCalling DER_DecodeTimeChoice).\n"); 2954 rv = DER_DecodeTimeChoice(&prtime, &(cert->nssCert->validity.notAfter)); 2955 if (rv != SECSuccess){ 2956 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED); 2957 } 2958 2959 PKIX_CHECK(pkix_pl_Date_CreateFromPRTime 2960 (prtime, pDate, plContext), 2961 PKIX_DATECREATEFROMPRTIMEFAILED); 2962 2963 cleanup: 2964 PKIX_RETURN(CERT); 2965 } 2966 2967 /* 2968 * FUNCTION: PKIX_PL_Cert_VerifyCertAndKeyType (see comments in pkix_pl_pki.h) 2969 */ 2970 PKIX_Error * 2971 PKIX_PL_Cert_VerifyCertAndKeyType( 2972 PKIX_PL_Cert *cert, 2973 PKIX_Boolean isChainCert, 2974 void *plContext) 2975 { 2976 PKIX_PL_CertBasicConstraints *basicConstraints = NULL; 2977 SECCertificateUsage certificateUsage; 2978 SECCertUsage certUsage = 0; 2979 unsigned int requiredKeyUsage; 2980 unsigned int requiredCertType; 2981 unsigned int certType; 2982 SECStatus rv = SECSuccess; 2983 2984 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyCertType"); 2985 PKIX_NULLCHECK_TWO(cert, plContext); 2986 2987 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; 2988 2989 /* ensure we obtained a single usage bit only */ 2990 PORT_Assert(!(certificateUsage & (certificateUsage - 1))); 2991 2992 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ 2993 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } 2994 2995 /* check key usage and netscape cert type */ 2996 cert_GetCertType(cert->nssCert); 2997 certType = cert->nssCert->nsCertType; 2998 if (isChainCert || 2999 (certUsage != certUsageVerifyCA && certUsage != certUsageAnyCA)) { 3000 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, isChainCert, 3001 &requiredKeyUsage, 3002 &requiredCertType); 3003 if (rv == SECFailure) { 3004 PKIX_ERROR(PKIX_UNSUPPORTEDCERTUSAGE); 3005 } 3006 } else { 3007 /* use this key usage and cert type for certUsageAnyCA and 3008 * certUsageVerifyCA. */ 3009 requiredKeyUsage = KU_KEY_CERT_SIGN; 3010 requiredCertType = NS_CERT_TYPE_CA; 3011 } 3012 if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) { 3013 PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); 3014 } 3015 if (!(certType & requiredCertType)) { 3016 PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED); 3017 } 3018 cleanup: 3019 PKIX_DECREF(basicConstraints); 3020 PKIX_RETURN(CERT); 3021 } 3022 3023 /* 3024 * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage (see comments in pkix_pl_pki.h) 3025 */ 3026 PKIX_Error * 3027 PKIX_PL_Cert_VerifyKeyUsage( 3028 PKIX_PL_Cert *cert, 3029 PKIX_UInt32 keyUsage, 3030 void *plContext) 3031 { 3032 CERTCertificate *nssCert = NULL; 3033 PKIX_UInt32 nssKeyUsage = 0; 3034 SECStatus status; 3035 3036 PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyKeyUsage"); 3037 PKIX_NULLCHECK_TWO(cert, cert->nssCert); 3038 3039 nssCert = cert->nssCert; 3040 3041 /* if cert doesn't have keyUsage extension, all keyUsages are valid */ 3042 if (!nssCert->keyUsagePresent){ 3043 goto cleanup; 3044 } 3045 3046 if (keyUsage & PKIX_DIGITAL_SIGNATURE){ 3047 nssKeyUsage = nssKeyUsage | KU_DIGITAL_SIGNATURE; 3048 } 3049 3050 if (keyUsage & PKIX_NON_REPUDIATION){ 3051 nssKeyUsage = nssKeyUsage | KU_NON_REPUDIATION; 3052 } 3053 3054 if (keyUsage & PKIX_KEY_ENCIPHERMENT){ 3055 nssKeyUsage = nssKeyUsage | KU_KEY_ENCIPHERMENT; 3056 } 3057 3058 if (keyUsage & PKIX_DATA_ENCIPHERMENT){ 3059 nssKeyUsage = nssKeyUsage | KU_DATA_ENCIPHERMENT; 3060 } 3061 3062 if (keyUsage & PKIX_KEY_AGREEMENT){ 3063 nssKeyUsage = nssKeyUsage | KU_KEY_AGREEMENT; 3064 } 3065 3066 if (keyUsage & PKIX_KEY_CERT_SIGN){ 3067 nssKeyUsage = nssKeyUsage | KU_KEY_CERT_SIGN; 3068 } 3069 3070 if (keyUsage & PKIX_CRL_SIGN){ 3071 nssKeyUsage = nssKeyUsage | KU_CRL_SIGN; 3072 } 3073 3074 if (keyUsage & PKIX_ENCIPHER_ONLY){ 3075 nssKeyUsage = nssKeyUsage | 0x01; 3076 } 3077 3078 if (keyUsage & PKIX_DECIPHER_ONLY){ 3079 /* XXX we should support this once it is fixed in NSS */ 3080 PKIX_ERROR(PKIX_DECIPHERONLYKEYUSAGENOTSUPPORTED); 3081 } 3082 3083 status = CERT_CheckKeyUsage(nssCert, nssKeyUsage); 3084 if (status != SECSuccess) { 3085 PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); 3086 } 3087 3088 cleanup: 3089 PKIX_RETURN(CERT); 3090 } 3091 3092 /* 3093 * FUNCTION: PKIX_PL_Cert_GetNameConstraints 3094 * (see comments in pkix_pl_pki.h) 3095 */ 3096 PKIX_Error * 3097 PKIX_PL_Cert_GetNameConstraints( 3098 PKIX_PL_Cert *cert, 3099 PKIX_PL_CertNameConstraints **pNameConstraints, 3100 void *plContext) 3101 { 3102 PKIX_PL_CertNameConstraints *nameConstraints = NULL; 3103 3104 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNameConstraints"); 3105 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pNameConstraints); 3106 3107 /* if we don't have a cached copy from before, we create one */ 3108 if (cert->nameConstraints == NULL && !cert->nameConstraintsAbsent) { 3109 3110 PKIX_OBJECT_LOCK(cert); 3111 3112 if (cert->nameConstraints == NULL && 3113 !cert->nameConstraintsAbsent) { 3114 3115 PKIX_CHECK(pkix_pl_CertNameConstraints_Create 3116 (cert->nssCert, &nameConstraints, plContext), 3117 PKIX_CERTNAMECONSTRAINTSCREATEFAILED); 3118 3119 if (nameConstraints == NULL) { 3120 cert->nameConstraintsAbsent = PKIX_TRUE; 3121 } 3122 3123 cert->nameConstraints = nameConstraints; 3124 } 3125 3126 PKIX_OBJECT_UNLOCK(cert); 3127 3128 } 3129 3130 PKIX_INCREF(cert->nameConstraints); 3131 3132 *pNameConstraints = cert->nameConstraints; 3133 3134 cleanup: 3135 PKIX_OBJECT_UNLOCK(lockedObject); 3136 PKIX_RETURN(CERT); 3137 } 3138 3139 /* 3140 * FUNCTION: PKIX_PL_Cert_CheckNameConstraints 3141 * (see comments in pkix_pl_pki.h) 3142 */ 3143 PKIX_Error * 3144 PKIX_PL_Cert_CheckNameConstraints( 3145 PKIX_PL_Cert *cert, 3146 PKIX_PL_CertNameConstraints *nameConstraints, 3147 PKIX_Boolean treatCommonNameAsDNSName, 3148 void *plContext) 3149 { 3150 PKIX_Boolean checkPass = PKIX_TRUE; 3151 CERTGeneralName *nssSubjectNames = NULL; 3152 PLArenaPool *arena = NULL; 3153 3154 PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckNameConstraints"); 3155 PKIX_NULLCHECK_ONE(cert); 3156 3157 if (nameConstraints != NULL) { 3158 3159 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 3160 if (arena == NULL) { 3161 PKIX_ERROR(PKIX_OUTOFMEMORY); 3162 } 3163 /* only check common Name if the usage requires it */ 3164 if (treatCommonNameAsDNSName) { 3165 SECCertificateUsage certificateUsage; 3166 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; 3167 if ((certificateUsage != certificateUsageSSLServer) && 3168 (certificateUsage != certificateUsageIPsec)) { 3169 treatCommonNameAsDNSName = PKIX_FALSE; 3170 } 3171 } 3172 3173 /* This NSS call returns Subject Alt Names. If 3174 * treatCommonNameAsDNSName is true, it also returns the 3175 * Subject Common Name 3176 */ 3177 PKIX_CERT_DEBUG 3178 ("\t\tCalling CERT_GetConstrainedCertificateNames\n"); 3179 nssSubjectNames = CERT_GetConstrainedCertificateNames 3180 (cert->nssCert, arena, treatCommonNameAsDNSName); 3181 3182 PKIX_CHECK(pkix_pl_CertNameConstraints_CheckNameSpaceNssNames 3183 (nssSubjectNames, 3184 nameConstraints, 3185 &checkPass, 3186 plContext), 3187 PKIX_CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED); 3188 3189 if (checkPass != PKIX_TRUE) { 3190 PKIX_ERROR(PKIX_CERTFAILEDNAMECONSTRAINTSCHECKING); 3191 } 3192 } 3193 3194 cleanup: 3195 if (arena){ 3196 PORT_FreeArena(arena, PR_FALSE); 3197 } 3198 3199 PKIX_RETURN(CERT); 3200 } 3201 3202 /* 3203 * FUNCTION: PKIX_PL_Cert_MergeNameConstraints 3204 * (see comments in pkix_pl_pki.h) 3205 */ 3206 PKIX_Error * 3207 PKIX_PL_Cert_MergeNameConstraints( 3208 PKIX_PL_CertNameConstraints *firstNC, 3209 PKIX_PL_CertNameConstraints *secondNC, 3210 PKIX_PL_CertNameConstraints **pResultNC, 3211 void *plContext) 3212 { 3213 PKIX_PL_CertNameConstraints *mergedNC = NULL; 3214 3215 PKIX_ENTER(CERT, "PKIX_PL_Cert_MergeNameConstraints"); 3216 PKIX_NULLCHECK_TWO(firstNC, pResultNC); 3217 3218 if (secondNC == NULL) { 3219 3220 PKIX_INCREF(firstNC); 3221 *pResultNC = firstNC; 3222 3223 goto cleanup; 3224 } 3225 3226 PKIX_CHECK(pkix_pl_CertNameConstraints_Merge 3227 (firstNC, secondNC, &mergedNC, plContext), 3228 PKIX_CERTNAMECONSTRAINTSMERGEFAILED); 3229 3230 *pResultNC = mergedNC; 3231 3232 cleanup: 3233 PKIX_RETURN(CERT); 3234 } 3235 3236 /* 3237 * Find out the state of the NSS trust bits for the requested usage. 3238 * Returns SECFailure if the cert is explicitly distrusted. 3239 * Returns SECSuccess if the cert can be used to form a chain (normal case), 3240 * or it is explicitly trusted. The trusted bool is set to true if it is 3241 * explicitly trusted. 3242 */ 3243 static SECStatus 3244 pkix_pl_Cert_GetTrusted(void *plContext, 3245 PKIX_PL_Cert *cert, 3246 PKIX_Boolean *trusted, 3247 PKIX_Boolean isCA) 3248 { 3249 SECStatus rv; 3250 CERTCertificate *nssCert = NULL; 3251 SECCertUsage certUsage = 0; 3252 SECCertificateUsage certificateUsage; 3253 SECTrustType trustType; 3254 unsigned int trustFlags; 3255 unsigned int requiredFlags; 3256 CERTCertTrust trust; 3257 3258 *trusted = PKIX_FALSE; 3259 3260 /* no key usage information */ 3261 if (plContext == NULL) { 3262 return SECSuccess; 3263 } 3264 3265 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; 3266 3267 /* ensure we obtained a single usage bit only */ 3268 PORT_Assert(!(certificateUsage & (certificateUsage - 1))); 3269 3270 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ 3271 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } 3272 3273 nssCert = cert->nssCert; 3274 3275 if (!isCA) { 3276 PRBool prTrusted; 3277 unsigned int failedFlags; 3278 rv = cert_CheckLeafTrust(nssCert, certUsage, 3279 &failedFlags, &prTrusted); 3280 *trusted = (PKIX_Boolean) prTrusted; 3281 return rv; 3282 } 3283 rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, 3284 &trustType); 3285 if (rv != SECSuccess) { 3286 return SECSuccess; 3287 } 3288 3289 rv = CERT_GetCertTrust(nssCert, &trust); 3290 if (rv != SECSuccess) { 3291 return SECSuccess; 3292 } 3293 trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType); 3294 /* normally trustTypeNone usages accept any of the given trust bits 3295 * being on as acceptable. If any are distrusted (and none are trusted), 3296 * then we will also distrust the cert */ 3297 if ((trustFlags == 0) && (trustType == trustTypeNone)) { 3298 trustFlags = trust.sslFlags | trust.emailFlags | 3299 trust.objectSigningFlags; 3300 } 3301 if ((trustFlags & requiredFlags) == requiredFlags) { 3302 *trusted = PKIX_TRUE; 3303 return SECSuccess; 3304 } 3305 if ((trustFlags & CERTDB_TERMINAL_RECORD) && 3306 ((trustFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED)) == 0)) { 3307 return SECFailure; 3308 } 3309 return SECSuccess; 3310 } 3311 3312 /* 3313 * FUNCTION: PKIX_PL_Cert_IsCertTrusted 3314 * (see comments in pkix_pl_pki.h) 3315 */ 3316 PKIX_Error * 3317 PKIX_PL_Cert_IsCertTrusted( 3318 PKIX_PL_Cert *cert, 3319 PKIX_PL_TrustAnchorMode trustAnchorMode, 3320 PKIX_Boolean *pTrusted, 3321 void *plContext) 3322 { 3323 PKIX_CertStore_CheckTrustCallback trustCallback = NULL; 3324 PKIX_Boolean trusted = PKIX_FALSE; 3325 SECStatus rv = SECFailure; 3326 3327 PKIX_ENTER(CERT, "PKIX_PL_Cert_IsCertTrusted"); 3328 PKIX_NULLCHECK_TWO(cert, pTrusted); 3329 3330 /* Call GetTrusted first to see if we are going to distrust the 3331 * certificate */ 3332 rv = pkix_pl_Cert_GetTrusted(plContext, cert, &trusted, PKIX_TRUE); 3333 if (rv != SECSuccess) { 3334 /* Failure means the cert is explicitly distrusted, 3335 * let the next level know not to use it. */ 3336 *pTrusted = PKIX_FALSE; 3337 PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED); 3338 } 3339 3340 if (trustAnchorMode == PKIX_PL_TrustAnchorMode_Exclusive || 3341 (trustAnchorMode == PKIX_PL_TrustAnchorMode_Additive && 3342 cert->isUserTrustAnchor)) { 3343 /* Use the trust anchor's |trusted| value */ 3344 *pTrusted = cert->isUserTrustAnchor; 3345 goto cleanup; 3346 } 3347 3348 /* no key usage information or store is not trusted */ 3349 if (plContext == NULL || cert->store == NULL) { 3350 *pTrusted = PKIX_FALSE; 3351 goto cleanup; 3352 } 3353 3354 PKIX_CHECK(PKIX_CertStore_GetTrustCallback 3355 (cert->store, &trustCallback, plContext), 3356 PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); 3357 3358 PKIX_CHECK_ONLY_FATAL(trustCallback 3359 (cert->store, cert, &trusted, plContext), 3360 PKIX_CHECKTRUSTCALLBACKFAILED); 3361 3362 /* allow trust store to override if we can trust the trust 3363 * bits */ 3364 if (PKIX_ERROR_RECEIVED || (trusted == PKIX_FALSE)) { 3365 *pTrusted = PKIX_FALSE; 3366 goto cleanup; 3367 } 3368 3369 *pTrusted = trusted; 3370 3371 cleanup: 3372 PKIX_RETURN(CERT); 3373 } 3374 3375 /* 3376 * FUNCTION: PKIX_PL_Cert_IsLeafCertTrusted 3377 * (see comments in pkix_pl_pki.h) 3378 */ 3379 PKIX_Error * 3380 PKIX_PL_Cert_IsLeafCertTrusted( 3381 PKIX_PL_Cert *cert, 3382 PKIX_Boolean *pTrusted, 3383 void *plContext) 3384 { 3385 SECStatus rv; 3386 3387 PKIX_ENTER(CERT, "PKIX_PL_Cert_IsLeafCertTrusted"); 3388 PKIX_NULLCHECK_TWO(cert, pTrusted); 3389 3390 *pTrusted = PKIX_FALSE; 3391 3392 rv = pkix_pl_Cert_GetTrusted(plContext, cert, pTrusted, PKIX_FALSE); 3393 if (rv != SECSuccess) { 3394 /* Failure means the cert is explicitly distrusted, 3395 * let the next level know not to use it. */ 3396 *pTrusted = PKIX_FALSE; 3397 PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED); 3398 } 3399 3400 cleanup: 3401 PKIX_RETURN(CERT); 3402 } 3403 3404 /* FUNCTION: PKIX_PL_Cert_SetAsTrustAnchor */ 3405 PKIX_Error* 3406 PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert *cert, 3407 void *plContext) 3408 { 3409 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetAsTrustAnchor"); 3410 PKIX_NULLCHECK_ONE(cert); 3411 3412 cert->isUserTrustAnchor = PKIX_TRUE; 3413 3414 PKIX_RETURN(CERT); 3415 } 3416 3417 /* 3418 * FUNCTION: PKIX_PL_Cert_GetCacheFlag (see comments in pkix_pl_pki.h) 3419 */ 3420 PKIX_Error * 3421 PKIX_PL_Cert_GetCacheFlag( 3422 PKIX_PL_Cert *cert, 3423 PKIX_Boolean *pCacheFlag, 3424 void *plContext) 3425 { 3426 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCacheFlag"); 3427 PKIX_NULLCHECK_TWO(cert, pCacheFlag); 3428 3429 *pCacheFlag = cert->cacheFlag; 3430 3431 PKIX_RETURN(CERT); 3432 } 3433 3434 /* 3435 * FUNCTION: PKIX_PL_Cert_SetCacheFlag (see comments in pkix_pl_pki.h) 3436 */ 3437 PKIX_Error * 3438 PKIX_PL_Cert_SetCacheFlag( 3439 PKIX_PL_Cert *cert, 3440 PKIX_Boolean cacheFlag, 3441 void *plContext) 3442 { 3443 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetCacheFlag"); 3444 PKIX_NULLCHECK_ONE(cert); 3445 3446 cert->cacheFlag = cacheFlag; 3447 3448 PKIX_RETURN(CERT); 3449 } 3450 3451 /* 3452 * FUNCTION: PKIX_PL_Cert_GetTrustCertStore (see comments in pkix_pl_pki.h) 3453 */ 3454 PKIX_Error * 3455 PKIX_PL_Cert_GetTrustCertStore( 3456 PKIX_PL_Cert *cert, 3457 PKIX_CertStore **pTrustCertStore, 3458 void *plContext) 3459 { 3460 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetTrustCertStore"); 3461 PKIX_NULLCHECK_TWO(cert, pTrustCertStore); 3462 3463 PKIX_INCREF(cert->store); 3464 *pTrustCertStore = cert->store; 3465 3466 cleanup: 3467 PKIX_RETURN(CERT); 3468 } 3469 3470 /* 3471 * FUNCTION: PKIX_PL_Cert_SetTrustCertStore (see comments in pkix_pl_pki.h) 3472 */ 3473 PKIX_Error * 3474 PKIX_PL_Cert_SetTrustCertStore( 3475 PKIX_PL_Cert *cert, 3476 PKIX_CertStore *trustCertStore, 3477 void *plContext) 3478 { 3479 PKIX_ENTER(CERT, "PKIX_PL_Cert_SetTrustCertStore"); 3480 PKIX_NULLCHECK_TWO(cert, trustCertStore); 3481 3482 PKIX_INCREF(trustCertStore); 3483 cert->store = trustCertStore; 3484 3485 cleanup: 3486 PKIX_RETURN(CERT); 3487 } 3488 3489 /* 3490 * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess 3491 * (see comments in pkix_pl_pki.h) 3492 */ 3493 PKIX_Error * 3494 PKIX_PL_Cert_GetAuthorityInfoAccess( 3495 PKIX_PL_Cert *cert, 3496 PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */ 3497 void *plContext) 3498 { 3499 PKIX_List *aiaList = NULL; /* of PKIX_PL_InfoAccess */ 3500 SECItem *encodedAIA = NULL; 3501 CERTAuthInfoAccess **aia = NULL; 3502 PLArenaPool *arena = NULL; 3503 SECStatus rv; 3504 3505 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityInfoAccess"); 3506 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAiaList); 3507 3508 /* if we don't have a cached copy from before, we create one */ 3509 if (cert->authorityInfoAccess == NULL) { 3510 3511 PKIX_OBJECT_LOCK(cert); 3512 3513 if (cert->authorityInfoAccess == NULL) { 3514 3515 PKIX_PL_NSSCALLRV(CERT, encodedAIA, SECITEM_AllocItem, 3516 (NULL, NULL, 0)); 3517 3518 if (encodedAIA == NULL) { 3519 PKIX_ERROR(PKIX_OUTOFMEMORY); 3520 } 3521 3522 PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension, 3523 (cert->nssCert, 3524 SEC_OID_X509_AUTH_INFO_ACCESS, 3525 encodedAIA)); 3526 3527 if (rv == SECFailure) { 3528 goto cleanup; 3529 } 3530 3531 PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena, 3532 (DER_DEFAULT_CHUNKSIZE)); 3533 3534 if (arena == NULL) { 3535 PKIX_ERROR(PKIX_OUTOFMEMORY); 3536 } 3537 3538 PKIX_PL_NSSCALLRV 3539 (CERT, aia, CERT_DecodeAuthInfoAccessExtension, 3540 (arena, encodedAIA)); 3541 3542 PKIX_CHECK(pkix_pl_InfoAccess_CreateList 3543 (aia, &aiaList, plContext), 3544 PKIX_INFOACCESSCREATELISTFAILED); 3545 3546 cert->authorityInfoAccess = aiaList; 3547 } 3548 3549 PKIX_OBJECT_UNLOCK(cert); 3550 } 3551 3552 PKIX_INCREF(cert->authorityInfoAccess); 3553 3554 *pAiaList = cert->authorityInfoAccess; 3555 3556 cleanup: 3557 PKIX_OBJECT_UNLOCK(lockedObject); 3558 if (arena != NULL) { 3559 PORT_FreeArena(arena, PR_FALSE); 3560 } 3561 3562 if (encodedAIA != NULL) { 3563 SECITEM_FreeItem(encodedAIA, PR_TRUE); 3564 } 3565 3566 PKIX_RETURN(CERT); 3567 } 3568 3569 /* XXX Following defines belongs to NSS */ 3570 static const unsigned char siaOIDString[] = {0x2b, 0x06, 0x01, 0x05, 0x05, 3571 0x07, 0x01, 0x0b}; 3572 #define OI(x) { siDEROID, (unsigned char *)x, sizeof x } 3573 3574 /* 3575 * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess 3576 * (see comments in pkix_pl_pki.h) 3577 */ 3578 PKIX_Error * 3579 PKIX_PL_Cert_GetSubjectInfoAccess( 3580 PKIX_PL_Cert *cert, 3581 PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */ 3582 void *plContext) 3583 { 3584 PKIX_List *siaList; /* of PKIX_PL_InfoAccess */ 3585 SECItem siaOID = OI(siaOIDString); 3586 SECItem *encodedSubjInfoAccess = NULL; 3587 CERTAuthInfoAccess **subjInfoAccess = NULL; 3588 PLArenaPool *arena = NULL; 3589 SECStatus rv; 3590 3591 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectInfoAccess"); 3592 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSiaList); 3593 3594 /* XXX 3595 * Codes to deal with SubjectInfoAccess OID should be moved to 3596 * NSS soon. I implemented them here so we don't touch NSS 3597 * source tree, from JP's suggestion. 3598 */ 3599 3600 /* if we don't have a cached copy from before, we create one */ 3601 if (cert->subjectInfoAccess == NULL) { 3602 3603 PKIX_OBJECT_LOCK(cert); 3604 3605 if (cert->subjectInfoAccess == NULL) { 3606 3607 encodedSubjInfoAccess = SECITEM_AllocItem(NULL, NULL, 0); 3608 if (encodedSubjInfoAccess == NULL) { 3609 PKIX_ERROR(PKIX_OUTOFMEMORY); 3610 } 3611 3612 PKIX_CERT_DEBUG 3613 ("\t\tCalling CERT_FindCertExtensionByOID).\n"); 3614 rv = CERT_FindCertExtensionByOID 3615 (cert->nssCert, &siaOID, encodedSubjInfoAccess); 3616 3617 if (rv == SECFailure) { 3618 goto cleanup; 3619 } 3620 3621 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 3622 if (arena == NULL) { 3623 PKIX_ERROR(PKIX_OUTOFMEMORY); 3624 } 3625 3626 /* XXX 3627 * Decode Subject Information Access - 3628 * since its type is the same as Authority Information 3629 * Access, reuse the call. NSS- change name to avoid 3630 * confusion. 3631 */ 3632 PKIX_CERT_DEBUG 3633 ("\t\tCalling CERT_DecodeAuthInfoAccessExtension).\n"); 3634 subjInfoAccess = CERT_DecodeAuthInfoAccessExtension 3635 (arena, encodedSubjInfoAccess); 3636 3637 PKIX_CHECK(pkix_pl_InfoAccess_CreateList 3638 (subjInfoAccess, &siaList, plContext), 3639 PKIX_INFOACCESSCREATELISTFAILED); 3640 3641 cert->subjectInfoAccess = siaList; 3642 3643 } 3644 3645 PKIX_OBJECT_UNLOCK(cert); 3646 } 3647 3648 PKIX_INCREF(cert->subjectInfoAccess); 3649 *pSiaList = cert->subjectInfoAccess; 3650 3651 cleanup: 3652 PKIX_OBJECT_UNLOCK(lockedObject); 3653 if (arena != NULL) { 3654 PORT_FreeArena(arena, PR_FALSE); 3655 } 3656 3657 if (encodedSubjInfoAccess != NULL) { 3658 SECITEM_FreeItem(encodedSubjInfoAccess, PR_TRUE); 3659 } 3660 PKIX_RETURN(CERT); 3661 } 3662 3663 /* 3664 * FUNCTION: PKIX_PL_Cert_GetCrlDp 3665 * (see comments in pkix_pl_pki.h) 3666 */ 3667 PKIX_Error * 3668 PKIX_PL_Cert_GetCrlDp( 3669 PKIX_PL_Cert *cert, 3670 PKIX_List **pDpList, 3671 void *plContext) 3672 { 3673 PKIX_UInt32 dpIndex = 0; 3674 pkix_pl_CrlDp *dp = NULL; 3675 CERTCrlDistributionPoints *dpoints = NULL; 3676 3677 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCrlDp"); 3678 PKIX_NULLCHECK_THREE(cert, cert->nssCert, pDpList); 3679 3680 /* if we don't have a cached copy from before, we create one */ 3681 if (cert->crldpList == NULL) { 3682 PKIX_OBJECT_LOCK(cert); 3683 if (cert->crldpList != NULL) { 3684 goto cleanup; 3685 } 3686 PKIX_CHECK(PKIX_List_Create(&cert->crldpList, plContext), 3687 PKIX_LISTCREATEFAILED); 3688 dpoints = CERT_FindCRLDistributionPoints(cert->nssCert); 3689 if (!dpoints || !dpoints->distPoints) { 3690 goto cleanup; 3691 } 3692 for (;dpoints->distPoints[dpIndex];dpIndex++) { 3693 PKIX_CHECK( 3694 pkix_pl_CrlDp_Create(dpoints->distPoints[dpIndex], 3695 &cert->nssCert->issuer, 3696 &dp, plContext), 3697 PKIX_CRLDPCREATEFAILED); 3698 /* Create crldp list in reverse order in attempt to get 3699 * to the whole crl first. */ 3700 PKIX_CHECK( 3701 PKIX_List_InsertItem(cert->crldpList, 0, 3702 (PKIX_PL_Object*)dp, 3703 plContext), 3704 PKIX_LISTAPPENDITEMFAILED); 3705 PKIX_DECREF(dp); 3706 } 3707 } 3708 cleanup: 3709 PKIX_INCREF(cert->crldpList); 3710 *pDpList = cert->crldpList; 3711 3712 PKIX_OBJECT_UNLOCK(lockedObject); 3713 PKIX_DECREF(dp); 3714 3715 PKIX_RETURN(CERT); 3716 } 3717 3718 /* 3719 * FUNCTION: PKIX_PL_Cert_GetCERTCertificate 3720 * (see comments in pkix_pl_pki.h) 3721 */ 3722 PKIX_Error * 3723 PKIX_PL_Cert_GetCERTCertificate( 3724 PKIX_PL_Cert *cert, 3725 CERTCertificate **pnssCert, 3726 void *plContext) 3727 { 3728 PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNssCert"); 3729 PKIX_NULLCHECK_TWO(cert, pnssCert); 3730 3731 *pnssCert = CERT_DupCertificate(cert->nssCert); 3732 3733 PKIX_RETURN(CERT); 3734 }