1 /*
2  * Copyright (C) 1999  Descolada (dyn1-tnt9-237.chicago.il.ameritech.net)
3  * Copyright (C) 1999,2000  Ross Combs (rocombs@cs.nmsu.edu)
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  */
19 #include "common/setup_before.h"
20 #include <stdio.h>
21 #ifdef HAVE_STDDEF_H
22 # include <stddef.h>
23 #else
24 # ifndef NULL
25 #  define NULL ((void *)0)
26 # endif
27 #endif
28 #ifdef STDC_HEADERS
29 # include <stdlib.h>
30 #endif
31 #ifdef HAVE_STRING_H
32 # include <string.h>
33 #else
34 # ifdef HAVE_STRINGS_H
35 #  include <strings.h>
36 # endif
37 #endif
38 #include "compat/uint.h"
39 #include "common/introtate.h"
40 #include "common/eventlog.h"
41 #include "common/bnethash.h"
42 #include "common/setup_after.h"
43 
44 
45 static void hash_init(t_hash * hash);
46 static void do_hash(t_hash * hash, t_uint32 * tmp);
47 static void hash_set_16(t_uint32 * dst, unsigned char const * src, unsigned int count);
48 
49 
hash_init(t_hash * hash)50 static void hash_init(t_hash * hash)
51 {
52     (*hash)[0] = 0x67452301;
53     (*hash)[1] = 0xefcdab89;
54     (*hash)[2] = 0x98badcfe;
55     (*hash)[3] = 0x10325476;
56     (*hash)[4] = 0xc3d2e1f0;
57 }
58 
59 
do_hash(t_hash * hash,t_uint32 * tmp)60 static void do_hash(t_hash * hash, t_uint32 * tmp)
61 {
62     unsigned int i;
63     t_uint32     a,b,c,d,e,g;
64 
65     for (i=0; i<64; i++)
66 	tmp[i+16] = ROTL32(1,tmp[i] ^ tmp[i+8] ^ tmp[i+2] ^ tmp[i+13]);
67 
68     a = (*hash)[0];
69     b = (*hash)[1];
70     c = (*hash)[2];
71     d = (*hash)[3];
72     e = (*hash)[4];
73 
74     for (i=0; i<20*1; i++)
75     {
76 	g = tmp[i] + ROTL32(a,5) + e + ((b & c) | (~b & d)) + 0x5a827999;
77 	e = d;
78 	d = c;
79 	c = ROTL32(b,30);
80 	b = a;
81 	a = g;
82     }
83 
84     for (; i<20*2; i++)
85     {
86 	g = (d ^ c ^ b) + e + ROTL32(g,5) + tmp[i] + 0x6ed9eba1;
87 	e = d;
88 	d = c;
89 	c = ROTL32(b,30);
90 	b = a;
91 	a = g;
92     }
93 
94     for (; i<20*3; i++)
95     {
96 	g = tmp[i] + ROTL32(g,5) + e + ((c & b) | (d & c) | (d & b)) - 0x70e44324;
97 	e = d;
98 	d = c;
99 	c = ROTL32(b,30);
100 	b = a;
101 	a = g;
102     }
103 
104     for (; i<20*4; i++)
105     {
106 	g = (d ^ c ^ b) + e + ROTL32(g,5) + tmp[i] - 0x359d3e2a;
107 	e = d;
108 	d = c;
109 	c = ROTL32(b,30);
110 	b = a;
111 	a = g;
112     }
113 
114     (*hash)[0] += g;
115     (*hash)[1] += b;
116     (*hash)[2] += c;
117     (*hash)[3] += d;
118     (*hash)[4] += e;
119 }
120 
121 
122 /*
123  * Fill 16 elements of the array of 32 bit values with the bytes from
124  * dst up to count in little endian order. Fill left over space with
125  * zeros
126  */
hash_set_16(t_uint32 * dst,unsigned char const * src,unsigned int count)127 static void hash_set_16(t_uint32 * dst, unsigned char const * src, unsigned int count)
128 {
129     unsigned int i;
130     unsigned int pos;
131 
132     for (pos=0,i=0; i<16; i++)
133     {
134 	dst[i] = 0;
135         if (pos<count)
136 	    dst[i] |= ((t_uint32)src[pos]);
137 	pos++;
138         if (pos<count)
139 	    dst[i] |= ((t_uint32)src[pos])<<8;
140 	pos++;
141         if (pos<count)
142 	    dst[i] |= ((t_uint32)src[pos])<<16;
143 	pos++;
144         if (pos<count)
145 	    dst[i] |= ((t_uint32)src[pos])<<24;
146 	pos++;
147     }
148 }
149 
150 
bnet_hash(t_hash * hashout,unsigned int size,void const * datain)151 extern int bnet_hash(t_hash * hashout, unsigned int size, void const * datain)
152 {
153     t_uint32              tmp[64+16];
154     unsigned char const * data;
155     unsigned int          inc;
156 
157     if (!hashout || !*hashout)
158     {
159 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL hashout");
160 	return -1;
161     }
162     if (size>0 && !datain)
163     {
164 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL datain with size=%u",size);
165 	return -1;
166     }
167 
168     hash_init(hashout);
169 
170     data = datain;
171     while (size>0)
172     {
173 	if (size>64)
174 	    inc = 64;
175 	else
176 	    inc = size;
177 
178 	hash_set_16(tmp,data,inc);
179 	do_hash(hashout,tmp);
180 
181 	data += inc;
182 	size -= inc;
183     }
184 
185     return 0;
186 }
187 
188 
hash_eq(t_hash const h1,t_hash const h2)189 extern int hash_eq(t_hash const h1, t_hash const h2)
190 {
191     unsigned int i;
192 
193     if (!h1 || !h2)
194     {
195 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL hash");
196 	return -1;
197     }
198 
199     for (i=0; i<5; i++)
200 	if (h1[i]!=h2[i])
201 	    return 0;
202 
203     return 1;
204 }
205 
206 
hash_get_str(t_hash const hash)207 extern char const * hash_get_str(t_hash const hash)
208 {
209     static char  temp[8*5+1]; /* each of 5 ints to 8 chars + null */
210     unsigned int i;
211 
212     if (!hash)
213     {
214 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL hash");
215 	return NULL;
216     }
217 
218     for (i=0; i<5; i++)
219         sprintf(&temp[i*8],"%08x",hash[i]);
220 
221     return temp;
222 }
223 
224 
hash_set_str(t_hash * hash,char const * str)225 extern int hash_set_str(t_hash * hash, char const * str)
226 {
227     unsigned int i;
228 
229     if (!hash)
230     {
231 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL hash pointer");
232         return -1;
233     }
234     if (!*hash)
235     {
236 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL hash");
237         return -1;
238     }
239     if (!str)
240     {
241 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL str");
242         return -1;
243     }
244     if (strlen(str)!=5*8)
245     {
246 	eventlog(eventlog_level_error,__FUNCTION__,"got string with length %u (should be %u)",strlen(str),5*8);
247         return -1;
248     }
249 
250     for (i=0; i<5; i++)
251         if (sscanf(&str[i*8],"%8x",&(*hash)[i])!=1)
252 	{
253 	    eventlog(eventlog_level_error,__FUNCTION__,"got bad string");
254 	    return -1;
255 	}
256 
257     return 0;
258 }
259 
260 
261