nss: import at 3.0.1 beta 1
[mozilla-nss.git] / security / nss / lib / libpkix / pkix / util / pkix_tools.c
blobacd0704651822937ae12a89c7536609abe299706
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the PKIX-C library.
16 * The Initial Developer of the Original Code is
17 * Sun Microsystems, Inc.
18 * Portions created by the Initial Developer are
19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
21 * Contributor(s):
22 * Sun Microsystems, Inc.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * pkix_tools.c
40 * Private Utility Functions
44 #include "pkix_tools.h"
46 #define CACHE_ITEM_PERIOD_SECONDS (3600) /* one hour */
49 * This cahce period is only for CertCache. A Cert from a trusted CertStore
50 * should be checked more frequently for update new arrival, etc.
52 #define CACHE_TRUST_ITEM_PERIOD_SECONDS (CACHE_ITEM_PERIOD_SECONDS/10)
54 extern PKIX_PL_HashTable *cachedCertChainTable;
55 extern PKIX_PL_HashTable *cachedCertTable;
56 extern PKIX_PL_HashTable *cachedCrlEntryTable;
58 /* Following variables are used to checked cache hits - can be taken out */
59 extern int pkix_ccAddCount;
60 extern int pkix_ccLookupCount;
61 extern int pkix_ccRemoveCount;
62 extern int pkix_cAddCount;
63 extern int pkix_cLookupCount;
64 extern int pkix_cRemoveCount;
65 extern int pkix_ceAddCount;
66 extern int pkix_ceLookupCount;
68 #ifdef PKIX_OBJECT_LEAK_TEST
69 /* Following variables are used for object leak test */
70 char *nonNullValue = "Non Empty Value";
71 PKIX_Boolean noErrorState = PKIX_TRUE;
72 PKIX_Boolean runningLeakTest;
73 PKIX_Boolean errorGenerated;
74 PKIX_UInt32 stackPosition;
75 PKIX_UInt32 *fnStackInvCountArr;
76 char **fnStackNameArr;
77 PLHashTable *fnInvTable;
78 #endif /* PKIX_OBJECT_LEAK_TEST */
80 /* --Private-Functions-------------------------------------------- */
82 #ifdef PKIX_OBJECT_LEAK_TEST
84 * FUNCTION: pkix_ErrorGen_Hash
85 * DESCRIPTION:
87 * Hash function to be used in object leak test hash table.
90 PLHashNumber PR_CALLBACK
91 pkix_ErrorGen_Hash (const void *key)
93 char *str = NULL;
94 PLHashNumber rv = (*(PRUint8*)key) << 5;
95 PRUint32 i, counter = 0;
96 PRUint8 *rvc = (PRUint8 *)&rv;
98 while ((str = fnStackNameArr[counter++]) != NULL) {
99 PRUint32 len = strlen(str);
100 for( i = 0; i < len; i++ ) {
101 rvc[ i % sizeof(rv) ] ^= *str;
102 str++;
106 return rv;
109 #endif /* PKIX_OBJECT_LEAK_TEST */
112 * FUNCTION: pkix_IsCertSelfIssued
113 * DESCRIPTION:
115 * Checks whether the Cert pointed to by "cert" is self-issued and stores the
116 * Boolean result at "pSelfIssued". A Cert is considered self-issued if the
117 * Cert's issuer matches the Cert's subject. If the subject or issuer is
118 * not specified, a PKIX_FALSE is returned.
120 * PARAMETERS:
121 * "cert"
122 * Address of Cert used to determine whether Cert is self-issued.
123 * Must be non-NULL.
124 * "pSelfIssued"
125 * Address where Boolean will be stored. Must be non-NULL.
126 * "plContext"
127 * Platform-specific context pointer.
128 * THREAD SAFETY:
129 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
130 * RETURNS:
131 * Returns NULL if the function succeeds.
132 * Returns a Cert Error if the function fails in a non-fatal way.
133 * Returns a Fatal Error if the function fails in an unrecoverable way.
135 PKIX_Error *
136 pkix_IsCertSelfIssued(
137 PKIX_PL_Cert *cert,
138 PKIX_Boolean *pSelfIssued,
139 void *plContext)
141 PKIX_PL_X500Name *subject = NULL;
142 PKIX_PL_X500Name *issuer = NULL;
144 PKIX_ENTER(CERT, "pkix_IsCertSelfIssued");
145 PKIX_NULLCHECK_TWO(cert, pSelfIssued);
147 PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &subject, plContext),
148 PKIX_CERTGETSUBJECTFAILED);
150 PKIX_CHECK(PKIX_PL_Cert_GetIssuer(cert, &issuer, plContext),
151 PKIX_CERTGETISSUERFAILED);
153 if (subject == NULL || issuer == NULL) {
154 *pSelfIssued = PKIX_FALSE;
155 } else {
157 PKIX_CHECK(PKIX_PL_X500Name_Match
158 (subject, issuer, pSelfIssued, plContext),
159 PKIX_X500NAMEMATCHFAILED);
162 cleanup:
163 PKIX_DECREF(subject);
164 PKIX_DECREF(issuer);
166 PKIX_RETURN(CERT);
170 * FUNCTION: pkix_Throw
171 * DESCRIPTION:
173 * Creates an Error using the value of "errorCode", the character array
174 * pointed to by "funcName", the character array pointed to by "errorText",
175 * and the Error pointed to by "cause" (if any), and stores it at "pError".
177 * If "cause" is not NULL and has an errorCode of "PKIX_FATAL_ERROR",
178 * then there is no point creating a new Error object. Rather, we simply
179 * store "cause" at "pError".
181 * PARAMETERS:
182 * "errorCode"
183 * Value of error code.
184 * "funcName"
185 * Address of EscASCII array representing name of function throwing error.
186 * Must be non-NULL.
187 * "errnum"
188 * PKIX_ERRMSGNUM of error description for new error.
189 * "cause"
190 * Address of Error representing error's cause.
191 * "pError"
192 * Address where object pointer will be stored. Must be non-NULL.
193 * "plContext"
194 * Platform-specific context pointer.
195 * THREAD SAFETY:
196 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
197 * RETURNS:
198 * Returns NULL if the function succeeds.
199 * Returns an Error Error if the function fails in a non-fatal way.
200 * Returns a Fatal Error if the function fails in an unrecoverable way.
202 PKIX_Error *
203 pkix_Throw(
204 PKIX_ERRORCLASS errorClass,
205 const char *funcName,
206 PKIX_ERRORCODE errorCode,
207 PKIX_ERRORCLASS overrideClass,
208 PKIX_Error *cause,
209 PKIX_Error **pError,
210 void *plContext)
212 PKIX_Error *error = NULL;
214 PKIX_ENTER(ERROR, "pkix_Throw");
215 PKIX_NULLCHECK_TWO(funcName, pError);
217 *pError = NULL;
219 #ifdef PKIX_OBJECT_LEAK_TEST
220 noErrorState = PKIX_TRUE;
221 if (pkixLog) {
222 PR_LOG(pkixLog, 4, ("Error in function \"%s\":\"%s\" with cause \"%s\"\n",
223 funcName, PKIX_ErrorText[errorCode],
224 (cause ? PKIX_ErrorText[cause->errCode] : "null")));
226 PORT_Assert(strcmp(funcName, "PKIX_PL_Object_DecRef"));
228 #endif /* PKIX_OBJECT_LEAK_TEST */
230 /* if cause has error class of PKIX_FATAL_ERROR, return immediately */
231 if (cause) {
232 if (cause->errClass == PKIX_FATAL_ERROR){
233 PKIX_INCREF(cause);
234 *pError = cause;
235 goto cleanup;
239 if (overrideClass == PKIX_FATAL_ERROR){
240 errorClass = overrideClass;
243 pkixTempResult = PKIX_Error_Create(errorClass, cause, NULL,
244 errorCode, &error, plContext);
246 if (!pkixTempResult) {
247 /* Setting plErr error code:
248 * get it from PORT_GetError if it is a leaf error and
249 * default error code does not exist(eq 0) */
250 if (!cause && !error->plErr) {
251 error->plErr = PKIX_PL_GetPLErrorCode();
255 *pError = error;
257 cleanup:
259 PKIX_DEBUG_EXIT(ERROR);
260 pkixErrorClass = 0;
261 #ifdef PKIX_OBJECT_LEAK_TEST
262 noErrorState = PKIX_FALSE;
264 if (runningLeakTest && fnStackNameArr) {
265 PR_LOG(pkixLog, 5,
266 ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "),
267 stackPosition, " ", fnStackNameArr[stackPosition],
268 stackPosition, myFuncName));
269 fnStackNameArr[stackPosition--] = NULL;
271 #endif /* PKIX_OBJECT_LEAK_TEST */
272 return (pkixTempResult);
276 * FUNCTION: pkix_CheckTypes
277 * DESCRIPTION:
279 * Checks that the types of the Object pointed to by "first" and the Object
280 * pointed to by "second" are both equal to the value of "type". If they
281 * are not equal, a PKIX_Error is returned.
283 * PARAMETERS:
284 * "first"
285 * Address of first Object. Must be non-NULL.
286 * "second"
287 * Address of second Object. Must be non-NULL.
288 * "type"
289 * Value of type to check against.
290 * "plContext"
291 * Platform-specific context pointer.
292 * THREAD SAFETY:
293 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
294 * RETURNS:
295 * Returns NULL if the function succeeds.
296 * Returns an Error Error if the function fails in a non-fatal way.
297 * Returns a Fatal Error if the function fails in an unrecoverable way.
299 PKIX_Error *
300 pkix_CheckTypes(
301 PKIX_PL_Object *first,
302 PKIX_PL_Object *second,
303 PKIX_UInt32 type,
304 void *plContext)
306 PKIX_UInt32 firstType, secondType;
308 PKIX_ENTER(OBJECT, "pkix_CheckTypes");
309 PKIX_NULLCHECK_TWO(first, second);
311 PKIX_CHECK(PKIX_PL_Object_GetType(first, &firstType, plContext),
312 PKIX_COULDNOTGETFIRSTOBJECTTYPE);
314 PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
315 PKIX_COULDNOTGETSECONDOBJECTTYPE);
317 if ((firstType != type)||(firstType != secondType)) {
318 PKIX_ERROR(PKIX_OBJECTTYPESDONOTMATCH);
321 cleanup:
323 PKIX_RETURN(OBJECT);
327 * FUNCTION: pkix_CheckType
328 * DESCRIPTION:
330 * Checks that the type of the Object pointed to by "object" is equal to the
331 * value of "type". If it is not equal, a PKIX_Error is returned.
333 * PARAMETERS:
334 * "object"
335 * Address of Object. Must be non-NULL.
336 * "type"
337 * Value of type to check against.
338 * "plContext"
339 * Platform-specific context pointer.
340 * THREAD SAFETY:
341 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
342 * RETURNS:
343 * Returns NULL if the function succeeds.
344 * Returns an Error Error if the function fails in a non-fatal way.
345 * Returns a Fatal Error if the function fails in an unrecoverable way.
347 PKIX_Error *
348 pkix_CheckType(
349 PKIX_PL_Object *object,
350 PKIX_UInt32 type,
351 void *plContext)
353 return (pkix_CheckTypes(object, object, type, plContext));
357 * FUNCTION: pkix_hash
358 * DESCRIPTION:
360 * Computes a hash value for "length" bytes starting at the array of bytes
361 * pointed to by "bytes" and stores the result at "pHash".
363 * XXX To speed this up, we could probably read 32 bits at a time from
364 * bytes (maybe even 64 bits on some platforms)
366 * PARAMETERS:
367 * "bytes"
368 * Address of array of bytes to hash. Must be non-NULL.
369 * "length"
370 * Number of bytes to hash.
371 * "pHash"
372 * Address where object pointer will be stored. Must be non-NULL.
373 * "plContext"
374 * Platform-specific context pointer.
375 * THREAD SAFETY:
376 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
377 * RETURNS:
378 * Returns NULL if the function succeeds.
379 * Returns a Fatal Error if the function fails in an unrecoverable way.
381 PKIX_Error *
382 pkix_hash(
383 const unsigned char *bytes,
384 PKIX_UInt32 length,
385 PKIX_UInt32 *pHash,
386 void *plContext)
388 PKIX_UInt32 i;
389 PKIX_UInt32 hash;
391 PKIX_ENTER(OBJECT, "pkix_hash");
392 PKIX_NULLCHECK_TWO(bytes, pHash);
394 hash = 0;
395 for (i = 0; i < length; i++) {
396 /* hash = 31 * hash + bytes[i]; */
397 hash = (hash << 5) - hash + bytes[i];
400 *pHash = hash;
402 PKIX_RETURN(OBJECT);
406 * FUNCTION: pkix_countArray
407 * DESCRIPTION:
409 * Counts the number of elements in the null-terminated array of pointers
410 * pointed to by "array" and returns the result.
412 * PARAMETERS
413 * "array"
414 * Address of null-terminated array of pointers.
415 * THREAD SAFETY:
416 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
417 * RETURNS:
418 * Returns the number of elements in the array.
420 PKIX_UInt32
421 pkix_countArray(void **array)
423 PKIX_UInt32 count = 0;
425 if (array) {
426 while (*array++) {
427 count++;
430 return (count);
434 * FUNCTION: pkix_duplicateImmutable
435 * DESCRIPTION:
437 * Convenience callback function used for duplicating immutable objects.
438 * Since the objects can not be modified, this function simply increments the
439 * reference count on the object, and returns a reference to that object.
441 * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
443 PKIX_Error *
444 pkix_duplicateImmutable(
445 PKIX_PL_Object *object,
446 PKIX_PL_Object **pNewObject,
447 void *plContext)
449 PKIX_ENTER(OBJECT, "pkix_duplicateImmutable");
450 PKIX_NULLCHECK_TWO(object, pNewObject);
452 PKIX_INCREF(object);
454 *pNewObject = object;
456 cleanup:
457 PKIX_RETURN(OBJECT);
460 /* --String-Encoding-Conversion-Functions------------------------ */
463 * FUNCTION: pkix_hex2i
464 * DESCRIPTION:
466 * Converts hexadecimal character "c" to its integer value and returns result.
468 * PARAMETERS
469 * "c"
470 * Character to convert to a hex value.
471 * THREAD SAFETY:
472 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
473 * RETURNS:
474 * The hexadecimal value of "c". Otherwise -1. (Unsigned 0xFFFFFFFF).
476 PKIX_UInt32
477 pkix_hex2i(char c)
479 if ((c >= '0')&&(c <= '9'))
480 return (c-'0');
481 else if ((c >= 'a')&&(c <= 'f'))
482 return (c-'a'+10);
483 else if ((c >= 'A')&&(c <= 'F'))
484 return (c-'A'+10);
485 else
486 return ((PKIX_UInt32)(-1));
490 * FUNCTION: pkix_i2hex
491 * DESCRIPTION:
493 * Converts integer value "digit" to its ASCII hex value
495 * PARAMETERS
496 * "digit"
497 * Value of integer to convert to ASCII hex value. Must be 0-15.
498 * THREAD SAFETY:
499 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
500 * RETURNS:
501 * The ASCII hexadecimal value of "digit".
503 char
504 pkix_i2hex(char digit)
506 if ((digit >= 0)&&(digit <= 9))
507 return (digit+'0');
508 else if ((digit >= 0xa)&&(digit <= 0xf))
509 return (digit - 10 + 'a');
510 else
511 return (-1);
515 * FUNCTION: pkix_isPlaintext
516 * DESCRIPTION:
518 * Returns whether character "c" is plaintext using EscASCII or EscASCII_Debug
519 * depending on the value of "debug".
521 * In EscASCII, [01, 7E] except '&' are plaintext.
522 * In EscASCII_Debug [20, 7E] except '&' are plaintext.
524 * PARAMETERS:
525 * "c"
526 * Character to check.
527 * "debug"
528 * Value of debug flag.
529 * THREAD SAFETY:
530 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
531 * RETURNS:
532 * True if "c" is plaintext.
534 PKIX_Boolean
535 pkix_isPlaintext(unsigned char c, PKIX_Boolean debug) {
536 return ((c >= 0x01)&&(c <= 0x7E)&&(c != '&')&&(!debug || (c >= 20)));
539 /* --Cache-Functions------------------------ */
542 * FUNCTION: pkix_CacheCertChain_Lookup
543 * DESCRIPTION:
545 * Look up CertChain Hash Table for a cached BuildResult based on "targetCert"
546 * and "anchors" as the hash keys. If there is no item to match the key,
547 * PKIX_FALSE is stored at "pFound". If an item is found, its cache time is
548 * compared to "testDate". If expired, the item is removed and PKIX_FALSE is
549 * stored at "pFound". Otherwise, PKIX_TRUE is stored at "pFound" and the
550 * BuildResult is stored at "pBuildResult".
551 * The hashtable is maintained in the following ways:
552 * 1) When creating the hashtable, maximum bucket size can be specified (0 for
553 * unlimited). If items in a bucket reaches its full size, an new addition
554 * will trigger the removal of the old as FIFO sequence.
555 * 2) A PKIX_PL_Date created with current time offset by constant
556 * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
557 * When an item is retrieved, this date is compared against "testDate" for
558 * validity. If comparison indicates this item is expired, the item is
559 * removed from the bucket.
561 * PARAMETERS:
562 * "targetCert"
563 * Address of Target Cert as key to retrieve this CertChain. Must be
564 * non-NULL.
565 * "anchors"
566 * Address of PKIX_List of "anchors" is used as key to retrive CertChain.
567 * Must be non-NULL.
568 * "testDate"
569 * Address of PKIX_PL_Date for verifying time validity and cache validity.
570 * May be NULL. If testDate is NULL, this cache item will not be out-dated.
571 * "pFound"
572 * Address of PKIX_Boolean indicating valid data is found.
573 * Must be non-NULL.
574 * "pBuildResult"
575 * Address where BuildResult will be stored. Must be non-NULL.
576 * "plContext"
577 * Platform-specific context pointer.
578 * THREAD SAFETY:
579 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
580 * RETURNS:
581 * Returns NULL if the function succeeds.
582 * Returns an Error Error if the function fails in a non-fatal way.
583 * Returns a Fatal Error if the function fails in an unrecoverable way.
585 PKIX_Error *
586 pkix_CacheCertChain_Lookup(
587 PKIX_PL_Cert* targetCert,
588 PKIX_List* anchors,
589 PKIX_PL_Date *testDate,
590 PKIX_Boolean *pFound,
591 PKIX_BuildResult **pBuildResult,
592 void *plContext)
594 PKIX_List *cachedValues = NULL;
595 PKIX_List *cachedKeys = NULL;
596 PKIX_Error *cachedCertChainError = NULL;
597 PKIX_PL_Date *cacheValidUntilDate = NULL;
598 PKIX_PL_Date *validityDate = NULL;
599 PKIX_Int32 cmpValidTimeResult = 0;
600 PKIX_Int32 cmpCacheTimeResult = 0;
602 PKIX_ENTER(BUILD, "pkix_CacheCertChain_Lookup");
604 PKIX_NULLCHECK_FOUR(targetCert, anchors, pFound, pBuildResult);
606 *pFound = PKIX_FALSE;
608 /* use trust anchors and target cert as hash key */
610 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
611 PKIX_LISTCREATEFAILED);
613 PKIX_CHECK(PKIX_List_AppendItem
614 (cachedKeys,
615 (PKIX_PL_Object *)targetCert,
616 plContext),
617 PKIX_LISTAPPENDITEMFAILED);
619 PKIX_CHECK(PKIX_List_AppendItem
620 (cachedKeys,
621 (PKIX_PL_Object *)anchors,
622 plContext),
623 PKIX_LISTAPPENDITEMFAILED);
625 cachedCertChainError = PKIX_PL_HashTable_Lookup
626 (cachedCertChainTable,
627 (PKIX_PL_Object *) cachedKeys,
628 (PKIX_PL_Object **) &cachedValues,
629 plContext);
631 pkix_ccLookupCount++;
633 /* retrieve data from hashed value list */
635 if (cachedValues != NULL && cachedCertChainError == NULL) {
637 PKIX_CHECK(PKIX_List_GetItem
638 (cachedValues,
640 (PKIX_PL_Object **) &cacheValidUntilDate,
641 plContext),
642 PKIX_LISTGETITEMFAILED);
644 /* check validity time and cache age time */
645 PKIX_CHECK(PKIX_List_GetItem
646 (cachedValues,
648 (PKIX_PL_Object **) &validityDate,
649 plContext),
650 PKIX_LISTGETITEMFAILED);
652 /* if testDate is not set, this cache item is not out-dated */
653 if (testDate) {
655 PKIX_CHECK(PKIX_PL_Object_Compare
656 ((PKIX_PL_Object *)testDate,
657 (PKIX_PL_Object *)cacheValidUntilDate,
658 &cmpCacheTimeResult,
659 plContext),
660 PKIX_OBJECTCOMPARATORFAILED);
662 PKIX_CHECK(PKIX_PL_Object_Compare
663 ((PKIX_PL_Object *)testDate,
664 (PKIX_PL_Object *)validityDate,
665 &cmpValidTimeResult,
666 plContext),
667 PKIX_OBJECTCOMPARATORFAILED);
670 /* certs' date are all valid and cache item is not old */
671 if (cmpValidTimeResult <= 0 && cmpCacheTimeResult <=0) {
673 PKIX_CHECK(PKIX_List_GetItem
674 (cachedValues,
676 (PKIX_PL_Object **) pBuildResult,
677 plContext),
678 PKIX_LISTGETITEMFAILED);
680 *pFound = PKIX_TRUE;
682 } else {
684 pkix_ccRemoveCount++;
685 *pFound = PKIX_FALSE;
687 /* out-dated item, remove it from cache */
688 PKIX_CHECK(PKIX_PL_HashTable_Remove
689 (cachedCertChainTable,
690 (PKIX_PL_Object *) cachedKeys,
691 plContext),
692 PKIX_HASHTABLEREMOVEFAILED);
696 cleanup:
698 PKIX_DECREF(cachedValues);
699 PKIX_DECREF(cachedKeys);
700 PKIX_DECREF(cachedCertChainError);
701 PKIX_DECREF(cacheValidUntilDate);
702 PKIX_DECREF(validityDate);
704 PKIX_RETURN(BUILD);
709 * FUNCTION: pkix_CacheCertChain_Remove
710 * DESCRIPTION:
712 * Remove CertChain Hash Table entry based on "targetCert" and "anchors"
713 * as the hash keys. If there is no item to match the key, no action is
714 * taken.
715 * The hashtable is maintained in the following ways:
716 * 1) When creating the hashtable, maximum bucket size can be specified (0 for
717 * unlimited). If items in a bucket reaches its full size, an new addition
718 * will trigger the removal of the old as FIFO sequence.
719 * 2) A PKIX_PL_Date created with current time offset by constant
720 * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
721 * When an item is retrieved, this date is compared against "testDate" for
722 * validity. If comparison indicates this item is expired, the item is
723 * removed from the bucket.
725 * PARAMETERS:
726 * "targetCert"
727 * Address of Target Cert as key to retrieve this CertChain. Must be
728 * non-NULL.
729 * "anchors"
730 * Address of PKIX_List of "anchors" is used as key to retrive CertChain.
731 * Must be non-NULL.
732 * "plContext"
733 * Platform-specific context pointer.
734 * THREAD SAFETY:
735 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
736 * RETURNS:
737 * Returns NULL if the function succeeds.
738 * Returns an Error Error if the function fails in a non-fatal way.
739 * Returns a Fatal Error if the function fails in an unrecoverable way.
741 PKIX_Error *
742 pkix_CacheCertChain_Remove(
743 PKIX_PL_Cert* targetCert,
744 PKIX_List* anchors,
745 void *plContext)
747 PKIX_List *cachedKeys = NULL;
749 PKIX_ENTER(BUILD, "pkix_CacheCertChain_Remove");
750 PKIX_NULLCHECK_TWO(targetCert, anchors);
752 /* use trust anchors and target cert as hash key */
754 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
755 PKIX_LISTCREATEFAILED);
757 PKIX_CHECK(PKIX_List_AppendItem
758 (cachedKeys,
759 (PKIX_PL_Object *)targetCert,
760 plContext),
761 PKIX_LISTAPPENDITEMFAILED);
763 PKIX_CHECK(PKIX_List_AppendItem
764 (cachedKeys,
765 (PKIX_PL_Object *)anchors,
766 plContext),
767 PKIX_LISTAPPENDITEMFAILED);
769 PKIX_CHECK_ONLY_FATAL(PKIX_PL_HashTable_Remove
770 (cachedCertChainTable,
771 (PKIX_PL_Object *) cachedKeys,
772 plContext),
773 PKIX_HASHTABLEREMOVEFAILED);
775 pkix_ccRemoveCount++;
777 cleanup:
779 PKIX_DECREF(cachedKeys);
781 PKIX_RETURN(BUILD);
786 * FUNCTION: pkix_CacheCertChain_Add
787 * DESCRIPTION:
789 * Add a BuildResult to the CertChain Hash Table for a "buildResult" with
790 * "targetCert" and "anchors" as the hash keys.
791 * "validityDate" is the most restricted notAfter date of all Certs in
792 * this CertChain and is verified when this BuildChain is retrieved.
793 * The hashtable is maintained in the following ways:
794 * 1) When creating the hashtable, maximum bucket size can be specified (0 for
795 * unlimited). If items in a bucket reaches its full size, an new addition
796 * will trigger the removal of the old as FIFO sequence.
797 * 2) A PKIX_PL_Date created with current time offset by constant
798 * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
799 * When an item is retrieved, this date is compared against "testDate" for
800 * validity. If comparison indicates this item is expired, the item is
801 * removed from the bucket.
803 * PARAMETERS:
804 * "targetCert"
805 * Address of Target Cert as key to retrieve this CertChain. Must be
806 * non-NULL.
807 * "anchors"
808 * Address of PKIX_List of "anchors" is used as key to retrive CertChain.
809 * Must be non-NULL.
810 * "validityDate"
811 * Address of PKIX_PL_Date contains the most restriced notAfter time of
812 * all "certs". Must be non-NULL.
813 * Address of PKIX_Boolean indicating valid data is found.
814 * Must be non-NULL.
815 * "buildResult"
816 * Address of BuildResult to be cached. Must be non-NULL.
817 * "plContext"
818 * Platform-specific context pointer.
819 * THREAD SAFETY:
820 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
821 * RETURNS:
822 * Returns NULL if the function succeeds.
823 * Returns an Error Error if the function fails in a non-fatal way.
824 * Returns a Fatal Error if the function fails in an unrecoverable way.
826 PKIX_Error *
827 pkix_CacheCertChain_Add(
828 PKIX_PL_Cert* targetCert,
829 PKIX_List* anchors,
830 PKIX_PL_Date *validityDate,
831 PKIX_BuildResult *buildResult,
832 void *plContext)
834 PKIX_List *cachedValues = NULL;
835 PKIX_List *cachedKeys = NULL;
836 PKIX_Error *cachedCertChainError = NULL;
837 PKIX_PL_Date *cacheValidUntilDate = NULL;
839 PKIX_ENTER(BUILD, "pkix_CacheCertChain_Add");
841 PKIX_NULLCHECK_FOUR(targetCert, anchors, validityDate, buildResult);
843 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
844 PKIX_LISTCREATEFAILED);
846 PKIX_CHECK(PKIX_List_AppendItem
847 (cachedKeys, (PKIX_PL_Object *)targetCert, plContext),
848 PKIX_LISTAPPENDITEMFAILED);
850 PKIX_CHECK(PKIX_List_AppendItem
851 (cachedKeys, (PKIX_PL_Object *)anchors, plContext),
852 PKIX_LISTAPPENDITEMFAILED);
854 PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext),
855 PKIX_LISTCREATEFAILED);
857 PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
858 (CACHE_ITEM_PERIOD_SECONDS,
859 &cacheValidUntilDate,
860 plContext),
861 PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
863 PKIX_CHECK(PKIX_List_AppendItem
864 (cachedValues,
865 (PKIX_PL_Object *)cacheValidUntilDate,
866 plContext),
867 PKIX_LISTAPPENDITEMFAILED);
869 PKIX_CHECK(PKIX_List_AppendItem
870 (cachedValues, (PKIX_PL_Object *)validityDate, plContext),
871 PKIX_LISTAPPENDITEMFAILED);
873 PKIX_CHECK(PKIX_List_AppendItem
874 (cachedValues, (PKIX_PL_Object *)buildResult, plContext),
875 PKIX_LISTAPPENDITEMFAILED);
877 cachedCertChainError = PKIX_PL_HashTable_Add
878 (cachedCertChainTable,
879 (PKIX_PL_Object *) cachedKeys,
880 (PKIX_PL_Object *) cachedValues,
881 plContext);
883 pkix_ccAddCount++;
885 if (cachedCertChainError != NULL) {
886 PKIX_DEBUG("PKIX_PL_HashTable_Add for CertChain skipped: "
887 "entry existed\n");
890 cleanup:
892 PKIX_DECREF(cachedValues);
893 PKIX_DECREF(cachedKeys);
894 PKIX_DECREF(cachedCertChainError);
895 PKIX_DECREF(cacheValidUntilDate);
897 PKIX_RETURN(BUILD);
901 * FUNCTION: pkix_CacheCert_Lookup
902 * DESCRIPTION:
904 * Look up Cert Hash Table for a cached item based on "store" and Subject in
905 * "certSelParams" as the hash keys and returns values Certs in "pCerts".
906 * If there isn't an item to match the key, a PKIX_FALSE is returned at
907 * "pFound". The item's cache time is verified with "testDate". If out-dated,
908 * this item is removed and PKIX_FALSE is returned at "pFound".
909 * This hashtable is maintained in the following ways:
910 * 1) When creating the hashtable, maximum bucket size can be specified (0 for
911 * unlimited). If items in a bucket reaches its full size, an new addition
912 * will trigger the removal of the old as FIFO sequence.
913 * 2) A PKIX_PL_Date created with current time offset by constant
914 * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
915 * If the CertStore this Cert is from is a trusted one, the cache period is
916 * shorter so cache can be updated more frequently.
917 * When an item is retrieved, this date is compared against "testDate" for
918 * validity. If comparison indicates this item is expired, the item is
919 * removed from the bucket.
921 * PARAMETERS:
922 * "store"
923 * Address of CertStore as key to retrieve this CertChain. Must be
924 * non-NULL.
925 * "certSelParams"
926 * Address of ComCertSelParams that its subject is used as key to retrieve
927 * this CertChain. Must be non-NULL.
928 * "testDate"
929 * Address of PKIX_PL_Date for verifying time cache validity.
930 * Must be non-NULL. If testDate is NULL, this cache item won't be out
931 * dated.
932 * "pFound"
933 * Address of KPKIX_Boolean indicating valid data is found.
934 * Must be non-NULL.
935 * "pCerts"
936 * Address PKIX_List where the CertChain will be stored. Must be no-NULL.
937 * "plContext"
938 * Platform-specific context pointer.
939 * THREAD SAFETY:
940 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
941 * RETURNS:
942 * Returns NULL if the function succeeds.
943 * Returns an Error Error if the function fails in a non-fatal way.
944 * Returns a Fatal Error if the function fails in an unrecoverable way.
946 PKIX_Error *
947 pkix_CacheCert_Lookup(
948 PKIX_CertStore *store,
949 PKIX_ComCertSelParams *certSelParams,
950 PKIX_PL_Date *testDate,
951 PKIX_Boolean *pFound,
952 PKIX_List** pCerts,
953 void *plContext)
955 PKIX_PL_Cert *cert = NULL;
956 PKIX_List *cachedKeys = NULL;
957 PKIX_List *cachedValues = NULL;
958 PKIX_List *cachedCertList = NULL;
959 PKIX_List *selCertList = NULL;
960 PKIX_PL_X500Name *subject = NULL;
961 PKIX_PL_Date *invalidAfterDate = NULL;
962 PKIX_PL_Date *cacheValidUntilDate = NULL;
963 PKIX_CertSelector *certSel = NULL;
964 PKIX_Error *cachedCertError = NULL;
965 PKIX_CertSelector_MatchCallback selectorMatch = NULL;
966 PKIX_Int32 cmpValidTimeResult = PKIX_FALSE;
967 PKIX_Int32 cmpCacheTimeResult = 0;
968 PKIX_Boolean certMatch = PKIX_FALSE;
969 PKIX_UInt32 numItems = 0;
970 PKIX_UInt32 i;
972 PKIX_ENTER(BUILD, "pkix_CacheCert_Lookup");
973 PKIX_NULLCHECK_TWO(store, certSelParams);
974 PKIX_NULLCHECK_TWO(pFound, pCerts);
976 *pFound = PKIX_FALSE;
978 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
979 PKIX_LISTCREATEFAILED);
981 PKIX_CHECK(PKIX_List_AppendItem
982 (cachedKeys, (PKIX_PL_Object *)store, plContext),
983 PKIX_LISTAPPENDITEMFAILED);
985 PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
986 (certSelParams, &subject, plContext),
987 PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
989 PKIX_NULLCHECK_ONE(subject);
991 PKIX_CHECK(PKIX_List_AppendItem
992 (cachedKeys, (PKIX_PL_Object *)subject, plContext),
993 PKIX_LISTAPPENDITEMFAILED);
995 cachedCertError = PKIX_PL_HashTable_Lookup
996 (cachedCertTable,
997 (PKIX_PL_Object *) cachedKeys,
998 (PKIX_PL_Object **) &cachedValues,
999 plContext);
1000 pkix_cLookupCount++;
1002 if (cachedValues != NULL && cachedCertError == NULL) {
1004 PKIX_CHECK(PKIX_List_GetItem
1005 (cachedValues,
1007 (PKIX_PL_Object **) &cacheValidUntilDate,
1008 plContext),
1009 PKIX_LISTGETITEMFAILED);
1011 if (testDate) {
1012 PKIX_CHECK(PKIX_PL_Object_Compare
1013 ((PKIX_PL_Object *)testDate,
1014 (PKIX_PL_Object *)cacheValidUntilDate,
1015 &cmpCacheTimeResult,
1016 plContext),
1017 PKIX_OBJECTCOMPARATORFAILED);
1020 if (cmpCacheTimeResult <= 0) {
1022 PKIX_CHECK(PKIX_List_GetItem
1023 (cachedValues,
1025 (PKIX_PL_Object **) &cachedCertList,
1026 plContext),
1027 PKIX_LISTGETITEMFAILED);
1030 * Certs put on cache satifies only for Subject,
1031 * user selector and ComCertSelParams to filter.
1033 PKIX_CHECK(PKIX_CertSelector_Create
1034 (NULL, NULL, &certSel, plContext),
1035 PKIX_CERTSELECTORCREATEFAILED);
1037 PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
1038 (certSel, certSelParams, plContext),
1039 PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
1041 PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
1042 (certSel, &selectorMatch, plContext),
1043 PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
1045 PKIX_CHECK(PKIX_List_Create(&selCertList, plContext),
1046 PKIX_LISTCREATEFAILED);
1049 * If any of the Cert on the list is out-dated, invalidate
1050 * this cache item.
1052 PKIX_CHECK(PKIX_List_GetLength
1053 (cachedCertList, &numItems, plContext),
1054 PKIX_LISTGETLENGTHFAILED);
1056 for (i = 0; i < numItems; i++){
1058 PKIX_CHECK(PKIX_List_GetItem
1059 (cachedCertList,
1061 (PKIX_PL_Object **)&cert,
1062 plContext),
1063 PKIX_LISTGETITEMFAILED);
1065 PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
1066 (cert, &invalidAfterDate, plContext),
1067 PKIX_CERTGETVALIDITYNOTAFTERFAILED);
1069 if (testDate) {
1070 PKIX_CHECK(PKIX_PL_Object_Compare
1071 ((PKIX_PL_Object *)invalidAfterDate,
1072 (PKIX_PL_Object *)testDate,
1073 &cmpValidTimeResult,
1074 plContext),
1075 PKIX_OBJECTCOMPARATORFAILED);
1078 if (cmpValidTimeResult < 0) {
1080 pkix_cRemoveCount++;
1081 *pFound = PKIX_FALSE;
1083 /* one cert is out-dated, remove item from cache */
1084 PKIX_CHECK(PKIX_PL_HashTable_Remove
1085 (cachedCertTable,
1086 (PKIX_PL_Object *) cachedKeys,
1087 plContext),
1088 PKIX_HASHTABLEREMOVEFAILED);
1089 goto cleanup;
1092 PKIX_CHECK(selectorMatch
1093 (certSel,
1094 cert,
1095 &certMatch,
1096 plContext),
1097 PKIX_SELECTORMATCHFAILED);
1099 if (certMatch){
1100 /* put on the return list */
1101 PKIX_CHECK(PKIX_List_AppendItem
1102 (selCertList,
1103 (PKIX_PL_Object *)cert,
1104 plContext),
1105 PKIX_LISTAPPENDITEMFAILED);
1107 *pFound = PKIX_TRUE;
1110 PKIX_DECREF(cert);
1111 PKIX_DECREF(invalidAfterDate);
1115 if (*pFound) {
1116 PKIX_INCREF(selCertList);
1117 *pCerts = selCertList;
1120 } else {
1122 pkix_cRemoveCount++;
1123 *pFound = PKIX_FALSE;
1124 /* cache item is out-dated, remove it from cache */
1125 PKIX_CHECK(PKIX_PL_HashTable_Remove
1126 (cachedCertTable,
1127 (PKIX_PL_Object *) cachedKeys,
1128 plContext),
1129 PKIX_HASHTABLEREMOVEFAILED);
1134 cleanup:
1136 PKIX_DECREF(subject);
1137 PKIX_DECREF(certSel);
1138 PKIX_DECREF(cachedKeys);
1139 PKIX_DECREF(cachedValues);
1140 PKIX_DECREF(cacheValidUntilDate);
1141 PKIX_DECREF(cert);
1142 PKIX_DECREF(cachedCertList);
1143 PKIX_DECREF(selCertList);
1144 PKIX_DECREF(invalidAfterDate);
1145 PKIX_DECREF(cachedCertError);
1147 PKIX_RETURN(BUILD);
1151 * FUNCTION: pkix_CacheCert_Add
1152 * DESCRIPTION:
1154 * Add Cert Hash Table for a cached item based on "store" and Subject in
1155 * "certSelParams" as the hash keys and have "certs" as the key value.
1156 * This hashtable is maintained in the following ways:
1157 * 1) When creating the hashtable, maximum bucket size can be specified (0 for
1158 * unlimited). If items in a bucket reaches its full size, an new addition
1159 * will trigger the removal of the old as FIFO sequence.
1160 * 2) A PKIX_PL_Date created with current time offset by constant
1161 * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
1162 * If the CertStore this Cert is from is a trusted one, the cache period is
1163 * shorter so cache can be updated more frequently.
1164 * When an item is retrieved, this date is compared against "testDate" for
1165 * validity. If comparison indicates this item is expired, the item is
1166 * removed from the bucket.
1168 * PARAMETERS:
1169 * "store"
1170 * Address of CertStore as key to retrieve this CertChain. Must be
1171 * non-NULL.
1172 * "certSelParams"
1173 * Address of ComCertSelParams that its subject is used as key to retrieve
1174 * this CertChain. Must be non-NULL.
1175 * "certs"
1176 * Address PKIX_List of Certs will be stored. Must be no-NULL.
1177 * "plContext"
1178 * Platform-specific context pointer.
1179 * THREAD SAFETY:
1180 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1181 * RETURNS:
1182 * Returns NULL if the function succeeds.
1183 * Returns an Error Error if the function fails in a non-fatal way.
1184 * Returns a Fatal Error if the function fails in an unrecoverable way.
1186 PKIX_Error *
1187 pkix_CacheCert_Add(
1188 PKIX_CertStore *store,
1189 PKIX_ComCertSelParams *certSelParams,
1190 PKIX_List* certs,
1191 void *plContext)
1193 PKIX_List *cachedKeys = NULL;
1194 PKIX_List *cachedValues = NULL;
1195 PKIX_PL_Date *cacheValidUntilDate = NULL;
1196 PKIX_PL_X500Name *subject = NULL;
1197 PKIX_Error *cachedCertError = NULL;
1198 PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
1199 PKIX_UInt32 cachePeriod = CACHE_ITEM_PERIOD_SECONDS;
1200 PKIX_UInt32 numCerts = 0;
1202 PKIX_ENTER(BUILD, "pkix_CacheCert_Add");
1203 PKIX_NULLCHECK_THREE(store, certSelParams, certs);
1205 PKIX_CHECK(PKIX_List_GetLength(certs, &numCerts,
1206 plContext),
1207 PKIX_LISTGETLENGTHFAILED);
1208 if (numCerts == 0) {
1209 /* Don't want to add an empty list. */
1210 goto cleanup;
1213 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
1214 PKIX_LISTCREATEFAILED);
1216 PKIX_CHECK(PKIX_List_AppendItem
1217 (cachedKeys, (PKIX_PL_Object *)store, plContext),
1218 PKIX_LISTAPPENDITEMFAILED);
1220 PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
1221 (certSelParams, &subject, plContext),
1222 PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
1224 PKIX_NULLCHECK_ONE(subject);
1226 PKIX_CHECK(PKIX_List_AppendItem
1227 (cachedKeys, (PKIX_PL_Object *)subject, plContext),
1228 PKIX_LISTAPPENDITEMFAILED);
1230 PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext),
1231 PKIX_LISTCREATEFAILED);
1233 PKIX_CHECK(PKIX_CertStore_GetTrustCallback
1234 (store, &trustCallback, plContext),
1235 PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
1237 if (trustCallback) {
1238 cachePeriod = CACHE_TRUST_ITEM_PERIOD_SECONDS;
1241 PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
1242 (cachePeriod, &cacheValidUntilDate, plContext),
1243 PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
1245 PKIX_CHECK(PKIX_List_AppendItem
1246 (cachedValues,
1247 (PKIX_PL_Object *)cacheValidUntilDate,
1248 plContext),
1249 PKIX_LISTAPPENDITEMFAILED);
1251 PKIX_CHECK(PKIX_List_AppendItem
1252 (cachedValues,
1253 (PKIX_PL_Object *)certs,
1254 plContext),
1255 PKIX_LISTAPPENDITEMFAILED);
1257 cachedCertError = PKIX_PL_HashTable_Add
1258 (cachedCertTable,
1259 (PKIX_PL_Object *) cachedKeys,
1260 (PKIX_PL_Object *) cachedValues,
1261 plContext);
1263 pkix_cAddCount++;
1265 if (cachedCertError != NULL) {
1266 PKIX_DEBUG("PKIX_PL_HashTable_Add for Certs skipped: "
1267 "entry existed\n");
1270 cleanup:
1272 PKIX_DECREF(subject);
1273 PKIX_DECREF(cachedKeys);
1274 PKIX_DECREF(cachedValues);
1275 PKIX_DECREF(cacheValidUntilDate);
1276 PKIX_DECREF(cachedCertError);
1278 PKIX_RETURN(BUILD);
1282 * FUNCTION: pkix_CacheCrlEntry_Lookup
1283 * DESCRIPTION:
1285 * Look up CrlEntry Hash Table for a cached item based on "store",
1286 * "certIssuer" and "certSerialNumber" as the hash keys and returns values
1287 * "pCrls". If there isn't an item to match the key, a PKIX_FALSE is
1288 * returned at "pFound".
1289 * This hashtable is maintained in the following way:
1290 * 1) When creating the hashtable, maximum bucket size can be specified (0 for
1291 * unlimited). If items in a bucket reaches its full size, an new addition
1292 * will trigger the removal of the old as FIFO sequence.
1294 * PARAMETERS:
1295 * "store"
1296 * Address of CertStore as key to retrieve this CertChain. Must be
1297 * non-NULL.
1298 * "certIssuer"
1299 * Address of X500Name that is used as key to retrieve the CRLEntries.
1300 * Must be non-NULL.
1301 * "certSerialNumber"
1302 * Address of BigInt that is used as key to retrieve the CRLEntries.
1303 * Must be non-NULL.
1304 * "pFound"
1305 * Address of KPKIX_Boolean indicating valid data is found.
1306 * Must be non-NULL.
1307 * "pCrls"
1308 * Address PKIX_List where the CRLEntry will be stored. Must be no-NULL.
1309 * "plContext"
1310 * Platform-specific context pointer.
1311 * THREAD SAFETY:
1312 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1313 * RETURNS:
1314 * Returns NULL if the function succeeds.
1315 * Returns an Error Error if the function fails in a non-fatal way.
1316 * Returns a Fatal Error if the function fails in an unrecoverable way.
1318 PKIX_Error *
1319 pkix_CacheCrlEntry_Lookup(
1320 PKIX_CertStore *store,
1321 PKIX_PL_X500Name *certIssuer,
1322 PKIX_PL_BigInt *certSerialNumber,
1323 PKIX_Boolean *pFound,
1324 PKIX_List** pCrls,
1325 void *plContext)
1327 PKIX_List *cachedKeys = NULL;
1328 PKIX_List *cachedCrlEntryList = NULL;
1329 PKIX_Error *cachedCrlEntryError = NULL;
1331 PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Lookup");
1332 PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber);
1333 PKIX_NULLCHECK_TWO(pFound, pCrls);
1335 *pFound = PKIX_FALSE;
1337 /* Find CrlEntry(s) by issuer and serial number */
1339 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
1340 PKIX_LISTCREATEFAILED);
1342 PKIX_CHECK(PKIX_List_AppendItem
1343 (cachedKeys, (PKIX_PL_Object *)store, plContext),
1344 PKIX_LISTAPPENDITEMFAILED);
1346 PKIX_CHECK(PKIX_List_AppendItem
1347 (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext),
1348 PKIX_LISTAPPENDITEMFAILED);
1350 PKIX_CHECK(PKIX_List_AppendItem
1351 (cachedKeys,
1352 (PKIX_PL_Object *)certSerialNumber,
1353 plContext),
1354 PKIX_LISTAPPENDITEMFAILED);
1356 cachedCrlEntryError = PKIX_PL_HashTable_Lookup
1357 (cachedCrlEntryTable,
1358 (PKIX_PL_Object *) cachedKeys,
1359 (PKIX_PL_Object **) &cachedCrlEntryList,
1360 plContext);
1361 pkix_ceLookupCount++;
1364 * We don't need check Date to invalidate this cache item,
1365 * the item is uniquely defined and won't be reverted. Let
1366 * the FIFO for cleaning up.
1369 if (cachedCrlEntryList != NULL && cachedCrlEntryError == NULL ) {
1371 PKIX_INCREF(cachedCrlEntryList);
1372 *pCrls = cachedCrlEntryList;
1374 *pFound = PKIX_TRUE;
1376 } else {
1378 *pFound = PKIX_FALSE;
1381 cleanup:
1383 PKIX_DECREF(cachedKeys);
1384 PKIX_DECREF(cachedCrlEntryList);
1385 PKIX_DECREF(cachedCrlEntryError);
1387 PKIX_RETURN(BUILD);
1391 * FUNCTION: pkix_CacheCrlEntry_Add
1392 * DESCRIPTION:
1394 * Look up CrlEntry Hash Table for a cached item based on "store",
1395 * "certIssuer" and "certSerialNumber" as the hash keys and have "pCrls" as
1396 * the hash value. If there isn't an item to match the key, a PKIX_FALSE is
1397 * returned at "pFound".
1398 * This hashtable is maintained in the following way:
1399 * 1) When creating the hashtable, maximum bucket size can be specified (0 for
1400 * unlimited). If items in a bucket reaches its full size, an new addition
1401 * will trigger the removal of the old as FIFO sequence.
1403 * PARAMETERS:
1404 * "store"
1405 * Address of CertStore as key to retrieve this CertChain. Must be
1406 * non-NULL.
1407 * "certIssuer"
1408 * Address of X500Name that is used as key to retrieve the CRLEntries.
1409 * Must be non-NULL.
1410 * "certSerialNumber"
1411 * Address of BigInt that is used as key to retrieve the CRLEntries.
1412 * Must be non-NULL.
1413 * "crls"
1414 * Address PKIX_List where the CRLEntry is stored. Must be no-NULL.
1415 * "plContext"
1416 * Platform-specific context pointer.
1417 * THREAD SAFETY:
1418 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1419 * RETURNS:
1420 * Returns NULL if the function succeeds.
1421 * Returns an Error Error if the function fails in a non-fatal way.
1422 * Returns a Fatal Error if the function fails in an unrecoverable way.
1424 PKIX_Error *
1425 pkix_CacheCrlEntry_Add(
1426 PKIX_CertStore *store,
1427 PKIX_PL_X500Name *certIssuer,
1428 PKIX_PL_BigInt *certSerialNumber,
1429 PKIX_List* crls,
1430 void *plContext)
1432 PKIX_List *cachedKeys = NULL;
1433 PKIX_Error *cachedCrlEntryError = NULL;
1435 PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Add");
1436 PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber);
1437 PKIX_NULLCHECK_ONE(crls);
1439 /* Add CrlEntry(s) by issuer and serial number */
1441 PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
1442 PKIX_LISTCREATEFAILED);
1444 PKIX_CHECK(PKIX_List_AppendItem
1445 (cachedKeys, (PKIX_PL_Object *)store, plContext),
1446 PKIX_LISTAPPENDITEMFAILED);
1448 PKIX_CHECK(PKIX_List_AppendItem
1449 (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext),
1450 PKIX_LISTAPPENDITEMFAILED);
1452 PKIX_CHECK(PKIX_List_AppendItem
1453 (cachedKeys,
1454 (PKIX_PL_Object *)certSerialNumber,
1455 plContext),
1456 PKIX_LISTAPPENDITEMFAILED);
1458 cachedCrlEntryError = PKIX_PL_HashTable_Add
1459 (cachedCrlEntryTable,
1460 (PKIX_PL_Object *) cachedKeys,
1461 (PKIX_PL_Object *) crls,
1462 plContext);
1463 pkix_ceAddCount++;
1465 cleanup:
1467 PKIX_DECREF(cachedKeys);
1468 PKIX_DECREF(cachedCrlEntryError);
1470 PKIX_RETURN(BUILD);
1473 #ifdef PKIX_OBJECT_LEAK_TEST
1475 /* TEST_START_FN and TEST_START_FN_STACK_POS define at what state
1476 * of the stack the object leak testing should begin. The condition
1477 * in pkix_CheckForGeneratedError works the following way: do leak
1478 * testing if at position TEST_START_FN_STACK_POS in stack array
1479 * (fnStackNameArr) we have called function TEST_START_FN.
1480 * Note, that stack array get filled only when executing libpkix
1481 * functions.
1482 * */
1483 #define TEST_START_FN "PKIX_BuildChain"
1484 #define TEST_START_FN_STACK_POS 2
1486 PKIX_Error*
1487 pkix_CheckForGeneratedError(PKIX_StdVars * stdVars,
1488 PKIX_ERRORCLASS errClass,
1489 char * fnName,
1490 PKIX_Boolean *errSetFlag,
1491 void * plContext)
1493 PKIX_Error *genErr = NULL;
1495 if (fnName) {
1496 if (fnStackNameArr[TEST_START_FN_STACK_POS] == NULL ||
1497 strcmp(fnStackNameArr[TEST_START_FN_STACK_POS], TEST_START_FN)
1499 /* return with out error if not with in boundary */
1500 return NULL;
1502 if (!strcmp(fnName, TEST_START_FN)) {
1503 *errSetFlag = PKIX_TRUE;
1504 noErrorState = PKIX_FALSE;
1505 errorGenerated = PKIX_FALSE;
1509 if (noErrorState || errorGenerated) return NULL;
1511 if (fnName && (
1512 !strcmp(fnName, "PKIX_PL_Object_DecRef") ||
1513 !strcmp(fnName, "PKIX_PL_Object_Unlock") ||
1514 !strcmp(fnName, "pkix_UnlockObject") ||
1515 !strcmp(fnName, "pkix_Throw") ||
1516 !strcmp(fnName, "pkix_trace_dump_cert") ||
1517 !strcmp(fnName, "PKIX_PL_Free"))) {
1518 /* do not generate error for this functions */
1519 noErrorState = PKIX_TRUE;
1520 *errSetFlag = PKIX_TRUE;
1521 return NULL;
1524 if (PL_HashTableLookup(fnInvTable, &fnStackInvCountArr[stackPosition - 1])) {
1525 return NULL;
1528 PL_HashTableAdd(fnInvTable, &fnStackInvCountArr[stackPosition - 1], nonNullValue);
1529 errorGenerated = PKIX_TRUE;
1530 noErrorState = PKIX_TRUE;
1531 genErr = PKIX_DoThrow(stdVars, errClass, PKIX_MEMLEAKGENERATEDERROR,
1532 errClass, plContext);
1533 noErrorState = PKIX_FALSE;
1535 return genErr;
1537 #endif /* PKIX_OBJECT_LEAK_TEST */