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

Packit 40b132
/* This Source Code Form is subject to the terms of the Mozilla Public
Packit 40b132
 * License, v. 2.0. If a copy of the MPL was not distributed with this
Packit 40b132
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Packit 40b132
/*
Packit 40b132
 * pkix_tools.c
Packit 40b132
 *
Packit 40b132
 * Private Utility Functions
Packit 40b132
 *
Packit 40b132
 */
Packit 40b132
Packit 40b132
#include "pkix_tools.h"
Packit 40b132
Packit 40b132
#define CACHE_ITEM_PERIOD_SECONDS  (3600)  /* one hour */
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * This cahce period is only for CertCache. A Cert from a trusted CertStore
Packit 40b132
 * should be checked more frequently for update new arrival, etc.
Packit 40b132
 */
Packit 40b132
#define CACHE_TRUST_ITEM_PERIOD_SECONDS  (CACHE_ITEM_PERIOD_SECONDS/10)
Packit 40b132
Packit 40b132
extern PKIX_PL_HashTable *cachedCertChainTable;
Packit 40b132
extern PKIX_PL_HashTable *cachedCertTable;
Packit 40b132
extern PKIX_PL_HashTable *cachedCrlEntryTable;
Packit 40b132
Packit 40b132
/* Following variables are used to checked cache hits - can be taken out */
Packit 40b132
extern int pkix_ccAddCount;
Packit 40b132
extern int pkix_ccLookupCount;
Packit 40b132
extern int pkix_ccRemoveCount;
Packit 40b132
extern int pkix_cAddCount;
Packit 40b132
extern int pkix_cLookupCount;
Packit 40b132
extern int pkix_cRemoveCount;
Packit 40b132
extern int pkix_ceAddCount;
Packit 40b132
extern int pkix_ceLookupCount;
Packit 40b132
Packit 40b132
#ifdef PKIX_OBJECT_LEAK_TEST
Packit 40b132
/* Following variables are used for object leak test */
Packit 40b132
char *nonNullValue = "Non Empty Value";
Packit 40b132
PKIX_Boolean noErrorState = PKIX_TRUE;
Packit 40b132
PKIX_Boolean runningLeakTest;
Packit 40b132
PKIX_Boolean errorGenerated;
Packit 40b132
PKIX_UInt32 stackPosition;
Packit 40b132
PKIX_UInt32 *fnStackInvCountArr;
Packit 40b132
char **fnStackNameArr;
Packit 40b132
PLHashTable *fnInvTable;
Packit 40b132
PKIX_UInt32 testStartFnStackPosition;
Packit 40b132
char *errorFnStackString;
Packit 40b132
#endif /* PKIX_OBJECT_LEAK_TEST */
Packit 40b132
Packit 40b132
/* --Private-Functions-------------------------------------------- */
Packit 40b132
Packit 40b132
#ifdef PKIX_OBJECT_LEAK_TEST
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_ErrorGen_Hash
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 * Hash function to be used in object leak test hash table.
Packit 40b132
 *
Packit 40b132
 */
Packit 40b132
PLHashNumber PR_CALLBACK
Packit 40b132
pkix_ErrorGen_Hash (const void *key)
Packit 40b132
{
Packit 40b132
    char *str = NULL;
Packit 40b132
    PLHashNumber rv = (*(PRUint8*)key) << 5;
Packit 40b132
    PRUint32 i, counter = 0;
Packit 40b132
    PRUint8 *rvc = (PRUint8 *)&rv;
Packit 40b132
Packit 40b132
    while ((str = fnStackNameArr[counter++]) != NULL) {
Packit 40b132
        PRUint32 len = strlen(str);
Packit 40b132
        for( i = 0; i < len; i++ ) {
Packit 40b132
            rvc[ i % sizeof(rv) ] ^= *str;
Packit 40b132
            str++;
Packit 40b132
        }
Packit 40b132
    }
Packit 40b132
Packit 40b132
    return rv;
Packit 40b132
}
Packit 40b132
Packit 40b132
#endif /* PKIX_OBJECT_LEAK_TEST */
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_IsCertSelfIssued
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Checks whether the Cert pointed to by "cert" is self-issued and stores the
Packit 40b132
 *  Boolean result at "pSelfIssued". A Cert is considered self-issued if the
Packit 40b132
 *  Cert's issuer matches the Cert's subject. If the subject or issuer is
Packit 40b132
 *  not specified, a PKIX_FALSE is returned.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "cert"
Packit 40b132
 *      Address of Cert used to determine whether Cert is self-issued.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "pSelfIssued"
Packit 40b132
 *      Address where Boolean will be stored. Must be non-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns a Cert Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_IsCertSelfIssued(
Packit 40b132
        PKIX_PL_Cert *cert,
Packit 40b132
        PKIX_Boolean *pSelfIssued,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_PL_X500Name *subject = NULL;
Packit 40b132
        PKIX_PL_X500Name *issuer = NULL;
Packit 40b132
Packit 40b132
        PKIX_ENTER(CERT, "pkix_IsCertSelfIssued");
Packit 40b132
        PKIX_NULLCHECK_TWO(cert, pSelfIssued);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &subject, plContext),
Packit 40b132
                    PKIX_CERTGETSUBJECTFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_PL_Cert_GetIssuer(cert, &issuer, plContext),
Packit 40b132
                    PKIX_CERTGETISSUERFAILED);
Packit 40b132
Packit 40b132
        if (subject == NULL || issuer == NULL) {
Packit 40b132
                *pSelfIssued = PKIX_FALSE;
Packit 40b132
        } else {
Packit 40b132
Packit 40b132
                PKIX_CHECK(PKIX_PL_X500Name_Match
Packit 40b132
                    (subject, issuer, pSelfIssued, plContext),
Packit 40b132
                    PKIX_X500NAMEMATCHFAILED);
Packit 40b132
        }
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
        PKIX_DECREF(subject);
Packit 40b132
        PKIX_DECREF(issuer);
Packit 40b132
Packit 40b132
        PKIX_RETURN(CERT);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_Throw
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Creates an Error using the value of "errorCode", the character array
Packit 40b132
 *  pointed to by "funcName", the character array pointed to by "errorText",
Packit 40b132
 *  and the Error pointed to by "cause" (if any), and stores it at "pError".
Packit 40b132
 *
Packit 40b132
 *  If "cause" is not NULL and has an errorCode of "PKIX_FATAL_ERROR",
Packit 40b132
 *  then there is no point creating a new Error object. Rather, we simply
Packit 40b132
 *  store "cause" at "pError".
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "errorCode"
Packit 40b132
 *      Value of error code.
Packit 40b132
 *  "funcName"
Packit 40b132
 *      Address of EscASCII array representing name of function throwing error.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "errnum"
Packit 40b132
 *      PKIX_ERRMSGNUM of error description for new error.
Packit 40b132
 *  "cause"
Packit 40b132
 *      Address of Error representing error's cause.
Packit 40b132
 *  "pError"
Packit 40b132
 *      Address where object pointer will be stored. Must be non-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns an Error Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_Throw(
Packit 40b132
        PKIX_ERRORCLASS errorClass,
Packit 40b132
        const char *funcName,
Packit 40b132
        PKIX_ERRORCODE errorCode,
Packit 40b132
        PKIX_ERRORCLASS overrideClass,
Packit 40b132
        PKIX_Error *cause,
Packit 40b132
        PKIX_Error **pError,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_Error *error = NULL;
Packit 40b132
Packit 40b132
        PKIX_ENTER(ERROR, "pkix_Throw");
Packit 40b132
        PKIX_NULLCHECK_TWO(funcName, pError);
Packit 40b132
Packit 40b132
        *pError = NULL;
Packit 40b132
Packit 40b132
#ifdef PKIX_OBJECT_LEAK_TEST        
Packit 40b132
        noErrorState = PKIX_TRUE;
Packit 40b132
        if (pkixLog) {
Packit 40b132
#ifdef PKIX_ERROR_DESCRIPTION            
Packit 40b132
            PR_LOG(pkixLog, 4, ("Error in function \"%s\":\"%s\" with cause \"%s\"\n",
Packit 40b132
                                funcName, PKIX_ErrorText[errorCode],
Packit 40b132
                                (cause ? PKIX_ErrorText[cause->errCode] : "null")));
Packit 40b132
#else
Packit 40b132
            PR_LOG(pkixLog, 4, ("Error in function \"%s\": error code \"%d\"\n",
Packit 40b132
                                funcName, errorCode));
Packit 40b132
#endif /* PKIX_ERROR_DESCRIPTION */
Packit 40b132
            PORT_Assert(strcmp(funcName, "PKIX_PL_Object_DecRef"));
Packit 40b132
        }
Packit 40b132
#endif /* PKIX_OBJECT_LEAK_TEST */
Packit 40b132
Packit 40b132
        /* if cause has error class of PKIX_FATAL_ERROR, return immediately */
Packit 40b132
        if (cause) {
Packit 40b132
                if (cause->errClass == PKIX_FATAL_ERROR){
Packit 40b132
                        PKIX_INCREF(cause);
Packit 40b132
                        *pError = cause;
Packit 40b132
                        goto cleanup;
Packit 40b132
                }
Packit 40b132
        }
Packit 40b132
        
Packit 40b132
        if (overrideClass == PKIX_FATAL_ERROR){
Packit 40b132
                errorClass = overrideClass;
Packit 40b132
        }
Packit 40b132
Packit 40b132
       pkixTempResult = PKIX_Error_Create(errorClass, cause, NULL,
Packit 40b132
                                           errorCode, &error, plContext);
Packit 40b132
       
Packit 40b132
       if (!pkixTempResult) {
Packit 40b132
           /* Setting plErr error code:
Packit 40b132
            *    get it from PORT_GetError if it is a leaf error and
Packit 40b132
            *    default error code does not exist(eq 0)               */
Packit 40b132
           if (!cause && !error->plErr) {
Packit 40b132
               error->plErr = PKIX_PL_GetPLErrorCode();
Packit 40b132
           }
Packit 40b132
       }
Packit 40b132
Packit 40b132
       *pError = error;
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_DEBUG_EXIT(ERROR);
Packit 40b132
        pkixErrorClass = 0;
Packit 40b132
#ifdef PKIX_OBJECT_LEAK_TEST        
Packit 40b132
        noErrorState = PKIX_FALSE;
Packit 40b132
Packit 40b132
        if (runningLeakTest && fnStackNameArr) {
Packit 40b132
            PR_LOG(pkixLog, 5,
Packit 40b132
                   ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "),
Packit 40b132
                    stackPosition, " ", fnStackNameArr[stackPosition],
Packit 40b132
                    stackPosition, myFuncName));
Packit 40b132
            fnStackNameArr[stackPosition--] = NULL;
Packit 40b132
        }
Packit 40b132
#endif /* PKIX_OBJECT_LEAK_TEST */
Packit 40b132
        return (pkixTempResult);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_CheckTypes
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Checks that the types of the Object pointed to by "first" and the Object
Packit 40b132
 *  pointed to by "second" are both equal to the value of "type". If they
Packit 40b132
 *  are not equal, a PKIX_Error is returned.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "first"
Packit 40b132
 *      Address of first Object. Must be non-NULL.
Packit 40b132
 *  "second"
Packit 40b132
 *      Address of second Object. Must be non-NULL.
Packit 40b132
 *  "type"
Packit 40b132
 *      Value of type to check against.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns an Error Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_CheckTypes(
Packit 40b132
        PKIX_PL_Object *first,
Packit 40b132
        PKIX_PL_Object *second,
Packit 40b132
        PKIX_UInt32 type,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_UInt32 firstType, secondType;
Packit 40b132
Packit 40b132
        PKIX_ENTER(OBJECT, "pkix_CheckTypes");
Packit 40b132
        PKIX_NULLCHECK_TWO(first, second);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_PL_Object_GetType(first, &firstType, plContext),
Packit 40b132
                    PKIX_COULDNOTGETFIRSTOBJECTTYPE);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
Packit 40b132
                    PKIX_COULDNOTGETSECONDOBJECTTYPE);
Packit 40b132
Packit 40b132
        if ((firstType != type)||(firstType != secondType)) {
Packit 40b132
                PKIX_ERROR(PKIX_OBJECTTYPESDONOTMATCH);
Packit 40b132
        }
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_RETURN(OBJECT);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_CheckType
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Checks that the type of the Object pointed to by "object" is equal to the
Packit 40b132
 *  value of "type". If it is not equal, a PKIX_Error is returned.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "object"
Packit 40b132
 *      Address of Object. Must be non-NULL.
Packit 40b132
 *  "type"
Packit 40b132
 *      Value of type to check against.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns an Error Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_CheckType(
Packit 40b132
        PKIX_PL_Object *object,
Packit 40b132
        PKIX_UInt32 type,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        return (pkix_CheckTypes(object, object, type, plContext));
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_hash
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Computes a hash value for "length" bytes starting at the array of bytes
Packit 40b132
 *  pointed to by "bytes" and stores the result at "pHash".
Packit 40b132
 *
Packit 40b132
 *  XXX To speed this up, we could probably read 32 bits at a time from
Packit 40b132
 *  bytes (maybe even 64 bits on some platforms)
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "bytes"
Packit 40b132
 *      Address of array of bytes to hash. Must be non-NULL.
Packit 40b132
 *  "length"
Packit 40b132
 *      Number of bytes to hash.
Packit 40b132
 *  "pHash"
Packit 40b132
 *      Address where object pointer will be stored. Must be non-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_hash(
Packit 40b132
        const unsigned char *bytes,
Packit 40b132
        PKIX_UInt32 length,
Packit 40b132
        PKIX_UInt32 *pHash,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_UInt32 i;
Packit 40b132
        PKIX_UInt32 hash;
Packit 40b132
Packit 40b132
        PKIX_ENTER(OBJECT, "pkix_hash");
Packit 40b132
        if (length != 0) {
Packit 40b132
                PKIX_NULLCHECK_ONE(bytes);
Packit 40b132
        }
Packit 40b132
        PKIX_NULLCHECK_ONE(pHash);
Packit 40b132
Packit 40b132
        hash = 0;
Packit 40b132
        for (i = 0; i < length; i++) {
Packit 40b132
                /* hash = 31 * hash + bytes[i]; */
Packit 40b132
                hash = (hash << 5) - hash + bytes[i];
Packit 40b132
        }
Packit 40b132
Packit 40b132
        *pHash = hash;
Packit 40b132
Packit 40b132
        PKIX_RETURN(OBJECT);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_countArray
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Counts the number of elements in the  null-terminated array of pointers
Packit 40b132
 *  pointed to by "array" and returns the result.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS
Packit 40b132
 *  "array"
Packit 40b132
 *      Address of null-terminated array of pointers.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns the number of elements in the array.
Packit 40b132
 */
Packit 40b132
PKIX_UInt32
Packit 40b132
pkix_countArray(void **array)
Packit 40b132
{
Packit 40b132
        PKIX_UInt32 count = 0;
Packit 40b132
Packit 40b132
        if (array) {
Packit 40b132
                while (*array++) {
Packit 40b132
                        count++;
Packit 40b132
                }
Packit 40b132
        }
Packit 40b132
        return (count);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_duplicateImmutable
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Convenience callback function used for duplicating immutable objects.
Packit 40b132
 *  Since the objects can not be modified, this function simply increments the
Packit 40b132
 *  reference count on the object, and returns a reference to that object.
Packit 40b132
 *
Packit 40b132
 *  (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_duplicateImmutable(
Packit 40b132
        PKIX_PL_Object *object,
Packit 40b132
        PKIX_PL_Object **pNewObject,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_ENTER(OBJECT, "pkix_duplicateImmutable");
Packit 40b132
        PKIX_NULLCHECK_TWO(object, pNewObject);
Packit 40b132
Packit 40b132
        PKIX_INCREF(object);
Packit 40b132
Packit 40b132
        *pNewObject = object;
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
        PKIX_RETURN(OBJECT);
Packit 40b132
}
Packit 40b132
Packit 40b132
/* --String-Encoding-Conversion-Functions------------------------ */
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_hex2i
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Converts hexadecimal character "c" to its integer value and returns result.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS
Packit 40b132
 *  "c"
Packit 40b132
 *      Character to convert to a hex value.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  The hexadecimal value of "c". Otherwise -1. (Unsigned 0xFFFFFFFF).
Packit 40b132
 */
Packit 40b132
PKIX_UInt32
Packit 40b132
pkix_hex2i(char c)
Packit 40b132
{
Packit 40b132
        if ((c >= '0')&&(c <= '9'))
Packit 40b132
                return (c-'0');
Packit 40b132
        else if ((c >= 'a')&&(c <= 'f'))
Packit 40b132
                return (c-'a'+10);
Packit 40b132
        else if ((c >= 'A')&&(c <= 'F'))
Packit 40b132
                return (c-'A'+10);
Packit 40b132
        else
Packit 40b132
                return ((PKIX_UInt32)(-1));
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_i2hex
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Converts integer value "digit" to its ASCII hex value
Packit 40b132
 *
Packit 40b132
 * PARAMETERS
Packit 40b132
 *  "digit"
Packit 40b132
 *      Value of integer to convert to ASCII hex value. Must be 0-15.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  The ASCII hexadecimal value of "digit".
Packit 40b132
 */
Packit 40b132
char
Packit 40b132
pkix_i2hex(char digit)
Packit 40b132
{
Packit 40b132
        if ((digit >= 0)&&(digit <= 9))
Packit 40b132
                return (digit+'0');
Packit 40b132
        else if ((digit >= 0xa)&&(digit <= 0xf))
Packit 40b132
                return (digit - 10 + 'a');
Packit 40b132
        else
Packit 40b132
                return (-1);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_isPlaintext
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Returns whether character "c" is plaintext using EscASCII or EscASCII_Debug
Packit 40b132
 *  depending on the value of "debug".
Packit 40b132
 *
Packit 40b132
 *  In EscASCII, [01, 7E] except '&' are plaintext.
Packit 40b132
 *  In EscASCII_Debug [20, 7E] except '&' are plaintext.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "c"
Packit 40b132
 *      Character to check.
Packit 40b132
 *  "debug"
Packit 40b132
 *      Value of debug flag.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  True if "c" is plaintext.
Packit 40b132
 */
Packit 40b132
PKIX_Boolean
Packit 40b132
pkix_isPlaintext(unsigned char c, PKIX_Boolean debug) {
Packit 40b132
        return ((c >= 0x01)&&(c <= 0x7E)&&(c != '&')&&(!debug || (c >= 20)));
Packit 40b132
}
Packit 40b132
Packit 40b132
/* --Cache-Functions------------------------ */
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_CacheCertChain_Lookup
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Look up CertChain Hash Table for a cached BuildResult based on "targetCert"
Packit 40b132
 *  and "anchors" as the hash keys. If there is no item to match the key,
Packit 40b132
 *  PKIX_FALSE is stored at "pFound". If an item is found, its cache time is
Packit 40b132
 *  compared to "testDate". If expired, the item is removed and PKIX_FALSE is
Packit 40b132
 *  stored at "pFound". Otherwise, PKIX_TRUE is stored at "pFound" and the 
Packit 40b132
 *  BuildResult is stored at "pBuildResult".
Packit 40b132
 *  The hashtable is maintained in the following ways:
Packit 40b132
 *  1) When creating the hashtable, maximum bucket size can be specified (0 for
Packit 40b132
 *     unlimited). If items in a bucket reaches its full size, an new addition
Packit 40b132
 *     will trigger the removal of the old as FIFO sequence.
Packit 40b132
 *  2) A PKIX_PL_Date created with current time offset by constant 
Packit 40b132
 *     CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
Packit 40b132
 *     When an item is retrieved, this date is compared against "testDate" for
Packit 40b132
 *     validity. If comparison indicates this item is expired, the item is
Packit 40b132
 *     removed from the bucket.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "targetCert"
Packit 40b132
 *      Address of Target Cert as key to retrieve this CertChain. Must be 
Packit 40b132
 *      non-NULL.
Packit 40b132
 *  "anchors"
Packit 40b132
 *      Address of PKIX_List of "anchors" is used as key to retrive CertChain.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "testDate"
Packit 40b132
 *      Address of PKIX_PL_Date for verifying time validity and cache validity.
Packit 40b132
 *      May be NULL. If testDate is NULL, this cache item will not be out-dated.
Packit 40b132
 *  "pFound"
Packit 40b132
 *      Address of PKIX_Boolean indicating valid data is found.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "pBuildResult"
Packit 40b132
 *      Address where BuildResult will be stored. Must be non-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns an Error Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_CacheCertChain_Lookup(
Packit 40b132
        PKIX_PL_Cert* targetCert,
Packit 40b132
        PKIX_List* anchors,
Packit 40b132
        PKIX_PL_Date *testDate,
Packit 40b132
        PKIX_Boolean *pFound,
Packit 40b132
        PKIX_BuildResult **pBuildResult,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_List *cachedValues = NULL;
Packit 40b132
        PKIX_List *cachedKeys = NULL;
Packit 40b132
        PKIX_Error *cachedCertChainError = NULL;
Packit 40b132
        PKIX_PL_Date *cacheValidUntilDate = NULL;
Packit 40b132
        PKIX_PL_Date *validityDate = NULL;
Packit 40b132
        PKIX_Int32 cmpValidTimeResult = 0;
Packit 40b132
        PKIX_Int32 cmpCacheTimeResult = 0;
Packit 40b132
Packit 40b132
        PKIX_ENTER(BUILD, "pkix_CacheCertChain_Lookup");
Packit 40b132
Packit 40b132
        PKIX_NULLCHECK_FOUR(targetCert, anchors, pFound, pBuildResult);
Packit 40b132
Packit 40b132
        *pFound = PKIX_FALSE;
Packit 40b132
Packit 40b132
        /* use trust anchors and target cert as hash key */
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
Packit 40b132
                    PKIX_LISTCREATEFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                    (cachedKeys,
Packit 40b132
                    (PKIX_PL_Object *)targetCert,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                    (cachedKeys,
Packit 40b132
                    (PKIX_PL_Object *)anchors,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        cachedCertChainError = PKIX_PL_HashTable_Lookup
Packit 40b132
                    (cachedCertChainTable,
Packit 40b132
                    (PKIX_PL_Object *) cachedKeys,
Packit 40b132
                    (PKIX_PL_Object **) &cachedValues,
Packit 40b132
                    plContext);
Packit 40b132
Packit 40b132
        pkix_ccLookupCount++;
Packit 40b132
Packit 40b132
        /* retrieve data from hashed value list */
Packit 40b132
Packit 40b132
        if (cachedValues != NULL && cachedCertChainError == NULL) {
Packit 40b132
Packit 40b132
            PKIX_CHECK(PKIX_List_GetItem
Packit 40b132
                    (cachedValues,
Packit 40b132
                    0,
Packit 40b132
                    (PKIX_PL_Object **) &cacheValidUntilDate,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_LISTGETITEMFAILED);
Packit 40b132
Packit 40b132
            /* check validity time and cache age time */
Packit 40b132
            PKIX_CHECK(PKIX_List_GetItem
Packit 40b132
                    (cachedValues,
Packit 40b132
                    1,
Packit 40b132
                    (PKIX_PL_Object **) &validityDate,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_LISTGETITEMFAILED);
Packit 40b132
Packit 40b132
            /* if testDate is not set, this cache item is not out-dated */
Packit 40b132
            if (testDate) {
Packit 40b132
Packit 40b132
                PKIX_CHECK(PKIX_PL_Object_Compare
Packit 40b132
                     ((PKIX_PL_Object *)testDate,
Packit 40b132
                     (PKIX_PL_Object *)cacheValidUntilDate,
Packit 40b132
                     &cmpCacheTimeResult,
Packit 40b132
                     plContext),
Packit 40b132
                     PKIX_OBJECTCOMPARATORFAILED);
Packit 40b132
Packit 40b132
                PKIX_CHECK(PKIX_PL_Object_Compare
Packit 40b132
                     ((PKIX_PL_Object *)testDate,
Packit 40b132
                     (PKIX_PL_Object *)validityDate,
Packit 40b132
                     &cmpValidTimeResult,
Packit 40b132
                     plContext),
Packit 40b132
                     PKIX_OBJECTCOMPARATORFAILED);
Packit 40b132
            }
Packit 40b132
Packit 40b132
            /* certs' date are all valid and cache item is not old */
Packit 40b132
            if (cmpValidTimeResult <= 0 && cmpCacheTimeResult <=0) {
Packit 40b132
Packit 40b132
                PKIX_CHECK(PKIX_List_GetItem
Packit 40b132
                    (cachedValues,
Packit 40b132
                    2,
Packit 40b132
                    (PKIX_PL_Object **) pBuildResult,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_LISTGETITEMFAILED);
Packit 40b132
Packit 40b132
                *pFound = PKIX_TRUE;
Packit 40b132
Packit 40b132
            } else {
Packit 40b132
Packit 40b132
                pkix_ccRemoveCount++;
Packit 40b132
                *pFound = PKIX_FALSE;
Packit 40b132
Packit 40b132
                /* out-dated item, remove it from cache */
Packit 40b132
                PKIX_CHECK(PKIX_PL_HashTable_Remove
Packit 40b132
                    (cachedCertChainTable,
Packit 40b132
                    (PKIX_PL_Object *) cachedKeys,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_HASHTABLEREMOVEFAILED);
Packit 40b132
            }
Packit 40b132
        }
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_DECREF(cachedValues);
Packit 40b132
        PKIX_DECREF(cachedKeys);
Packit 40b132
        PKIX_DECREF(cachedCertChainError);
Packit 40b132
        PKIX_DECREF(cacheValidUntilDate);
Packit 40b132
        PKIX_DECREF(validityDate);
Packit 40b132
Packit 40b132
        PKIX_RETURN(BUILD);
Packit 40b132
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_CacheCertChain_Remove
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Remove CertChain Hash Table entry based on "targetCert" and "anchors"
Packit 40b132
 *  as the hash keys. If there is no item to match the key, no action is
Packit 40b132
 *  taken.
Packit 40b132
 *  The hashtable is maintained in the following ways:
Packit 40b132
 *  1) When creating the hashtable, maximum bucket size can be specified (0 for
Packit 40b132
 *     unlimited). If items in a bucket reaches its full size, an new addition
Packit 40b132
 *     will trigger the removal of the old as FIFO sequence.
Packit 40b132
 *  2) A PKIX_PL_Date created with current time offset by constant 
Packit 40b132
 *     CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
Packit 40b132
 *     When an item is retrieved, this date is compared against "testDate" for
Packit 40b132
 *     validity. If comparison indicates this item is expired, the item is
Packit 40b132
 *     removed from the bucket.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "targetCert"
Packit 40b132
 *      Address of Target Cert as key to retrieve this CertChain. Must be 
Packit 40b132
 *      non-NULL.
Packit 40b132
 *  "anchors"
Packit 40b132
 *      Address of PKIX_List of "anchors" is used as key to retrive CertChain.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns an Error Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_CacheCertChain_Remove(
Packit 40b132
        PKIX_PL_Cert* targetCert,
Packit 40b132
        PKIX_List* anchors,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_List *cachedKeys = NULL;
Packit 40b132
Packit 40b132
        PKIX_ENTER(BUILD, "pkix_CacheCertChain_Remove");
Packit 40b132
        PKIX_NULLCHECK_TWO(targetCert, anchors);
Packit 40b132
Packit 40b132
        /* use trust anchors and target cert as hash key */
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
Packit 40b132
                    PKIX_LISTCREATEFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                    (cachedKeys,
Packit 40b132
                    (PKIX_PL_Object *)targetCert,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                    (cachedKeys,
Packit 40b132
                    (PKIX_PL_Object *)anchors,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK_ONLY_FATAL(PKIX_PL_HashTable_Remove
Packit 40b132
                    (cachedCertChainTable,
Packit 40b132
                    (PKIX_PL_Object *) cachedKeys,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_HASHTABLEREMOVEFAILED);
Packit 40b132
Packit 40b132
        pkix_ccRemoveCount++;
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_DECREF(cachedKeys);
Packit 40b132
Packit 40b132
        PKIX_RETURN(BUILD);
Packit 40b132
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_CacheCertChain_Add
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Add a BuildResult to the CertChain Hash Table for a "buildResult" with
Packit 40b132
 *  "targetCert" and "anchors" as the hash keys.
Packit 40b132
 *  "validityDate" is the most restricted notAfter date of all Certs in
Packit 40b132
 *  this CertChain and is verified when this BuildChain is retrieved.
Packit 40b132
 *  The hashtable is maintained in the following ways:
Packit 40b132
 *  1) When creating the hashtable, maximum bucket size can be specified (0 for
Packit 40b132
 *     unlimited). If items in a bucket reaches its full size, an new addition
Packit 40b132
 *     will trigger the removal of the old as FIFO sequence.
Packit 40b132
 *  2) A PKIX_PL_Date created with current time offset by constant 
Packit 40b132
 *     CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
Packit 40b132
 *     When an item is retrieved, this date is compared against "testDate" for
Packit 40b132
 *     validity. If comparison indicates this item is expired, the item is
Packit 40b132
 *     removed from the bucket.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "targetCert"
Packit 40b132
 *      Address of Target Cert as key to retrieve this CertChain. Must be 
Packit 40b132
 *      non-NULL.
Packit 40b132
 *  "anchors"
Packit 40b132
 *      Address of PKIX_List of "anchors" is used as key to retrive CertChain.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "validityDate"
Packit 40b132
 *      Address of PKIX_PL_Date contains the most restriced notAfter time of
Packit 40b132
 *      all "certs". Must be non-NULL.
Packit 40b132
 *      Address of PKIX_Boolean indicating valid data is found.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "buildResult"
Packit 40b132
 *      Address of BuildResult to be cached. Must be non-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns an Error Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_CacheCertChain_Add(
Packit 40b132
        PKIX_PL_Cert* targetCert,
Packit 40b132
        PKIX_List* anchors,
Packit 40b132
        PKIX_PL_Date *validityDate,
Packit 40b132
        PKIX_BuildResult *buildResult,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_List *cachedValues = NULL;
Packit 40b132
        PKIX_List *cachedKeys = NULL;
Packit 40b132
        PKIX_Error *cachedCertChainError = NULL;
Packit 40b132
        PKIX_PL_Date *cacheValidUntilDate = NULL;
Packit 40b132
Packit 40b132
        PKIX_ENTER(BUILD, "pkix_CacheCertChain_Add");
Packit 40b132
Packit 40b132
        PKIX_NULLCHECK_FOUR(targetCert, anchors, validityDate, buildResult);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
Packit 40b132
                PKIX_LISTCREATEFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                (cachedKeys, (PKIX_PL_Object *)targetCert, plContext),
Packit 40b132
                PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                (cachedKeys, (PKIX_PL_Object *)anchors, plContext),
Packit 40b132
                PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext),
Packit 40b132
                PKIX_LISTCREATEFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
Packit 40b132
                (CACHE_ITEM_PERIOD_SECONDS,
Packit 40b132
                &cacheValidUntilDate,
Packit 40b132
                plContext),
Packit 40b132
               PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                (cachedValues,
Packit 40b132
                (PKIX_PL_Object *)cacheValidUntilDate,
Packit 40b132
                plContext),
Packit 40b132
                PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                (cachedValues, (PKIX_PL_Object *)validityDate, plContext),
Packit 40b132
                PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                (cachedValues, (PKIX_PL_Object *)buildResult, plContext),
Packit 40b132
                PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        cachedCertChainError = PKIX_PL_HashTable_Add
Packit 40b132
                (cachedCertChainTable,
Packit 40b132
                (PKIX_PL_Object *) cachedKeys,
Packit 40b132
                (PKIX_PL_Object *) cachedValues,
Packit 40b132
                plContext);
Packit 40b132
Packit 40b132
        pkix_ccAddCount++;
Packit 40b132
Packit 40b132
        if (cachedCertChainError != NULL) {
Packit 40b132
                PKIX_DEBUG("PKIX_PL_HashTable_Add for CertChain skipped: "
Packit 40b132
                        "entry existed\n");
Packit 40b132
        }
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_DECREF(cachedValues);
Packit 40b132
        PKIX_DECREF(cachedKeys);
Packit 40b132
        PKIX_DECREF(cachedCertChainError);
Packit 40b132
        PKIX_DECREF(cacheValidUntilDate);
Packit 40b132
Packit 40b132
        PKIX_RETURN(BUILD);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_CacheCert_Lookup
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Look up Cert Hash Table for a cached item based on "store" and Subject in
Packit 40b132
 *  "certSelParams" as the hash keys and returns values Certs in "pCerts".
Packit 40b132
 *  If there isn't an item to match the key, a PKIX_FALSE is returned at
Packit 40b132
 *  "pFound". The item's cache time is verified with "testDate". If out-dated,
Packit 40b132
 *  this item is removed and PKIX_FALSE is returned at "pFound".
Packit 40b132
 *  This hashtable is maintained in the following ways:
Packit 40b132
 *  1) When creating the hashtable, maximum bucket size can be specified (0 for
Packit 40b132
 *     unlimited). If items in a bucket reaches its full size, an new addition
Packit 40b132
 *     will trigger the removal of the old as FIFO sequence.
Packit 40b132
 *  2) A PKIX_PL_Date created with current time offset by constant 
Packit 40b132
 *     CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
Packit 40b132
 *     If the CertStore this Cert is from is a trusted one, the cache period is
Packit 40b132
 *     shorter so cache can be updated more frequently.
Packit 40b132
 *     When an item is retrieved, this date is compared against "testDate" for
Packit 40b132
 *     validity. If comparison indicates this item is expired, the item is
Packit 40b132
 *     removed from the bucket.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "store"
Packit 40b132
 *      Address of CertStore as key to retrieve this CertChain. Must be 
Packit 40b132
 *      non-NULL.
Packit 40b132
 *  "certSelParams"
Packit 40b132
 *      Address of ComCertSelParams that its subject is used as key to retrieve
Packit 40b132
 *      this CertChain. Must be non-NULL.
Packit 40b132
 *  "testDate"
Packit 40b132
 *      Address of PKIX_PL_Date for verifying time cache validity.
Packit 40b132
 *      Must be non-NULL. If testDate is NULL, this cache item won't be out
Packit 40b132
 *      dated.
Packit 40b132
 *  "pFound"
Packit 40b132
 *      Address of KPKIX_Boolean indicating valid data is found.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "pCerts"
Packit 40b132
 *      Address PKIX_List where the CertChain will be stored. Must be no-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns an Error Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_CacheCert_Lookup(
Packit 40b132
        PKIX_CertStore *store,
Packit 40b132
        PKIX_ComCertSelParams *certSelParams,
Packit 40b132
        PKIX_PL_Date *testDate,
Packit 40b132
        PKIX_Boolean *pFound,
Packit 40b132
        PKIX_List** pCerts,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_PL_Cert *cert = NULL;
Packit 40b132
        PKIX_List *cachedKeys = NULL;
Packit 40b132
        PKIX_List *cachedValues = NULL;
Packit 40b132
        PKIX_List *cachedCertList = NULL;
Packit 40b132
        PKIX_List *selCertList = NULL;
Packit 40b132
        PKIX_PL_X500Name *subject = NULL;
Packit 40b132
        PKIX_PL_Date *invalidAfterDate = NULL;
Packit 40b132
        PKIX_PL_Date *cacheValidUntilDate = NULL;
Packit 40b132
        PKIX_CertSelector *certSel = NULL;
Packit 40b132
        PKIX_Error *cachedCertError = NULL;
Packit 40b132
        PKIX_Error *selectorError = NULL;
Packit 40b132
        PKIX_CertSelector_MatchCallback selectorMatch = NULL;
Packit 40b132
        PKIX_Int32 cmpValidTimeResult = PKIX_FALSE;
Packit 40b132
        PKIX_Int32 cmpCacheTimeResult = 0;
Packit 40b132
        PKIX_UInt32 numItems = 0;
Packit 40b132
        PKIX_UInt32 i;
Packit 40b132
Packit 40b132
        PKIX_ENTER(BUILD, "pkix_CacheCert_Lookup");
Packit 40b132
        PKIX_NULLCHECK_TWO(store, certSelParams);
Packit 40b132
        PKIX_NULLCHECK_TWO(pFound, pCerts);
Packit 40b132
Packit 40b132
        *pFound = PKIX_FALSE;
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
Packit 40b132
                PKIX_LISTCREATEFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                (cachedKeys, (PKIX_PL_Object *)store, plContext),
Packit 40b132
                PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
Packit 40b132
                (certSelParams, &subject, plContext),
Packit 40b132
                PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
Packit 40b132
Packit 40b132
        PKIX_NULLCHECK_ONE(subject);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                (cachedKeys, (PKIX_PL_Object *)subject, plContext),
Packit 40b132
                PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        cachedCertError = PKIX_PL_HashTable_Lookup
Packit 40b132
                    (cachedCertTable,
Packit 40b132
                    (PKIX_PL_Object *) cachedKeys,
Packit 40b132
                    (PKIX_PL_Object **) &cachedValues,
Packit 40b132
                    plContext);
Packit 40b132
        pkix_cLookupCount++;
Packit 40b132
Packit 40b132
        if (cachedValues != NULL && cachedCertError == NULL) {
Packit 40b132
Packit 40b132
                PKIX_CHECK(PKIX_List_GetItem
Packit 40b132
                        (cachedValues,
Packit 40b132
                        0,
Packit 40b132
                        (PKIX_PL_Object **) &cacheValidUntilDate,
Packit 40b132
                        plContext),
Packit 40b132
                        PKIX_LISTGETITEMFAILED);
Packit 40b132
Packit 40b132
                if (testDate) {
Packit 40b132
                    PKIX_CHECK(PKIX_PL_Object_Compare
Packit 40b132
                         ((PKIX_PL_Object *)testDate,
Packit 40b132
                         (PKIX_PL_Object *)cacheValidUntilDate,
Packit 40b132
                         &cmpCacheTimeResult,
Packit 40b132
                         plContext),
Packit 40b132
                         PKIX_OBJECTCOMPARATORFAILED);
Packit 40b132
                }
Packit 40b132
Packit 40b132
                if (cmpCacheTimeResult <= 0) {
Packit 40b132
Packit 40b132
                    PKIX_CHECK(PKIX_List_GetItem
Packit 40b132
                        (cachedValues,
Packit 40b132
                        1,
Packit 40b132
                        (PKIX_PL_Object **) &cachedCertList,
Packit 40b132
                        plContext),
Packit 40b132
                        PKIX_LISTGETITEMFAILED);
Packit 40b132
Packit 40b132
                    /*
Packit 40b132
                     * Certs put on cache satifies only for Subject,
Packit 40b132
                     * user selector and ComCertSelParams to filter.
Packit 40b132
                     */
Packit 40b132
                    PKIX_CHECK(PKIX_CertSelector_Create
Packit 40b132
                          (NULL, NULL, &certSel, plContext),
Packit 40b132
                          PKIX_CERTSELECTORCREATEFAILED);
Packit 40b132
Packit 40b132
                    PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
Packit 40b132
                          (certSel, certSelParams, plContext),
Packit 40b132
                          PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
Packit 40b132
Packit 40b132
                    PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
Packit 40b132
                          (certSel, &selectorMatch, plContext),
Packit 40b132
                          PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
Packit 40b132
Packit 40b132
                    PKIX_CHECK(PKIX_List_Create(&selCertList, plContext),
Packit 40b132
                            PKIX_LISTCREATEFAILED);
Packit 40b132
Packit 40b132
                    /* 
Packit 40b132
                     * If any of the Cert on the list is out-dated, invalidate
Packit 40b132
                     * this cache item.
Packit 40b132
                     */
Packit 40b132
                    PKIX_CHECK(PKIX_List_GetLength
Packit 40b132
                        (cachedCertList, &numItems, plContext),
Packit 40b132
                        PKIX_LISTGETLENGTHFAILED);
Packit 40b132
Packit 40b132
                    for (i = 0; i < numItems; i++){
Packit 40b132
Packit 40b132
                        PKIX_CHECK(PKIX_List_GetItem
Packit 40b132
                            (cachedCertList,
Packit 40b132
                            i,
Packit 40b132
                            (PKIX_PL_Object **)&cert,
Packit 40b132
                            plContext),
Packit 40b132
                            PKIX_LISTGETITEMFAILED);
Packit 40b132
Packit 40b132
                        PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
Packit 40b132
                            (cert, &invalidAfterDate, plContext),
Packit 40b132
                            PKIX_CERTGETVALIDITYNOTAFTERFAILED);
Packit 40b132
Packit 40b132
                        if (testDate) {
Packit 40b132
                            PKIX_CHECK(PKIX_PL_Object_Compare
Packit 40b132
                                ((PKIX_PL_Object *)invalidAfterDate,
Packit 40b132
                                (PKIX_PL_Object *)testDate,
Packit 40b132
                                &cmpValidTimeResult,
Packit 40b132
                                plContext),
Packit 40b132
                                PKIX_OBJECTCOMPARATORFAILED);
Packit 40b132
                        }
Packit 40b132
Packit 40b132
                        if (cmpValidTimeResult < 0) {
Packit 40b132
Packit 40b132
                            pkix_cRemoveCount++;
Packit 40b132
                            *pFound = PKIX_FALSE;
Packit 40b132
Packit 40b132
                            /* one cert is out-dated, remove item from cache */
Packit 40b132
                            PKIX_CHECK(PKIX_PL_HashTable_Remove
Packit 40b132
                                    (cachedCertTable,
Packit 40b132
                                    (PKIX_PL_Object *) cachedKeys,
Packit 40b132
                                    plContext),
Packit 40b132
                                    PKIX_HASHTABLEREMOVEFAILED);
Packit 40b132
                            goto cleanup;
Packit 40b132
                        }
Packit 40b132
Packit 40b132
                        selectorError = selectorMatch(certSel, cert, plContext);
Packit 40b132
                        if (!selectorError){
Packit 40b132
                            /* put on the return list */
Packit 40b132
                            PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                                   (selCertList,
Packit 40b132
                                   (PKIX_PL_Object *)cert,
Packit 40b132
                                   plContext),
Packit 40b132
                                  PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
                        } else {
Packit 40b132
                            PKIX_DECREF(selectorError);
Packit 40b132
                        }
Packit 40b132
Packit 40b132
                        PKIX_DECREF(cert);
Packit 40b132
                        PKIX_DECREF(invalidAfterDate);
Packit 40b132
Packit 40b132
                    }
Packit 40b132
Packit 40b132
                    if (*pFound) {
Packit 40b132
                        PKIX_INCREF(selCertList);
Packit 40b132
                        *pCerts = selCertList;
Packit 40b132
                    }
Packit 40b132
Packit 40b132
                } else {
Packit 40b132
Packit 40b132
                    pkix_cRemoveCount++;
Packit 40b132
                    *pFound = PKIX_FALSE;
Packit 40b132
                    /* cache item is out-dated, remove it from cache */
Packit 40b132
                    PKIX_CHECK(PKIX_PL_HashTable_Remove
Packit 40b132
                                (cachedCertTable,
Packit 40b132
                                (PKIX_PL_Object *) cachedKeys,
Packit 40b132
                                plContext),
Packit 40b132
                                PKIX_HASHTABLEREMOVEFAILED);
Packit 40b132
                }
Packit 40b132
Packit 40b132
        } 
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_DECREF(subject);
Packit 40b132
        PKIX_DECREF(certSel);
Packit 40b132
        PKIX_DECREF(cachedKeys);
Packit 40b132
        PKIX_DECREF(cachedValues);
Packit 40b132
        PKIX_DECREF(cacheValidUntilDate);
Packit 40b132
        PKIX_DECREF(cert);
Packit 40b132
        PKIX_DECREF(cachedCertList);
Packit 40b132
        PKIX_DECREF(selCertList);
Packit 40b132
        PKIX_DECREF(invalidAfterDate);
Packit 40b132
        PKIX_DECREF(cachedCertError);
Packit 40b132
        PKIX_DECREF(selectorError);
Packit 40b132
Packit 40b132
        PKIX_RETURN(BUILD);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_CacheCert_Add
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Add Cert Hash Table for a cached item based on "store" and Subject in
Packit 40b132
 *  "certSelParams" as the hash keys and have "certs" as the key value.
Packit 40b132
 *  This hashtable is maintained in the following ways:
Packit 40b132
 *  1) When creating the hashtable, maximum bucket size can be specified (0 for
Packit 40b132
 *     unlimited). If items in a bucket reaches its full size, an new addition
Packit 40b132
 *     will trigger the removal of the old as FIFO sequence.
Packit 40b132
 *  2) A PKIX_PL_Date created with current time offset by constant 
Packit 40b132
 *     CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
Packit 40b132
 *     If the CertStore this Cert is from is a trusted one, the cache period is
Packit 40b132
 *     shorter so cache can be updated more frequently.
Packit 40b132
 *     When an item is retrieved, this date is compared against "testDate" for
Packit 40b132
 *     validity. If comparison indicates this item is expired, the item is
Packit 40b132
 *     removed from the bucket.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "store"
Packit 40b132
 *      Address of CertStore as key to retrieve this CertChain. Must be 
Packit 40b132
 *      non-NULL.
Packit 40b132
 *  "certSelParams"
Packit 40b132
 *      Address of ComCertSelParams that its subject is used as key to retrieve
Packit 40b132
 *      this CertChain. Must be non-NULL.
Packit 40b132
 *  "certs"
Packit 40b132
 *      Address PKIX_List of Certs will be stored. Must be no-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns an Error Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_CacheCert_Add(
Packit 40b132
        PKIX_CertStore *store,
Packit 40b132
        PKIX_ComCertSelParams *certSelParams,
Packit 40b132
        PKIX_List* certs,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_List *cachedKeys = NULL;
Packit 40b132
        PKIX_List *cachedValues = NULL;
Packit 40b132
        PKIX_PL_Date *cacheValidUntilDate = NULL;
Packit 40b132
        PKIX_PL_X500Name *subject = NULL;
Packit 40b132
        PKIX_Error *cachedCertError = NULL;
Packit 40b132
        PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
Packit 40b132
        PKIX_UInt32 cachePeriod = CACHE_ITEM_PERIOD_SECONDS;
Packit 40b132
        PKIX_UInt32 numCerts = 0;
Packit 40b132
Packit 40b132
        PKIX_ENTER(BUILD, "pkix_CacheCert_Add");
Packit 40b132
        PKIX_NULLCHECK_THREE(store, certSelParams, certs);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_GetLength(certs, &numCerts,
Packit 40b132
                                       plContext),
Packit 40b132
                   PKIX_LISTGETLENGTHFAILED);
Packit 40b132
        if (numCerts == 0) {
Packit 40b132
            /* Don't want to add an empty list. */
Packit 40b132
            goto cleanup;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
Packit 40b132
                PKIX_LISTCREATEFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                (cachedKeys, (PKIX_PL_Object *)store, plContext),
Packit 40b132
                PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
Packit 40b132
                (certSelParams, &subject, plContext),
Packit 40b132
                PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
Packit 40b132
Packit 40b132
        PKIX_NULLCHECK_ONE(subject);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                (cachedKeys, (PKIX_PL_Object *)subject, plContext),
Packit 40b132
                PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext),
Packit 40b132
                PKIX_LISTCREATEFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_CertStore_GetTrustCallback
Packit 40b132
                (store, &trustCallback, plContext),
Packit 40b132
                PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
Packit 40b132
Packit 40b132
        if (trustCallback) {
Packit 40b132
                cachePeriod = CACHE_TRUST_ITEM_PERIOD_SECONDS;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
Packit 40b132
               (cachePeriod, &cacheValidUntilDate, plContext),
Packit 40b132
               PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                (cachedValues,
Packit 40b132
                (PKIX_PL_Object *)cacheValidUntilDate,
Packit 40b132
                plContext),
Packit 40b132
                PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                (cachedValues,
Packit 40b132
                (PKIX_PL_Object *)certs,
Packit 40b132
                plContext),
Packit 40b132
                PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        cachedCertError = PKIX_PL_HashTable_Add
Packit 40b132
                    (cachedCertTable,
Packit 40b132
                    (PKIX_PL_Object *) cachedKeys,
Packit 40b132
                    (PKIX_PL_Object *) cachedValues,
Packit 40b132
                    plContext);
Packit 40b132
Packit 40b132
        pkix_cAddCount++;
Packit 40b132
Packit 40b132
        if (cachedCertError != NULL) {
Packit 40b132
                PKIX_DEBUG("PKIX_PL_HashTable_Add for Certs skipped: "
Packit 40b132
                        "entry existed\n");
Packit 40b132
        }
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_DECREF(subject);
Packit 40b132
        PKIX_DECREF(cachedKeys);
Packit 40b132
        PKIX_DECREF(cachedValues);
Packit 40b132
        PKIX_DECREF(cacheValidUntilDate);
Packit 40b132
        PKIX_DECREF(cachedCertError);
Packit 40b132
Packit 40b132
        PKIX_RETURN(BUILD);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_CacheCrlEntry_Lookup
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Look up CrlEntry Hash Table for a cached item based on "store",
Packit 40b132
 *  "certIssuer" and "certSerialNumber" as the hash keys and returns values
Packit 40b132
 *  "pCrls". If there isn't an item to match the key, a PKIX_FALSE is
Packit 40b132
 *  returned at "pFound".
Packit 40b132
 *  This hashtable is maintained in the following way:
Packit 40b132
 *  1) When creating the hashtable, maximum bucket size can be specified (0 for
Packit 40b132
 *     unlimited). If items in a bucket reaches its full size, an new addition
Packit 40b132
 *     will trigger the removal of the old as FIFO sequence.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "store"
Packit 40b132
 *      Address of CertStore as key to retrieve this CertChain. Must be 
Packit 40b132
 *      non-NULL.
Packit 40b132
 *  "certIssuer"
Packit 40b132
 *      Address of X500Name that is used as key to retrieve the CRLEntries.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "certSerialNumber"
Packit 40b132
 *      Address of BigInt that is used as key to retrieve the CRLEntries.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "pFound"
Packit 40b132
 *      Address of KPKIX_Boolean indicating valid data is found.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "pCrls"
Packit 40b132
 *      Address PKIX_List where the CRLEntry will be stored. Must be no-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns an Error Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_CacheCrlEntry_Lookup(
Packit 40b132
        PKIX_CertStore *store,
Packit 40b132
        PKIX_PL_X500Name *certIssuer,
Packit 40b132
        PKIX_PL_BigInt *certSerialNumber,
Packit 40b132
        PKIX_Boolean *pFound,
Packit 40b132
        PKIX_List** pCrls,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_List *cachedKeys = NULL;
Packit 40b132
        PKIX_List *cachedCrlEntryList = NULL;
Packit 40b132
        PKIX_Error *cachedCrlEntryError = NULL;
Packit 40b132
Packit 40b132
        PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Lookup");
Packit 40b132
        PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber);
Packit 40b132
        PKIX_NULLCHECK_TWO(pFound, pCrls);
Packit 40b132
Packit 40b132
        *pFound = PKIX_FALSE;
Packit 40b132
Packit 40b132
        /* Find CrlEntry(s) by issuer and serial number */
Packit 40b132
         
Packit 40b132
        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
Packit 40b132
                    PKIX_LISTCREATEFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                    (cachedKeys, (PKIX_PL_Object *)store, plContext),
Packit 40b132
                    PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                    (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext),
Packit 40b132
                    PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                    (cachedKeys,
Packit 40b132
                    (PKIX_PL_Object *)certSerialNumber,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        cachedCrlEntryError = PKIX_PL_HashTable_Lookup
Packit 40b132
                    (cachedCrlEntryTable,
Packit 40b132
                    (PKIX_PL_Object *) cachedKeys,
Packit 40b132
                    (PKIX_PL_Object **) &cachedCrlEntryList,
Packit 40b132
                    plContext);
Packit 40b132
        pkix_ceLookupCount++;
Packit 40b132
Packit 40b132
        /* 
Packit 40b132
         * We don't need check Date to invalidate this cache item,
Packit 40b132
         * the item is uniquely defined and won't be reverted. Let
Packit 40b132
         * the FIFO for cleaning up.
Packit 40b132
         */
Packit 40b132
Packit 40b132
        if (cachedCrlEntryList != NULL && cachedCrlEntryError == NULL ) {
Packit 40b132
Packit 40b132
                PKIX_INCREF(cachedCrlEntryList);
Packit 40b132
                *pCrls = cachedCrlEntryList;
Packit 40b132
Packit 40b132
                *pFound = PKIX_TRUE;
Packit 40b132
Packit 40b132
        } else {
Packit 40b132
Packit 40b132
                *pFound = PKIX_FALSE;
Packit 40b132
        }
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_DECREF(cachedKeys);
Packit 40b132
        PKIX_DECREF(cachedCrlEntryList);
Packit 40b132
        PKIX_DECREF(cachedCrlEntryError);
Packit 40b132
Packit 40b132
        PKIX_RETURN(BUILD);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_CacheCrlEntry_Add
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Look up CrlEntry Hash Table for a cached item based on "store",
Packit 40b132
 *  "certIssuer" and "certSerialNumber" as the hash keys and have "pCrls" as
Packit 40b132
 *  the hash value. If there isn't an item to match the key, a PKIX_FALSE is
Packit 40b132
 *  returned at "pFound".
Packit 40b132
 *  This hashtable is maintained in the following way:
Packit 40b132
 *  1) When creating the hashtable, maximum bucket size can be specified (0 for
Packit 40b132
 *     unlimited). If items in a bucket reaches its full size, an new addition
Packit 40b132
 *     will trigger the removal of the old as FIFO sequence.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS:
Packit 40b132
 *  "store"
Packit 40b132
 *      Address of CertStore as key to retrieve this CertChain. Must be 
Packit 40b132
 *      non-NULL.
Packit 40b132
 *  "certIssuer"
Packit 40b132
 *      Address of X500Name that is used as key to retrieve the CRLEntries.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "certSerialNumber"
Packit 40b132
 *      Address of BigInt that is used as key to retrieve the CRLEntries.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "crls"
Packit 40b132
 *      Address PKIX_List where the CRLEntry is stored. Must be no-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns an Error Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_CacheCrlEntry_Add(
Packit 40b132
        PKIX_CertStore *store,
Packit 40b132
        PKIX_PL_X500Name *certIssuer,
Packit 40b132
        PKIX_PL_BigInt *certSerialNumber,
Packit 40b132
        PKIX_List* crls,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_List *cachedKeys = NULL;
Packit 40b132
        PKIX_Error *cachedCrlEntryError = NULL;
Packit 40b132
Packit 40b132
        PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Add");
Packit 40b132
        PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber);
Packit 40b132
        PKIX_NULLCHECK_ONE(crls);
Packit 40b132
Packit 40b132
        /* Add CrlEntry(s) by issuer and serial number */
Packit 40b132
         
Packit 40b132
        PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
Packit 40b132
                    PKIX_LISTCREATEFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                    (cachedKeys, (PKIX_PL_Object *)store, plContext),
Packit 40b132
                    PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                    (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext),
Packit 40b132
                    PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                    (cachedKeys,
Packit 40b132
                    (PKIX_PL_Object *)certSerialNumber,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
Packit 40b132
        cachedCrlEntryError = PKIX_PL_HashTable_Add
Packit 40b132
                    (cachedCrlEntryTable,
Packit 40b132
                    (PKIX_PL_Object *) cachedKeys,
Packit 40b132
                    (PKIX_PL_Object *) crls,
Packit 40b132
                    plContext);
Packit 40b132
        pkix_ceAddCount++;
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_DECREF(cachedKeys);
Packit 40b132
        PKIX_DECREF(cachedCrlEntryError);
Packit 40b132
Packit 40b132
        PKIX_RETURN(BUILD);
Packit 40b132
}
Packit 40b132
Packit 40b132
#ifdef PKIX_OBJECT_LEAK_TEST
Packit 40b132
Packit 40b132
/* TEST_START_FN and testStartFnStackPosition define at what state
Packit 40b132
 * of the stack the object leak testing should begin. The condition
Packit 40b132
 * in pkix_CheckForGeneratedError works the following way: do leak
Packit 40b132
 * testing if at position testStartFnStackPosition in stack array
Packit 40b132
 * (fnStackNameArr) we have called function TEST_START_FN.
Packit 40b132
 * Note, that stack array get filled only when executing libpkix
Packit 40b132
 * functions.
Packit 40b132
 * */
Packit 40b132
#define TEST_START_FN "PKIX_BuildChain"
Packit 40b132
Packit 40b132
PKIX_Error*
Packit 40b132
pkix_CheckForGeneratedError(PKIX_StdVars * stdVars, 
Packit 40b132
                            PKIX_ERRORCLASS errClass, 
Packit 40b132
                            char * fnName,
Packit 40b132
                            PKIX_Boolean *errSetFlag,
Packit 40b132
                            void * plContext)
Packit 40b132
{
Packit 40b132
    PKIX_Error *genErr = NULL;
Packit 40b132
    PKIX_UInt32 pos = 0;
Packit 40b132
    PKIX_UInt32 strLen = 0;
Packit 40b132
Packit 40b132
    if (fnName) { 
Packit 40b132
        if (fnStackNameArr[testStartFnStackPosition] == NULL ||
Packit 40b132
            strcmp(fnStackNameArr[testStartFnStackPosition], TEST_START_FN)
Packit 40b132
            ) {
Packit 40b132
            /* return with out error if not with in boundary */
Packit 40b132
            return NULL;
Packit 40b132
        }
Packit 40b132
        if (!strcmp(fnName, TEST_START_FN)) {
Packit 40b132
            *errSetFlag = PKIX_TRUE;
Packit 40b132
            noErrorState = PKIX_FALSE;
Packit 40b132
            errorGenerated = PKIX_FALSE;
Packit 40b132
        }
Packit 40b132
    }   
Packit 40b132
Packit 40b132
    if (noErrorState || errorGenerated)  return NULL;
Packit 40b132
Packit 40b132
    if (fnName && (
Packit 40b132
        !strcmp(fnName, "PKIX_PL_Object_DecRef") ||
Packit 40b132
        !strcmp(fnName, "PKIX_PL_Object_Unlock") ||
Packit 40b132
        !strcmp(fnName, "pkix_UnlockObject") ||
Packit 40b132
        !strcmp(fnName, "pkix_Throw") ||
Packit 40b132
        !strcmp(fnName, "pkix_trace_dump_cert") ||
Packit 40b132
        !strcmp(fnName, "PKIX_PL_Free"))) {
Packit 40b132
        /* do not generate error for this functions */
Packit 40b132
        noErrorState = PKIX_TRUE;
Packit 40b132
        *errSetFlag = PKIX_TRUE;
Packit 40b132
        return NULL;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    if (PL_HashTableLookup(fnInvTable, &fnStackInvCountArr[stackPosition - 1])) {
Packit 40b132
        return NULL;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    PL_HashTableAdd(fnInvTable, &fnStackInvCountArr[stackPosition - 1], nonNullValue);
Packit 40b132
    errorGenerated = PKIX_TRUE;
Packit 40b132
    noErrorState = PKIX_TRUE;
Packit 40b132
    genErr = PKIX_DoThrow(stdVars, errClass, PKIX_MEMLEAKGENERATEDERROR,
Packit 40b132
                          errClass, plContext);
Packit 40b132
    while(fnStackNameArr[pos]) {
Packit 40b132
        strLen += PORT_Strlen(fnStackNameArr[pos++]) + 1;
Packit 40b132
    }
Packit 40b132
    strLen += 1; /* end of line. */
Packit 40b132
    pos = 0;
Packit 40b132
    errorFnStackString = PORT_ZAlloc(strLen);
Packit 40b132
    while(fnStackNameArr[pos]) {
Packit 40b132
        strcat(errorFnStackString, "/");
Packit 40b132
        strcat(errorFnStackString, fnStackNameArr[pos++]);
Packit 40b132
    }
Packit 40b132
    noErrorState = PKIX_FALSE;
Packit 40b132
    
Packit 40b132
    return genErr;
Packit 40b132
}
Packit 40b132
#endif /* PKIX_OBJECT_LEAK_TEST */