PageRenderTime 89ms CodeModel.GetById 16ms app.highlight 63ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/lib/libpkix/pkix/util/pkix_tools.c

http://github.com/zpao/v8monkey
C | 1552 lines | 777 code | 205 blank | 570 comment | 79 complexity | 93549263314e07b9f59400cc6c8a245c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file