/contrib/bind9/lib/isc/hash.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 404 lines · 261 code · 66 blank · 77 comment · 61 complexity · 98ad5dcb59b8bc6a34c0ec844d73af6c MD5 · raw file

  1. /*
  2. * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 2003 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. * PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /* $Id: hash.c,v 1.16 2009/09/01 00:22:28 jinmei Exp $ */
  18. /*! \file
  19. * Some portion of this code was derived from universal hash function
  20. * libraries of Rice University.
  21. \section license UH Universal Hashing Library
  22. Copyright ((c)) 2002, Rice University
  23. All rights reserved.
  24. Redistribution and use in source and binary forms, with or without
  25. modification, are permitted provided that the following conditions are
  26. met:
  27. * Redistributions of source code must retain the above copyright
  28. notice, this list of conditions and the following disclaimer.
  29. * Redistributions in binary form must reproduce the above
  30. copyright notice, this list of conditions and the following
  31. disclaimer in the documentation and/or other materials provided
  32. with the distribution.
  33. * Neither the name of Rice University (RICE) nor the names of its
  34. contributors may be used to endorse or promote products derived
  35. from this software without specific prior written permission.
  36. This software is provided by RICE and the contributors on an "as is"
  37. basis, without any representations or warranties of any kind, express
  38. or implied including, but not limited to, representations or
  39. warranties of non-infringement, merchantability or fitness for a
  40. particular purpose. In no event shall RICE or contributors be liable
  41. for any direct, indirect, incidental, special, exemplary, or
  42. consequential damages (including, but not limited to, procurement of
  43. substitute goods or services; loss of use, data, or profits; or
  44. business interruption) however caused and on any theory of liability,
  45. whether in contract, strict liability, or tort (including negligence
  46. or otherwise) arising in any way out of the use of this software, even
  47. if advised of the possibility of such damage.
  48. */
  49. #include <config.h>
  50. #include <isc/entropy.h>
  51. #include <isc/hash.h>
  52. #include <isc/mem.h>
  53. #include <isc/magic.h>
  54. #include <isc/mutex.h>
  55. #include <isc/once.h>
  56. #include <isc/random.h>
  57. #include <isc/refcount.h>
  58. #include <isc/string.h>
  59. #include <isc/util.h>
  60. #define HASH_MAGIC ISC_MAGIC('H', 'a', 's', 'h')
  61. #define VALID_HASH(h) ISC_MAGIC_VALID((h), HASH_MAGIC)
  62. /*%
  63. * A large 32-bit prime number that specifies the range of the hash output.
  64. */
  65. #define PRIME32 0xFFFFFFFB /* 2^32 - 5 */
  66. /*@{*/
  67. /*%
  68. * Types of random seed and hash accumulator. Perhaps they can be system
  69. * dependent.
  70. */
  71. typedef isc_uint32_t hash_accum_t;
  72. typedef isc_uint16_t hash_random_t;
  73. /*@}*/
  74. /*% isc hash structure */
  75. struct isc_hash {
  76. unsigned int magic;
  77. isc_mem_t *mctx;
  78. isc_mutex_t lock;
  79. isc_boolean_t initialized;
  80. isc_refcount_t refcnt;
  81. isc_entropy_t *entropy; /*%< entropy source */
  82. unsigned int limit; /*%< upper limit of key length */
  83. size_t vectorlen; /*%< size of the vector below */
  84. hash_random_t *rndvector; /*%< random vector for universal hashing */
  85. };
  86. static isc_mutex_t createlock;
  87. static isc_once_t once = ISC_ONCE_INIT;
  88. static isc_hash_t *hash = NULL;
  89. static unsigned char maptolower[] = {
  90. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  91. 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  92. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  93. 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  94. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
  95. 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  96. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  97. 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  98. 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
  99. 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
  100. 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
  101. 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
  102. 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
  103. 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
  104. 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
  105. 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
  106. 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
  107. 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
  108. 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
  109. 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
  110. 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
  111. 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
  112. 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
  113. 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
  114. 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
  115. 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
  116. 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
  117. 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
  118. 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
  119. 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
  120. 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
  121. 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
  122. };
  123. isc_result_t
  124. isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy,
  125. unsigned int limit, isc_hash_t **hctxp)
  126. {
  127. isc_result_t result;
  128. isc_hash_t *hctx;
  129. size_t vlen;
  130. hash_random_t *rv;
  131. hash_accum_t overflow_limit;
  132. REQUIRE(mctx != NULL);
  133. REQUIRE(hctxp != NULL && *hctxp == NULL);
  134. /*
  135. * Overflow check. Since our implementation only does a modulo
  136. * operation at the last stage of hash calculation, the accumulator
  137. * must not overflow.
  138. */
  139. overflow_limit =
  140. 1 << (((sizeof(hash_accum_t) - sizeof(hash_random_t))) * 8);
  141. if (overflow_limit < (limit + 1) * 0xff)
  142. return (ISC_R_RANGE);
  143. hctx = isc_mem_get(mctx, sizeof(isc_hash_t));
  144. if (hctx == NULL)
  145. return (ISC_R_NOMEMORY);
  146. vlen = sizeof(hash_random_t) * (limit + 1);
  147. rv = isc_mem_get(mctx, vlen);
  148. if (rv == NULL) {
  149. result = ISC_R_NOMEMORY;
  150. goto errout;
  151. }
  152. /*
  153. * We need a lock.
  154. */
  155. result = isc_mutex_init(&hctx->lock);
  156. if (result != ISC_R_SUCCESS)
  157. goto errout;
  158. /*
  159. * From here down, no failures will/can occur.
  160. */
  161. hctx->magic = HASH_MAGIC;
  162. hctx->mctx = NULL;
  163. isc_mem_attach(mctx, &hctx->mctx);
  164. hctx->initialized = ISC_FALSE;
  165. result = isc_refcount_init(&hctx->refcnt, 1);
  166. if (result != ISC_R_SUCCESS)
  167. goto cleanup_lock;
  168. hctx->entropy = NULL;
  169. hctx->limit = limit;
  170. hctx->vectorlen = vlen;
  171. hctx->rndvector = rv;
  172. #ifdef BIND9
  173. if (entropy != NULL)
  174. isc_entropy_attach(entropy, &hctx->entropy);
  175. #else
  176. UNUSED(entropy);
  177. #endif
  178. *hctxp = hctx;
  179. return (ISC_R_SUCCESS);
  180. cleanup_lock:
  181. DESTROYLOCK(&hctx->lock);
  182. errout:
  183. isc_mem_put(mctx, hctx, sizeof(isc_hash_t));
  184. if (rv != NULL)
  185. isc_mem_put(mctx, rv, vlen);
  186. return (result);
  187. }
  188. static void
  189. initialize_lock(void) {
  190. RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
  191. }
  192. isc_result_t
  193. isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit) {
  194. isc_result_t result = ISC_R_SUCCESS;
  195. REQUIRE(mctx != NULL);
  196. INSIST(hash == NULL);
  197. RUNTIME_CHECK(isc_once_do(&once, initialize_lock) == ISC_R_SUCCESS);
  198. LOCK(&createlock);
  199. if (hash == NULL)
  200. result = isc_hash_ctxcreate(mctx, entropy, limit, &hash);
  201. UNLOCK(&createlock);
  202. return (result);
  203. }
  204. void
  205. isc_hash_ctxinit(isc_hash_t *hctx) {
  206. LOCK(&hctx->lock);
  207. if (hctx->initialized == ISC_TRUE)
  208. goto out;
  209. if (hctx->entropy) {
  210. #ifdef BIND9
  211. isc_result_t result;
  212. result = isc_entropy_getdata(hctx->entropy,
  213. hctx->rndvector, hctx->vectorlen,
  214. NULL, 0);
  215. INSIST(result == ISC_R_SUCCESS);
  216. #else
  217. INSIST(0);
  218. #endif
  219. } else {
  220. isc_uint32_t pr;
  221. unsigned int i, copylen;
  222. unsigned char *p;
  223. p = (unsigned char *)hctx->rndvector;
  224. for (i = 0; i < hctx->vectorlen; i += copylen, p += copylen) {
  225. isc_random_get(&pr);
  226. if (i + sizeof(pr) <= hctx->vectorlen)
  227. copylen = sizeof(pr);
  228. else
  229. copylen = hctx->vectorlen - i;
  230. memcpy(p, &pr, copylen);
  231. }
  232. INSIST(p == (unsigned char *)hctx->rndvector +
  233. hctx->vectorlen);
  234. }
  235. hctx->initialized = ISC_TRUE;
  236. out:
  237. UNLOCK(&hctx->lock);
  238. }
  239. void
  240. isc_hash_init() {
  241. INSIST(hash != NULL && VALID_HASH(hash));
  242. isc_hash_ctxinit(hash);
  243. }
  244. void
  245. isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp) {
  246. REQUIRE(VALID_HASH(hctx));
  247. REQUIRE(hctxp != NULL && *hctxp == NULL);
  248. isc_refcount_increment(&hctx->refcnt, NULL);
  249. *hctxp = hctx;
  250. }
  251. static void
  252. destroy(isc_hash_t **hctxp) {
  253. isc_hash_t *hctx;
  254. isc_mem_t *mctx;
  255. unsigned char canary0[4], canary1[4];
  256. REQUIRE(hctxp != NULL && *hctxp != NULL);
  257. hctx = *hctxp;
  258. *hctxp = NULL;
  259. LOCK(&hctx->lock);
  260. isc_refcount_destroy(&hctx->refcnt);
  261. mctx = hctx->mctx;
  262. #ifdef BIND9
  263. if (hctx->entropy != NULL)
  264. isc_entropy_detach(&hctx->entropy);
  265. #endif
  266. if (hctx->rndvector != NULL)
  267. isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen);
  268. UNLOCK(&hctx->lock);
  269. DESTROYLOCK(&hctx->lock);
  270. memcpy(canary0, hctx + 1, sizeof(canary0));
  271. memset(hctx, 0, sizeof(isc_hash_t));
  272. memcpy(canary1, hctx + 1, sizeof(canary1));
  273. INSIST(memcmp(canary0, canary1, sizeof(canary0)) == 0);
  274. isc_mem_put(mctx, hctx, sizeof(isc_hash_t));
  275. isc_mem_detach(&mctx);
  276. }
  277. void
  278. isc_hash_ctxdetach(isc_hash_t **hctxp) {
  279. isc_hash_t *hctx;
  280. unsigned int refs;
  281. REQUIRE(hctxp != NULL && VALID_HASH(*hctxp));
  282. hctx = *hctxp;
  283. isc_refcount_decrement(&hctx->refcnt, &refs);
  284. if (refs == 0)
  285. destroy(&hctx);
  286. *hctxp = NULL;
  287. }
  288. void
  289. isc_hash_destroy() {
  290. unsigned int refs;
  291. INSIST(hash != NULL && VALID_HASH(hash));
  292. isc_refcount_decrement(&hash->refcnt, &refs);
  293. INSIST(refs == 0);
  294. destroy(&hash);
  295. }
  296. static inline unsigned int
  297. hash_calc(isc_hash_t *hctx, const unsigned char *key, unsigned int keylen,
  298. isc_boolean_t case_sensitive)
  299. {
  300. hash_accum_t partial_sum = 0;
  301. hash_random_t *p = hctx->rndvector;
  302. unsigned int i = 0;
  303. /* Make it sure that the hash context is initialized. */
  304. if (hctx->initialized == ISC_FALSE)
  305. isc_hash_ctxinit(hctx);
  306. if (case_sensitive) {
  307. for (i = 0; i < keylen; i++)
  308. partial_sum += key[i] * (hash_accum_t)p[i];
  309. } else {
  310. for (i = 0; i < keylen; i++)
  311. partial_sum += maptolower[key[i]] * (hash_accum_t)p[i];
  312. }
  313. partial_sum += p[i];
  314. return ((unsigned int)(partial_sum % PRIME32));
  315. }
  316. unsigned int
  317. isc_hash_ctxcalc(isc_hash_t *hctx, const unsigned char *key,
  318. unsigned int keylen, isc_boolean_t case_sensitive)
  319. {
  320. REQUIRE(hctx != NULL && VALID_HASH(hctx));
  321. REQUIRE(keylen <= hctx->limit);
  322. return (hash_calc(hctx, key, keylen, case_sensitive));
  323. }
  324. unsigned int
  325. isc_hash_calc(const unsigned char *key, unsigned int keylen,
  326. isc_boolean_t case_sensitive)
  327. {
  328. INSIST(hash != NULL && VALID_HASH(hash));
  329. REQUIRE(keylen <= hash->limit);
  330. return (hash_calc(hash, key, keylen, case_sensitive));
  331. }