pkix_pl_crlentry.c (28432B)
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_crlentry.c 6 * 7 * CRLENTRY Function Definitions 8 * 9 */ 10 11 #include "pkix_pl_crlentry.h" 12 13 /* --Private-CRLEntry-Functions------------------------------------- */ 14 15 /* 16 * FUNCTION: pkix_pl_CRLEntry_Destroy 17 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) 18 */ 19 static PKIX_Error * 20 pkix_pl_CRLEntry_Destroy( 21 PKIX_PL_Object *object, 22 void *plContext) 23 { 24 PKIX_PL_CRLEntry *crlEntry = NULL; 25 26 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Destroy"); 27 PKIX_NULLCHECK_ONE(object); 28 29 PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext), 30 PKIX_OBJECTNOTCRLENTRY); 31 32 crlEntry = (PKIX_PL_CRLEntry*)object; 33 34 /* crlEntry->nssCrlEntry is freed by NSS when freeing CRL */ 35 crlEntry->userReasonCode = 0; 36 crlEntry->userReasonCodeAbsent = PKIX_FALSE; 37 crlEntry->nssCrlEntry = NULL; 38 PKIX_DECREF(crlEntry->serialNumber); 39 PKIX_DECREF(crlEntry->critExtOids); 40 41 cleanup: 42 43 PKIX_RETURN(CRLENTRY); 44 } 45 46 /* 47 * FUNCTION: pkix_pl_CRLEntry_ToString_Helper 48 * 49 * DESCRIPTION: 50 * Helper function that creates a string representation of the CRLEntry 51 * pointed to by "crlEntry" and stores it at "pString". 52 * 53 * PARAMETERS 54 * "crlEntry" 55 * Address of CRLEntry whose string representation is desired. 56 * Must be non-NULL. 57 * "pString" 58 * Address where object pointer will be stored. Must be non-NULL. 59 * "plContext" 60 * Platform-specific context pointer. 61 * THREAD SAFETY: 62 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 63 * RETURNS: 64 * Returns NULL if the function succeeds. 65 * Returns a CRLEntry Error if the function fails in a non-fatal way. 66 * Returns a Fatal Error if the function fails in an unrecoverable way. 67 */ 68 PKIX_Error * 69 pkix_pl_CRLEntry_ToString_Helper( 70 PKIX_PL_CRLEntry *crlEntry, 71 PKIX_PL_String **pString, 72 void *plContext) 73 { 74 char *asciiFormat = NULL; 75 PKIX_List *critExtOIDs = NULL; 76 PKIX_PL_String *crlEntryString = NULL; 77 PKIX_PL_String *formatString = NULL; 78 PKIX_PL_String *crlSerialNumberString = NULL; 79 PKIX_PL_String *crlRevocationDateString = NULL; 80 PKIX_PL_String *critExtOIDsString = NULL; 81 PKIX_Int32 reasonCode = 0; 82 83 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString_Helper"); 84 PKIX_NULLCHECK_FOUR 85 (crlEntry, 86 crlEntry->serialNumber, 87 crlEntry->nssCrlEntry, 88 pString); 89 90 asciiFormat = 91 "\n\t[\n" 92 "\tSerialNumber: %s\n" 93 "\tReasonCode: %d\n" 94 "\tRevocationDate: %s\n" 95 "\tCritExtOIDs: %s\n" 96 "\t]\n\t"; 97 98 PKIX_CHECK(PKIX_PL_String_Create 99 (PKIX_ESCASCII, 100 asciiFormat, 101 0, 102 &formatString, 103 plContext), 104 PKIX_STRINGCREATEFAILED); 105 106 /* SerialNumber */ 107 PKIX_CHECK(PKIX_PL_Object_ToString 108 ((PKIX_PL_Object *)crlEntry->serialNumber, 109 &crlSerialNumberString, 110 plContext), 111 PKIX_BIGINTTOSTRINGHELPERFAILED); 112 113 /* RevocationDate - No Date object created, use nss data directly */ 114 PKIX_CHECK(pkix_pl_Date_ToString_Helper 115 (&(crlEntry->nssCrlEntry->revocationDate), 116 &crlRevocationDateString, 117 plContext), 118 PKIX_DATETOSTRINGHELPERFAILED); 119 120 /* CriticalExtensionOIDs */ 121 PKIX_CHECK(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs 122 (crlEntry, &critExtOIDs, plContext), 123 PKIX_CRLENTRYGETCRITICALEXTENSIONOIDSFAILED); 124 125 PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext, 126 PKIX_LISTTOSTRINGFAILED); 127 128 /* Revocation Reason Code */ 129 PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode 130 (crlEntry, &reasonCode, plContext), 131 PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED); 132 133 PKIX_CHECK(PKIX_PL_Sprintf 134 (&crlEntryString, 135 plContext, 136 formatString, 137 crlSerialNumberString, 138 reasonCode, 139 crlRevocationDateString, 140 critExtOIDsString), 141 PKIX_SPRINTFFAILED); 142 143 *pString = crlEntryString; 144 145 cleanup: 146 147 PKIX_DECREF(critExtOIDs); 148 PKIX_DECREF(crlSerialNumberString); 149 PKIX_DECREF(crlRevocationDateString); 150 PKIX_DECREF(critExtOIDsString); 151 PKIX_DECREF(formatString); 152 153 PKIX_RETURN(CRLENTRY); 154 } 155 156 /* 157 * FUNCTION: pkix_pl_CRLEntry_ToString 158 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) 159 */ 160 static PKIX_Error * 161 pkix_pl_CRLEntry_ToString( 162 PKIX_PL_Object *object, 163 PKIX_PL_String **pString, 164 void *plContext) 165 { 166 PKIX_PL_String *crlEntryString = NULL; 167 PKIX_PL_CRLEntry *crlEntry = NULL; 168 169 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString"); 170 PKIX_NULLCHECK_TWO(object, pString); 171 172 PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext), 173 PKIX_OBJECTNOTCRLENTRY); 174 175 crlEntry = (PKIX_PL_CRLEntry *) object; 176 177 PKIX_CHECK(pkix_pl_CRLEntry_ToString_Helper 178 (crlEntry, &crlEntryString, plContext), 179 PKIX_CRLENTRYTOSTRINGHELPERFAILED); 180 181 *pString = crlEntryString; 182 183 cleanup: 184 185 PKIX_RETURN(CRLENTRY); 186 } 187 188 /* 189 * FUNCTION: pkix_pl_CRLEntry_Extensions_Hashcode 190 * DESCRIPTION: 191 * 192 * For each CRL Entry extension stored at NSS structure CERTCertExtension, 193 * get its derbyte data and do the hash. 194 * 195 * PARAMETERS 196 * "extensions" 197 * Address of arrray of CERTCertExtension whose hash value is desired. 198 * Must be non-NULL. 199 * "pHashValue" 200 * Address where the final hash value is returned. Must be non-NULL. 201 * "plContext" 202 * Platform-specific context pointer. 203 * THREAD SAFETY: 204 * Conditional Thread Safe 205 * Though the value of extensions once created is not supposed to change, 206 * it may be de-allocated while we are accessing it. But since we are 207 * validating the object, it is unlikely we or someone is de-allocating 208 * at the moment. 209 * RETURNS: 210 * Returns NULL if the function succeeds. 211 * Returns an OID Error if the function fails in a non-fatal way. 212 * Returns a Fatal Error if the function fails in an unrecoverable way. 213 */ 214 static PKIX_Error * 215 pkix_pl_CRLEntry_Extensions_Hashcode( 216 CERTCertExtension **extensions, 217 PKIX_UInt32 *pHashValue, 218 void *plContext) 219 { 220 CERTCertExtension *extension = NULL; 221 PLArenaPool *arena = NULL; 222 PKIX_UInt32 extHash = 0; 223 PKIX_UInt32 hashValue = 0; 224 SECItem *derBytes = NULL; 225 SECItem *resultSecItem = NULL; 226 227 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Hashcode"); 228 PKIX_NULLCHECK_TWO(extensions, pHashValue); 229 230 if (extensions) { 231 232 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n"); 233 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 234 if (arena == NULL) { 235 PKIX_ERROR(PKIX_OUTOFMEMORY); 236 } 237 238 while (*extensions) { 239 240 extension = *extensions++; 241 242 PKIX_NULLCHECK_ONE(extension); 243 244 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n"); 245 derBytes = PORT_ArenaZNew(arena, SECItem); 246 if (derBytes == NULL) { 247 PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); 248 } 249 250 PKIX_CRLENTRY_DEBUG 251 ("\t\tCalling SEC_ASN1EncodeItem\n"); 252 resultSecItem = SEC_ASN1EncodeItem 253 (arena, 254 derBytes, 255 extension, 256 CERT_CertExtensionTemplate); 257 258 if (resultSecItem == NULL){ 259 PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); 260 } 261 262 PKIX_CHECK(pkix_hash 263 (derBytes->data, 264 derBytes->len, 265 &extHash, 266 plContext), 267 PKIX_HASHFAILED); 268 269 hashValue += (extHash << 7); 270 271 } 272 } 273 274 *pHashValue = hashValue; 275 276 cleanup: 277 278 if (arena){ 279 /* Note that freeing the arena also frees derBytes */ 280 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n"); 281 PORT_FreeArena(arena, PR_FALSE); 282 arena = NULL; 283 } 284 PKIX_RETURN(CRLENTRY); 285 } 286 287 /* 288 * FUNCTION: pkix_pl_CRLEntry_Hashcode 289 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) 290 */ 291 static PKIX_Error * 292 pkix_pl_CRLEntry_Hashcode( 293 PKIX_PL_Object *object, 294 PKIX_UInt32 *pHashcode, 295 void *plContext) 296 { 297 SECItem *nssDate = NULL; 298 PKIX_PL_CRLEntry *crlEntry = NULL; 299 PKIX_UInt32 crlEntryHash; 300 PKIX_UInt32 hashValue; 301 PKIX_Int32 reasonCode = 0; 302 303 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Hashcode"); 304 PKIX_NULLCHECK_TWO(object, pHashcode); 305 306 PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext), 307 PKIX_OBJECTNOTCRLENTRY); 308 309 crlEntry = (PKIX_PL_CRLEntry *)object; 310 311 PKIX_NULLCHECK_ONE(crlEntry->nssCrlEntry); 312 nssDate = &(crlEntry->nssCrlEntry->revocationDate); 313 314 PKIX_NULLCHECK_ONE(nssDate->data); 315 316 PKIX_CHECK(pkix_hash 317 ((const unsigned char *)nssDate->data, 318 nssDate->len, 319 &crlEntryHash, 320 plContext), 321 PKIX_ERRORGETTINGHASHCODE); 322 323 PKIX_CHECK(PKIX_PL_Object_Hashcode 324 ((PKIX_PL_Object *)crlEntry->serialNumber, 325 &hashValue, 326 plContext), 327 PKIX_OBJECTHASHCODEFAILED); 328 329 crlEntryHash += (hashValue << 7); 330 331 hashValue = 0; 332 333 if (crlEntry->nssCrlEntry->extensions) { 334 335 PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Hashcode 336 (crlEntry->nssCrlEntry->extensions, &hashValue, plContext), 337 PKIX_CRLENTRYEXTENSIONSHASHCODEFAILED); 338 } 339 340 crlEntryHash += (hashValue << 7); 341 342 PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode 343 (crlEntry, &reasonCode, plContext), 344 PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED); 345 346 crlEntryHash += (reasonCode + 777) << 3; 347 348 *pHashcode = crlEntryHash; 349 350 cleanup: 351 352 PKIX_RETURN(CRLENTRY); 353 } 354 355 /* 356 * FUNCTION: pkix_pl_CRLENTRY_Extensions_Equals 357 * DESCRIPTION: 358 * 359 * Compare each extension's DERbyte data in "firstExtensions" with extension 360 * in "secondExtensions" in sequential order and store the result in 361 * "pResult". 362 * 363 * PARAMETERS 364 * "firstExtensions" 365 * Address of first NSS structure CERTCertExtension to be compared. 366 * Must be non-NULL. 367 * "secondExtensions" 368 * Address of second NSS structure CERTCertExtension to be compared. 369 * Must be non-NULL. 370 * "pResult" 371 * Address where the comparison result is returned. Must be non-NULL. 372 * "plContext" 373 * Platform-specific context pointer. 374 * THREAD SAFETY: 375 * Conditionally Thread Safe 376 * Though the value of extensions once created is not supposed to change, 377 * it may be de-allocated while we are accessing it. But since we are 378 * validating the object, it is unlikely we or someone is de-allocating 379 * at the moment. 380 * RETURNS: 381 * Returns NULL if the function succeeds. 382 * Returns an OID Error if the function fails in a non-fatal way. 383 * Returns a Fatal Error if the function fails in an unrecoverable way. 384 */ 385 static PKIX_Error * 386 pkix_pl_CRLEntry_Extensions_Equals( 387 CERTCertExtension **extensions1, 388 CERTCertExtension **extensions2, 389 PKIX_Boolean *pResult, 390 void *plContext) 391 { 392 CERTCertExtension **firstExtensions; 393 CERTCertExtension **secondExtensions; 394 CERTCertExtension *firstExtension = NULL; 395 CERTCertExtension *secondExtension = NULL; 396 PLArenaPool *arena = NULL; 397 PKIX_Boolean cmpResult = PKIX_FALSE; 398 SECItem *firstDerBytes = NULL; 399 SECItem *secondDerBytes = NULL; 400 SECItem *firstResultSecItem = NULL; 401 SECItem *secondResultSecItem = NULL; 402 PKIX_UInt32 firstNumExt = 0; 403 PKIX_UInt32 secondNumExt = 0; 404 SECComparison secResult; 405 406 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Equals"); 407 PKIX_NULLCHECK_THREE(extensions1, extensions2, pResult); 408 409 firstExtensions = extensions1; 410 secondExtensions = extensions2; 411 412 if (firstExtensions) { 413 while (*firstExtensions) { 414 firstExtension = *firstExtensions++; 415 firstNumExt++; 416 } 417 } 418 419 if (secondExtensions) { 420 while (*secondExtensions) { 421 secondExtension = *secondExtensions++; 422 secondNumExt++; 423 } 424 } 425 426 if (firstNumExt != secondNumExt) { 427 *pResult = PKIX_FALSE; 428 goto cleanup; 429 } 430 431 if (firstNumExt == 0 && secondNumExt == 0) { 432 *pResult = PKIX_TRUE; 433 goto cleanup; 434 } 435 436 /* now have equal number, but non-zero extension items to compare */ 437 438 firstExtensions = extensions1; 439 secondExtensions = extensions2; 440 441 cmpResult = PKIX_TRUE; 442 443 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n"); 444 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE*2); 445 if (arena == NULL) { 446 PKIX_ERROR(PKIX_OUTOFMEMORY); 447 } 448 449 while (firstNumExt--) { 450 451 firstExtension = *firstExtensions++; 452 secondExtension = *secondExtensions++; 453 454 PKIX_NULLCHECK_TWO(firstExtension, secondExtension); 455 456 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n"); 457 firstDerBytes = PORT_ArenaZNew(arena, SECItem); 458 if (firstDerBytes == NULL) { 459 PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); 460 } 461 462 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n"); 463 secondDerBytes = PORT_ArenaZNew(arena, SECItem); 464 if (secondDerBytes == NULL) { 465 PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); 466 } 467 468 PKIX_CRLENTRY_DEBUG 469 ("\t\tCalling SEC_ASN1EncodeItem\n"); 470 firstResultSecItem = SEC_ASN1EncodeItem 471 (arena, 472 firstDerBytes, 473 firstExtension, 474 CERT_CertExtensionTemplate); 475 476 if (firstResultSecItem == NULL){ 477 PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); 478 } 479 480 PKIX_CRLENTRY_DEBUG 481 ("\t\tCalling SEC_ASN1EncodeItem\n"); 482 secondResultSecItem = SEC_ASN1EncodeItem 483 (arena, 484 secondDerBytes, 485 secondExtension, 486 CERT_CertExtensionTemplate); 487 488 if (secondResultSecItem == NULL){ 489 PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); 490 } 491 492 PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n"); 493 secResult = SECITEM_CompareItem 494 (firstResultSecItem, secondResultSecItem); 495 496 if (secResult != SECEqual) { 497 cmpResult = PKIX_FALSE; 498 break; 499 } 500 501 } 502 503 *pResult = cmpResult; 504 505 cleanup: 506 507 if (arena){ 508 /* Note that freeing the arena also frees derBytes */ 509 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n"); 510 PORT_FreeArena(arena, PR_FALSE); 511 arena = NULL; 512 } 513 514 PKIX_RETURN(CRLENTRY); 515 } 516 517 /* 518 * FUNCTION: pkix_pl_CRLEntry_Equals 519 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) 520 */ 521 static PKIX_Error * 522 pkix_pl_CRLEntry_Equals( 523 PKIX_PL_Object *firstObject, 524 PKIX_PL_Object *secondObject, 525 PKIX_Boolean *pResult, 526 void *plContext) 527 { 528 PKIX_PL_CRLEntry *firstCrlEntry = NULL; 529 PKIX_PL_CRLEntry *secondCrlEntry = NULL; 530 PKIX_UInt32 secondType; 531 PKIX_Boolean cmpResult = PKIX_FALSE; 532 533 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Equals"); 534 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); 535 536 /* test that firstObject is a CRLEntry */ 537 PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRLENTRY_TYPE, plContext), 538 PKIX_FIRSTOBJECTNOTCRLENTRY); 539 540 firstCrlEntry = (PKIX_PL_CRLEntry *)firstObject; 541 secondCrlEntry = (PKIX_PL_CRLEntry *)secondObject; 542 543 PKIX_NULLCHECK_TWO 544 (firstCrlEntry->nssCrlEntry, secondCrlEntry->nssCrlEntry); 545 546 /* 547 * Since we know firstObject is a CRLEntry, if both references are 548 * identical, they must be equal 549 */ 550 if (firstCrlEntry == secondCrlEntry){ 551 *pResult = PKIX_TRUE; 552 goto cleanup; 553 } 554 555 /* 556 * If secondCrlEntry isn't a CRL Entry, we don't throw an error. 557 * We simply return a Boolean result of FALSE 558 */ 559 *pResult = PKIX_FALSE; 560 PKIX_CHECK(PKIX_PL_Object_GetType 561 ((PKIX_PL_Object *)secondCrlEntry, &secondType, plContext), 562 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); 563 if (secondType != PKIX_CRLENTRY_TYPE) goto cleanup; 564 565 /* Compare userSerialNumber */ 566 PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n"); 567 if (SECITEM_CompareItem( 568 &(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry->serialNumber), 569 &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry->serialNumber)) 570 != SECEqual) { 571 *pResult = PKIX_FALSE; 572 goto cleanup; 573 } 574 575 /* Compare revocationDate */ 576 PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n"); 577 if (SECITEM_CompareItem 578 (&(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry-> 579 revocationDate), 580 &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry-> 581 revocationDate)) 582 != SECEqual) { 583 *pResult = PKIX_FALSE; 584 goto cleanup; 585 } 586 587 /* Compare Critical Extension List */ 588 PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Equals 589 (firstCrlEntry->nssCrlEntry->extensions, 590 secondCrlEntry->nssCrlEntry->extensions, 591 &cmpResult, 592 plContext), 593 PKIX_CRLENTRYEXTENSIONSEQUALSFAILED); 594 595 if (cmpResult != PKIX_TRUE){ 596 *pResult = PKIX_FALSE; 597 goto cleanup; 598 } 599 600 cmpResult = (firstCrlEntry->userReasonCode == 601 secondCrlEntry->userReasonCode); 602 603 *pResult = cmpResult; 604 605 cleanup: 606 607 PKIX_RETURN(CRLENTRY); 608 } 609 610 /* 611 * FUNCTION: pkix_pl_CRLEntry_RegisterSelf 612 * DESCRIPTION: 613 * Registers PKIX_CRLEntry_TYPE and its related functions with systemClasses[] 614 * THREAD SAFETY: 615 * Not Thread Safe - for performance and complexity reasons 616 * 617 * Since this function is only called by PKIX_PL_Initialize, which should 618 * only be called once, it is acceptable that this function is not 619 * thread-safe. 620 */ 621 PKIX_Error * 622 pkix_pl_CRLEntry_RegisterSelf(void *plContext) 623 { 624 625 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; 626 pkix_ClassTable_Entry entry; 627 628 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_RegisterSelf"); 629 630 entry.description = "CRLEntry"; 631 entry.objCounter = 0; 632 entry.typeObjectSize = sizeof(PKIX_PL_CRLEntry); 633 entry.destructor = pkix_pl_CRLEntry_Destroy; 634 entry.equalsFunction = pkix_pl_CRLEntry_Equals; 635 entry.hashcodeFunction = pkix_pl_CRLEntry_Hashcode; 636 entry.toStringFunction = pkix_pl_CRLEntry_ToString; 637 entry.comparator = NULL; 638 entry.duplicateFunction = pkix_duplicateImmutable; 639 640 systemClasses[PKIX_CRLENTRY_TYPE] = entry; 641 642 PKIX_RETURN(CRLENTRY); 643 } 644 645 /* 646 * FUNCTION: pkix_pl_CRLEntry_CreateEntry 647 * DESCRIPTION: 648 * 649 * Creates a new CRLEntry using the CertCrlEntry pointed to by "nssCrlEntry" 650 * and stores it at "pCrlEntry". Once created, a CRLEntry is immutable. 651 * 652 * revokedCertificates SEQUENCE OF SEQUENCE { 653 * userCertificate CertificateSerialNumber, 654 * revocationDate Time, 655 * crlEntryExtensions Extensions OPTIONAL 656 * -- if present, MUST be v2 657 * 658 * PARAMETERS: 659 * "nssCrlEntry" 660 * Address of CERTCrlEntry representing an NSS CRL entry. 661 * Must be non-NULL. 662 * "pCrlEntry" 663 * Address where object pointer will be stored. Must be non-NULL. 664 * "plContext" 665 * Platform-specific context pointer. 666 * THREAD SAFETY: 667 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 668 * RETURNS: 669 * Returns NULL if the function succeeds. 670 * Returns a CRLEntry Error if the function fails in a non-fatal way. 671 * Returns a Fatal Error if the function fails in an unrecoverable way. 672 */ 673 static PKIX_Error * 674 pkix_pl_CRLEntry_CreateEntry( 675 CERTCrlEntry *nssCrlEntry, /* entry data to be created from */ 676 PKIX_PL_CRLEntry **pCrlEntry, 677 void *plContext) 678 { 679 PKIX_PL_CRLEntry *crlEntry = NULL; 680 681 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_CreateEntry"); 682 PKIX_NULLCHECK_TWO(nssCrlEntry, pCrlEntry); 683 684 PKIX_CHECK(PKIX_PL_Object_Alloc 685 (PKIX_CRLENTRY_TYPE, 686 sizeof (PKIX_PL_CRLEntry), 687 (PKIX_PL_Object **)&crlEntry, 688 plContext), 689 PKIX_COULDNOTCREATECRLENTRYOBJECT); 690 691 crlEntry->nssCrlEntry = nssCrlEntry; 692 crlEntry->serialNumber = NULL; 693 crlEntry->critExtOids = NULL; 694 crlEntry->userReasonCode = 0; 695 crlEntry->userReasonCodeAbsent = PKIX_FALSE; 696 697 *pCrlEntry = crlEntry; 698 699 cleanup: 700 701 PKIX_RETURN(CRLENTRY); 702 } 703 704 /* 705 * FUNCTION: pkix_pl_CRLEntry_Create 706 * DESCRIPTION: 707 * 708 * Creates a List of CRLEntries using the array of CERTCrlEntries pointed to 709 * by "nssCrlEntries" and stores it at "pCrlEntryList". If "nssCrlEntries" is 710 * NULL, this function stores an empty List at "pCrlEntryList". 711 * } 712 * PARAMETERS: 713 * "nssCrlEntries" 714 * Address of array of CERTCrlEntries representing NSS CRL entries. 715 * Can be NULL if CRL has no NSS CRL entries. 716 * "pCrlEntryList" 717 * Address where object pointer will be stored. Must be non-NULL. 718 * "plContext" 719 * Platform-specific context pointer. 720 * THREAD SAFETY: 721 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 722 * RETURNS: 723 * Returns NULL if the function succeeds. 724 * Returns a CRLEntry Error if the function fails in a non-fatal way. 725 * Returns a Fatal Error if the function fails in an unrecoverable way. 726 */ 727 PKIX_Error * 728 pkix_pl_CRLEntry_Create( 729 CERTCrlEntry **nssCrlEntries, /* head of entry list */ 730 PKIX_List **pCrlEntryList, 731 void *plContext) 732 { 733 PKIX_List *entryList = NULL; 734 PKIX_PL_CRLEntry *crlEntry = NULL; 735 CERTCrlEntry **entries = NULL; 736 SECItem serialNumberItem; 737 PKIX_PL_BigInt *serialNumber; 738 char *bytes = NULL; 739 PKIX_UInt32 length; 740 741 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Create"); 742 PKIX_NULLCHECK_ONE(pCrlEntryList); 743 744 entries = nssCrlEntries; 745 746 PKIX_CHECK(PKIX_List_Create(&entryList, plContext), 747 PKIX_LISTCREATEFAILED); 748 749 if (entries) { 750 while (*entries){ 751 PKIX_CHECK(pkix_pl_CRLEntry_CreateEntry 752 (*entries, &crlEntry, plContext), 753 PKIX_COULDNOTCREATECRLENTRYOBJECT); 754 755 /* Get Serial Number */ 756 serialNumberItem = (*entries)->serialNumber; 757 length = serialNumberItem.len; 758 bytes = (char *)serialNumberItem.data; 759 760 PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes 761 (bytes, length, &serialNumber, plContext), 762 PKIX_BIGINTCREATEWITHBYTESFAILED); 763 764 crlEntry->serialNumber = serialNumber; 765 crlEntry->nssCrlEntry = *entries; 766 767 PKIX_CHECK(PKIX_List_AppendItem 768 (entryList, (PKIX_PL_Object *)crlEntry, plContext), 769 PKIX_LISTAPPENDITEMFAILED); 770 771 PKIX_DECREF(crlEntry); 772 773 entries++; 774 } 775 } 776 777 *pCrlEntryList = entryList; 778 779 cleanup: 780 PKIX_DECREF(crlEntry); 781 782 if (PKIX_ERROR_RECEIVED){ 783 PKIX_DECREF(entryList); 784 } 785 786 PKIX_RETURN(CRLENTRY); 787 } 788 789 /* --Public-CRLENTRY-Functions------------------------------------- */ 790 791 /* 792 * FUNCTION: PKIX_PL_CRLEntry_GetCRLEntryReasonCode 793 * (see comments in pkix_pl_pki.h) 794 */ 795 PKIX_Error * 796 PKIX_PL_CRLEntry_GetCRLEntryReasonCode ( 797 PKIX_PL_CRLEntry *crlEntry, 798 PKIX_Int32 *pReason, 799 void *plContext) 800 { 801 SECStatus status; 802 CERTCRLEntryReasonCode nssReasonCode; 803 804 PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCRLEntryReasonCode"); 805 PKIX_NULLCHECK_TWO(crlEntry, pReason); 806 807 if (!crlEntry->userReasonCodeAbsent && crlEntry->userReasonCode == 0) { 808 809 PKIX_OBJECT_LOCK(crlEntry); 810 811 if (!crlEntry->userReasonCodeAbsent && 812 crlEntry->userReasonCode == 0) { 813 814 /* reason code has not been cached in */ 815 PKIX_CRLENTRY_DEBUG("\t\tCERT_FindCRLEntryReasonExten.\n"); 816 status = CERT_FindCRLEntryReasonExten 817 (crlEntry->nssCrlEntry, &nssReasonCode); 818 819 if (status == SECSuccess) { 820 crlEntry->userReasonCode = (PKIX_Int32) nssReasonCode; 821 } else { 822 crlEntry->userReasonCodeAbsent = PKIX_TRUE; 823 } 824 } 825 826 PKIX_OBJECT_UNLOCK(crlEntry); 827 828 } 829 830 *pReason = crlEntry->userReasonCode; 831 832 cleanup: 833 834 PKIX_RETURN(CRLENTRY); 835 } 836 837 /* 838 * FUNCTION: PKIX_PL_CRLEntry_GetCriticalExtensionOIDs 839 * (see comments in pkix_pl_pki.h) 840 */ 841 PKIX_Error * 842 PKIX_PL_CRLEntry_GetCriticalExtensionOIDs ( 843 PKIX_PL_CRLEntry *crlEntry, 844 PKIX_List **pList, /* list of PKIX_PL_OID */ 845 void *plContext) 846 { 847 PKIX_List *oidsList = NULL; 848 CERTCertExtension **extensions; 849 850 PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCriticalExtensionOIDs"); 851 PKIX_NULLCHECK_THREE(crlEntry, crlEntry->nssCrlEntry, pList); 852 853 /* if we don't have a cached copy from before, we create one */ 854 if (crlEntry->critExtOids == NULL) { 855 856 PKIX_OBJECT_LOCK(crlEntry); 857 858 if (crlEntry->critExtOids == NULL) { 859 860 extensions = crlEntry->nssCrlEntry->extensions; 861 862 PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs 863 (extensions, &oidsList, plContext), 864 PKIX_GETCRITICALEXTENSIONOIDSFAILED); 865 866 crlEntry->critExtOids = oidsList; 867 } 868 869 PKIX_OBJECT_UNLOCK(crlEntry); 870 871 } 872 873 /* We should return a copy of the List since this list changes */ 874 PKIX_DUPLICATE(crlEntry->critExtOids, pList, plContext, 875 PKIX_OBJECTDUPLICATELISTFAILED); 876 877 cleanup: 878 879 PKIX_RETURN(CRLENTRY); 880 }