tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 */