PageRenderTime 53ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/lib/libpkix/pkix/util/pkix_tools.c

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