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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1519 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +/*
     1.8 + * pkix_tools.c
     1.9 + *
    1.10 + * Private Utility Functions
    1.11 + *
    1.12 + */
    1.13 +
    1.14 +#include "pkix_tools.h"
    1.15 +
    1.16 +#define CACHE_ITEM_PERIOD_SECONDS  (3600)  /* one hour */
    1.17 +
    1.18 +/*
    1.19 + * This cahce period is only for CertCache. A Cert from a trusted CertStore
    1.20 + * should be checked more frequently for update new arrival, etc.
    1.21 + */
    1.22 +#define CACHE_TRUST_ITEM_PERIOD_SECONDS  (CACHE_ITEM_PERIOD_SECONDS/10)
    1.23 +
    1.24 +extern PKIX_PL_HashTable *cachedCertChainTable;
    1.25 +extern PKIX_PL_HashTable *cachedCertTable;
    1.26 +extern PKIX_PL_HashTable *cachedCrlEntryTable;
    1.27 +
    1.28 +/* Following variables are used to checked cache hits - can be taken out */
    1.29 +extern int pkix_ccAddCount;
    1.30 +extern int pkix_ccLookupCount;
    1.31 +extern int pkix_ccRemoveCount;
    1.32 +extern int pkix_cAddCount;
    1.33 +extern int pkix_cLookupCount;
    1.34 +extern int pkix_cRemoveCount;
    1.35 +extern int pkix_ceAddCount;
    1.36 +extern int pkix_ceLookupCount;
    1.37 +
    1.38 +#ifdef PKIX_OBJECT_LEAK_TEST
    1.39 +/* Following variables are used for object leak test */
    1.40 +char *nonNullValue = "Non Empty Value";
    1.41 +PKIX_Boolean noErrorState = PKIX_TRUE;
    1.42 +PKIX_Boolean runningLeakTest;
    1.43 +PKIX_Boolean errorGenerated;
    1.44 +PKIX_UInt32 stackPosition;
    1.45 +PKIX_UInt32 *fnStackInvCountArr;
    1.46 +char **fnStackNameArr;
    1.47 +PLHashTable *fnInvTable;
    1.48 +PKIX_UInt32 testStartFnStackPosition;
    1.49 +char *errorFnStackString;
    1.50 +#endif /* PKIX_OBJECT_LEAK_TEST */
    1.51 +
    1.52 +/* --Private-Functions-------------------------------------------- */
    1.53 +
    1.54 +#ifdef PKIX_OBJECT_LEAK_TEST
    1.55 +/*
    1.56 + * FUNCTION: pkix_ErrorGen_Hash
    1.57 + * DESCRIPTION:
    1.58 + *
    1.59 + * Hash function to be used in object leak test hash table.
    1.60 + *
    1.61 + */
    1.62 +PLHashNumber PR_CALLBACK
    1.63 +pkix_ErrorGen_Hash (const void *key)
    1.64 +{
    1.65 +    char *str = NULL;
    1.66 +    PLHashNumber rv = (*(PRUint8*)key) << 5;
    1.67 +    PRUint32 i, counter = 0;
    1.68 +    PRUint8 *rvc = (PRUint8 *)&rv;
    1.69 +
    1.70 +    while ((str = fnStackNameArr[counter++]) != NULL) {
    1.71 +        PRUint32 len = strlen(str);
    1.72 +        for( i = 0; i < len; i++ ) {
    1.73 +            rvc[ i % sizeof(rv) ] ^= *str;
    1.74 +            str++;
    1.75 +        }
    1.76 +    }
    1.77 +
    1.78 +    return rv;
    1.79 +}
    1.80 +
    1.81 +#endif /* PKIX_OBJECT_LEAK_TEST */
    1.82 +
    1.83 +/*
    1.84 + * FUNCTION: pkix_IsCertSelfIssued
    1.85 + * DESCRIPTION:
    1.86 + *
    1.87 + *  Checks whether the Cert pointed to by "cert" is self-issued and stores the
    1.88 + *  Boolean result at "pSelfIssued". A Cert is considered self-issued if the
    1.89 + *  Cert's issuer matches the Cert's subject. If the subject or issuer is
    1.90 + *  not specified, a PKIX_FALSE is returned.
    1.91 + *
    1.92 + * PARAMETERS:
    1.93 + *  "cert"
    1.94 + *      Address of Cert used to determine whether Cert is self-issued.
    1.95 + *      Must be non-NULL.
    1.96 + *  "pSelfIssued"
    1.97 + *      Address where Boolean will be stored. Must be non-NULL.
    1.98 + *  "plContext"
    1.99 + *      Platform-specific context pointer.
   1.100 + * THREAD SAFETY:
   1.101 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.102 + * RETURNS:
   1.103 + *  Returns NULL if the function succeeds.
   1.104 + *  Returns a Cert Error if the function fails in a non-fatal way.
   1.105 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.106 + */
   1.107 +PKIX_Error *
   1.108 +pkix_IsCertSelfIssued(
   1.109 +        PKIX_PL_Cert *cert,
   1.110 +        PKIX_Boolean *pSelfIssued,
   1.111 +        void *plContext)
   1.112 +{
   1.113 +        PKIX_PL_X500Name *subject = NULL;
   1.114 +        PKIX_PL_X500Name *issuer = NULL;
   1.115 +
   1.116 +        PKIX_ENTER(CERT, "pkix_IsCertSelfIssued");
   1.117 +        PKIX_NULLCHECK_TWO(cert, pSelfIssued);
   1.118 +
   1.119 +        PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &subject, plContext),
   1.120 +                    PKIX_CERTGETSUBJECTFAILED);
   1.121 +
   1.122 +        PKIX_CHECK(PKIX_PL_Cert_GetIssuer(cert, &issuer, plContext),
   1.123 +                    PKIX_CERTGETISSUERFAILED);
   1.124 +
   1.125 +        if (subject == NULL || issuer == NULL) {
   1.126 +                *pSelfIssued = PKIX_FALSE;
   1.127 +        } else {
   1.128 +
   1.129 +                PKIX_CHECK(PKIX_PL_X500Name_Match
   1.130 +                    (subject, issuer, pSelfIssued, plContext),
   1.131 +                    PKIX_X500NAMEMATCHFAILED);
   1.132 +        }
   1.133 +
   1.134 +cleanup:
   1.135 +        PKIX_DECREF(subject);
   1.136 +        PKIX_DECREF(issuer);
   1.137 +
   1.138 +        PKIX_RETURN(CERT);
   1.139 +}
   1.140 +
   1.141 +/*
   1.142 + * FUNCTION: pkix_Throw
   1.143 + * DESCRIPTION:
   1.144 + *
   1.145 + *  Creates an Error using the value of "errorCode", the character array
   1.146 + *  pointed to by "funcName", the character array pointed to by "errorText",
   1.147 + *  and the Error pointed to by "cause" (if any), and stores it at "pError".
   1.148 + *
   1.149 + *  If "cause" is not NULL and has an errorCode of "PKIX_FATAL_ERROR",
   1.150 + *  then there is no point creating a new Error object. Rather, we simply
   1.151 + *  store "cause" at "pError".
   1.152 + *
   1.153 + * PARAMETERS:
   1.154 + *  "errorCode"
   1.155 + *      Value of error code.
   1.156 + *  "funcName"
   1.157 + *      Address of EscASCII array representing name of function throwing error.
   1.158 + *      Must be non-NULL.
   1.159 + *  "errnum"
   1.160 + *      PKIX_ERRMSGNUM of error description for new error.
   1.161 + *  "cause"
   1.162 + *      Address of Error representing error's cause.
   1.163 + *  "pError"
   1.164 + *      Address where object pointer will be stored. Must be non-NULL.
   1.165 + *  "plContext"
   1.166 + *      Platform-specific context pointer.
   1.167 + * THREAD SAFETY:
   1.168 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.169 + * RETURNS:
   1.170 + *  Returns NULL if the function succeeds.
   1.171 + *  Returns an Error Error if the function fails in a non-fatal way.
   1.172 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.173 + */
   1.174 +PKIX_Error *
   1.175 +pkix_Throw(
   1.176 +        PKIX_ERRORCLASS errorClass,
   1.177 +        const char *funcName,
   1.178 +        PKIX_ERRORCODE errorCode,
   1.179 +        PKIX_ERRORCLASS overrideClass,
   1.180 +        PKIX_Error *cause,
   1.181 +        PKIX_Error **pError,
   1.182 +        void *plContext)
   1.183 +{
   1.184 +        PKIX_Error *error = NULL;
   1.185 +
   1.186 +        PKIX_ENTER(ERROR, "pkix_Throw");
   1.187 +        PKIX_NULLCHECK_TWO(funcName, pError);
   1.188 +
   1.189 +        *pError = NULL;
   1.190 +
   1.191 +#ifdef PKIX_OBJECT_LEAK_TEST        
   1.192 +        noErrorState = PKIX_TRUE;
   1.193 +        if (pkixLog) {
   1.194 +#ifdef PKIX_ERROR_DESCRIPTION            
   1.195 +            PR_LOG(pkixLog, 4, ("Error in function \"%s\":\"%s\" with cause \"%s\"\n",
   1.196 +                                funcName, PKIX_ErrorText[errorCode],
   1.197 +                                (cause ? PKIX_ErrorText[cause->errCode] : "null")));
   1.198 +#else
   1.199 +            PR_LOG(pkixLog, 4, ("Error in function \"%s\": error code \"%d\"\n",
   1.200 +                                funcName, errorCode));
   1.201 +#endif /* PKIX_ERROR_DESCRIPTION */
   1.202 +            PORT_Assert(strcmp(funcName, "PKIX_PL_Object_DecRef"));
   1.203 +        }
   1.204 +#endif /* PKIX_OBJECT_LEAK_TEST */
   1.205 +
   1.206 +        /* if cause has error class of PKIX_FATAL_ERROR, return immediately */
   1.207 +        if (cause) {
   1.208 +                if (cause->errClass == PKIX_FATAL_ERROR){
   1.209 +                        PKIX_INCREF(cause);
   1.210 +                        *pError = cause;
   1.211 +                        goto cleanup;
   1.212 +                }
   1.213 +        }
   1.214 +        
   1.215 +        if (overrideClass == PKIX_FATAL_ERROR){
   1.216 +                errorClass = overrideClass;
   1.217 +        }
   1.218 +
   1.219 +       pkixTempResult = PKIX_Error_Create(errorClass, cause, NULL,
   1.220 +                                           errorCode, &error, plContext);
   1.221 +       
   1.222 +       if (!pkixTempResult) {
   1.223 +           /* Setting plErr error code:
   1.224 +            *    get it from PORT_GetError if it is a leaf error and
   1.225 +            *    default error code does not exist(eq 0)               */
   1.226 +           if (!cause && !error->plErr) {
   1.227 +               error->plErr = PKIX_PL_GetPLErrorCode();
   1.228 +           }
   1.229 +       }
   1.230 +
   1.231 +       *pError = error;
   1.232 +
   1.233 +cleanup:
   1.234 +
   1.235 +        PKIX_DEBUG_EXIT(ERROR);
   1.236 +        pkixErrorClass = 0;
   1.237 +#ifdef PKIX_OBJECT_LEAK_TEST        
   1.238 +        noErrorState = PKIX_FALSE;
   1.239 +
   1.240 +        if (runningLeakTest && fnStackNameArr) {
   1.241 +            PR_LOG(pkixLog, 5,
   1.242 +                   ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "),
   1.243 +                    stackPosition, " ", fnStackNameArr[stackPosition],
   1.244 +                    stackPosition, myFuncName));
   1.245 +            fnStackNameArr[stackPosition--] = NULL;
   1.246 +        }
   1.247 +#endif /* PKIX_OBJECT_LEAK_TEST */
   1.248 +        return (pkixTempResult);
   1.249 +}
   1.250 +
   1.251 +/*
   1.252 + * FUNCTION: pkix_CheckTypes
   1.253 + * DESCRIPTION:
   1.254 + *
   1.255 + *  Checks that the types of the Object pointed to by "first" and the Object
   1.256 + *  pointed to by "second" are both equal to the value of "type". If they
   1.257 + *  are not equal, a PKIX_Error is returned.
   1.258 + *
   1.259 + * PARAMETERS:
   1.260 + *  "first"
   1.261 + *      Address of first Object. Must be non-NULL.
   1.262 + *  "second"
   1.263 + *      Address of second Object. Must be non-NULL.
   1.264 + *  "type"
   1.265 + *      Value of type to check against.
   1.266 + *  "plContext"
   1.267 + *      Platform-specific context pointer.
   1.268 + * THREAD SAFETY:
   1.269 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.270 + * RETURNS:
   1.271 + *  Returns NULL if the function succeeds.
   1.272 + *  Returns an Error Error if the function fails in a non-fatal way.
   1.273 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.274 + */
   1.275 +PKIX_Error *
   1.276 +pkix_CheckTypes(
   1.277 +        PKIX_PL_Object *first,
   1.278 +        PKIX_PL_Object *second,
   1.279 +        PKIX_UInt32 type,
   1.280 +        void *plContext)
   1.281 +{
   1.282 +        PKIX_UInt32 firstType, secondType;
   1.283 +
   1.284 +        PKIX_ENTER(OBJECT, "pkix_CheckTypes");
   1.285 +        PKIX_NULLCHECK_TWO(first, second);
   1.286 +
   1.287 +        PKIX_CHECK(PKIX_PL_Object_GetType(first, &firstType, plContext),
   1.288 +                    PKIX_COULDNOTGETFIRSTOBJECTTYPE);
   1.289 +
   1.290 +        PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
   1.291 +                    PKIX_COULDNOTGETSECONDOBJECTTYPE);
   1.292 +
   1.293 +        if ((firstType != type)||(firstType != secondType)) {
   1.294 +                PKIX_ERROR(PKIX_OBJECTTYPESDONOTMATCH);
   1.295 +        }
   1.296 +
   1.297 +cleanup:
   1.298 +
   1.299 +        PKIX_RETURN(OBJECT);
   1.300 +}
   1.301 +
   1.302 +/*
   1.303 + * FUNCTION: pkix_CheckType
   1.304 + * DESCRIPTION:
   1.305 + *
   1.306 + *  Checks that the type of the Object pointed to by "object" is equal to the
   1.307 + *  value of "type". If it is not equal, a PKIX_Error is returned.
   1.308 + *
   1.309 + * PARAMETERS:
   1.310 + *  "object"
   1.311 + *      Address of Object. Must be non-NULL.
   1.312 + *  "type"
   1.313 + *      Value of type to check against.
   1.314 + *  "plContext"
   1.315 + *      Platform-specific context pointer.
   1.316 + * THREAD SAFETY:
   1.317 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.318 + * RETURNS:
   1.319 + *  Returns NULL if the function succeeds.
   1.320 + *  Returns an Error Error if the function fails in a non-fatal way.
   1.321 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.322 + */
   1.323 +PKIX_Error *
   1.324 +pkix_CheckType(
   1.325 +        PKIX_PL_Object *object,
   1.326 +        PKIX_UInt32 type,
   1.327 +        void *plContext)
   1.328 +{
   1.329 +        return (pkix_CheckTypes(object, object, type, plContext));
   1.330 +}
   1.331 +
   1.332 +/*
   1.333 + * FUNCTION: pkix_hash
   1.334 + * DESCRIPTION:
   1.335 + *
   1.336 + *  Computes a hash value for "length" bytes starting at the array of bytes
   1.337 + *  pointed to by "bytes" and stores the result at "pHash".
   1.338 + *
   1.339 + *  XXX To speed this up, we could probably read 32 bits at a time from
   1.340 + *  bytes (maybe even 64 bits on some platforms)
   1.341 + *
   1.342 + * PARAMETERS:
   1.343 + *  "bytes"
   1.344 + *      Address of array of bytes to hash. Must be non-NULL.
   1.345 + *  "length"
   1.346 + *      Number of bytes to hash.
   1.347 + *  "pHash"
   1.348 + *      Address where object pointer will be stored. Must be non-NULL.
   1.349 + *  "plContext"
   1.350 + *      Platform-specific context pointer.
   1.351 + * THREAD SAFETY:
   1.352 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.353 + * RETURNS:
   1.354 + *  Returns NULL if the function succeeds.
   1.355 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.356 + */
   1.357 +PKIX_Error *
   1.358 +pkix_hash(
   1.359 +        const unsigned char *bytes,
   1.360 +        PKIX_UInt32 length,
   1.361 +        PKIX_UInt32 *pHash,
   1.362 +        void *plContext)
   1.363 +{
   1.364 +        PKIX_UInt32 i;
   1.365 +        PKIX_UInt32 hash;
   1.366 +
   1.367 +        PKIX_ENTER(OBJECT, "pkix_hash");
   1.368 +        if (length != 0) {
   1.369 +                PKIX_NULLCHECK_ONE(bytes);
   1.370 +        }
   1.371 +        PKIX_NULLCHECK_ONE(pHash);
   1.372 +
   1.373 +        hash = 0;
   1.374 +        for (i = 0; i < length; i++) {
   1.375 +                /* hash = 31 * hash + bytes[i]; */
   1.376 +                hash = (hash << 5) - hash + bytes[i];
   1.377 +        }
   1.378 +
   1.379 +        *pHash = hash;
   1.380 +
   1.381 +        PKIX_RETURN(OBJECT);
   1.382 +}
   1.383 +
   1.384 +/*
   1.385 + * FUNCTION: pkix_countArray
   1.386 + * DESCRIPTION:
   1.387 + *
   1.388 + *  Counts the number of elements in the  null-terminated array of pointers
   1.389 + *  pointed to by "array" and returns the result.
   1.390 + *
   1.391 + * PARAMETERS
   1.392 + *  "array"
   1.393 + *      Address of null-terminated array of pointers.
   1.394 + * THREAD SAFETY:
   1.395 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.396 + * RETURNS:
   1.397 + *  Returns the number of elements in the array.
   1.398 + */
   1.399 +PKIX_UInt32
   1.400 +pkix_countArray(void **array)
   1.401 +{
   1.402 +        PKIX_UInt32 count = 0;
   1.403 +
   1.404 +        if (array) {
   1.405 +                while (*array++) {
   1.406 +                        count++;
   1.407 +                }
   1.408 +        }
   1.409 +        return (count);
   1.410 +}
   1.411 +
   1.412 +/*
   1.413 + * FUNCTION: pkix_duplicateImmutable
   1.414 + * DESCRIPTION:
   1.415 + *
   1.416 + *  Convenience callback function used for duplicating immutable objects.
   1.417 + *  Since the objects can not be modified, this function simply increments the
   1.418 + *  reference count on the object, and returns a reference to that object.
   1.419 + *
   1.420 + *  (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
   1.421 + */
   1.422 +PKIX_Error *
   1.423 +pkix_duplicateImmutable(
   1.424 +        PKIX_PL_Object *object,
   1.425 +        PKIX_PL_Object **pNewObject,
   1.426 +        void *plContext)
   1.427 +{
   1.428 +        PKIX_ENTER(OBJECT, "pkix_duplicateImmutable");
   1.429 +        PKIX_NULLCHECK_TWO(object, pNewObject);
   1.430 +
   1.431 +        PKIX_INCREF(object);
   1.432 +
   1.433 +        *pNewObject = object;
   1.434 +
   1.435 +cleanup:
   1.436 +        PKIX_RETURN(OBJECT);
   1.437 +}
   1.438 +
   1.439 +/* --String-Encoding-Conversion-Functions------------------------ */
   1.440 +
   1.441 +/*
   1.442 + * FUNCTION: pkix_hex2i
   1.443 + * DESCRIPTION:
   1.444 + *
   1.445 + *  Converts hexadecimal character "c" to its integer value and returns result.
   1.446 + *
   1.447 + * PARAMETERS
   1.448 + *  "c"
   1.449 + *      Character to convert to a hex value.
   1.450 + * THREAD SAFETY:
   1.451 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.452 + * RETURNS:
   1.453 + *  The hexadecimal value of "c". Otherwise -1. (Unsigned 0xFFFFFFFF).
   1.454 + */
   1.455 +PKIX_UInt32
   1.456 +pkix_hex2i(char c)
   1.457 +{
   1.458 +        if ((c >= '0')&&(c <= '9'))
   1.459 +                return (c-'0');
   1.460 +        else if ((c >= 'a')&&(c <= 'f'))
   1.461 +                return (c-'a'+10);
   1.462 +        else if ((c >= 'A')&&(c <= 'F'))
   1.463 +                return (c-'A'+10);
   1.464 +        else
   1.465 +                return ((PKIX_UInt32)(-1));
   1.466 +}
   1.467 +
   1.468 +/*
   1.469 + * FUNCTION: pkix_i2hex
   1.470 + * DESCRIPTION:
   1.471 + *
   1.472 + *  Converts integer value "digit" to its ASCII hex value
   1.473 + *
   1.474 + * PARAMETERS
   1.475 + *  "digit"
   1.476 + *      Value of integer to convert to ASCII hex value. Must be 0-15.
   1.477 + * THREAD SAFETY:
   1.478 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.479 + * RETURNS:
   1.480 + *  The ASCII hexadecimal value of "digit".
   1.481 + */
   1.482 +char
   1.483 +pkix_i2hex(char digit)
   1.484 +{
   1.485 +        if ((digit >= 0)&&(digit <= 9))
   1.486 +                return (digit+'0');
   1.487 +        else if ((digit >= 0xa)&&(digit <= 0xf))
   1.488 +                return (digit - 10 + 'a');
   1.489 +        else
   1.490 +                return (-1);
   1.491 +}
   1.492 +
   1.493 +/*
   1.494 + * FUNCTION: pkix_isPlaintext
   1.495 + * DESCRIPTION:
   1.496 + *
   1.497 + *  Returns whether character "c" is plaintext using EscASCII or EscASCII_Debug
   1.498 + *  depending on the value of "debug".
   1.499 + *
   1.500 + *  In EscASCII, [01, 7E] except '&' are plaintext.
   1.501 + *  In EscASCII_Debug [20, 7E] except '&' are plaintext.
   1.502 + *
   1.503 + * PARAMETERS:
   1.504 + *  "c"
   1.505 + *      Character to check.
   1.506 + *  "debug"
   1.507 + *      Value of debug flag.
   1.508 + * THREAD SAFETY:
   1.509 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.510 + * RETURNS:
   1.511 + *  True if "c" is plaintext.
   1.512 + */
   1.513 +PKIX_Boolean
   1.514 +pkix_isPlaintext(unsigned char c, PKIX_Boolean debug) {
   1.515 +        return ((c >= 0x01)&&(c <= 0x7E)&&(c != '&')&&(!debug || (c >= 20)));
   1.516 +}
   1.517 +
   1.518 +/* --Cache-Functions------------------------ */
   1.519 +
   1.520 +/*
   1.521 + * FUNCTION: pkix_CacheCertChain_Lookup
   1.522 + * DESCRIPTION:
   1.523 + *
   1.524 + *  Look up CertChain Hash Table for a cached BuildResult based on "targetCert"
   1.525 + *  and "anchors" as the hash keys. If there is no item to match the key,
   1.526 + *  PKIX_FALSE is stored at "pFound". If an item is found, its cache time is
   1.527 + *  compared to "testDate". If expired, the item is removed and PKIX_FALSE is
   1.528 + *  stored at "pFound". Otherwise, PKIX_TRUE is stored at "pFound" and the 
   1.529 + *  BuildResult is stored at "pBuildResult".
   1.530 + *  The hashtable is maintained in the following ways:
   1.531 + *  1) When creating the hashtable, maximum bucket size can be specified (0 for
   1.532 + *     unlimited). If items in a bucket reaches its full size, an new addition
   1.533 + *     will trigger the removal of the old as FIFO sequence.
   1.534 + *  2) A PKIX_PL_Date created with current time offset by constant 
   1.535 + *     CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
   1.536 + *     When an item is retrieved, this date is compared against "testDate" for
   1.537 + *     validity. If comparison indicates this item is expired, the item is
   1.538 + *     removed from the bucket.
   1.539 + *
   1.540 + * PARAMETERS:
   1.541 + *  "targetCert"
   1.542 + *      Address of Target Cert as key to retrieve this CertChain. Must be 
   1.543 + *      non-NULL.
   1.544 + *  "anchors"
   1.545 + *      Address of PKIX_List of "anchors" is used as key to retrive CertChain.
   1.546 + *      Must be non-NULL.
   1.547 + *  "testDate"
   1.548 + *      Address of PKIX_PL_Date for verifying time validity and cache validity.
   1.549 + *      May be NULL. If testDate is NULL, this cache item will not be out-dated.
   1.550 + *  "pFound"
   1.551 + *      Address of PKIX_Boolean indicating valid data is found.
   1.552 + *      Must be non-NULL.
   1.553 + *  "pBuildResult"
   1.554 + *      Address where BuildResult will be stored. Must be non-NULL.
   1.555 + *  "plContext"
   1.556 + *      Platform-specific context pointer.
   1.557 + * THREAD SAFETY:
   1.558 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.559 + * RETURNS:
   1.560 + *  Returns NULL if the function succeeds.
   1.561 + *  Returns an Error Error if the function fails in a non-fatal way.
   1.562 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.563 + */
   1.564 +PKIX_Error *
   1.565 +pkix_CacheCertChain_Lookup(
   1.566 +        PKIX_PL_Cert* targetCert,
   1.567 +        PKIX_List* anchors,
   1.568 +        PKIX_PL_Date *testDate,
   1.569 +        PKIX_Boolean *pFound,
   1.570 +        PKIX_BuildResult **pBuildResult,
   1.571 +        void *plContext)
   1.572 +{
   1.573 +        PKIX_List *cachedValues = NULL;
   1.574 +        PKIX_List *cachedKeys = NULL;
   1.575 +        PKIX_Error *cachedCertChainError = NULL;
   1.576 +        PKIX_PL_Date *cacheValidUntilDate = NULL;
   1.577 +        PKIX_PL_Date *validityDate = NULL;
   1.578 +        PKIX_Int32 cmpValidTimeResult = 0;
   1.579 +        PKIX_Int32 cmpCacheTimeResult = 0;
   1.580 +
   1.581 +        PKIX_ENTER(BUILD, "pkix_CacheCertChain_Lookup");
   1.582 +
   1.583 +        PKIX_NULLCHECK_FOUR(targetCert, anchors, pFound, pBuildResult);
   1.584 +
   1.585 +        *pFound = PKIX_FALSE;
   1.586 +
   1.587 +        /* use trust anchors and target cert as hash key */
   1.588 +
   1.589 +        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
   1.590 +                    PKIX_LISTCREATEFAILED);
   1.591 +
   1.592 +        PKIX_CHECK(PKIX_List_AppendItem
   1.593 +                    (cachedKeys,
   1.594 +                    (PKIX_PL_Object *)targetCert,
   1.595 +                    plContext),
   1.596 +                    PKIX_LISTAPPENDITEMFAILED);
   1.597 +
   1.598 +        PKIX_CHECK(PKIX_List_AppendItem
   1.599 +                    (cachedKeys,
   1.600 +                    (PKIX_PL_Object *)anchors,
   1.601 +                    plContext),
   1.602 +                    PKIX_LISTAPPENDITEMFAILED);
   1.603 +
   1.604 +        cachedCertChainError = PKIX_PL_HashTable_Lookup
   1.605 +                    (cachedCertChainTable,
   1.606 +                    (PKIX_PL_Object *) cachedKeys,
   1.607 +                    (PKIX_PL_Object **) &cachedValues,
   1.608 +                    plContext);
   1.609 +
   1.610 +        pkix_ccLookupCount++;
   1.611 +
   1.612 +        /* retrieve data from hashed value list */
   1.613 +
   1.614 +        if (cachedValues != NULL && cachedCertChainError == NULL) {
   1.615 +
   1.616 +            PKIX_CHECK(PKIX_List_GetItem
   1.617 +                    (cachedValues,
   1.618 +                    0,
   1.619 +                    (PKIX_PL_Object **) &cacheValidUntilDate,
   1.620 +                    plContext),
   1.621 +                    PKIX_LISTGETITEMFAILED);
   1.622 +
   1.623 +            /* check validity time and cache age time */
   1.624 +            PKIX_CHECK(PKIX_List_GetItem
   1.625 +                    (cachedValues,
   1.626 +                    1,
   1.627 +                    (PKIX_PL_Object **) &validityDate,
   1.628 +                    plContext),
   1.629 +                    PKIX_LISTGETITEMFAILED);
   1.630 +
   1.631 +            /* if testDate is not set, this cache item is not out-dated */
   1.632 +            if (testDate) {
   1.633 +
   1.634 +                PKIX_CHECK(PKIX_PL_Object_Compare
   1.635 +                     ((PKIX_PL_Object *)testDate,
   1.636 +                     (PKIX_PL_Object *)cacheValidUntilDate,
   1.637 +                     &cmpCacheTimeResult,
   1.638 +                     plContext),
   1.639 +                     PKIX_OBJECTCOMPARATORFAILED);
   1.640 +
   1.641 +                PKIX_CHECK(PKIX_PL_Object_Compare
   1.642 +                     ((PKIX_PL_Object *)testDate,
   1.643 +                     (PKIX_PL_Object *)validityDate,
   1.644 +                     &cmpValidTimeResult,
   1.645 +                     plContext),
   1.646 +                     PKIX_OBJECTCOMPARATORFAILED);
   1.647 +            }
   1.648 +
   1.649 +            /* certs' date are all valid and cache item is not old */
   1.650 +            if (cmpValidTimeResult <= 0 && cmpCacheTimeResult <=0) {
   1.651 +
   1.652 +                PKIX_CHECK(PKIX_List_GetItem
   1.653 +                    (cachedValues,
   1.654 +                    2,
   1.655 +                    (PKIX_PL_Object **) pBuildResult,
   1.656 +                    plContext),
   1.657 +                    PKIX_LISTGETITEMFAILED);
   1.658 +
   1.659 +                *pFound = PKIX_TRUE;
   1.660 +
   1.661 +            } else {
   1.662 +
   1.663 +                pkix_ccRemoveCount++;
   1.664 +                *pFound = PKIX_FALSE;
   1.665 +
   1.666 +                /* out-dated item, remove it from cache */
   1.667 +                PKIX_CHECK(PKIX_PL_HashTable_Remove
   1.668 +                    (cachedCertChainTable,
   1.669 +                    (PKIX_PL_Object *) cachedKeys,
   1.670 +                    plContext),
   1.671 +                    PKIX_HASHTABLEREMOVEFAILED);
   1.672 +            }
   1.673 +        }
   1.674 +
   1.675 +cleanup:
   1.676 +
   1.677 +        PKIX_DECREF(cachedValues);
   1.678 +        PKIX_DECREF(cachedKeys);
   1.679 +        PKIX_DECREF(cachedCertChainError);
   1.680 +        PKIX_DECREF(cacheValidUntilDate);
   1.681 +        PKIX_DECREF(validityDate);
   1.682 +
   1.683 +        PKIX_RETURN(BUILD);
   1.684 +
   1.685 +}
   1.686 +
   1.687 +/*
   1.688 + * FUNCTION: pkix_CacheCertChain_Remove
   1.689 + * DESCRIPTION:
   1.690 + *
   1.691 + *  Remove CertChain Hash Table entry based on "targetCert" and "anchors"
   1.692 + *  as the hash keys. If there is no item to match the key, no action is
   1.693 + *  taken.
   1.694 + *  The hashtable is maintained in the following ways:
   1.695 + *  1) When creating the hashtable, maximum bucket size can be specified (0 for
   1.696 + *     unlimited). If items in a bucket reaches its full size, an new addition
   1.697 + *     will trigger the removal of the old as FIFO sequence.
   1.698 + *  2) A PKIX_PL_Date created with current time offset by constant 
   1.699 + *     CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
   1.700 + *     When an item is retrieved, this date is compared against "testDate" for
   1.701 + *     validity. If comparison indicates this item is expired, the item is
   1.702 + *     removed from the bucket.
   1.703 + *
   1.704 + * PARAMETERS:
   1.705 + *  "targetCert"
   1.706 + *      Address of Target Cert as key to retrieve this CertChain. Must be 
   1.707 + *      non-NULL.
   1.708 + *  "anchors"
   1.709 + *      Address of PKIX_List of "anchors" is used as key to retrive CertChain.
   1.710 + *      Must be non-NULL.
   1.711 + *  "plContext"
   1.712 + *      Platform-specific context pointer.
   1.713 + * THREAD SAFETY:
   1.714 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.715 + * RETURNS:
   1.716 + *  Returns NULL if the function succeeds.
   1.717 + *  Returns an Error Error if the function fails in a non-fatal way.
   1.718 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.719 + */
   1.720 +PKIX_Error *
   1.721 +pkix_CacheCertChain_Remove(
   1.722 +        PKIX_PL_Cert* targetCert,
   1.723 +        PKIX_List* anchors,
   1.724 +        void *plContext)
   1.725 +{
   1.726 +        PKIX_List *cachedKeys = NULL;
   1.727 +
   1.728 +        PKIX_ENTER(BUILD, "pkix_CacheCertChain_Remove");
   1.729 +        PKIX_NULLCHECK_TWO(targetCert, anchors);
   1.730 +
   1.731 +        /* use trust anchors and target cert as hash key */
   1.732 +
   1.733 +        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
   1.734 +                    PKIX_LISTCREATEFAILED);
   1.735 +
   1.736 +        PKIX_CHECK(PKIX_List_AppendItem
   1.737 +                    (cachedKeys,
   1.738 +                    (PKIX_PL_Object *)targetCert,
   1.739 +                    plContext),
   1.740 +                    PKIX_LISTAPPENDITEMFAILED);
   1.741 +
   1.742 +        PKIX_CHECK(PKIX_List_AppendItem
   1.743 +                    (cachedKeys,
   1.744 +                    (PKIX_PL_Object *)anchors,
   1.745 +                    plContext),
   1.746 +                    PKIX_LISTAPPENDITEMFAILED);
   1.747 +
   1.748 +        PKIX_CHECK_ONLY_FATAL(PKIX_PL_HashTable_Remove
   1.749 +                    (cachedCertChainTable,
   1.750 +                    (PKIX_PL_Object *) cachedKeys,
   1.751 +                    plContext),
   1.752 +                    PKIX_HASHTABLEREMOVEFAILED);
   1.753 +
   1.754 +        pkix_ccRemoveCount++;
   1.755 +
   1.756 +cleanup:
   1.757 +
   1.758 +        PKIX_DECREF(cachedKeys);
   1.759 +
   1.760 +        PKIX_RETURN(BUILD);
   1.761 +
   1.762 +}
   1.763 +
   1.764 +/*
   1.765 + * FUNCTION: pkix_CacheCertChain_Add
   1.766 + * DESCRIPTION:
   1.767 + *
   1.768 + *  Add a BuildResult to the CertChain Hash Table for a "buildResult" with
   1.769 + *  "targetCert" and "anchors" as the hash keys.
   1.770 + *  "validityDate" is the most restricted notAfter date of all Certs in
   1.771 + *  this CertChain and is verified when this BuildChain is retrieved.
   1.772 + *  The hashtable is maintained in the following ways:
   1.773 + *  1) When creating the hashtable, maximum bucket size can be specified (0 for
   1.774 + *     unlimited). If items in a bucket reaches its full size, an new addition
   1.775 + *     will trigger the removal of the old as FIFO sequence.
   1.776 + *  2) A PKIX_PL_Date created with current time offset by constant 
   1.777 + *     CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
   1.778 + *     When an item is retrieved, this date is compared against "testDate" for
   1.779 + *     validity. If comparison indicates this item is expired, the item is
   1.780 + *     removed from the bucket.
   1.781 + *
   1.782 + * PARAMETERS:
   1.783 + *  "targetCert"
   1.784 + *      Address of Target Cert as key to retrieve this CertChain. Must be 
   1.785 + *      non-NULL.
   1.786 + *  "anchors"
   1.787 + *      Address of PKIX_List of "anchors" is used as key to retrive CertChain.
   1.788 + *      Must be non-NULL.
   1.789 + *  "validityDate"
   1.790 + *      Address of PKIX_PL_Date contains the most restriced notAfter time of
   1.791 + *      all "certs". Must be non-NULL.
   1.792 + *      Address of PKIX_Boolean indicating valid data is found.
   1.793 + *      Must be non-NULL.
   1.794 + *  "buildResult"
   1.795 + *      Address of BuildResult to be cached. Must be non-NULL.
   1.796 + *  "plContext"
   1.797 + *      Platform-specific context pointer.
   1.798 + * THREAD SAFETY:
   1.799 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.800 + * RETURNS:
   1.801 + *  Returns NULL if the function succeeds.
   1.802 + *  Returns an Error Error if the function fails in a non-fatal way.
   1.803 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.804 + */
   1.805 +PKIX_Error *
   1.806 +pkix_CacheCertChain_Add(
   1.807 +        PKIX_PL_Cert* targetCert,
   1.808 +        PKIX_List* anchors,
   1.809 +        PKIX_PL_Date *validityDate,
   1.810 +        PKIX_BuildResult *buildResult,
   1.811 +        void *plContext)
   1.812 +{
   1.813 +        PKIX_List *cachedValues = NULL;
   1.814 +        PKIX_List *cachedKeys = NULL;
   1.815 +        PKIX_Error *cachedCertChainError = NULL;
   1.816 +        PKIX_PL_Date *cacheValidUntilDate = NULL;
   1.817 +
   1.818 +        PKIX_ENTER(BUILD, "pkix_CacheCertChain_Add");
   1.819 +
   1.820 +        PKIX_NULLCHECK_FOUR(targetCert, anchors, validityDate, buildResult);
   1.821 +
   1.822 +        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
   1.823 +                PKIX_LISTCREATEFAILED);
   1.824 +
   1.825 +        PKIX_CHECK(PKIX_List_AppendItem
   1.826 +                (cachedKeys, (PKIX_PL_Object *)targetCert, plContext),
   1.827 +                PKIX_LISTAPPENDITEMFAILED);
   1.828 +
   1.829 +        PKIX_CHECK(PKIX_List_AppendItem
   1.830 +                (cachedKeys, (PKIX_PL_Object *)anchors, plContext),
   1.831 +                PKIX_LISTAPPENDITEMFAILED);
   1.832 +
   1.833 +        PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext),
   1.834 +                PKIX_LISTCREATEFAILED);
   1.835 +
   1.836 +        PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
   1.837 +                (CACHE_ITEM_PERIOD_SECONDS,
   1.838 +                &cacheValidUntilDate,
   1.839 +                plContext),
   1.840 +               PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
   1.841 +
   1.842 +        PKIX_CHECK(PKIX_List_AppendItem
   1.843 +                (cachedValues,
   1.844 +                (PKIX_PL_Object *)cacheValidUntilDate,
   1.845 +                plContext),
   1.846 +                PKIX_LISTAPPENDITEMFAILED);
   1.847 +
   1.848 +        PKIX_CHECK(PKIX_List_AppendItem
   1.849 +                (cachedValues, (PKIX_PL_Object *)validityDate, plContext),
   1.850 +                PKIX_LISTAPPENDITEMFAILED);
   1.851 +
   1.852 +        PKIX_CHECK(PKIX_List_AppendItem
   1.853 +                (cachedValues, (PKIX_PL_Object *)buildResult, plContext),
   1.854 +                PKIX_LISTAPPENDITEMFAILED);
   1.855 +
   1.856 +        cachedCertChainError = PKIX_PL_HashTable_Add
   1.857 +                (cachedCertChainTable,
   1.858 +                (PKIX_PL_Object *) cachedKeys,
   1.859 +                (PKIX_PL_Object *) cachedValues,
   1.860 +                plContext);
   1.861 +
   1.862 +        pkix_ccAddCount++;
   1.863 +
   1.864 +        if (cachedCertChainError != NULL) {
   1.865 +                PKIX_DEBUG("PKIX_PL_HashTable_Add for CertChain skipped: "
   1.866 +                        "entry existed\n");
   1.867 +        }
   1.868 +
   1.869 +cleanup:
   1.870 +
   1.871 +        PKIX_DECREF(cachedValues);
   1.872 +        PKIX_DECREF(cachedKeys);
   1.873 +        PKIX_DECREF(cachedCertChainError);
   1.874 +        PKIX_DECREF(cacheValidUntilDate);
   1.875 +
   1.876 +        PKIX_RETURN(BUILD);
   1.877 +}
   1.878 +
   1.879 +/*
   1.880 + * FUNCTION: pkix_CacheCert_Lookup
   1.881 + * DESCRIPTION:
   1.882 + *
   1.883 + *  Look up Cert Hash Table for a cached item based on "store" and Subject in
   1.884 + *  "certSelParams" as the hash keys and returns values Certs in "pCerts".
   1.885 + *  If there isn't an item to match the key, a PKIX_FALSE is returned at
   1.886 + *  "pFound". The item's cache time is verified with "testDate". If out-dated,
   1.887 + *  this item is removed and PKIX_FALSE is returned at "pFound".
   1.888 + *  This hashtable is maintained in the following ways:
   1.889 + *  1) When creating the hashtable, maximum bucket size can be specified (0 for
   1.890 + *     unlimited). If items in a bucket reaches its full size, an new addition
   1.891 + *     will trigger the removal of the old as FIFO sequence.
   1.892 + *  2) A PKIX_PL_Date created with current time offset by constant 
   1.893 + *     CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
   1.894 + *     If the CertStore this Cert is from is a trusted one, the cache period is
   1.895 + *     shorter so cache can be updated more frequently.
   1.896 + *     When an item is retrieved, this date is compared against "testDate" for
   1.897 + *     validity. If comparison indicates this item is expired, the item is
   1.898 + *     removed from the bucket.
   1.899 + *
   1.900 + * PARAMETERS:
   1.901 + *  "store"
   1.902 + *      Address of CertStore as key to retrieve this CertChain. Must be 
   1.903 + *      non-NULL.
   1.904 + *  "certSelParams"
   1.905 + *      Address of ComCertSelParams that its subject is used as key to retrieve
   1.906 + *      this CertChain. Must be non-NULL.
   1.907 + *  "testDate"
   1.908 + *      Address of PKIX_PL_Date for verifying time cache validity.
   1.909 + *      Must be non-NULL. If testDate is NULL, this cache item won't be out
   1.910 + *      dated.
   1.911 + *  "pFound"
   1.912 + *      Address of KPKIX_Boolean indicating valid data is found.
   1.913 + *      Must be non-NULL.
   1.914 + *  "pCerts"
   1.915 + *      Address PKIX_List where the CertChain will be stored. Must be no-NULL.
   1.916 + *  "plContext"
   1.917 + *      Platform-specific context pointer.
   1.918 + * THREAD SAFETY:
   1.919 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.920 + * RETURNS:
   1.921 + *  Returns NULL if the function succeeds.
   1.922 + *  Returns an Error Error if the function fails in a non-fatal way.
   1.923 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.924 + */
   1.925 +PKIX_Error *
   1.926 +pkix_CacheCert_Lookup(
   1.927 +        PKIX_CertStore *store,
   1.928 +        PKIX_ComCertSelParams *certSelParams,
   1.929 +        PKIX_PL_Date *testDate,
   1.930 +        PKIX_Boolean *pFound,
   1.931 +        PKIX_List** pCerts,
   1.932 +        void *plContext)
   1.933 +{
   1.934 +        PKIX_PL_Cert *cert = NULL;
   1.935 +        PKIX_List *cachedKeys = NULL;
   1.936 +        PKIX_List *cachedValues = NULL;
   1.937 +        PKIX_List *cachedCertList = NULL;
   1.938 +        PKIX_List *selCertList = NULL;
   1.939 +        PKIX_PL_X500Name *subject = NULL;
   1.940 +        PKIX_PL_Date *invalidAfterDate = NULL;
   1.941 +        PKIX_PL_Date *cacheValidUntilDate = NULL;
   1.942 +        PKIX_CertSelector *certSel = NULL;
   1.943 +        PKIX_Error *cachedCertError = NULL;
   1.944 +        PKIX_Error *selectorError = NULL;
   1.945 +        PKIX_CertSelector_MatchCallback selectorMatch = NULL;
   1.946 +        PKIX_Int32 cmpValidTimeResult = PKIX_FALSE;
   1.947 +        PKIX_Int32 cmpCacheTimeResult = 0;
   1.948 +        PKIX_UInt32 numItems = 0;
   1.949 +        PKIX_UInt32 i;
   1.950 +
   1.951 +        PKIX_ENTER(BUILD, "pkix_CacheCert_Lookup");
   1.952 +        PKIX_NULLCHECK_TWO(store, certSelParams);
   1.953 +        PKIX_NULLCHECK_TWO(pFound, pCerts);
   1.954 +
   1.955 +        *pFound = PKIX_FALSE;
   1.956 +
   1.957 +        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
   1.958 +                PKIX_LISTCREATEFAILED);
   1.959 +
   1.960 +        PKIX_CHECK(PKIX_List_AppendItem
   1.961 +                (cachedKeys, (PKIX_PL_Object *)store, plContext),
   1.962 +                PKIX_LISTAPPENDITEMFAILED);
   1.963 +
   1.964 +        PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
   1.965 +                (certSelParams, &subject, plContext),
   1.966 +                PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
   1.967 +
   1.968 +        PKIX_NULLCHECK_ONE(subject);
   1.969 +
   1.970 +        PKIX_CHECK(PKIX_List_AppendItem
   1.971 +                (cachedKeys, (PKIX_PL_Object *)subject, plContext),
   1.972 +                PKIX_LISTAPPENDITEMFAILED);
   1.973 +
   1.974 +        cachedCertError = PKIX_PL_HashTable_Lookup
   1.975 +                    (cachedCertTable,
   1.976 +                    (PKIX_PL_Object *) cachedKeys,
   1.977 +                    (PKIX_PL_Object **) &cachedValues,
   1.978 +                    plContext);
   1.979 +        pkix_cLookupCount++;
   1.980 +
   1.981 +        if (cachedValues != NULL && cachedCertError == NULL) {
   1.982 +
   1.983 +                PKIX_CHECK(PKIX_List_GetItem
   1.984 +                        (cachedValues,
   1.985 +                        0,
   1.986 +                        (PKIX_PL_Object **) &cacheValidUntilDate,
   1.987 +                        plContext),
   1.988 +                        PKIX_LISTGETITEMFAILED);
   1.989 +
   1.990 +                if (testDate) {
   1.991 +                    PKIX_CHECK(PKIX_PL_Object_Compare
   1.992 +                         ((PKIX_PL_Object *)testDate,
   1.993 +                         (PKIX_PL_Object *)cacheValidUntilDate,
   1.994 +                         &cmpCacheTimeResult,
   1.995 +                         plContext),
   1.996 +                         PKIX_OBJECTCOMPARATORFAILED);
   1.997 +                }
   1.998 +
   1.999 +                if (cmpCacheTimeResult <= 0) {
  1.1000 +
  1.1001 +                    PKIX_CHECK(PKIX_List_GetItem
  1.1002 +                        (cachedValues,
  1.1003 +                        1,
  1.1004 +                        (PKIX_PL_Object **) &cachedCertList,
  1.1005 +                        plContext),
  1.1006 +                        PKIX_LISTGETITEMFAILED);
  1.1007 +
  1.1008 +                    /*
  1.1009 +                     * Certs put on cache satifies only for Subject,
  1.1010 +                     * user selector and ComCertSelParams to filter.
  1.1011 +                     */
  1.1012 +                    PKIX_CHECK(PKIX_CertSelector_Create
  1.1013 +                          (NULL, NULL, &certSel, plContext),
  1.1014 +                          PKIX_CERTSELECTORCREATEFAILED);
  1.1015 +
  1.1016 +                    PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
  1.1017 +                          (certSel, certSelParams, plContext),
  1.1018 +                          PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
  1.1019 +
  1.1020 +                    PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
  1.1021 +                          (certSel, &selectorMatch, plContext),
  1.1022 +                          PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
  1.1023 +
  1.1024 +                    PKIX_CHECK(PKIX_List_Create(&selCertList, plContext),
  1.1025 +                            PKIX_LISTCREATEFAILED);
  1.1026 +
  1.1027 +                    /* 
  1.1028 +                     * If any of the Cert on the list is out-dated, invalidate
  1.1029 +                     * this cache item.
  1.1030 +                     */
  1.1031 +                    PKIX_CHECK(PKIX_List_GetLength
  1.1032 +                        (cachedCertList, &numItems, plContext),
  1.1033 +                        PKIX_LISTGETLENGTHFAILED);
  1.1034 +
  1.1035 +                    for (i = 0; i < numItems; i++){
  1.1036 +
  1.1037 +                        PKIX_CHECK(PKIX_List_GetItem
  1.1038 +                            (cachedCertList,
  1.1039 +                            i,
  1.1040 +                            (PKIX_PL_Object **)&cert,
  1.1041 +                            plContext),
  1.1042 +                            PKIX_LISTGETITEMFAILED);
  1.1043 +
  1.1044 +                        PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
  1.1045 +                            (cert, &invalidAfterDate, plContext),
  1.1046 +                            PKIX_CERTGETVALIDITYNOTAFTERFAILED);
  1.1047 +
  1.1048 +                        if (testDate) {
  1.1049 +                            PKIX_CHECK(PKIX_PL_Object_Compare
  1.1050 +                                ((PKIX_PL_Object *)invalidAfterDate,
  1.1051 +                                (PKIX_PL_Object *)testDate,
  1.1052 +                                &cmpValidTimeResult,
  1.1053 +                                plContext),
  1.1054 +                                PKIX_OBJECTCOMPARATORFAILED);
  1.1055 +                        }
  1.1056 +
  1.1057 +                        if (cmpValidTimeResult < 0) {
  1.1058 +
  1.1059 +                            pkix_cRemoveCount++;
  1.1060 +                            *pFound = PKIX_FALSE;
  1.1061 +
  1.1062 +                            /* one cert is out-dated, remove item from cache */
  1.1063 +                            PKIX_CHECK(PKIX_PL_HashTable_Remove
  1.1064 +                                    (cachedCertTable,
  1.1065 +                                    (PKIX_PL_Object *) cachedKeys,
  1.1066 +                                    plContext),
  1.1067 +                                    PKIX_HASHTABLEREMOVEFAILED);
  1.1068 +                            goto cleanup;
  1.1069 +                        }
  1.1070 +
  1.1071 +                        selectorError = selectorMatch(certSel, cert, plContext);
  1.1072 +                        if (!selectorError){
  1.1073 +                            /* put on the return list */
  1.1074 +                            PKIX_CHECK(PKIX_List_AppendItem
  1.1075 +                                   (selCertList,
  1.1076 +                                   (PKIX_PL_Object *)cert,
  1.1077 +                                   plContext),
  1.1078 +                                  PKIX_LISTAPPENDITEMFAILED);
  1.1079 +                        } else {
  1.1080 +                            PKIX_DECREF(selectorError);
  1.1081 +                        }
  1.1082 +
  1.1083 +                        PKIX_DECREF(cert);
  1.1084 +                        PKIX_DECREF(invalidAfterDate);
  1.1085 +
  1.1086 +                    }
  1.1087 +
  1.1088 +                    if (*pFound) {
  1.1089 +                        PKIX_INCREF(selCertList);
  1.1090 +                        *pCerts = selCertList;
  1.1091 +                    }
  1.1092 +
  1.1093 +                } else {
  1.1094 +
  1.1095 +                    pkix_cRemoveCount++;
  1.1096 +                    *pFound = PKIX_FALSE;
  1.1097 +                    /* cache item is out-dated, remove it from cache */
  1.1098 +                    PKIX_CHECK(PKIX_PL_HashTable_Remove
  1.1099 +                                (cachedCertTable,
  1.1100 +                                (PKIX_PL_Object *) cachedKeys,
  1.1101 +                                plContext),
  1.1102 +                                PKIX_HASHTABLEREMOVEFAILED);
  1.1103 +                }
  1.1104 +
  1.1105 +        } 
  1.1106 +
  1.1107 +cleanup:
  1.1108 +
  1.1109 +        PKIX_DECREF(subject);
  1.1110 +        PKIX_DECREF(certSel);
  1.1111 +        PKIX_DECREF(cachedKeys);
  1.1112 +        PKIX_DECREF(cachedValues);
  1.1113 +        PKIX_DECREF(cacheValidUntilDate);
  1.1114 +        PKIX_DECREF(cert);
  1.1115 +        PKIX_DECREF(cachedCertList);
  1.1116 +        PKIX_DECREF(selCertList);
  1.1117 +        PKIX_DECREF(invalidAfterDate);
  1.1118 +        PKIX_DECREF(cachedCertError);
  1.1119 +        PKIX_DECREF(selectorError);
  1.1120 +
  1.1121 +        PKIX_RETURN(BUILD);
  1.1122 +}
  1.1123 +
  1.1124 +/*
  1.1125 + * FUNCTION: pkix_CacheCert_Add
  1.1126 + * DESCRIPTION:
  1.1127 + *
  1.1128 + *  Add Cert Hash Table for a cached item based on "store" and Subject in
  1.1129 + *  "certSelParams" as the hash keys and have "certs" as the key value.
  1.1130 + *  This hashtable is maintained in the following ways:
  1.1131 + *  1) When creating the hashtable, maximum bucket size can be specified (0 for
  1.1132 + *     unlimited). If items in a bucket reaches its full size, an new addition
  1.1133 + *     will trigger the removal of the old as FIFO sequence.
  1.1134 + *  2) A PKIX_PL_Date created with current time offset by constant 
  1.1135 + *     CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
  1.1136 + *     If the CertStore this Cert is from is a trusted one, the cache period is
  1.1137 + *     shorter so cache can be updated more frequently.
  1.1138 + *     When an item is retrieved, this date is compared against "testDate" for
  1.1139 + *     validity. If comparison indicates this item is expired, the item is
  1.1140 + *     removed from the bucket.
  1.1141 + *
  1.1142 + * PARAMETERS:
  1.1143 + *  "store"
  1.1144 + *      Address of CertStore as key to retrieve this CertChain. Must be 
  1.1145 + *      non-NULL.
  1.1146 + *  "certSelParams"
  1.1147 + *      Address of ComCertSelParams that its subject is used as key to retrieve
  1.1148 + *      this CertChain. Must be non-NULL.
  1.1149 + *  "certs"
  1.1150 + *      Address PKIX_List of Certs will be stored. Must be no-NULL.
  1.1151 + *  "plContext"
  1.1152 + *      Platform-specific context pointer.
  1.1153 + * THREAD SAFETY:
  1.1154 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.1155 + * RETURNS:
  1.1156 + *  Returns NULL if the function succeeds.
  1.1157 + *  Returns an Error Error if the function fails in a non-fatal way.
  1.1158 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.1159 + */
  1.1160 +PKIX_Error *
  1.1161 +pkix_CacheCert_Add(
  1.1162 +        PKIX_CertStore *store,
  1.1163 +        PKIX_ComCertSelParams *certSelParams,
  1.1164 +        PKIX_List* certs,
  1.1165 +        void *plContext)
  1.1166 +{
  1.1167 +        PKIX_List *cachedKeys = NULL;
  1.1168 +        PKIX_List *cachedValues = NULL;
  1.1169 +        PKIX_PL_Date *cacheValidUntilDate = NULL;
  1.1170 +        PKIX_PL_X500Name *subject = NULL;
  1.1171 +        PKIX_Error *cachedCertError = NULL;
  1.1172 +        PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
  1.1173 +        PKIX_UInt32 cachePeriod = CACHE_ITEM_PERIOD_SECONDS;
  1.1174 +        PKIX_UInt32 numCerts = 0;
  1.1175 +
  1.1176 +        PKIX_ENTER(BUILD, "pkix_CacheCert_Add");
  1.1177 +        PKIX_NULLCHECK_THREE(store, certSelParams, certs);
  1.1178 +
  1.1179 +        PKIX_CHECK(PKIX_List_GetLength(certs, &numCerts,
  1.1180 +                                       plContext),
  1.1181 +                   PKIX_LISTGETLENGTHFAILED);
  1.1182 +        if (numCerts == 0) {
  1.1183 +            /* Don't want to add an empty list. */
  1.1184 +            goto cleanup;
  1.1185 +        }
  1.1186 +
  1.1187 +        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
  1.1188 +                PKIX_LISTCREATEFAILED);
  1.1189 +
  1.1190 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1191 +                (cachedKeys, (PKIX_PL_Object *)store, plContext),
  1.1192 +                PKIX_LISTAPPENDITEMFAILED);
  1.1193 +
  1.1194 +        PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
  1.1195 +                (certSelParams, &subject, plContext),
  1.1196 +                PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
  1.1197 +
  1.1198 +        PKIX_NULLCHECK_ONE(subject);
  1.1199 +
  1.1200 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1201 +                (cachedKeys, (PKIX_PL_Object *)subject, plContext),
  1.1202 +                PKIX_LISTAPPENDITEMFAILED);
  1.1203 +
  1.1204 +        PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext),
  1.1205 +                PKIX_LISTCREATEFAILED);
  1.1206 +
  1.1207 +        PKIX_CHECK(PKIX_CertStore_GetTrustCallback
  1.1208 +                (store, &trustCallback, plContext),
  1.1209 +                PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
  1.1210 +
  1.1211 +        if (trustCallback) {
  1.1212 +                cachePeriod = CACHE_TRUST_ITEM_PERIOD_SECONDS;
  1.1213 +        }
  1.1214 +
  1.1215 +        PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
  1.1216 +               (cachePeriod, &cacheValidUntilDate, plContext),
  1.1217 +               PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
  1.1218 +
  1.1219 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1220 +                (cachedValues,
  1.1221 +                (PKIX_PL_Object *)cacheValidUntilDate,
  1.1222 +                plContext),
  1.1223 +                PKIX_LISTAPPENDITEMFAILED);
  1.1224 +
  1.1225 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1226 +                (cachedValues,
  1.1227 +                (PKIX_PL_Object *)certs,
  1.1228 +                plContext),
  1.1229 +                PKIX_LISTAPPENDITEMFAILED);
  1.1230 +
  1.1231 +        cachedCertError = PKIX_PL_HashTable_Add
  1.1232 +                    (cachedCertTable,
  1.1233 +                    (PKIX_PL_Object *) cachedKeys,
  1.1234 +                    (PKIX_PL_Object *) cachedValues,
  1.1235 +                    plContext);
  1.1236 +
  1.1237 +        pkix_cAddCount++;
  1.1238 +
  1.1239 +        if (cachedCertError != NULL) {
  1.1240 +                PKIX_DEBUG("PKIX_PL_HashTable_Add for Certs skipped: "
  1.1241 +                        "entry existed\n");
  1.1242 +        }
  1.1243 +
  1.1244 +cleanup:
  1.1245 +
  1.1246 +        PKIX_DECREF(subject);
  1.1247 +        PKIX_DECREF(cachedKeys);
  1.1248 +        PKIX_DECREF(cachedValues);
  1.1249 +        PKIX_DECREF(cacheValidUntilDate);
  1.1250 +        PKIX_DECREF(cachedCertError);
  1.1251 +
  1.1252 +        PKIX_RETURN(BUILD);
  1.1253 +}
  1.1254 +
  1.1255 +/*
  1.1256 + * FUNCTION: pkix_CacheCrlEntry_Lookup
  1.1257 + * DESCRIPTION:
  1.1258 + *
  1.1259 + *  Look up CrlEntry Hash Table for a cached item based on "store",
  1.1260 + *  "certIssuer" and "certSerialNumber" as the hash keys and returns values
  1.1261 + *  "pCrls". If there isn't an item to match the key, a PKIX_FALSE is
  1.1262 + *  returned at "pFound".
  1.1263 + *  This hashtable is maintained in the following way:
  1.1264 + *  1) When creating the hashtable, maximum bucket size can be specified (0 for
  1.1265 + *     unlimited). If items in a bucket reaches its full size, an new addition
  1.1266 + *     will trigger the removal of the old as FIFO sequence.
  1.1267 + *
  1.1268 + * PARAMETERS:
  1.1269 + *  "store"
  1.1270 + *      Address of CertStore as key to retrieve this CertChain. Must be 
  1.1271 + *      non-NULL.
  1.1272 + *  "certIssuer"
  1.1273 + *      Address of X500Name that is used as key to retrieve the CRLEntries.
  1.1274 + *      Must be non-NULL.
  1.1275 + *  "certSerialNumber"
  1.1276 + *      Address of BigInt that is used as key to retrieve the CRLEntries.
  1.1277 + *      Must be non-NULL.
  1.1278 + *  "pFound"
  1.1279 + *      Address of KPKIX_Boolean indicating valid data is found.
  1.1280 + *      Must be non-NULL.
  1.1281 + *  "pCrls"
  1.1282 + *      Address PKIX_List where the CRLEntry will be stored. Must be no-NULL.
  1.1283 + *  "plContext"
  1.1284 + *      Platform-specific context pointer.
  1.1285 + * THREAD SAFETY:
  1.1286 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.1287 + * RETURNS:
  1.1288 + *  Returns NULL if the function succeeds.
  1.1289 + *  Returns an Error Error if the function fails in a non-fatal way.
  1.1290 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.1291 + */
  1.1292 +PKIX_Error *
  1.1293 +pkix_CacheCrlEntry_Lookup(
  1.1294 +        PKIX_CertStore *store,
  1.1295 +        PKIX_PL_X500Name *certIssuer,
  1.1296 +        PKIX_PL_BigInt *certSerialNumber,
  1.1297 +        PKIX_Boolean *pFound,
  1.1298 +        PKIX_List** pCrls,
  1.1299 +        void *plContext)
  1.1300 +{
  1.1301 +        PKIX_List *cachedKeys = NULL;
  1.1302 +        PKIX_List *cachedCrlEntryList = NULL;
  1.1303 +        PKIX_Error *cachedCrlEntryError = NULL;
  1.1304 +
  1.1305 +        PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Lookup");
  1.1306 +        PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber);
  1.1307 +        PKIX_NULLCHECK_TWO(pFound, pCrls);
  1.1308 +
  1.1309 +        *pFound = PKIX_FALSE;
  1.1310 +
  1.1311 +        /* Find CrlEntry(s) by issuer and serial number */
  1.1312 +         
  1.1313 +        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
  1.1314 +                    PKIX_LISTCREATEFAILED);
  1.1315 +
  1.1316 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1317 +                    (cachedKeys, (PKIX_PL_Object *)store, plContext),
  1.1318 +                    PKIX_LISTAPPENDITEMFAILED);
  1.1319 +
  1.1320 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1321 +                    (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext),
  1.1322 +                    PKIX_LISTAPPENDITEMFAILED);
  1.1323 +
  1.1324 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1325 +                    (cachedKeys,
  1.1326 +                    (PKIX_PL_Object *)certSerialNumber,
  1.1327 +                    plContext),
  1.1328 +                    PKIX_LISTAPPENDITEMFAILED);
  1.1329 +
  1.1330 +        cachedCrlEntryError = PKIX_PL_HashTable_Lookup
  1.1331 +                    (cachedCrlEntryTable,
  1.1332 +                    (PKIX_PL_Object *) cachedKeys,
  1.1333 +                    (PKIX_PL_Object **) &cachedCrlEntryList,
  1.1334 +                    plContext);
  1.1335 +        pkix_ceLookupCount++;
  1.1336 +
  1.1337 +        /* 
  1.1338 +         * We don't need check Date to invalidate this cache item,
  1.1339 +         * the item is uniquely defined and won't be reverted. Let
  1.1340 +         * the FIFO for cleaning up.
  1.1341 +         */
  1.1342 +
  1.1343 +        if (cachedCrlEntryList != NULL && cachedCrlEntryError == NULL ) {
  1.1344 +
  1.1345 +                PKIX_INCREF(cachedCrlEntryList);
  1.1346 +                *pCrls = cachedCrlEntryList;
  1.1347 +
  1.1348 +                *pFound = PKIX_TRUE;
  1.1349 +
  1.1350 +        } else {
  1.1351 +
  1.1352 +                *pFound = PKIX_FALSE;
  1.1353 +        }
  1.1354 +
  1.1355 +cleanup:
  1.1356 +
  1.1357 +        PKIX_DECREF(cachedKeys);
  1.1358 +        PKIX_DECREF(cachedCrlEntryList);
  1.1359 +        PKIX_DECREF(cachedCrlEntryError);
  1.1360 +
  1.1361 +        PKIX_RETURN(BUILD);
  1.1362 +}
  1.1363 +
  1.1364 +/*
  1.1365 + * FUNCTION: pkix_CacheCrlEntry_Add
  1.1366 + * DESCRIPTION:
  1.1367 + *
  1.1368 + *  Look up CrlEntry Hash Table for a cached item based on "store",
  1.1369 + *  "certIssuer" and "certSerialNumber" as the hash keys and have "pCrls" as
  1.1370 + *  the hash value. If there isn't an item to match the key, a PKIX_FALSE is
  1.1371 + *  returned at "pFound".
  1.1372 + *  This hashtable is maintained in the following way:
  1.1373 + *  1) When creating the hashtable, maximum bucket size can be specified (0 for
  1.1374 + *     unlimited). If items in a bucket reaches its full size, an new addition
  1.1375 + *     will trigger the removal of the old as FIFO sequence.
  1.1376 + *
  1.1377 + * PARAMETERS:
  1.1378 + *  "store"
  1.1379 + *      Address of CertStore as key to retrieve this CertChain. Must be 
  1.1380 + *      non-NULL.
  1.1381 + *  "certIssuer"
  1.1382 + *      Address of X500Name that is used as key to retrieve the CRLEntries.
  1.1383 + *      Must be non-NULL.
  1.1384 + *  "certSerialNumber"
  1.1385 + *      Address of BigInt that is used as key to retrieve the CRLEntries.
  1.1386 + *      Must be non-NULL.
  1.1387 + *  "crls"
  1.1388 + *      Address PKIX_List where the CRLEntry is stored. Must be no-NULL.
  1.1389 + *  "plContext"
  1.1390 + *      Platform-specific context pointer.
  1.1391 + * THREAD SAFETY:
  1.1392 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.1393 + * RETURNS:
  1.1394 + *  Returns NULL if the function succeeds.
  1.1395 + *  Returns an Error Error if the function fails in a non-fatal way.
  1.1396 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.1397 + */
  1.1398 +PKIX_Error *
  1.1399 +pkix_CacheCrlEntry_Add(
  1.1400 +        PKIX_CertStore *store,
  1.1401 +        PKIX_PL_X500Name *certIssuer,
  1.1402 +        PKIX_PL_BigInt *certSerialNumber,
  1.1403 +        PKIX_List* crls,
  1.1404 +        void *plContext)
  1.1405 +{
  1.1406 +        PKIX_List *cachedKeys = NULL;
  1.1407 +        PKIX_Error *cachedCrlEntryError = NULL;
  1.1408 +
  1.1409 +        PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Add");
  1.1410 +        PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber);
  1.1411 +        PKIX_NULLCHECK_ONE(crls);
  1.1412 +
  1.1413 +        /* Add CrlEntry(s) by issuer and serial number */
  1.1414 +         
  1.1415 +        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
  1.1416 +                    PKIX_LISTCREATEFAILED);
  1.1417 +
  1.1418 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1419 +                    (cachedKeys, (PKIX_PL_Object *)store, plContext),
  1.1420 +                    PKIX_LISTAPPENDITEMFAILED);
  1.1421 +
  1.1422 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1423 +                    (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext),
  1.1424 +                    PKIX_LISTAPPENDITEMFAILED);
  1.1425 +
  1.1426 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1427 +                    (cachedKeys,
  1.1428 +                    (PKIX_PL_Object *)certSerialNumber,
  1.1429 +                    plContext),
  1.1430 +                    PKIX_LISTAPPENDITEMFAILED);
  1.1431 +
  1.1432 +        cachedCrlEntryError = PKIX_PL_HashTable_Add
  1.1433 +                    (cachedCrlEntryTable,
  1.1434 +                    (PKIX_PL_Object *) cachedKeys,
  1.1435 +                    (PKIX_PL_Object *) crls,
  1.1436 +                    plContext);
  1.1437 +        pkix_ceAddCount++;
  1.1438 +
  1.1439 +cleanup:
  1.1440 +
  1.1441 +        PKIX_DECREF(cachedKeys);
  1.1442 +        PKIX_DECREF(cachedCrlEntryError);
  1.1443 +
  1.1444 +        PKIX_RETURN(BUILD);
  1.1445 +}
  1.1446 +
  1.1447 +#ifdef PKIX_OBJECT_LEAK_TEST
  1.1448 +
  1.1449 +/* TEST_START_FN and testStartFnStackPosition define at what state
  1.1450 + * of the stack the object leak testing should begin. The condition
  1.1451 + * in pkix_CheckForGeneratedError works the following way: do leak
  1.1452 + * testing if at position testStartFnStackPosition in stack array
  1.1453 + * (fnStackNameArr) we have called function TEST_START_FN.
  1.1454 + * Note, that stack array get filled only when executing libpkix
  1.1455 + * functions.
  1.1456 + * */
  1.1457 +#define TEST_START_FN "PKIX_BuildChain"
  1.1458 +
  1.1459 +PKIX_Error*
  1.1460 +pkix_CheckForGeneratedError(PKIX_StdVars * stdVars, 
  1.1461 +                            PKIX_ERRORCLASS errClass, 
  1.1462 +                            char * fnName,
  1.1463 +                            PKIX_Boolean *errSetFlag,
  1.1464 +                            void * plContext)
  1.1465 +{
  1.1466 +    PKIX_Error *genErr = NULL;
  1.1467 +    PKIX_UInt32 pos = 0;
  1.1468 +    PKIX_UInt32 strLen = 0;
  1.1469 +
  1.1470 +    if (fnName) { 
  1.1471 +        if (fnStackNameArr[testStartFnStackPosition] == NULL ||
  1.1472 +            strcmp(fnStackNameArr[testStartFnStackPosition], TEST_START_FN)
  1.1473 +            ) {
  1.1474 +            /* return with out error if not with in boundary */
  1.1475 +            return NULL;
  1.1476 +        }
  1.1477 +        if (!strcmp(fnName, TEST_START_FN)) {
  1.1478 +            *errSetFlag = PKIX_TRUE;
  1.1479 +            noErrorState = PKIX_FALSE;
  1.1480 +            errorGenerated = PKIX_FALSE;
  1.1481 +        }
  1.1482 +    }   
  1.1483 +
  1.1484 +    if (noErrorState || errorGenerated)  return NULL;
  1.1485 +
  1.1486 +    if (fnName && (
  1.1487 +        !strcmp(fnName, "PKIX_PL_Object_DecRef") ||
  1.1488 +        !strcmp(fnName, "PKIX_PL_Object_Unlock") ||
  1.1489 +        !strcmp(fnName, "pkix_UnlockObject") ||
  1.1490 +        !strcmp(fnName, "pkix_Throw") ||
  1.1491 +        !strcmp(fnName, "pkix_trace_dump_cert") ||
  1.1492 +        !strcmp(fnName, "PKIX_PL_Free"))) {
  1.1493 +        /* do not generate error for this functions */
  1.1494 +        noErrorState = PKIX_TRUE;
  1.1495 +        *errSetFlag = PKIX_TRUE;
  1.1496 +        return NULL;
  1.1497 +    }
  1.1498 +
  1.1499 +    if (PL_HashTableLookup(fnInvTable, &fnStackInvCountArr[stackPosition - 1])) {
  1.1500 +        return NULL;
  1.1501 +    }
  1.1502 +
  1.1503 +    PL_HashTableAdd(fnInvTable, &fnStackInvCountArr[stackPosition - 1], nonNullValue);
  1.1504 +    errorGenerated = PKIX_TRUE;
  1.1505 +    noErrorState = PKIX_TRUE;
  1.1506 +    genErr = PKIX_DoThrow(stdVars, errClass, PKIX_MEMLEAKGENERATEDERROR,
  1.1507 +                          errClass, plContext);
  1.1508 +    while(fnStackNameArr[pos]) {
  1.1509 +        strLen += PORT_Strlen(fnStackNameArr[pos++]) + 1;
  1.1510 +    }
  1.1511 +    strLen += 1; /* end of line. */
  1.1512 +    pos = 0;
  1.1513 +    errorFnStackString = PORT_ZAlloc(strLen);
  1.1514 +    while(fnStackNameArr[pos]) {
  1.1515 +        strcat(errorFnStackString, "/");
  1.1516 +        strcat(errorFnStackString, fnStackNameArr[pos++]);
  1.1517 +    }
  1.1518 +    noErrorState = PKIX_FALSE;
  1.1519 +    
  1.1520 +    return genErr;
  1.1521 +}
  1.1522 +#endif /* PKIX_OBJECT_LEAK_TEST */

mercurial