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

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

mercurial