Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/libpkix/pkix/util/pkix_tools.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 */ |