kernel: fq_codel: dont reinit flow state
[openwrt/staging/dedeckeh.git] / package / ead / src / tinysrp / t_misc.c
1 /*
2 * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
18 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
21 * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
22 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
23 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
24 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 *
26 * In addition, the following conditions apply:
27 *
28 * 1. Any software that incorporates the SRP authentication technology
29 * must display the following acknowlegment:
30 * "This product uses the 'Secure Remote Password' cryptographic
31 * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
32 *
33 * 2. Any software that incorporates all or part of the SRP distribution
34 * itself must also display the following acknowledgment:
35 * "This product includes software developed by Tom Wu and Eugene
36 * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
37 *
38 * 3. Redistributions in source or binary form must retain an intact copy
39 * of this copyright notice and list of conditions.
40 */
41
42 #include "t_defines.h"
43
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif /* HAVE_UNISTD_H */
47
48 #include <stdio.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <fcntl.h>
52
53 #include "t_sha.h"
54
55 #ifndef NULL
56 #define NULL 0
57 #endif
58
59 static unsigned char randpool[SHA_DIGESTSIZE], randout[SHA_DIGESTSIZE];
60 static unsigned long randcnt = 0;
61 static unsigned int outpos = 0;
62 SHA1_CTX randctxt;
63
64 /*
65 * t_envhash - Generate a 160-bit SHA hash of the environment
66 *
67 * This routine performs an SHA hash of all the "name=value" pairs
68 * in the environment concatenated together and dumps them in the
69 * output. While it is true that anyone on the system can see
70 * your environment, someone not on the system will have a very
71 * difficult time guessing it, especially since some systems play
72 * tricks with variable ordering and sometimes define quirky
73 * environment variables like $WINDOWID or $_.
74 */
75 extern char ** environ;
76
77 static void
78 t_envhash(out)
79 unsigned char * out;
80 {
81 char ** ptr;
82 char ebuf[256];
83 SHA1_CTX ctxt;
84
85 SHA1Init(&ctxt);
86 for(ptr = environ; *ptr; ++ptr) {
87 strncpy(ebuf, *ptr, 255);
88 ebuf[255] = '\0';
89 SHA1Update(&ctxt, ebuf, strlen(ebuf));
90 }
91 SHA1Final(out, &ctxt);
92 }
93
94 /*
95 * t_fshash - Generate a 160-bit SHA hash from the file system
96 *
97 * This routine climbs up the directory tree from the current
98 * directory, running stat() on each directory until it hits the
99 * root directory. This information is sensitive to the last
100 * access/modification times of all the directories above you,
101 * so someone who lists one of those directories injects some
102 * entropy into the system. Obviously, this hash is very sensitive
103 * to your current directory when the program is run.
104 *
105 * For good measure, it also performs an fstat on the standard input,
106 * usually your tty, throws that into the buffer, creates a file in
107 * /tmp (the inode is unpredictable on a busy system), and runs stat()
108 * on that before deleting it.
109 *
110 * The entire buffer is run once through SHA to obtain the final result.
111 */
112 static void
113 t_fshash(out)
114 unsigned char * out;
115 {
116 char dotpath[128];
117 struct stat st;
118 SHA1_CTX ctxt;
119 int i, pinode;
120 dev_t pdev;
121
122 SHA1Init(&ctxt);
123 if(stat(".", &st) >= 0) {
124 SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
125 pinode = st.st_ino;
126 pdev = st.st_dev;
127 strcpy(dotpath, "..");
128 for(i = 0; i < 40; ++i) {
129 if(stat(dotpath, &st) < 0)
130 break;
131 if(st.st_ino == pinode && st.st_dev == pdev)
132 break;
133 SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
134 pinode = st.st_ino;
135 pdev = st.st_dev;
136 strcat(dotpath, "/..");
137 }
138 }
139
140 if(fstat(0, &st) >= 0)
141 SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
142
143 sprintf(dotpath, "/tmp/rnd.%d", getpid());
144 if(creat(dotpath, 0600) >= 0 && stat(dotpath, &st) >= 0)
145 SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
146 unlink(dotpath);
147
148 SHA1Final(out, &ctxt);
149 }
150
151 /*
152 * Generate a high-entropy seed for the strong random number generator.
153 * This uses a wide variety of quickly gathered and somewhat unpredictable
154 * system information. The 'preseed' structure is assembled from:
155 *
156 * The system time in seconds
157 * The system time in microseconds
158 * The current process ID
159 * The parent process ID
160 * A hash of the user's environment
161 * A hash gathered from the file system
162 * Input from a random device, if available
163 * Timings of system interrupts
164 *
165 * The entire structure (60 bytes on most systems) is fed to SHA to produce
166 * a 160-bit seed for the strong random number generator. It is believed
167 * that in the worst case (on a quiet system with no random device versus
168 * an attacker who has access to the system already), the seed contains at
169 * least about 80 bits of entropy. Versus an attacker who does not have
170 * access to the system, the entropy should be slightly over 128 bits.
171 */
172 static char initialized = 0;
173
174 static struct {
175 unsigned int trand1;
176 time_t sec;
177 time_t usec;
178 short pid;
179 short ppid;
180 unsigned char envh[SHA_DIGESTSIZE];
181 unsigned char fsh[SHA_DIGESTSIZE];
182 unsigned char devrand[20];
183 unsigned int trand2;
184 } preseed;
185
186 unsigned long raw_truerand();
187
188 void
189 t_initrand()
190 {
191 SHA1_CTX ctxt;
192 #ifdef USE_FTIME
193 struct timeb t;
194 #else
195 struct timeval t;
196 #endif
197 int i, r=0;
198
199 if(initialized)
200 return;
201
202 initialized = 1;
203
204 i = open("/dev/urandom", O_RDONLY);
205 if(i > 0) {
206 r += read(i, preseed.devrand, sizeof(preseed.devrand));
207 close(i);
208 }
209
210 /* Resort to truerand only if desperate for some Real entropy */
211 if(r == 0)
212 preseed.trand1 = raw_truerand();
213
214 #ifdef USE_FTIME
215 ftime(&t);
216 #else
217 gettimeofday(&t, NULL);
218 #endif
219
220 #ifdef USE_FTIME
221 preseed.sec = t.time;
222 preseed.usec = t.millitm;
223 #else
224 preseed.sec = t.tv_sec;
225 preseed.usec = t.tv_usec;
226 #endif
227 preseed.pid = getpid();
228 preseed.ppid = getppid();
229 t_envhash(preseed.envh);
230 t_fshash(preseed.fsh);
231
232 if(r == 0)
233 preseed.trand2 = raw_truerand();
234
235 SHA1Init(&ctxt);
236 SHA1Update(&ctxt, (unsigned char *) &preseed, sizeof(preseed));
237 SHA1Final(randpool, &ctxt);
238 outpos = 0;
239 memset((unsigned char *) &preseed, 0, sizeof(preseed));
240 memset((unsigned char *) &ctxt, 0, sizeof(ctxt));
241 }
242
243 #define NUM_RANDOMS 12
244
245 /*
246 * The strong random number generator. This uses a 160-bit seed
247 * and uses SHA-1 in a feedback configuration to generate successive
248 * outputs. If S[0] is set to the initial seed, then:
249 *
250 * S[i+1] = SHA-1(i || S[i])
251 * A[i] = SHA-1(S[i])
252 *
253 * where the A[i] are the output blocks starting with i=0.
254 * Each cycle generates 20 bytes of new output.
255 */
256 _TYPE( void )
257 t_random(data, size)
258 unsigned char * data;
259 unsigned size;
260 {
261 if(!initialized)
262 t_initrand();
263
264 if(size <= 0) /* t_random(NULL, 0) forces seed initialization */
265 return;
266
267 while(size > outpos) {
268 if(outpos > 0) {
269 memcpy(data, randout + (sizeof(randout) - outpos), outpos);
270 data += outpos;
271 size -= outpos;
272 }
273
274 /* Recycle */
275 SHA1Init(&randctxt);
276 SHA1Update(&randctxt, randpool, sizeof(randpool));
277 SHA1Final(randout, &randctxt);
278 SHA1Init(&randctxt);
279 SHA1Update(&randctxt, (unsigned char *) &randcnt, sizeof(randcnt));
280 SHA1Update(&randctxt, randpool, sizeof(randpool));
281 SHA1Final(randpool, &randctxt);
282 ++randcnt;
283 outpos = sizeof(randout);
284 }
285
286 if(size > 0) {
287 memcpy(data, randout + (sizeof(randout) - outpos), size);
288 outpos -= size;
289 }
290 }
291
292 /*
293 * The interleaved session-key hash. This separates the even and the odd
294 * bytes of the input (ignoring the first byte if the input length is odd),
295 * hashes them separately, and re-interleaves the two outputs to form a
296 * single 320-bit value.
297 */
298 _TYPE( unsigned char * )
299 t_sessionkey(key, sk, sklen)
300 unsigned char * key;
301 unsigned char * sk;
302 unsigned sklen;
303 {
304 unsigned i, klen;
305 unsigned char * hbuf;
306 unsigned char hout[SHA_DIGESTSIZE];
307 SHA1_CTX ctxt;
308
309 while(sklen > 0 && *sk == 0) { /* Skip leading 0's */
310 --sklen;
311 ++sk;
312 }
313
314 klen = sklen / 2;
315 if((hbuf = malloc(klen * sizeof(char))) == 0)
316 return 0;
317
318 for(i = 0; i < klen; ++i)
319 hbuf[i] = sk[sklen - 2 * i - 1];
320 SHA1Init(&ctxt);
321 SHA1Update(&ctxt, hbuf, klen);
322 SHA1Final(hout, &ctxt);
323 for(i = 0; i < sizeof(hout); ++i)
324 key[2 * i] = hout[i];
325
326 for(i = 0; i < klen; ++i)
327 hbuf[i] = sk[sklen - 2 * i - 2];
328 SHA1Init(&ctxt);
329 SHA1Update(&ctxt, hbuf, klen);
330 SHA1Final(hout, &ctxt);
331 for(i = 0; i < sizeof(hout); ++i)
332 key[2 * i + 1] = hout[i];
333
334 memset(hout, 0, sizeof(hout));
335 memset(hbuf, 0, klen);
336 free(hbuf);
337 return key;
338 }