|
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 */ |