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