pkix_pl_crl.c (33165B)
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_crl.c 6 * 7 * CRL Function Definitions 8 * 9 */ 10 11 #include "pkix_pl_crl.h" 12 #include "certxutl.h" 13 14 extern PKIX_PL_HashTable *cachedCrlSigTable; 15 16 /* --Private-CRL-Functions------------------------------------- */ 17 18 /* 19 * FUNCTION: pkix_pl_CRL_GetVersion 20 * DESCRIPTION: 21 * 22 * Retrieves the version of the CRL pointed to by "crl" and stores it at 23 * "pVersion". The version number will either be 0 or 1 (corresponding to 24 * v1 or v2, respectively). 25 * 26 * Version ::= INTEGER { v1(0), v2(1), v3(2) } 27 * 28 * PARAMETERS: 29 * "crl" 30 * Address of CRL whose version is to be stored. Must be non-NULL. 31 * "pVersion" 32 * Address where a version will be stored. Must be non-NULL. 33 * "plContext" 34 * Platform-specific context pointer. 35 * THREAD SAFETY: 36 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 37 * RETURNS: 38 * Returns NULL if the function succeeds. 39 * Returns a CRL Error if the function fails in a non-fatal way. 40 * Returns a Fatal Error if the function fails in an unrecoverable way. 41 */ 42 static PKIX_Error * 43 pkix_pl_CRL_GetVersion( 44 PKIX_PL_CRL *crl, 45 PKIX_UInt32 *pVersion, 46 void *plContext) 47 { 48 PKIX_UInt32 myVersion; 49 50 PKIX_ENTER(CRL, "pkix_pl_CRL_GetVersion"); 51 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pVersion); 52 53 PKIX_NULLCHECK_ONE(crl->nssSignedCrl->crl.version.data); 54 55 myVersion = *(crl->nssSignedCrl->crl.version.data); 56 57 if (myVersion > 1) { 58 PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1ORV2); 59 } 60 61 *pVersion = myVersion; 62 63 cleanup: 64 65 PKIX_RETURN(CRL); 66 } 67 68 /* 69 * FUNCTION: PKIX_PL_CRL_GetCRLNumber (see comments in pkix_pl_pki.h) 70 */ 71 PKIX_Error * 72 PKIX_PL_CRL_GetCRLNumber( 73 PKIX_PL_CRL *crl, 74 PKIX_PL_BigInt **pCrlNumber, 75 void *plContext) 76 { 77 PKIX_PL_BigInt *crlNumber = NULL; 78 SECItem nssCrlNumber; 79 PLArenaPool *arena = NULL; 80 SECStatus status; 81 PKIX_UInt32 length = 0; 82 char *bytes = NULL; 83 84 PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCRLNumber"); 85 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlNumber); 86 87 /* Can call this function only with der been adopted. */ 88 PORT_Assert(crl->adoptedDerCrl); 89 90 if (!crl->crlNumberAbsent && crl->crlNumber == NULL) { 91 92 PKIX_OBJECT_LOCK(crl); 93 94 if (!crl->crlNumberAbsent && crl->crlNumber == NULL) { 95 96 nssCrlNumber.type = 0; 97 nssCrlNumber.len = 0; 98 nssCrlNumber.data = NULL; 99 100 PKIX_CRL_DEBUG("\t\tCalling PORT_NewArena).\n"); 101 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 102 if (arena == NULL) { 103 PKIX_ERROR(PKIX_OUTOFMEMORY); 104 } 105 106 PKIX_CRL_DEBUG("\t\tCalling CERT_FindCRLNumberExten\n"); 107 status = CERT_FindCRLNumberExten 108 (arena, &crl->nssSignedCrl->crl, &nssCrlNumber); 109 110 if (status == SECSuccess) { 111 /* Get data in bytes then convert to bigint */ 112 length = nssCrlNumber.len; 113 bytes = (char *)nssCrlNumber.data; 114 115 PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes 116 (bytes, length, &crlNumber, plContext), 117 PKIX_BIGINTCREATEWITHBYTESFAILED); 118 119 /* arena release does the job 120 PKIX_CRL_DEBUG("\t\tCalling SECITEM_FreeItem\n"); 121 SECITEM_FreeItem(&nssCrlNumber, PKIX_FALSE); 122 */ 123 crl->crlNumber = crlNumber; 124 125 } else { 126 127 crl->crlNumberAbsent = PKIX_TRUE; 128 } 129 } 130 131 PKIX_OBJECT_UNLOCK(crl); 132 133 } 134 135 PKIX_INCREF(crl->crlNumber); 136 137 *pCrlNumber = crl->crlNumber; 138 139 cleanup: 140 141 if (arena){ 142 PKIX_CRL_DEBUG("\t\tCalling PORT_FreeArena).\n"); 143 PORT_FreeArena(arena, PR_FALSE); 144 } 145 146 PKIX_RETURN(CRL); 147 } 148 149 /* 150 * FUNCTION: pkix_pl_CRL_GetSignatureAlgId 151 * 152 * DESCRIPTION: 153 * Retrieves a pointer to the OID that represents the signature algorithm of 154 * the CRL pointed to by "crl" and stores it at "pSignatureAlgId". 155 * 156 * AlgorithmIdentifier ::= SEQUENCE { 157 * algorithm OBJECT IDENTIFIER, 158 * parameters ANY DEFINED BY algorithm OPTIONAL } 159 * 160 * PARAMETERS: 161 * "crl" 162 * Address of CRL whose signature algorithm OID is to be stored. 163 * Must be non-NULL. 164 * "pSignatureAlgId" 165 * Address where object pointer will be stored. Must be non-NULL. 166 * "plContext" 167 * Platform-specific context pointer. 168 * THREAD SAFETY: 169 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 170 * RETURNS: 171 * Returns NULL if the function succeeds. 172 * Returns a CRL Error if the function fails in a non-fatal way. 173 * Returns a Fatal Error if the function fails in an unrecoverable way. 174 */ 175 static PKIX_Error * 176 pkix_pl_CRL_GetSignatureAlgId( 177 PKIX_PL_CRL *crl, 178 PKIX_PL_OID **pSignatureAlgId, 179 void *plContext) 180 { 181 PKIX_PL_OID *signatureAlgId = NULL; 182 183 PKIX_ENTER(CRL, "pkix_pl_CRL_GetSignatureAlgId"); 184 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pSignatureAlgId); 185 186 /* if we don't have a cached copy from before, we create one */ 187 if (crl->signatureAlgId == NULL){ 188 PKIX_OBJECT_LOCK(crl); 189 if (crl->signatureAlgId == NULL){ 190 CERTCrl *nssCrl = &(crl->nssSignedCrl->crl); 191 SECAlgorithmID *algorithm = &nssCrl->signatureAlg; 192 SECItem *algBytes = &algorithm->algorithm; 193 194 if (!algBytes->data || !algBytes->len) { 195 PKIX_ERROR(PKIX_OIDBYTESLENGTH0); 196 } 197 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem 198 (algBytes, &signatureAlgId, plContext), 199 PKIX_OIDCREATEFAILED); 200 201 /* save a cached copy in case it is asked for again */ 202 crl->signatureAlgId = signatureAlgId; 203 signatureAlgId = NULL; 204 } 205 PKIX_OBJECT_UNLOCK(crl); 206 } 207 PKIX_INCREF(crl->signatureAlgId); 208 *pSignatureAlgId = crl->signatureAlgId; 209 cleanup: 210 PKIX_DECREF(signatureAlgId); 211 PKIX_RETURN(CRL); 212 } 213 214 /* 215 * FUNCTION: pkix_pl_CRL_GetCRLEntries 216 * DESCRIPTION: 217 * 218 * Retrieves a pointer to the List of CRLEntries found in the CRL pointed to 219 * by "crl" and stores it at "pCRLEntries". If there are no CRLEntries, 220 * this functions stores NULL at "pCRLEntries". 221 * 222 * PARAMETERS: 223 * "crl" 224 * Address of CRL whose CRL Entries are to be retrieved. Must be non-NULL. 225 * "pCRLEntries" 226 * Address where object pointer will be stored. Must be non-NULL. 227 * "plContext" 228 * Platform-specific context pointer. 229 * THREAD SAFETY: 230 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 231 * RETURNS: 232 * Returns NULL if the function succeeds. 233 * Returns a CRL Error if the function fails in a non-fatal way. 234 * Returns a Fatal Error if the function fails in an unrecoverable way. 235 */ 236 static PKIX_Error * 237 pkix_pl_CRL_GetCRLEntries( 238 PKIX_PL_CRL *crl, 239 PKIX_List **pCrlEntries, 240 void *plContext) 241 { 242 PKIX_List *entryList = NULL; 243 CERTCrl *nssCrl = NULL; 244 245 PKIX_ENTER(CRL, "pkix_pl_CRL_GetCRLEntries"); 246 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlEntries); 247 248 /* if we don't have a cached copy from before, we create one */ 249 if (crl->crlEntryList == NULL) { 250 251 PKIX_OBJECT_LOCK(crl); 252 253 if (crl->crlEntryList == NULL){ 254 255 nssCrl = &(crl->nssSignedCrl->crl); 256 257 PKIX_CHECK(pkix_pl_CRLEntry_Create 258 (nssCrl->entries, &entryList, plContext), 259 PKIX_CRLENTRYCREATEFAILED); 260 261 PKIX_CHECK(PKIX_List_SetImmutable 262 (entryList, plContext), 263 PKIX_LISTSETIMMUTABLEFAILED); 264 265 crl->crlEntryList = entryList; 266 } 267 268 PKIX_OBJECT_UNLOCK(crl); 269 270 } 271 272 PKIX_INCREF(crl->crlEntryList); 273 274 *pCrlEntries = crl->crlEntryList; 275 276 cleanup: 277 278 PKIX_RETURN(CRL); 279 } 280 281 /* 282 * FUNCTION: pkix_pl_CRL_Destroy 283 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) 284 */ 285 static PKIX_Error * 286 pkix_pl_CRL_Destroy( 287 PKIX_PL_Object *object, 288 void *plContext) 289 { 290 PKIX_PL_CRL *crl = NULL; 291 292 PKIX_ENTER(CRL, "pkix_pl_CRL_Destroy"); 293 PKIX_NULLCHECK_ONE(object); 294 295 PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext), 296 PKIX_OBJECTNOTCRL); 297 298 crl = (PKIX_PL_CRL*)object; 299 300 PKIX_CRL_DEBUG("\t\tCalling CERT_DestroyCrl\n"); 301 if (crl->nssSignedCrl) { 302 CERT_DestroyCrl(crl->nssSignedCrl); 303 } 304 if (crl->adoptedDerCrl) { 305 SECITEM_FreeItem(crl->adoptedDerCrl, PR_TRUE); 306 } 307 crl->nssSignedCrl = NULL; 308 crl->adoptedDerCrl = NULL; 309 crl->crlNumberAbsent = PKIX_FALSE; 310 311 PKIX_DECREF(crl->issuer); 312 PKIX_DECREF(crl->signatureAlgId); 313 PKIX_DECREF(crl->crlNumber); 314 PKIX_DECREF(crl->crlEntryList); 315 PKIX_DECREF(crl->critExtOids); 316 if (crl->derGenName) { 317 SECITEM_FreeItem(crl->derGenName, PR_TRUE); 318 } 319 320 cleanup: 321 322 PKIX_RETURN(CRL); 323 } 324 325 /* 326 * FUNCTION: pkix_pl_CRL_ToString_Helper 327 * DESCRIPTION: 328 * 329 * Helper function that creates a string representation of the CRL pointed 330 * to by "crl" and stores it at "pString". 331 * 332 * PARAMETERS 333 * "crl" 334 * Address of CRL whose string representation is desired. 335 * Must be non-NULL. 336 * "pString" 337 * Address where object pointer will be stored. Must be non-NULL. 338 * "plContext" 339 * Platform-specific context pointer. 340 * THREAD SAFETY: 341 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 342 * RETURNS: 343 * Returns NULL if the function succeeds. 344 * Returns a CRL Error if the function fails in a non-fatal way. 345 * Returns a Fatal Error if the function fails in an unrecoverable way. 346 */ 347 static PKIX_Error * 348 pkix_pl_CRL_ToString_Helper( 349 PKIX_PL_CRL *crl, 350 PKIX_PL_String **pString, 351 void *plContext) 352 { 353 char *asciiFormat = NULL; 354 PKIX_UInt32 crlVersion = 0; 355 PKIX_PL_X500Name *crlIssuer = NULL; 356 PKIX_PL_OID *nssSignatureAlgId = NULL; 357 PKIX_PL_BigInt *crlNumber = NULL; 358 PKIX_List *crlEntryList = NULL; 359 PKIX_List *critExtOIDs = NULL; 360 PKIX_PL_String *formatString = NULL; 361 PKIX_PL_String *crlIssuerString = NULL; 362 PKIX_PL_String *lastUpdateString = NULL; 363 PKIX_PL_String *nextUpdateString = NULL; 364 PKIX_PL_String *nssSignatureAlgIdString = NULL; 365 PKIX_PL_String *crlNumberString = NULL; 366 PKIX_PL_String *crlEntryListString = NULL; 367 PKIX_PL_String *critExtOIDsString = NULL; 368 PKIX_PL_String *crlString = NULL; 369 370 PKIX_ENTER(CRL, "pkix_pl_CRL_ToString_Helper"); 371 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pString); 372 373 asciiFormat = 374 "[\n" 375 "\tVersion: v%d\n" 376 "\tIssuer: %s\n" 377 "\tUpdate: [Last: %s\n" 378 "\t Next: %s]\n" 379 "\tSignatureAlgId: %s\n" 380 "\tCRL Number : %s\n" 381 "\n" 382 "\tEntry List: %s\n" 383 "\n" 384 "\tCritExtOIDs: %s\n" 385 "]\n"; 386 387 PKIX_CHECK(PKIX_PL_String_Create 388 (PKIX_ESCASCII, 389 asciiFormat, 390 0, 391 &formatString, 392 plContext), 393 PKIX_STRINGCREATEFAILED); 394 395 /* Version */ 396 PKIX_CHECK(pkix_pl_CRL_GetVersion(crl, &crlVersion, plContext), 397 PKIX_CRLGETVERSIONFAILED); 398 399 /* Issuer */ 400 PKIX_CHECK(PKIX_PL_CRL_GetIssuer(crl, &crlIssuer, plContext), 401 PKIX_CRLGETISSUERFAILED); 402 403 PKIX_CHECK(PKIX_PL_Object_ToString 404 ((PKIX_PL_Object *)crlIssuer, &crlIssuerString, plContext), 405 PKIX_X500NAMETOSTRINGFAILED); 406 407 /* This update - No Date object created, use nss data directly */ 408 PKIX_CHECK(pkix_pl_Date_ToString_Helper 409 (&(crl->nssSignedCrl->crl.lastUpdate), 410 &lastUpdateString, 411 plContext), 412 PKIX_DATETOSTRINGHELPERFAILED); 413 414 /* Next update - No Date object created, use nss data directly */ 415 PKIX_CHECK(pkix_pl_Date_ToString_Helper 416 (&(crl->nssSignedCrl->crl.nextUpdate), 417 &nextUpdateString, 418 plContext), 419 PKIX_DATETOSTRINGHELPERFAILED); 420 421 /* Signature Algorithm Id */ 422 PKIX_CHECK(pkix_pl_CRL_GetSignatureAlgId 423 (crl, &nssSignatureAlgId, plContext), 424 PKIX_CRLGETSIGNATUREALGIDFAILED); 425 426 PKIX_CHECK(PKIX_PL_Object_ToString 427 ((PKIX_PL_Object *)nssSignatureAlgId, 428 &nssSignatureAlgIdString, 429 plContext), 430 PKIX_OIDTOSTRINGFAILED); 431 432 /* CRL Number */ 433 PKIX_CHECK(PKIX_PL_CRL_GetCRLNumber 434 (crl, &crlNumber, plContext), 435 PKIX_CRLGETCRLNUMBERFAILED); 436 437 PKIX_TOSTRING(crlNumber, &crlNumberString, plContext, 438 PKIX_BIGINTTOSTRINGFAILED); 439 440 /* CRL Entries */ 441 PKIX_CHECK(pkix_pl_CRL_GetCRLEntries(crl, &crlEntryList, plContext), 442 PKIX_CRLGETCRLENTRIESFAILED); 443 444 PKIX_TOSTRING(crlEntryList, &crlEntryListString, plContext, 445 PKIX_LISTTOSTRINGFAILED); 446 447 /* CriticalExtensionOIDs */ 448 PKIX_CHECK(PKIX_PL_CRL_GetCriticalExtensionOIDs 449 (crl, &critExtOIDs, plContext), 450 PKIX_CRLGETCRITICALEXTENSIONOIDSFAILED); 451 452 PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext, 453 PKIX_LISTTOSTRINGFAILED); 454 455 PKIX_CHECK(PKIX_PL_Sprintf 456 (&crlString, 457 plContext, 458 formatString, 459 crlVersion + 1, 460 crlIssuerString, 461 lastUpdateString, 462 nextUpdateString, 463 nssSignatureAlgIdString, 464 crlNumberString, 465 crlEntryListString, 466 critExtOIDsString), 467 PKIX_SPRINTFFAILED); 468 469 *pString = crlString; 470 471 cleanup: 472 473 PKIX_DECREF(crlIssuer); 474 PKIX_DECREF(nssSignatureAlgId); 475 PKIX_DECREF(crlNumber); 476 PKIX_DECREF(crlEntryList); 477 PKIX_DECREF(critExtOIDs); 478 PKIX_DECREF(crlIssuerString); 479 PKIX_DECREF(lastUpdateString); 480 PKIX_DECREF(nextUpdateString); 481 PKIX_DECREF(nssSignatureAlgIdString); 482 PKIX_DECREF(crlNumberString); 483 PKIX_DECREF(crlEntryListString); 484 PKIX_DECREF(critExtOIDsString); 485 PKIX_DECREF(formatString); 486 487 PKIX_RETURN(CRL); 488 } 489 490 /* 491 * FUNCTION: pkix_pl_CRL_ToString 492 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) 493 */ 494 static PKIX_Error * 495 pkix_pl_CRL_ToString( 496 PKIX_PL_Object *object, 497 PKIX_PL_String **pString, 498 void *plContext) 499 { 500 PKIX_PL_String *crlString = NULL; 501 PKIX_PL_CRL *crl = NULL; 502 503 PKIX_ENTER(CRL, "pkix_pl_CRL_ToString"); 504 PKIX_NULLCHECK_TWO(object, pString); 505 506 PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext), 507 PKIX_OBJECTNOTCRL); 508 509 crl = (PKIX_PL_CRL *) object; 510 511 PKIX_CHECK(pkix_pl_CRL_ToString_Helper(crl, &crlString, plContext), 512 PKIX_CRLTOSTRINGHELPERFAILED); 513 514 *pString = crlString; 515 516 cleanup: 517 518 PKIX_RETURN(CRL); 519 } 520 521 /* 522 * FUNCTION: pkix_pl_CRL_Hashcode 523 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) 524 */ 525 static PKIX_Error * 526 pkix_pl_CRL_Hashcode( 527 PKIX_PL_Object *object, 528 PKIX_UInt32 *pHashcode, 529 void *plContext) 530 { 531 PKIX_PL_CRL *crl = NULL; 532 PKIX_UInt32 certHash; 533 SECItem *crlDer = NULL; 534 535 PKIX_ENTER(CRL, "pkix_pl_CRL_Hashcode"); 536 PKIX_NULLCHECK_TWO(object, pHashcode); 537 538 PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext), 539 PKIX_OBJECTNOTCRL); 540 541 crl = (PKIX_PL_CRL *)object; 542 if (crl->adoptedDerCrl) { 543 crlDer = crl->adoptedDerCrl; 544 } else if (crl->nssSignedCrl && crl->nssSignedCrl->derCrl) { 545 crlDer = crl->nssSignedCrl->derCrl; 546 } 547 if (!crlDer || !crlDer->data) { 548 PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER); 549 } 550 551 PKIX_CHECK(pkix_hash(crlDer->data, crlDer->len, 552 &certHash, plContext), 553 PKIX_ERRORINHASH); 554 555 *pHashcode = certHash; 556 557 cleanup: 558 559 PKIX_RETURN(CRL); 560 } 561 562 /* 563 * FUNCTION: pkix_pl_CRL_Equals 564 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) 565 */ 566 static PKIX_Error * 567 pkix_pl_CRL_Equals( 568 PKIX_PL_Object *firstObject, 569 PKIX_PL_Object *secondObject, 570 PKIX_Boolean *pResult, 571 void *plContext) 572 { 573 PKIX_PL_CRL *firstCrl = NULL; 574 PKIX_PL_CRL *secondCrl = NULL; 575 SECItem *crlDerOne = NULL, *crlDerTwo = NULL; 576 PKIX_UInt32 secondType; 577 578 PKIX_ENTER(CRL, "pkix_pl_CRL_Equals"); 579 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); 580 581 /* test that firstObject is a CRL */ 582 PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRL_TYPE, plContext), 583 PKIX_FIRSTOBJECTNOTCRL); 584 585 firstCrl = (PKIX_PL_CRL *)firstObject; 586 secondCrl = (PKIX_PL_CRL *)secondObject; 587 588 /* 589 * Since we know firstObject is a CRL, if both references are 590 * identical, they must be equal 591 */ 592 if (firstCrl == secondCrl){ 593 *pResult = PKIX_TRUE; 594 goto cleanup; 595 } 596 597 /* 598 * If secondCrl isn't a CRL, we don't throw an error. 599 * We simply return a Boolean result of FALSE 600 */ 601 *pResult = PKIX_FALSE; 602 PKIX_CHECK(PKIX_PL_Object_GetType 603 ((PKIX_PL_Object *)secondCrl, &secondType, plContext), 604 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); 605 if (secondType != PKIX_CRL_TYPE) goto cleanup; 606 607 if (firstCrl->adoptedDerCrl) { 608 crlDerOne = firstCrl->adoptedDerCrl; 609 } else if (firstCrl->nssSignedCrl && firstCrl->nssSignedCrl->derCrl) { 610 crlDerOne = firstCrl->nssSignedCrl->derCrl; 611 } 612 613 if (secondCrl->adoptedDerCrl) { 614 crlDerTwo = secondCrl->adoptedDerCrl; 615 } else if (secondCrl->nssSignedCrl && secondCrl->nssSignedCrl->derCrl) { 616 crlDerTwo = secondCrl->nssSignedCrl->derCrl; 617 } 618 619 if (SECITEM_CompareItem(crlDerOne, crlDerTwo) == SECEqual) { 620 *pResult = PKIX_TRUE; 621 } 622 623 cleanup: 624 625 PKIX_RETURN(CRL); 626 } 627 628 /* 629 * FUNCTION: pkix_pl_CRL_RegisterSelf 630 * 631 * DESCRIPTION: 632 * Registers PKIX_CRL_TYPE and its related functions with systemClasses[] 633 * THREAD SAFETY: 634 * 635 * Not Thread Safe - for performance and complexity reasons 636 * 637 * Since this function is only called by PKIX_PL_Initialize, which should 638 * only be called once, it is acceptable that this function is not 639 * thread-safe. 640 */ 641 PKIX_Error * 642 pkix_pl_CRL_RegisterSelf(void *plContext) 643 { 644 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; 645 pkix_ClassTable_Entry *entry = &systemClasses[PKIX_CRL_TYPE]; 646 647 PKIX_ENTER(CRL, "pkix_pl_CRL_RegisterSelf"); 648 649 entry->description = "CRL"; 650 entry->typeObjectSize = sizeof(PKIX_PL_CRL); 651 entry->destructor = pkix_pl_CRL_Destroy; 652 entry->equalsFunction = pkix_pl_CRL_Equals; 653 entry->hashcodeFunction = pkix_pl_CRL_Hashcode; 654 entry->toStringFunction = pkix_pl_CRL_ToString; 655 entry->duplicateFunction = pkix_duplicateImmutable; 656 657 PKIX_RETURN(CRL); 658 } 659 660 /* 661 * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime (see comments in pkix_pl_pki.h) 662 */ 663 PKIX_Error * 664 PKIX_PL_CRL_VerifyUpdateTime( 665 PKIX_PL_CRL *crl, 666 PKIX_PL_Date *date, 667 PKIX_Boolean *pResult, 668 void *plContext) 669 { 670 PRTime timeToCheck; 671 PRTime nextUpdate; 672 PRTime lastUpdate; 673 SECStatus status; 674 CERTCrl *nssCrl = NULL; 675 SECItem *nextUpdateDer = NULL; 676 PKIX_Boolean haveNextUpdate = PR_FALSE; 677 678 PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifyUpdateTime"); 679 PKIX_NULLCHECK_FOUR(crl, crl->nssSignedCrl, date, pResult); 680 681 /* Can call this function only with der been adopted. */ 682 PORT_Assert(crl->adoptedDerCrl); 683 684 nssCrl = &(crl->nssSignedCrl->crl); 685 timeToCheck = date->nssTime; 686 687 /* nextUpdate can be NULL. Checking before using it */ 688 nextUpdateDer = &nssCrl->nextUpdate; 689 if (nextUpdateDer->data && nextUpdateDer->len) { 690 haveNextUpdate = PR_TRUE; 691 status = DER_DecodeTimeChoice(&nextUpdate, nextUpdateDer); 692 if (status != SECSuccess) { 693 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORNEXTUPDATEFAILED); 694 } 695 } 696 697 status = DER_DecodeTimeChoice(&lastUpdate, &(nssCrl->lastUpdate)); 698 if (status != SECSuccess) { 699 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORLASTUPDATEFAILED); 700 } 701 702 if (!haveNextUpdate || nextUpdate < timeToCheck) { 703 *pResult = PKIX_FALSE; 704 goto cleanup; 705 } 706 707 if (lastUpdate <= timeToCheck) { 708 *pResult = PKIX_TRUE; 709 } else { 710 *pResult = PKIX_FALSE; 711 } 712 713 cleanup: 714 715 PKIX_RETURN(CRL); 716 } 717 718 /* 719 * FUNCTION: pkix_pl_CRL_CreateWithSignedCRL 720 * DESCRIPTION: 721 * 722 * Creates a new CRL using the CERTSignedCrl pointed to by "nssSignedCrl" 723 * and stores it at "pCRL". If the decoding of the CERTSignedCrl fails, 724 * a PKIX_Error is returned. 725 * 726 * PARAMETERS: 727 * "nssSignedCrl" 728 * Address of CERTSignedCrl. Must be non-NULL. 729 * "adoptedDerCrl" 730 * SECItem ponter that if not NULL is indicating that memory used 731 * for der should be adopted by crl that is about to be created. 732 * "pCRL" 733 * Address where object pointer will be stored. Must be non-NULL. 734 * "plContext" 735 * Platform-specific context pointer. 736 * THREAD SAFETY: 737 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 738 * RETURNS: 739 * Returns NULL if the function succeeds. 740 * Returns a CRL Error if the function fails in a non-fatal way. 741 * Returns a Fatal Error if the function fails in an unrecoverable way. 742 */ 743 PKIX_Error * 744 pkix_pl_CRL_CreateWithSignedCRL( 745 CERTSignedCrl *nssSignedCrl, 746 SECItem *adoptedDerCrl, 747 SECItem *derGenName, 748 PKIX_PL_CRL **pCrl, 749 void *plContext) 750 { 751 PKIX_PL_CRL *crl = NULL; 752 753 PKIX_ENTER(CRL, "pkix_pl_CRL_CreateWithSignedCRL"); 754 PKIX_NULLCHECK_ONE(pCrl); 755 756 /* create a PKIX_PL_CRL object */ 757 PKIX_CHECK(PKIX_PL_Object_Alloc 758 (PKIX_CRL_TYPE, 759 sizeof (PKIX_PL_CRL), 760 (PKIX_PL_Object **)&crl, 761 plContext), 762 PKIX_COULDNOTCREATECRLOBJECT); 763 764 /* populate the nssSignedCrl field */ 765 crl->nssSignedCrl = nssSignedCrl; 766 crl->adoptedDerCrl = adoptedDerCrl; 767 crl->issuer = NULL; 768 crl->signatureAlgId = NULL; 769 crl->crlNumber = NULL; 770 crl->crlNumberAbsent = PKIX_FALSE; 771 crl->crlEntryList = NULL; 772 crl->critExtOids = NULL; 773 if (derGenName) { 774 crl->derGenName = 775 SECITEM_DupItem(derGenName); 776 if (!crl->derGenName) { 777 PKIX_ERROR(PKIX_ALLOCERROR); 778 } 779 } 780 781 *pCrl = crl; 782 783 cleanup: 784 785 if (PKIX_ERROR_RECEIVED){ 786 PKIX_DECREF(crl); 787 } 788 789 PKIX_RETURN(CRL); 790 } 791 792 /* --Public-CRL-Functions------------------------------------- */ 793 794 /* 795 * FUNCTION: PKIX_PL_CRL_Create (see comments in pkix_pl_pki.h) 796 */ 797 PKIX_Error * 798 PKIX_PL_CRL_Create( 799 PKIX_PL_ByteArray *byteArray, 800 PKIX_PL_CRL **pCrl, 801 void *plContext) 802 { 803 CERTSignedCrl *nssSignedCrl = NULL; 804 SECItem derItem, *derCrl = NULL; 805 PKIX_PL_CRL *crl = NULL; 806 807 PKIX_ENTER(CRL, "PKIX_PL_CRL_Create"); 808 PKIX_NULLCHECK_TWO(byteArray, pCrl); 809 810 if (byteArray->length == 0){ 811 PKIX_ERROR(PKIX_ZEROLENGTHBYTEARRAYFORCRLENCODING); 812 } 813 derItem.type = siBuffer; 814 derItem.data = byteArray->array; 815 derItem.len = byteArray->length; 816 derCrl = SECITEM_DupItem(&derItem); 817 if (!derCrl) { 818 PKIX_ERROR(PKIX_ALLOCERROR); 819 } 820 nssSignedCrl = 821 CERT_DecodeDERCrlWithFlags(NULL, derCrl, SEC_CRL_TYPE, 822 CRL_DECODE_DONT_COPY_DER | 823 CRL_DECODE_SKIP_ENTRIES); 824 if (!nssSignedCrl) { 825 PKIX_ERROR(PKIX_CERTDECODEDERCRLFAILED); 826 } 827 PKIX_CHECK( 828 pkix_pl_CRL_CreateWithSignedCRL(nssSignedCrl, derCrl, NULL, 829 &crl, plContext), 830 PKIX_CRLCREATEWITHSIGNEDCRLFAILED); 831 nssSignedCrl = NULL; 832 derCrl = NULL; 833 *pCrl = crl; 834 835 cleanup: 836 if (derCrl) { 837 SECITEM_FreeItem(derCrl, PR_TRUE); 838 } 839 if (nssSignedCrl) { 840 SEC_DestroyCrl(nssSignedCrl); 841 } 842 843 PKIX_RETURN(CRL); 844 } 845 846 /* 847 * FUNCTION: PKIX_PL_CRL_GetIssuer (see comments in pkix_pl_pki.h) 848 */ 849 PKIX_Error * 850 PKIX_PL_CRL_GetIssuer( 851 PKIX_PL_CRL *crl, 852 PKIX_PL_X500Name **pCRLIssuer, 853 void *plContext) 854 { 855 PKIX_PL_String *crlString = NULL; 856 PKIX_PL_X500Name *issuer = NULL; 857 SECItem *derIssuerName = NULL; 858 CERTName *issuerName = NULL; 859 860 PKIX_ENTER(CRL, "PKIX_PL_CRL_GetIssuer"); 861 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCRLIssuer); 862 863 /* Can call this function only with der been adopted. */ 864 PORT_Assert(crl->adoptedDerCrl); 865 866 /* if we don't have a cached copy from before, we create one */ 867 if (crl->issuer == NULL){ 868 869 PKIX_OBJECT_LOCK(crl); 870 871 if (crl->issuer == NULL) { 872 873 issuerName = &crl->nssSignedCrl->crl.name; 874 derIssuerName = &crl->nssSignedCrl->crl.derName; 875 876 PKIX_CHECK( 877 PKIX_PL_X500Name_CreateFromCERTName(derIssuerName, 878 issuerName, 879 &issuer, 880 plContext), 881 PKIX_X500NAMECREATEFROMCERTNAMEFAILED); 882 883 /* save a cached copy in case it is asked for again */ 884 crl->issuer = issuer; 885 } 886 887 PKIX_OBJECT_UNLOCK(crl); 888 889 } 890 891 PKIX_INCREF(crl->issuer); 892 893 *pCRLIssuer = crl->issuer; 894 895 cleanup: 896 897 PKIX_DECREF(crlString); 898 899 PKIX_RETURN(CRL); 900 } 901 902 903 /* 904 * FUNCTION: PKIX_PL_CRL_GetCriticalExtensionOIDs 905 * (see comments in pkix_pl_pki.h) 906 */ 907 PKIX_Error * 908 PKIX_PL_CRL_GetCriticalExtensionOIDs( 909 PKIX_PL_CRL *crl, 910 PKIX_List **pExtensions, /* list of PKIX_PL_OID */ 911 void *plContext) 912 { 913 PKIX_List *oidsList = NULL; 914 CERTCertExtension **extensions = NULL; 915 CERTCrl *nssSignedCrl = NULL; 916 917 PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCriticalExtensionOIDs"); 918 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pExtensions); 919 920 /* Can call this function only with der been adopted. */ 921 PORT_Assert(crl->adoptedDerCrl); 922 923 /* if we don't have a cached copy from before, we create one */ 924 if (crl->critExtOids == NULL) { 925 926 PKIX_OBJECT_LOCK(crl); 927 928 nssSignedCrl = &(crl->nssSignedCrl->crl); 929 extensions = nssSignedCrl->extensions; 930 931 if (crl->critExtOids == NULL) { 932 933 PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs 934 (extensions, &oidsList, plContext), 935 PKIX_GETCRITICALEXTENSIONOIDSFAILED); 936 937 crl->critExtOids = oidsList; 938 } 939 940 PKIX_OBJECT_UNLOCK(crl); 941 942 } 943 944 /* We should return a copy of the List since this list changes */ 945 PKIX_DUPLICATE(crl->critExtOids, pExtensions, plContext, 946 PKIX_OBJECTDUPLICATELISTFAILED); 947 948 cleanup: 949 950 PKIX_RETURN(CRL); 951 } 952 953 /* 954 * FUNCTION: PKIX_PL_CRL_VerifySignature (see comments in pkix_pl_pki.h) 955 */ 956 PKIX_Error * 957 PKIX_PL_CRL_VerifySignature( 958 PKIX_PL_CRL *crl, 959 PKIX_PL_PublicKey *pubKey, 960 void *plContext) 961 { 962 PKIX_PL_CRL *cachedCrl = NULL; 963 PKIX_Error *verifySig = NULL; 964 PKIX_Error *cachedSig = NULL; 965 PKIX_Boolean crlEqual = PKIX_FALSE; 966 PKIX_Boolean crlInHash= PKIX_FALSE; 967 CERTSignedCrl *nssSignedCrl = NULL; 968 SECKEYPublicKey *nssPubKey = NULL; 969 CERTSignedData *tbsCrl = NULL; 970 void* wincx = NULL; 971 SECStatus status; 972 973 PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifySignature"); 974 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pubKey); 975 976 /* Can call this function only with der been adopted. */ 977 PORT_Assert(crl->adoptedDerCrl); 978 979 verifySig = PKIX_PL_HashTable_Lookup 980 (cachedCrlSigTable, 981 (PKIX_PL_Object *) pubKey, 982 (PKIX_PL_Object **) &cachedCrl, 983 plContext); 984 985 if (cachedCrl != NULL && verifySig == NULL) { 986 /* Cached Signature Table lookup succeed */ 987 PKIX_EQUALS(crl, cachedCrl, &crlEqual, plContext, 988 PKIX_OBJECTEQUALSFAILED); 989 if (crlEqual == PKIX_TRUE) { 990 goto cleanup; 991 } 992 /* Different PubKey may hash to same value, skip add */ 993 crlInHash = PKIX_TRUE; 994 } 995 996 nssSignedCrl = crl->nssSignedCrl; 997 tbsCrl = &nssSignedCrl->signatureWrap; 998 999 PKIX_CRL_DEBUG("\t\tCalling SECKEY_ExtractPublicKey\n"); 1000 nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI); 1001 if (!nssPubKey){ 1002 PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED); 1003 } 1004 1005 PKIX_CHECK(pkix_pl_NssContext_GetWincx 1006 ((PKIX_PL_NssContext *)plContext, &wincx), 1007 PKIX_NSSCONTEXTGETWINCXFAILED); 1008 1009 PKIX_CRL_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey\n"); 1010 status = CERT_VerifySignedDataWithPublicKey(tbsCrl, nssPubKey, wincx); 1011 1012 if (status != SECSuccess) { 1013 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 1014 PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY); 1015 } 1016 1017 if (crlInHash == PKIX_FALSE) { 1018 cachedSig = PKIX_PL_HashTable_Add 1019 (cachedCrlSigTable, 1020 (PKIX_PL_Object *) pubKey, 1021 (PKIX_PL_Object *) crl, 1022 plContext); 1023 1024 if (cachedSig != NULL) { 1025 PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n"); 1026 } 1027 } 1028 1029 cleanup: 1030 1031 if (nssPubKey){ 1032 PKIX_CRL_DEBUG("\t\tCalling SECKEY_DestroyPublicKey\n"); 1033 SECKEY_DestroyPublicKey(nssPubKey); 1034 nssPubKey = NULL; 1035 } 1036 1037 PKIX_DECREF(cachedCrl); 1038 PKIX_DECREF(verifySig); 1039 PKIX_DECREF(cachedSig); 1040 1041 PKIX_RETURN(CRL); 1042 } 1043 1044 PKIX_Error* 1045 PKIX_PL_CRL_ReleaseDerCrl(PKIX_PL_CRL *crl, 1046 SECItem **derCrl, 1047 void *plContext) 1048 { 1049 PKIX_ENTER(CRL, "PKIX_PL_CRL_ReleaseDerCrl"); 1050 *derCrl = crl->adoptedDerCrl; 1051 crl->adoptedDerCrl = NULL; 1052 1053 PKIX_RETURN(CRL); 1054 } 1055 1056 PKIX_Error* 1057 PKIX_PL_CRL_AdoptDerCrl(PKIX_PL_CRL *crl, 1058 SECItem *derCrl, 1059 void *plContext) 1060 { 1061 PKIX_ENTER(CRL, "PKIX_PL_CRL_AquireDerCrl"); 1062 if (crl->adoptedDerCrl) { 1063 PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER); 1064 } 1065 crl->adoptedDerCrl = derCrl; 1066 cleanup: 1067 PKIX_RETURN(CRL); 1068 }