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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rwxr-xr-x

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial