pkix_tools.c (51404B)
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_tools.c 6 * 7 * Private Utility Functions 8 * 9 */ 10 11 #include "pkix_tools.h" 12 13 #define CACHE_ITEM_PERIOD_SECONDS (3600) /* one hour */ 14 15 /* 16 * This cahce period is only for CertCache. A Cert from a trusted CertStore 17 * should be checked more frequently for update new arrival, etc. 18 */ 19 #define CACHE_TRUST_ITEM_PERIOD_SECONDS (CACHE_ITEM_PERIOD_SECONDS/10) 20 21 extern PKIX_PL_HashTable *cachedCertChainTable; 22 extern PKIX_PL_HashTable *cachedCertTable; 23 extern PKIX_PL_HashTable *cachedCrlEntryTable; 24 25 /* Following variables are used to checked cache hits - can be taken out */ 26 extern int pkix_ccAddCount; 27 extern int pkix_ccLookupCount; 28 extern int pkix_ccRemoveCount; 29 extern int pkix_cAddCount; 30 extern int pkix_cLookupCount; 31 extern int pkix_cRemoveCount; 32 extern int pkix_ceAddCount; 33 extern int pkix_ceLookupCount; 34 35 #ifdef PKIX_OBJECT_LEAK_TEST 36 /* Following variables are used for object leak test */ 37 char *nonNullValue = "Non Empty Value"; 38 PKIX_Boolean noErrorState = PKIX_TRUE; 39 PKIX_Boolean runningLeakTest; 40 PKIX_Boolean errorGenerated; 41 PKIX_UInt32 stackPosition; 42 PKIX_UInt32 *fnStackInvCountArr; 43 char **fnStackNameArr; 44 PLHashTable *fnInvTable; 45 PKIX_UInt32 testStartFnStackPosition; 46 char *errorFnStackString; 47 #endif /* PKIX_OBJECT_LEAK_TEST */ 48 49 /* --Private-Functions-------------------------------------------- */ 50 51 #ifdef PKIX_OBJECT_LEAK_TEST 52 /* 53 * FUNCTION: pkix_ErrorGen_Hash 54 * DESCRIPTION: 55 * 56 * Hash function to be used in object leak test hash table. 57 * 58 */ 59 PLHashNumber PR_CALLBACK 60 pkix_ErrorGen_Hash (const void *key) 61 { 62 char *str = NULL; 63 PLHashNumber rv = (*(PRUint8*)key) << 5; 64 PRUint32 i, counter = 0; 65 PRUint8 *rvc = (PRUint8 *)&rv; 66 67 while ((str = fnStackNameArr[counter++]) != NULL) { 68 PRUint32 len = strlen(str); 69 for( i = 0; i < len; i++ ) { 70 rvc[ i % sizeof(rv) ] ^= *str; 71 str++; 72 } 73 } 74 75 return rv; 76 } 77 78 #endif /* PKIX_OBJECT_LEAK_TEST */ 79 80 /* 81 * FUNCTION: pkix_IsCertSelfIssued 82 * DESCRIPTION: 83 * 84 * Checks whether the Cert pointed to by "cert" is self-issued and stores the 85 * Boolean result at "pSelfIssued". A Cert is considered self-issued if the 86 * Cert's issuer matches the Cert's subject. If the subject or issuer is 87 * not specified, a PKIX_FALSE is returned. 88 * 89 * PARAMETERS: 90 * "cert" 91 * Address of Cert used to determine whether Cert is self-issued. 92 * Must be non-NULL. 93 * "pSelfIssued" 94 * Address where Boolean will be stored. Must be non-NULL. 95 * "plContext" 96 * Platform-specific context pointer. 97 * THREAD SAFETY: 98 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 99 * RETURNS: 100 * Returns NULL if the function succeeds. 101 * Returns a Cert Error if the function fails in a non-fatal way. 102 * Returns a Fatal Error if the function fails in an unrecoverable way. 103 */ 104 PKIX_Error * 105 pkix_IsCertSelfIssued( 106 PKIX_PL_Cert *cert, 107 PKIX_Boolean *pSelfIssued, 108 void *plContext) 109 { 110 PKIX_PL_X500Name *subject = NULL; 111 PKIX_PL_X500Name *issuer = NULL; 112 113 PKIX_ENTER(CERT, "pkix_IsCertSelfIssued"); 114 PKIX_NULLCHECK_TWO(cert, pSelfIssued); 115 116 PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &subject, plContext), 117 PKIX_CERTGETSUBJECTFAILED); 118 119 PKIX_CHECK(PKIX_PL_Cert_GetIssuer(cert, &issuer, plContext), 120 PKIX_CERTGETISSUERFAILED); 121 122 if (subject == NULL || issuer == NULL) { 123 *pSelfIssued = PKIX_FALSE; 124 } else { 125 126 PKIX_CHECK(PKIX_PL_X500Name_Match 127 (subject, issuer, pSelfIssued, plContext), 128 PKIX_X500NAMEMATCHFAILED); 129 } 130 131 cleanup: 132 PKIX_DECREF(subject); 133 PKIX_DECREF(issuer); 134 135 PKIX_RETURN(CERT); 136 } 137 138 /* 139 * FUNCTION: pkix_Throw 140 * DESCRIPTION: 141 * 142 * Creates an Error using the value of "errorCode", the character array 143 * pointed to by "funcName", the character array pointed to by "errorText", 144 * and the Error pointed to by "cause" (if any), and stores it at "pError". 145 * 146 * If "cause" is not NULL and has an errorCode of "PKIX_FATAL_ERROR", 147 * then there is no point creating a new Error object. Rather, we simply 148 * store "cause" at "pError". 149 * 150 * PARAMETERS: 151 * "errorCode" 152 * Value of error code. 153 * "funcName" 154 * Address of EscASCII array representing name of function throwing error. 155 * Must be non-NULL. 156 * "errnum" 157 * PKIX_ERRMSGNUM of error description for new error. 158 * "cause" 159 * Address of Error representing error's cause. 160 * "pError" 161 * Address where object pointer will be stored. Must be non-NULL. 162 * "plContext" 163 * Platform-specific context pointer. 164 * THREAD SAFETY: 165 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 166 * RETURNS: 167 * Returns NULL if the function succeeds. 168 * Returns an Error Error if the function fails in a non-fatal way. 169 * Returns a Fatal Error if the function fails in an unrecoverable way. 170 */ 171 PKIX_Error * 172 pkix_Throw( 173 PKIX_ERRORCLASS errorClass, 174 const char *funcName, 175 PKIX_ERRORCODE errorCode, 176 PKIX_ERRORCLASS overrideClass, 177 PKIX_Error *cause, 178 PKIX_Error **pError, 179 void *plContext) 180 { 181 PKIX_Error *error = NULL; 182 183 PKIX_ENTER(ERROR, "pkix_Throw"); 184 PKIX_NULLCHECK_TWO(funcName, pError); 185 186 *pError = NULL; 187 188 #ifdef PKIX_OBJECT_LEAK_TEST 189 noErrorState = PKIX_TRUE; 190 if (pkixLog) { 191 #ifdef PKIX_ERROR_DESCRIPTION 192 PR_LOG(pkixLog, 4, ("Error in function \"%s\":\"%s\" with cause \"%s\"\n", 193 funcName, PKIX_ErrorText[errorCode], 194 (cause ? PKIX_ErrorText[cause->errCode] : "null"))); 195 #else 196 PR_LOG(pkixLog, 4, ("Error in function \"%s\": error code \"%d\"\n", 197 funcName, errorCode)); 198 #endif /* PKIX_ERROR_DESCRIPTION */ 199 PORT_Assert(strcmp(funcName, "PKIX_PL_Object_DecRef")); 200 } 201 #endif /* PKIX_OBJECT_LEAK_TEST */ 202 203 /* if cause has error class of PKIX_FATAL_ERROR, return immediately */ 204 if (cause) { 205 if (cause->errClass == PKIX_FATAL_ERROR){ 206 PKIX_INCREF(cause); 207 *pError = cause; 208 goto cleanup; 209 } 210 } 211 212 if (overrideClass == PKIX_FATAL_ERROR){ 213 errorClass = overrideClass; 214 } 215 216 pkixTempResult = PKIX_Error_Create(errorClass, cause, NULL, 217 errorCode, &error, plContext); 218 219 if (!pkixTempResult) { 220 /* Setting plErr error code: 221 * get it from PORT_GetError if it is a leaf error and 222 * default error code does not exist(eq 0) */ 223 if (!cause && !error->plErr) { 224 error->plErr = PKIX_PL_GetPLErrorCode(); 225 } 226 } 227 228 *pError = error; 229 230 cleanup: 231 232 PKIX_DEBUG_EXIT(ERROR); 233 pkixErrorClass = 0; 234 #ifdef PKIX_OBJECT_LEAK_TEST 235 noErrorState = PKIX_FALSE; 236 237 if (runningLeakTest && fnStackNameArr) { 238 PR_LOG(pkixLog, 5, 239 ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), 240 stackPosition, " ", fnStackNameArr[stackPosition], 241 stackPosition, myFuncName)); 242 fnStackNameArr[stackPosition--] = NULL; 243 } 244 #endif /* PKIX_OBJECT_LEAK_TEST */ 245 return (pkixTempResult); 246 } 247 248 /* 249 * FUNCTION: pkix_CheckTypes 250 * DESCRIPTION: 251 * 252 * Checks that the types of the Object pointed to by "first" and the Object 253 * pointed to by "second" are both equal to the value of "type". If they 254 * are not equal, a PKIX_Error is returned. 255 * 256 * PARAMETERS: 257 * "first" 258 * Address of first Object. Must be non-NULL. 259 * "second" 260 * Address of second Object. Must be non-NULL. 261 * "type" 262 * Value of type to check against. 263 * "plContext" 264 * Platform-specific context pointer. 265 * THREAD SAFETY: 266 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 267 * RETURNS: 268 * Returns NULL if the function succeeds. 269 * Returns an Error Error if the function fails in a non-fatal way. 270 * Returns a Fatal Error if the function fails in an unrecoverable way. 271 */ 272 PKIX_Error * 273 pkix_CheckTypes( 274 PKIX_PL_Object *first, 275 PKIX_PL_Object *second, 276 PKIX_UInt32 type, 277 void *plContext) 278 { 279 PKIX_UInt32 firstType, secondType; 280 281 PKIX_ENTER(OBJECT, "pkix_CheckTypes"); 282 PKIX_NULLCHECK_TWO(first, second); 283 284 PKIX_CHECK(PKIX_PL_Object_GetType(first, &firstType, plContext), 285 PKIX_COULDNOTGETFIRSTOBJECTTYPE); 286 287 PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), 288 PKIX_COULDNOTGETSECONDOBJECTTYPE); 289 290 if ((firstType != type)||(firstType != secondType)) { 291 PKIX_ERROR(PKIX_OBJECTTYPESDONOTMATCH); 292 } 293 294 cleanup: 295 296 PKIX_RETURN(OBJECT); 297 } 298 299 /* 300 * FUNCTION: pkix_CheckType 301 * DESCRIPTION: 302 * 303 * Checks that the type of the Object pointed to by "object" is equal to the 304 * value of "type". If it is not equal, a PKIX_Error is returned. 305 * 306 * PARAMETERS: 307 * "object" 308 * Address of Object. Must be non-NULL. 309 * "type" 310 * Value of type to check against. 311 * "plContext" 312 * Platform-specific context pointer. 313 * THREAD SAFETY: 314 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 315 * RETURNS: 316 * Returns NULL if the function succeeds. 317 * Returns an Error Error if the function fails in a non-fatal way. 318 * Returns a Fatal Error if the function fails in an unrecoverable way. 319 */ 320 PKIX_Error * 321 pkix_CheckType( 322 PKIX_PL_Object *object, 323 PKIX_UInt32 type, 324 void *plContext) 325 { 326 return (pkix_CheckTypes(object, object, type, plContext)); 327 } 328 329 /* 330 * FUNCTION: pkix_hash 331 * DESCRIPTION: 332 * 333 * Computes a hash value for "length" bytes starting at the array of bytes 334 * pointed to by "bytes" and stores the result at "pHash". 335 * 336 * XXX To speed this up, we could probably read 32 bits at a time from 337 * bytes (maybe even 64 bits on some platforms) 338 * 339 * PARAMETERS: 340 * "bytes" 341 * Address of array of bytes to hash. Must be non-NULL. 342 * "length" 343 * Number of bytes to hash. 344 * "pHash" 345 * Address where object pointer will be stored. Must be non-NULL. 346 * "plContext" 347 * Platform-specific context pointer. 348 * THREAD SAFETY: 349 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 350 * RETURNS: 351 * Returns NULL if the function succeeds. 352 * Returns a Fatal Error if the function fails in an unrecoverable way. 353 */ 354 PKIX_Error * 355 pkix_hash( 356 const unsigned char *bytes, 357 PKIX_UInt32 length, 358 PKIX_UInt32 *pHash, 359 void *plContext) 360 { 361 PKIX_UInt32 i; 362 PKIX_UInt32 hash; 363 364 PKIX_ENTER(OBJECT, "pkix_hash"); 365 if (length != 0) { 366 PKIX_NULLCHECK_ONE(bytes); 367 } 368 PKIX_NULLCHECK_ONE(pHash); 369 370 hash = 0; 371 for (i = 0; i < length; i++) { 372 /* hash = 31 * hash + bytes[i]; */ 373 hash = (hash << 5) - hash + bytes[i]; 374 } 375 376 *pHash = hash; 377 378 PKIX_RETURN(OBJECT); 379 } 380 381 /* 382 * FUNCTION: pkix_countArray 383 * DESCRIPTION: 384 * 385 * Counts the number of elements in the null-terminated array of pointers 386 * pointed to by "array" and returns the result. 387 * 388 * PARAMETERS 389 * "array" 390 * Address of null-terminated array of pointers. 391 * THREAD SAFETY: 392 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 393 * RETURNS: 394 * Returns the number of elements in the array. 395 */ 396 PKIX_UInt32 397 pkix_countArray(void **array) 398 { 399 PKIX_UInt32 count = 0; 400 401 if (array) { 402 while (*array++) { 403 count++; 404 } 405 } 406 return (count); 407 } 408 409 /* 410 * FUNCTION: pkix_duplicateImmutable 411 * DESCRIPTION: 412 * 413 * Convenience callback function used for duplicating immutable objects. 414 * Since the objects can not be modified, this function simply increments the 415 * reference count on the object, and returns a reference to that object. 416 * 417 * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) 418 */ 419 PKIX_Error * 420 pkix_duplicateImmutable( 421 PKIX_PL_Object *object, 422 PKIX_PL_Object **pNewObject, 423 void *plContext) 424 { 425 PKIX_ENTER(OBJECT, "pkix_duplicateImmutable"); 426 PKIX_NULLCHECK_TWO(object, pNewObject); 427 428 PKIX_INCREF(object); 429 430 *pNewObject = object; 431 432 cleanup: 433 PKIX_RETURN(OBJECT); 434 } 435 436 /* --String-Encoding-Conversion-Functions------------------------ */ 437 438 /* 439 * FUNCTION: pkix_hex2i 440 * DESCRIPTION: 441 * 442 * Converts hexadecimal character "c" to its integer value and returns result. 443 * 444 * PARAMETERS 445 * "c" 446 * Character to convert to a hex value. 447 * THREAD SAFETY: 448 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 449 * RETURNS: 450 * The hexadecimal value of "c". Otherwise -1. (Unsigned 0xFFFFFFFF). 451 */ 452 PKIX_UInt32 453 pkix_hex2i(char c) 454 { 455 if ((c >= '0')&&(c <= '9')) 456 return (c-'0'); 457 else if ((c >= 'a')&&(c <= 'f')) 458 return (c-'a'+10); 459 else if ((c >= 'A')&&(c <= 'F')) 460 return (c-'A'+10); 461 else 462 return ((PKIX_UInt32)(-1)); 463 } 464 465 /* 466 * FUNCTION: pkix_i2hex 467 * DESCRIPTION: 468 * 469 * Converts integer value "digit" to its ASCII hex value 470 * 471 * PARAMETERS 472 * "digit" 473 * Value of integer to convert to ASCII hex value. Must be 0-15. 474 * THREAD SAFETY: 475 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 476 * RETURNS: 477 * The ASCII hexadecimal value of "digit". 478 */ 479 char 480 pkix_i2hex(char digit) 481 { 482 if ((digit >= 0)&&(digit <= 9)) 483 return (digit+'0'); 484 else if ((digit >= 0xa)&&(digit <= 0xf)) 485 return (digit - 10 + 'a'); 486 else 487 return (-1); 488 } 489 490 /* 491 * FUNCTION: pkix_isPlaintext 492 * DESCRIPTION: 493 * 494 * Returns whether character "c" is plaintext using EscASCII or EscASCII_Debug 495 * depending on the value of "debug". 496 * 497 * In EscASCII, [01, 7E] except '&' are plaintext. 498 * In EscASCII_Debug [20, 7E] except '&' are plaintext. 499 * 500 * PARAMETERS: 501 * "c" 502 * Character to check. 503 * "debug" 504 * Value of debug flag. 505 * THREAD SAFETY: 506 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 507 * RETURNS: 508 * True if "c" is plaintext. 509 */ 510 PKIX_Boolean 511 pkix_isPlaintext(unsigned char c, PKIX_Boolean debug) { 512 return ((c >= 0x01)&&(c <= 0x7E)&&(c != '&')&&(!debug || (c >= 20))); 513 } 514 515 /* --Cache-Functions------------------------ */ 516 517 /* 518 * FUNCTION: pkix_CacheCertChain_Lookup 519 * DESCRIPTION: 520 * 521 * Look up CertChain Hash Table for a cached BuildResult based on "targetCert" 522 * and "anchors" as the hash keys. If there is no item to match the key, 523 * PKIX_FALSE is stored at "pFound". If an item is found, its cache time is 524 * compared to "testDate". If expired, the item is removed and PKIX_FALSE is 525 * stored at "pFound". Otherwise, PKIX_TRUE is stored at "pFound" and the 526 * BuildResult is stored at "pBuildResult". 527 * The hashtable is maintained in the following ways: 528 * 1) When creating the hashtable, maximum bucket size can be specified (0 for 529 * unlimited). If items in a bucket reaches its full size, an new addition 530 * will trigger the removal of the old as FIFO sequence. 531 * 2) A PKIX_PL_Date created with current time offset by constant 532 * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. 533 * When an item is retrieved, this date is compared against "testDate" for 534 * validity. If comparison indicates this item is expired, the item is 535 * removed from the bucket. 536 * 537 * PARAMETERS: 538 * "targetCert" 539 * Address of Target Cert as key to retrieve this CertChain. Must be 540 * non-NULL. 541 * "anchors" 542 * Address of PKIX_List of "anchors" is used as key to retrive CertChain. 543 * Must be non-NULL. 544 * "testDate" 545 * Address of PKIX_PL_Date for verifying time validity and cache validity. 546 * May be NULL. If testDate is NULL, this cache item will not be out-dated. 547 * "pFound" 548 * Address of PKIX_Boolean indicating valid data is found. 549 * Must be non-NULL. 550 * "pBuildResult" 551 * Address where BuildResult will be stored. Must be non-NULL. 552 * "plContext" 553 * Platform-specific context pointer. 554 * THREAD SAFETY: 555 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 556 * RETURNS: 557 * Returns NULL if the function succeeds. 558 * Returns an Error Error if the function fails in a non-fatal way. 559 * Returns a Fatal Error if the function fails in an unrecoverable way. 560 */ 561 PKIX_Error * 562 pkix_CacheCertChain_Lookup( 563 PKIX_PL_Cert* targetCert, 564 PKIX_List* anchors, 565 PKIX_PL_Date *testDate, 566 PKIX_Boolean *pFound, 567 PKIX_BuildResult **pBuildResult, 568 void *plContext) 569 { 570 PKIX_List *cachedValues = NULL; 571 PKIX_List *cachedKeys = NULL; 572 PKIX_Error *cachedCertChainError = NULL; 573 PKIX_PL_Date *cacheValidUntilDate = NULL; 574 PKIX_PL_Date *validityDate = NULL; 575 PKIX_Int32 cmpValidTimeResult = 0; 576 PKIX_Int32 cmpCacheTimeResult = 0; 577 578 PKIX_ENTER(BUILD, "pkix_CacheCertChain_Lookup"); 579 580 PKIX_NULLCHECK_FOUR(targetCert, anchors, pFound, pBuildResult); 581 582 *pFound = PKIX_FALSE; 583 584 /* use trust anchors and target cert as hash key */ 585 586 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), 587 PKIX_LISTCREATEFAILED); 588 589 PKIX_CHECK(PKIX_List_AppendItem 590 (cachedKeys, 591 (PKIX_PL_Object *)targetCert, 592 plContext), 593 PKIX_LISTAPPENDITEMFAILED); 594 595 PKIX_CHECK(PKIX_List_AppendItem 596 (cachedKeys, 597 (PKIX_PL_Object *)anchors, 598 plContext), 599 PKIX_LISTAPPENDITEMFAILED); 600 601 cachedCertChainError = PKIX_PL_HashTable_Lookup 602 (cachedCertChainTable, 603 (PKIX_PL_Object *) cachedKeys, 604 (PKIX_PL_Object **) &cachedValues, 605 plContext); 606 607 pkix_ccLookupCount++; 608 609 /* retrieve data from hashed value list */ 610 611 if (cachedValues != NULL && cachedCertChainError == NULL) { 612 613 PKIX_CHECK(PKIX_List_GetItem 614 (cachedValues, 615 0, 616 (PKIX_PL_Object **) &cacheValidUntilDate, 617 plContext), 618 PKIX_LISTGETITEMFAILED); 619 620 /* check validity time and cache age time */ 621 PKIX_CHECK(PKIX_List_GetItem 622 (cachedValues, 623 1, 624 (PKIX_PL_Object **) &validityDate, 625 plContext), 626 PKIX_LISTGETITEMFAILED); 627 628 /* if testDate is not set, this cache item is not out-dated */ 629 if (testDate) { 630 631 PKIX_CHECK(PKIX_PL_Object_Compare 632 ((PKIX_PL_Object *)testDate, 633 (PKIX_PL_Object *)cacheValidUntilDate, 634 &cmpCacheTimeResult, 635 plContext), 636 PKIX_OBJECTCOMPARATORFAILED); 637 638 PKIX_CHECK(PKIX_PL_Object_Compare 639 ((PKIX_PL_Object *)testDate, 640 (PKIX_PL_Object *)validityDate, 641 &cmpValidTimeResult, 642 plContext), 643 PKIX_OBJECTCOMPARATORFAILED); 644 } 645 646 /* certs' date are all valid and cache item is not old */ 647 if (cmpValidTimeResult <= 0 && cmpCacheTimeResult <=0) { 648 649 PKIX_CHECK(PKIX_List_GetItem 650 (cachedValues, 651 2, 652 (PKIX_PL_Object **) pBuildResult, 653 plContext), 654 PKIX_LISTGETITEMFAILED); 655 656 *pFound = PKIX_TRUE; 657 658 } else { 659 660 pkix_ccRemoveCount++; 661 *pFound = PKIX_FALSE; 662 663 /* out-dated item, remove it from cache */ 664 PKIX_CHECK(PKIX_PL_HashTable_Remove 665 (cachedCertChainTable, 666 (PKIX_PL_Object *) cachedKeys, 667 plContext), 668 PKIX_HASHTABLEREMOVEFAILED); 669 } 670 } 671 672 cleanup: 673 674 PKIX_DECREF(cachedValues); 675 PKIX_DECREF(cachedKeys); 676 PKIX_DECREF(cachedCertChainError); 677 PKIX_DECREF(cacheValidUntilDate); 678 PKIX_DECREF(validityDate); 679 680 PKIX_RETURN(BUILD); 681 682 } 683 684 /* 685 * FUNCTION: pkix_CacheCertChain_Remove 686 * DESCRIPTION: 687 * 688 * Remove CertChain Hash Table entry based on "targetCert" and "anchors" 689 * as the hash keys. If there is no item to match the key, no action is 690 * taken. 691 * The hashtable is maintained in the following ways: 692 * 1) When creating the hashtable, maximum bucket size can be specified (0 for 693 * unlimited). If items in a bucket reaches its full size, an new addition 694 * will trigger the removal of the old as FIFO sequence. 695 * 2) A PKIX_PL_Date created with current time offset by constant 696 * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. 697 * When an item is retrieved, this date is compared against "testDate" for 698 * validity. If comparison indicates this item is expired, the item is 699 * removed from the bucket. 700 * 701 * PARAMETERS: 702 * "targetCert" 703 * Address of Target Cert as key to retrieve this CertChain. Must be 704 * non-NULL. 705 * "anchors" 706 * Address of PKIX_List of "anchors" is used as key to retrive CertChain. 707 * Must be non-NULL. 708 * "plContext" 709 * Platform-specific context pointer. 710 * THREAD SAFETY: 711 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 712 * RETURNS: 713 * Returns NULL if the function succeeds. 714 * Returns an Error Error if the function fails in a non-fatal way. 715 * Returns a Fatal Error if the function fails in an unrecoverable way. 716 */ 717 PKIX_Error * 718 pkix_CacheCertChain_Remove( 719 PKIX_PL_Cert* targetCert, 720 PKIX_List* anchors, 721 void *plContext) 722 { 723 PKIX_List *cachedKeys = NULL; 724 725 PKIX_ENTER(BUILD, "pkix_CacheCertChain_Remove"); 726 PKIX_NULLCHECK_TWO(targetCert, anchors); 727 728 /* use trust anchors and target cert as hash key */ 729 730 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), 731 PKIX_LISTCREATEFAILED); 732 733 PKIX_CHECK(PKIX_List_AppendItem 734 (cachedKeys, 735 (PKIX_PL_Object *)targetCert, 736 plContext), 737 PKIX_LISTAPPENDITEMFAILED); 738 739 PKIX_CHECK(PKIX_List_AppendItem 740 (cachedKeys, 741 (PKIX_PL_Object *)anchors, 742 plContext), 743 PKIX_LISTAPPENDITEMFAILED); 744 745 PKIX_CHECK_ONLY_FATAL(PKIX_PL_HashTable_Remove 746 (cachedCertChainTable, 747 (PKIX_PL_Object *) cachedKeys, 748 plContext), 749 PKIX_HASHTABLEREMOVEFAILED); 750 751 pkix_ccRemoveCount++; 752 753 cleanup: 754 755 PKIX_DECREF(cachedKeys); 756 757 PKIX_RETURN(BUILD); 758 759 } 760 761 /* 762 * FUNCTION: pkix_CacheCertChain_Add 763 * DESCRIPTION: 764 * 765 * Add a BuildResult to the CertChain Hash Table for a "buildResult" with 766 * "targetCert" and "anchors" as the hash keys. 767 * "validityDate" is the most restricted notAfter date of all Certs in 768 * this CertChain and is verified when this BuildChain is retrieved. 769 * The hashtable is maintained in the following ways: 770 * 1) When creating the hashtable, maximum bucket size can be specified (0 for 771 * unlimited). If items in a bucket reaches its full size, an new addition 772 * will trigger the removal of the old as FIFO sequence. 773 * 2) A PKIX_PL_Date created with current time offset by constant 774 * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. 775 * When an item is retrieved, this date is compared against "testDate" for 776 * validity. If comparison indicates this item is expired, the item is 777 * removed from the bucket. 778 * 779 * PARAMETERS: 780 * "targetCert" 781 * Address of Target Cert as key to retrieve this CertChain. Must be 782 * non-NULL. 783 * "anchors" 784 * Address of PKIX_List of "anchors" is used as key to retrive CertChain. 785 * Must be non-NULL. 786 * "validityDate" 787 * Address of PKIX_PL_Date contains the most restriced notAfter time of 788 * all "certs". Must be non-NULL. 789 * Address of PKIX_Boolean indicating valid data is found. 790 * Must be non-NULL. 791 * "buildResult" 792 * Address of BuildResult to be cached. Must be non-NULL. 793 * "plContext" 794 * Platform-specific context pointer. 795 * THREAD SAFETY: 796 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 797 * RETURNS: 798 * Returns NULL if the function succeeds. 799 * Returns an Error Error if the function fails in a non-fatal way. 800 * Returns a Fatal Error if the function fails in an unrecoverable way. 801 */ 802 PKIX_Error * 803 pkix_CacheCertChain_Add( 804 PKIX_PL_Cert* targetCert, 805 PKIX_List* anchors, 806 PKIX_PL_Date *validityDate, 807 PKIX_BuildResult *buildResult, 808 void *plContext) 809 { 810 PKIX_List *cachedValues = NULL; 811 PKIX_List *cachedKeys = NULL; 812 PKIX_Error *cachedCertChainError = NULL; 813 PKIX_PL_Date *cacheValidUntilDate = NULL; 814 815 PKIX_ENTER(BUILD, "pkix_CacheCertChain_Add"); 816 817 PKIX_NULLCHECK_FOUR(targetCert, anchors, validityDate, buildResult); 818 819 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), 820 PKIX_LISTCREATEFAILED); 821 822 PKIX_CHECK(PKIX_List_AppendItem 823 (cachedKeys, (PKIX_PL_Object *)targetCert, plContext), 824 PKIX_LISTAPPENDITEMFAILED); 825 826 PKIX_CHECK(PKIX_List_AppendItem 827 (cachedKeys, (PKIX_PL_Object *)anchors, plContext), 828 PKIX_LISTAPPENDITEMFAILED); 829 830 PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext), 831 PKIX_LISTCREATEFAILED); 832 833 PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds 834 (CACHE_ITEM_PERIOD_SECONDS, 835 &cacheValidUntilDate, 836 plContext), 837 PKIX_DATECREATECURRENTOFFBYSECONDSFAILED); 838 839 PKIX_CHECK(PKIX_List_AppendItem 840 (cachedValues, 841 (PKIX_PL_Object *)cacheValidUntilDate, 842 plContext), 843 PKIX_LISTAPPENDITEMFAILED); 844 845 PKIX_CHECK(PKIX_List_AppendItem 846 (cachedValues, (PKIX_PL_Object *)validityDate, plContext), 847 PKIX_LISTAPPENDITEMFAILED); 848 849 PKIX_CHECK(PKIX_List_AppendItem 850 (cachedValues, (PKIX_PL_Object *)buildResult, plContext), 851 PKIX_LISTAPPENDITEMFAILED); 852 853 cachedCertChainError = PKIX_PL_HashTable_Add 854 (cachedCertChainTable, 855 (PKIX_PL_Object *) cachedKeys, 856 (PKIX_PL_Object *) cachedValues, 857 plContext); 858 859 pkix_ccAddCount++; 860 861 if (cachedCertChainError != NULL) { 862 PKIX_DEBUG("PKIX_PL_HashTable_Add for CertChain skipped: " 863 "entry existed\n"); 864 } 865 866 cleanup: 867 868 PKIX_DECREF(cachedValues); 869 PKIX_DECREF(cachedKeys); 870 PKIX_DECREF(cachedCertChainError); 871 PKIX_DECREF(cacheValidUntilDate); 872 873 PKIX_RETURN(BUILD); 874 } 875 876 /* 877 * FUNCTION: pkix_CacheCert_Lookup 878 * DESCRIPTION: 879 * 880 * Look up Cert Hash Table for a cached item based on "store" and Subject in 881 * "certSelParams" as the hash keys and returns values Certs in "pCerts". 882 * If there isn't an item to match the key, a PKIX_FALSE is returned at 883 * "pFound". The item's cache time is verified with "testDate". If out-dated, 884 * this item is removed and PKIX_FALSE is returned at "pFound". 885 * This hashtable is maintained in the following ways: 886 * 1) When creating the hashtable, maximum bucket size can be specified (0 for 887 * unlimited). If items in a bucket reaches its full size, an new addition 888 * will trigger the removal of the old as FIFO sequence. 889 * 2) A PKIX_PL_Date created with current time offset by constant 890 * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. 891 * If the CertStore this Cert is from is a trusted one, the cache period is 892 * shorter so cache can be updated more frequently. 893 * When an item is retrieved, this date is compared against "testDate" for 894 * validity. If comparison indicates this item is expired, the item is 895 * removed from the bucket. 896 * 897 * PARAMETERS: 898 * "store" 899 * Address of CertStore as key to retrieve this CertChain. Must be 900 * non-NULL. 901 * "certSelParams" 902 * Address of ComCertSelParams that its subject is used as key to retrieve 903 * this CertChain. Must be non-NULL. 904 * "testDate" 905 * Address of PKIX_PL_Date for verifying time cache validity. 906 * Must be non-NULL. If testDate is NULL, this cache item won't be out 907 * dated. 908 * "pFound" 909 * Address of KPKIX_Boolean indicating valid data is found. 910 * Must be non-NULL. 911 * "pCerts" 912 * Address PKIX_List where the CertChain will be stored. Must be no-NULL. 913 * "plContext" 914 * Platform-specific context pointer. 915 * THREAD SAFETY: 916 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 917 * RETURNS: 918 * Returns NULL if the function succeeds. 919 * Returns an Error Error if the function fails in a non-fatal way. 920 * Returns a Fatal Error if the function fails in an unrecoverable way. 921 */ 922 PKIX_Error * 923 pkix_CacheCert_Lookup( 924 PKIX_CertStore *store, 925 PKIX_ComCertSelParams *certSelParams, 926 PKIX_PL_Date *testDate, 927 PKIX_Boolean *pFound, 928 PKIX_List** pCerts, 929 void *plContext) 930 { 931 PKIX_PL_Cert *cert = NULL; 932 PKIX_List *cachedKeys = NULL; 933 PKIX_List *cachedValues = NULL; 934 PKIX_List *cachedCertList = NULL; 935 PKIX_List *selCertList = NULL; 936 PKIX_PL_X500Name *subject = NULL; 937 PKIX_PL_Date *invalidAfterDate = NULL; 938 PKIX_PL_Date *cacheValidUntilDate = NULL; 939 PKIX_CertSelector *certSel = NULL; 940 PKIX_Error *cachedCertError = NULL; 941 PKIX_Error *selectorError = NULL; 942 PKIX_CertSelector_MatchCallback selectorMatch = NULL; 943 PKIX_Int32 cmpValidTimeResult = PKIX_FALSE; 944 PKIX_Int32 cmpCacheTimeResult = 0; 945 PKIX_UInt32 numItems = 0; 946 PKIX_UInt32 i; 947 948 PKIX_ENTER(BUILD, "pkix_CacheCert_Lookup"); 949 PKIX_NULLCHECK_TWO(store, certSelParams); 950 PKIX_NULLCHECK_TWO(pFound, pCerts); 951 952 *pFound = PKIX_FALSE; 953 954 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), 955 PKIX_LISTCREATEFAILED); 956 957 PKIX_CHECK(PKIX_List_AppendItem 958 (cachedKeys, (PKIX_PL_Object *)store, plContext), 959 PKIX_LISTAPPENDITEMFAILED); 960 961 PKIX_CHECK(PKIX_ComCertSelParams_GetSubject 962 (certSelParams, &subject, plContext), 963 PKIX_COMCERTSELPARAMSGETSUBJECTFAILED); 964 965 PKIX_NULLCHECK_ONE(subject); 966 967 PKIX_CHECK(PKIX_List_AppendItem 968 (cachedKeys, (PKIX_PL_Object *)subject, plContext), 969 PKIX_LISTAPPENDITEMFAILED); 970 971 cachedCertError = PKIX_PL_HashTable_Lookup 972 (cachedCertTable, 973 (PKIX_PL_Object *) cachedKeys, 974 (PKIX_PL_Object **) &cachedValues, 975 plContext); 976 pkix_cLookupCount++; 977 978 if (cachedValues != NULL && cachedCertError == NULL) { 979 980 PKIX_CHECK(PKIX_List_GetItem 981 (cachedValues, 982 0, 983 (PKIX_PL_Object **) &cacheValidUntilDate, 984 plContext), 985 PKIX_LISTGETITEMFAILED); 986 987 if (testDate) { 988 PKIX_CHECK(PKIX_PL_Object_Compare 989 ((PKIX_PL_Object *)testDate, 990 (PKIX_PL_Object *)cacheValidUntilDate, 991 &cmpCacheTimeResult, 992 plContext), 993 PKIX_OBJECTCOMPARATORFAILED); 994 } 995 996 if (cmpCacheTimeResult <= 0) { 997 998 PKIX_CHECK(PKIX_List_GetItem 999 (cachedValues, 1000 1, 1001 (PKIX_PL_Object **) &cachedCertList, 1002 plContext), 1003 PKIX_LISTGETITEMFAILED); 1004 1005 /* 1006 * Certs put on cache satifies only for Subject, 1007 * user selector and ComCertSelParams to filter. 1008 */ 1009 PKIX_CHECK(PKIX_CertSelector_Create 1010 (NULL, NULL, &certSel, plContext), 1011 PKIX_CERTSELECTORCREATEFAILED); 1012 1013 PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams 1014 (certSel, certSelParams, plContext), 1015 PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED); 1016 1017 PKIX_CHECK(PKIX_CertSelector_GetMatchCallback 1018 (certSel, &selectorMatch, plContext), 1019 PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); 1020 1021 PKIX_CHECK(PKIX_List_Create(&selCertList, plContext), 1022 PKIX_LISTCREATEFAILED); 1023 1024 /* 1025 * If any of the Cert on the list is out-dated, invalidate 1026 * this cache item. 1027 */ 1028 PKIX_CHECK(PKIX_List_GetLength 1029 (cachedCertList, &numItems, plContext), 1030 PKIX_LISTGETLENGTHFAILED); 1031 1032 for (i = 0; i < numItems; i++){ 1033 1034 PKIX_CHECK(PKIX_List_GetItem 1035 (cachedCertList, 1036 i, 1037 (PKIX_PL_Object **)&cert, 1038 plContext), 1039 PKIX_LISTGETITEMFAILED); 1040 1041 PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter 1042 (cert, &invalidAfterDate, plContext), 1043 PKIX_CERTGETVALIDITYNOTAFTERFAILED); 1044 1045 if (testDate) { 1046 PKIX_CHECK(PKIX_PL_Object_Compare 1047 ((PKIX_PL_Object *)invalidAfterDate, 1048 (PKIX_PL_Object *)testDate, 1049 &cmpValidTimeResult, 1050 plContext), 1051 PKIX_OBJECTCOMPARATORFAILED); 1052 } 1053 1054 if (cmpValidTimeResult < 0) { 1055 1056 pkix_cRemoveCount++; 1057 *pFound = PKIX_FALSE; 1058 1059 /* one cert is out-dated, remove item from cache */ 1060 PKIX_CHECK(PKIX_PL_HashTable_Remove 1061 (cachedCertTable, 1062 (PKIX_PL_Object *) cachedKeys, 1063 plContext), 1064 PKIX_HASHTABLEREMOVEFAILED); 1065 goto cleanup; 1066 } 1067 1068 selectorError = selectorMatch(certSel, cert, plContext); 1069 if (!selectorError){ 1070 /* put on the return list */ 1071 PKIX_CHECK(PKIX_List_AppendItem 1072 (selCertList, 1073 (PKIX_PL_Object *)cert, 1074 plContext), 1075 PKIX_LISTAPPENDITEMFAILED); 1076 *pFound = PKIX_TRUE; 1077 } else { 1078 PKIX_DECREF(selectorError); 1079 } 1080 1081 PKIX_DECREF(cert); 1082 PKIX_DECREF(invalidAfterDate); 1083 1084 } 1085 1086 if (*pFound) { 1087 PKIX_INCREF(selCertList); 1088 *pCerts = selCertList; 1089 } 1090 1091 } else { 1092 1093 pkix_cRemoveCount++; 1094 *pFound = PKIX_FALSE; 1095 /* cache item is out-dated, remove it from cache */ 1096 PKIX_CHECK(PKIX_PL_HashTable_Remove 1097 (cachedCertTable, 1098 (PKIX_PL_Object *) cachedKeys, 1099 plContext), 1100 PKIX_HASHTABLEREMOVEFAILED); 1101 } 1102 1103 } 1104 1105 cleanup: 1106 1107 PKIX_DECREF(subject); 1108 PKIX_DECREF(certSel); 1109 PKIX_DECREF(cachedKeys); 1110 PKIX_DECREF(cachedValues); 1111 PKIX_DECREF(cacheValidUntilDate); 1112 PKIX_DECREF(cert); 1113 PKIX_DECREF(cachedCertList); 1114 PKIX_DECREF(selCertList); 1115 PKIX_DECREF(invalidAfterDate); 1116 PKIX_DECREF(cachedCertError); 1117 PKIX_DECREF(selectorError); 1118 1119 PKIX_RETURN(BUILD); 1120 } 1121 1122 /* 1123 * FUNCTION: pkix_CacheCert_Add 1124 * DESCRIPTION: 1125 * 1126 * Add Cert Hash Table for a cached item based on "store" and Subject in 1127 * "certSelParams" as the hash keys and have "certs" as the key value. 1128 * This hashtable is maintained in the following ways: 1129 * 1) When creating the hashtable, maximum bucket size can be specified (0 for 1130 * unlimited). If items in a bucket reaches its full size, an new addition 1131 * will trigger the removal of the old as FIFO sequence. 1132 * 2) A PKIX_PL_Date created with current time offset by constant 1133 * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. 1134 * If the CertStore this Cert is from is a trusted one, the cache period is 1135 * shorter so cache can be updated more frequently. 1136 * When an item is retrieved, this date is compared against "testDate" for 1137 * validity. If comparison indicates this item is expired, the item is 1138 * removed from the bucket. 1139 * 1140 * PARAMETERS: 1141 * "store" 1142 * Address of CertStore as key to retrieve this CertChain. Must be 1143 * non-NULL. 1144 * "certSelParams" 1145 * Address of ComCertSelParams that its subject is used as key to retrieve 1146 * this CertChain. Must be non-NULL. 1147 * "certs" 1148 * Address PKIX_List of Certs will be stored. Must be no-NULL. 1149 * "plContext" 1150 * Platform-specific context pointer. 1151 * THREAD SAFETY: 1152 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1153 * RETURNS: 1154 * Returns NULL if the function succeeds. 1155 * Returns an Error Error if the function fails in a non-fatal way. 1156 * Returns a Fatal Error if the function fails in an unrecoverable way. 1157 */ 1158 PKIX_Error * 1159 pkix_CacheCert_Add( 1160 PKIX_CertStore *store, 1161 PKIX_ComCertSelParams *certSelParams, 1162 PKIX_List* certs, 1163 void *plContext) 1164 { 1165 PKIX_List *cachedKeys = NULL; 1166 PKIX_List *cachedValues = NULL; 1167 PKIX_List *cachedCerts = NULL; 1168 PKIX_PL_Date *cacheValidUntilDate = NULL; 1169 PKIX_PL_X500Name *subject = NULL; 1170 PKIX_Error *cachedCertError = NULL; 1171 PKIX_CertStore_CheckTrustCallback trustCallback = NULL; 1172 PKIX_UInt32 cachePeriod = CACHE_ITEM_PERIOD_SECONDS; 1173 PKIX_UInt32 numCerts = 0; 1174 1175 PKIX_ENTER(BUILD, "pkix_CacheCert_Add"); 1176 PKIX_NULLCHECK_THREE(store, certSelParams, certs); 1177 1178 PKIX_CHECK(PKIX_List_GetLength(certs, &numCerts, 1179 plContext), 1180 PKIX_LISTGETLENGTHFAILED); 1181 if (numCerts == 0) { 1182 /* Don't want to add an empty list. */ 1183 goto cleanup; 1184 } 1185 1186 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), 1187 PKIX_LISTCREATEFAILED); 1188 1189 PKIX_CHECK(PKIX_List_AppendItem 1190 (cachedKeys, (PKIX_PL_Object *)store, plContext), 1191 PKIX_LISTAPPENDITEMFAILED); 1192 1193 PKIX_CHECK(PKIX_ComCertSelParams_GetSubject 1194 (certSelParams, &subject, plContext), 1195 PKIX_COMCERTSELPARAMSGETSUBJECTFAILED); 1196 1197 PKIX_NULLCHECK_ONE(subject); 1198 1199 PKIX_CHECK(PKIX_List_AppendItem 1200 (cachedKeys, (PKIX_PL_Object *)subject, plContext), 1201 PKIX_LISTAPPENDITEMFAILED); 1202 1203 PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext), 1204 PKIX_LISTCREATEFAILED); 1205 1206 PKIX_CHECK(PKIX_CertStore_GetTrustCallback 1207 (store, &trustCallback, plContext), 1208 PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); 1209 1210 if (trustCallback) { 1211 cachePeriod = CACHE_TRUST_ITEM_PERIOD_SECONDS; 1212 } 1213 1214 PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds 1215 (cachePeriod, &cacheValidUntilDate, plContext), 1216 PKIX_DATECREATECURRENTOFFBYSECONDSFAILED); 1217 1218 PKIX_CHECK(PKIX_List_AppendItem 1219 (cachedValues, 1220 (PKIX_PL_Object *)cacheValidUntilDate, 1221 plContext), 1222 PKIX_LISTAPPENDITEMFAILED); 1223 1224 PKIX_DUPLICATE(certs, &cachedCerts, plContext, 1225 PKIX_OBJECTDUPLICATELISTFAILED); 1226 1227 PKIX_CHECK(PKIX_List_AppendItem 1228 (cachedValues, 1229 (PKIX_PL_Object *)cachedCerts, 1230 plContext), 1231 PKIX_LISTAPPENDITEMFAILED); 1232 1233 cachedCertError = PKIX_PL_HashTable_Add 1234 (cachedCertTable, 1235 (PKIX_PL_Object *) cachedKeys, 1236 (PKIX_PL_Object *) cachedValues, 1237 plContext); 1238 1239 pkix_cAddCount++; 1240 1241 if (cachedCertError != NULL) { 1242 PKIX_DEBUG("PKIX_PL_HashTable_Add for Certs skipped: " 1243 "entry existed\n"); 1244 } 1245 1246 cleanup: 1247 1248 PKIX_DECREF(subject); 1249 PKIX_DECREF(cachedKeys); 1250 PKIX_DECREF(cachedValues); 1251 PKIX_DECREF(cachedCerts); 1252 PKIX_DECREF(cacheValidUntilDate); 1253 PKIX_DECREF(cachedCertError); 1254 1255 PKIX_RETURN(BUILD); 1256 } 1257 1258 /* 1259 * FUNCTION: pkix_CacheCrlEntry_Lookup 1260 * DESCRIPTION: 1261 * 1262 * Look up CrlEntry Hash Table for a cached item based on "store", 1263 * "certIssuer" and "certSerialNumber" as the hash keys and returns values 1264 * "pCrls". If there isn't an item to match the key, a PKIX_FALSE is 1265 * returned at "pFound". 1266 * This hashtable is maintained in the following way: 1267 * 1) When creating the hashtable, maximum bucket size can be specified (0 for 1268 * unlimited). If items in a bucket reaches its full size, an new addition 1269 * will trigger the removal of the old as FIFO sequence. 1270 * 1271 * PARAMETERS: 1272 * "store" 1273 * Address of CertStore as key to retrieve this CertChain. Must be 1274 * non-NULL. 1275 * "certIssuer" 1276 * Address of X500Name that is used as key to retrieve the CRLEntries. 1277 * Must be non-NULL. 1278 * "certSerialNumber" 1279 * Address of BigInt that is used as key to retrieve the CRLEntries. 1280 * Must be non-NULL. 1281 * "pFound" 1282 * Address of KPKIX_Boolean indicating valid data is found. 1283 * Must be non-NULL. 1284 * "pCrls" 1285 * Address PKIX_List where the CRLEntry will be stored. Must be no-NULL. 1286 * "plContext" 1287 * Platform-specific context pointer. 1288 * THREAD SAFETY: 1289 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1290 * RETURNS: 1291 * Returns NULL if the function succeeds. 1292 * Returns an Error Error if the function fails in a non-fatal way. 1293 * Returns a Fatal Error if the function fails in an unrecoverable way. 1294 */ 1295 PKIX_Error * 1296 pkix_CacheCrlEntry_Lookup( 1297 PKIX_CertStore *store, 1298 PKIX_PL_X500Name *certIssuer, 1299 PKIX_PL_BigInt *certSerialNumber, 1300 PKIX_Boolean *pFound, 1301 PKIX_List** pCrls, 1302 void *plContext) 1303 { 1304 PKIX_List *cachedKeys = NULL; 1305 PKIX_List *cachedCrlEntryList = NULL; 1306 PKIX_Error *cachedCrlEntryError = NULL; 1307 1308 PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Lookup"); 1309 PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber); 1310 PKIX_NULLCHECK_TWO(pFound, pCrls); 1311 1312 *pFound = PKIX_FALSE; 1313 1314 /* Find CrlEntry(s) by issuer and serial number */ 1315 1316 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), 1317 PKIX_LISTCREATEFAILED); 1318 1319 PKIX_CHECK(PKIX_List_AppendItem 1320 (cachedKeys, (PKIX_PL_Object *)store, plContext), 1321 PKIX_LISTAPPENDITEMFAILED); 1322 1323 PKIX_CHECK(PKIX_List_AppendItem 1324 (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext), 1325 PKIX_LISTAPPENDITEMFAILED); 1326 1327 PKIX_CHECK(PKIX_List_AppendItem 1328 (cachedKeys, 1329 (PKIX_PL_Object *)certSerialNumber, 1330 plContext), 1331 PKIX_LISTAPPENDITEMFAILED); 1332 1333 cachedCrlEntryError = PKIX_PL_HashTable_Lookup 1334 (cachedCrlEntryTable, 1335 (PKIX_PL_Object *) cachedKeys, 1336 (PKIX_PL_Object **) &cachedCrlEntryList, 1337 plContext); 1338 pkix_ceLookupCount++; 1339 1340 /* 1341 * We don't need check Date to invalidate this cache item, 1342 * the item is uniquely defined and won't be reverted. Let 1343 * the FIFO for cleaning up. 1344 */ 1345 1346 if (cachedCrlEntryList != NULL && cachedCrlEntryError == NULL ) { 1347 1348 PKIX_INCREF(cachedCrlEntryList); 1349 *pCrls = cachedCrlEntryList; 1350 1351 *pFound = PKIX_TRUE; 1352 1353 } else { 1354 1355 *pFound = PKIX_FALSE; 1356 } 1357 1358 cleanup: 1359 1360 PKIX_DECREF(cachedKeys); 1361 PKIX_DECREF(cachedCrlEntryList); 1362 PKIX_DECREF(cachedCrlEntryError); 1363 1364 PKIX_RETURN(BUILD); 1365 } 1366 1367 /* 1368 * FUNCTION: pkix_CacheCrlEntry_Add 1369 * DESCRIPTION: 1370 * 1371 * Look up CrlEntry Hash Table for a cached item based on "store", 1372 * "certIssuer" and "certSerialNumber" as the hash keys and have "pCrls" as 1373 * the hash value. If there isn't an item to match the key, a PKIX_FALSE is 1374 * returned at "pFound". 1375 * This hashtable is maintained in the following way: 1376 * 1) When creating the hashtable, maximum bucket size can be specified (0 for 1377 * unlimited). If items in a bucket reaches its full size, an new addition 1378 * will trigger the removal of the old as FIFO sequence. 1379 * 1380 * PARAMETERS: 1381 * "store" 1382 * Address of CertStore as key to retrieve this CertChain. Must be 1383 * non-NULL. 1384 * "certIssuer" 1385 * Address of X500Name that is used as key to retrieve the CRLEntries. 1386 * Must be non-NULL. 1387 * "certSerialNumber" 1388 * Address of BigInt that is used as key to retrieve the CRLEntries. 1389 * Must be non-NULL. 1390 * "crls" 1391 * Address PKIX_List where the CRLEntry is stored. Must be no-NULL. 1392 * "plContext" 1393 * Platform-specific context pointer. 1394 * THREAD SAFETY: 1395 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1396 * RETURNS: 1397 * Returns NULL if the function succeeds. 1398 * Returns an Error Error if the function fails in a non-fatal way. 1399 * Returns a Fatal Error if the function fails in an unrecoverable way. 1400 */ 1401 PKIX_Error * 1402 pkix_CacheCrlEntry_Add( 1403 PKIX_CertStore *store, 1404 PKIX_PL_X500Name *certIssuer, 1405 PKIX_PL_BigInt *certSerialNumber, 1406 PKIX_List* crls, 1407 void *plContext) 1408 { 1409 PKIX_List *cachedKeys = NULL; 1410 PKIX_Error *cachedCrlEntryError = NULL; 1411 1412 PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Add"); 1413 PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber); 1414 PKIX_NULLCHECK_ONE(crls); 1415 1416 /* Add CrlEntry(s) by issuer and serial number */ 1417 1418 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), 1419 PKIX_LISTCREATEFAILED); 1420 1421 PKIX_CHECK(PKIX_List_AppendItem 1422 (cachedKeys, (PKIX_PL_Object *)store, plContext), 1423 PKIX_LISTAPPENDITEMFAILED); 1424 1425 PKIX_CHECK(PKIX_List_AppendItem 1426 (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext), 1427 PKIX_LISTAPPENDITEMFAILED); 1428 1429 PKIX_CHECK(PKIX_List_AppendItem 1430 (cachedKeys, 1431 (PKIX_PL_Object *)certSerialNumber, 1432 plContext), 1433 PKIX_LISTAPPENDITEMFAILED); 1434 1435 cachedCrlEntryError = PKIX_PL_HashTable_Add 1436 (cachedCrlEntryTable, 1437 (PKIX_PL_Object *) cachedKeys, 1438 (PKIX_PL_Object *) crls, 1439 plContext); 1440 pkix_ceAddCount++; 1441 1442 cleanup: 1443 1444 PKIX_DECREF(cachedKeys); 1445 PKIX_DECREF(cachedCrlEntryError); 1446 1447 PKIX_RETURN(BUILD); 1448 } 1449 1450 #ifdef PKIX_OBJECT_LEAK_TEST 1451 1452 /* TEST_START_FN and testStartFnStackPosition define at what state 1453 * of the stack the object leak testing should begin. The condition 1454 * in pkix_CheckForGeneratedError works the following way: do leak 1455 * testing if at position testStartFnStackPosition in stack array 1456 * (fnStackNameArr) we have called function TEST_START_FN. 1457 * Note, that stack array get filled only when executing libpkix 1458 * functions. 1459 * */ 1460 #define TEST_START_FN "PKIX_BuildChain" 1461 1462 PKIX_Error* 1463 pkix_CheckForGeneratedError(PKIX_StdVars * stdVars, 1464 PKIX_ERRORCLASS errClass, 1465 char * fnName, 1466 PKIX_Boolean *errSetFlag, 1467 void * plContext) 1468 { 1469 PKIX_Error *genErr = NULL; 1470 PKIX_UInt32 pos = 0; 1471 PKIX_UInt32 strLen = 0; 1472 1473 if (fnName) { 1474 if (fnStackNameArr[testStartFnStackPosition] == NULL || 1475 strcmp(fnStackNameArr[testStartFnStackPosition], TEST_START_FN) 1476 ) { 1477 /* return with out error if not with in boundary */ 1478 return NULL; 1479 } 1480 if (!strcmp(fnName, TEST_START_FN)) { 1481 *errSetFlag = PKIX_TRUE; 1482 noErrorState = PKIX_FALSE; 1483 errorGenerated = PKIX_FALSE; 1484 } 1485 } 1486 1487 if (noErrorState || errorGenerated) return NULL; 1488 1489 if (fnName && ( 1490 !strcmp(fnName, "PKIX_PL_Object_DecRef") || 1491 !strcmp(fnName, "PKIX_PL_Object_Unlock") || 1492 !strcmp(fnName, "pkix_UnlockObject") || 1493 !strcmp(fnName, "pkix_Throw") || 1494 !strcmp(fnName, "pkix_trace_dump_cert") || 1495 !strcmp(fnName, "PKIX_PL_Free"))) { 1496 /* do not generate error for this functions */ 1497 noErrorState = PKIX_TRUE; 1498 *errSetFlag = PKIX_TRUE; 1499 return NULL; 1500 } 1501 1502 if (PL_HashTableLookup(fnInvTable, &fnStackInvCountArr[stackPosition - 1])) { 1503 return NULL; 1504 } 1505 1506 PL_HashTableAdd(fnInvTable, &fnStackInvCountArr[stackPosition - 1], nonNullValue); 1507 errorGenerated = PKIX_TRUE; 1508 noErrorState = PKIX_TRUE; 1509 genErr = PKIX_DoThrow(stdVars, errClass, PKIX_MEMLEAKGENERATEDERROR, 1510 errClass, plContext); 1511 while(fnStackNameArr[pos]) { 1512 strLen += PORT_Strlen(fnStackNameArr[pos++]) + 1; 1513 } 1514 strLen += 1; /* end of line. */ 1515 pos = 0; 1516 errorFnStackString = PORT_ZAlloc(strLen); 1517 while(fnStackNameArr[pos]) { 1518 strcat(errorFnStackString, "/"); 1519 strcat(errorFnStackString, fnStackNameArr[pos++]); 1520 } 1521 noErrorState = PKIX_FALSE; 1522 1523 return genErr; 1524 } 1525 #endif /* PKIX_OBJECT_LEAK_TEST */