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