diff options
Diffstat (limited to '3rd_party/libsrp6a-sha512/t_misc.c')
-rw-r--r-- | 3rd_party/libsrp6a-sha512/t_misc.c | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/3rd_party/libsrp6a-sha512/t_misc.c b/3rd_party/libsrp6a-sha512/t_misc.c new file mode 100644 index 0000000..3a2cda1 --- /dev/null +++ b/3rd_party/libsrp6a-sha512/t_misc.c | |||
@@ -0,0 +1,439 @@ | |||
1 | /* | ||
2 | * Copyright (c) 1997-2007 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 | * Redistributions in source or binary form must retain an intact copy | ||
27 | * of this copyright notice. | ||
28 | */ | ||
29 | |||
30 | #include "t_defines.h" | ||
31 | |||
32 | #ifdef HAVE_UNISTD_H | ||
33 | #include <unistd.h> | ||
34 | #endif /* HAVE_UNISTD_H */ | ||
35 | |||
36 | #include <stdio.h> | ||
37 | #include <sys/types.h> | ||
38 | #include <sys/stat.h> | ||
39 | #include <fcntl.h> | ||
40 | |||
41 | #ifdef WIN32 | ||
42 | #include <process.h> | ||
43 | #include <io.h> | ||
44 | #endif | ||
45 | |||
46 | #include "t_sha.h" | ||
47 | |||
48 | #ifndef NULL | ||
49 | #define NULL 0 | ||
50 | #endif | ||
51 | |||
52 | #ifdef OPENSSL | ||
53 | #include <openssl/opensslv.h> | ||
54 | #include <openssl/rand.h> | ||
55 | #elif defined(TOMCRYPT) | ||
56 | #include "tomcrypt.h" | ||
57 | static prng_state g_rng; | ||
58 | static unsigned char entropy[32]; | ||
59 | #elif defined(CRYPTOLIB) | ||
60 | # include "libcrypt.h" | ||
61 | static unsigned char crpool[64]; | ||
62 | #else | ||
63 | static unsigned char randpool[SHA_DIGESTSIZE], randout[SHA_DIGESTSIZE]; | ||
64 | static unsigned long randcnt = 0; | ||
65 | static unsigned int outpos = 0; | ||
66 | SHA1_CTX randctxt; | ||
67 | #endif /* OPENSSL */ | ||
68 | |||
69 | /* | ||
70 | * t_envhash - Generate a 160-bit SHA hash of the environment | ||
71 | * | ||
72 | * This routine performs an SHA hash of all the "name=value" pairs | ||
73 | * in the environment concatenated together and dumps them in the | ||
74 | * output. While it is true that anyone on the system can see | ||
75 | * your environment, someone not on the system will have a very | ||
76 | * difficult time guessing it, especially since some systems play | ||
77 | * tricks with variable ordering and sometimes define quirky | ||
78 | * environment variables like $WINDOWID or $_. | ||
79 | */ | ||
80 | extern char ** environ; | ||
81 | |||
82 | static void | ||
83 | t_envhash(unsigned char * out) | ||
84 | { | ||
85 | char ** ptr; | ||
86 | char ebuf[256]; | ||
87 | SHA1_CTX ctxt; | ||
88 | |||
89 | SHA1Init(&ctxt); | ||
90 | for(ptr = environ; *ptr; ++ptr) { | ||
91 | strncpy(ebuf, *ptr, 255); | ||
92 | ebuf[255] = '\0'; | ||
93 | SHA1Update(&ctxt, ebuf, strlen(ebuf)); | ||
94 | } | ||
95 | SHA1Final(out, &ctxt); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * t_fshash - Generate a 160-bit SHA hash from the file system | ||
100 | * | ||
101 | * This routine climbs up the directory tree from the current | ||
102 | * directory, running stat() on each directory until it hits the | ||
103 | * root directory. This information is sensitive to the last | ||
104 | * access/modification times of all the directories above you, | ||
105 | * so someone who lists one of those directories injects some | ||
106 | * entropy into the system. Obviously, this hash is very sensitive | ||
107 | * to your current directory when the program is run. | ||
108 | * | ||
109 | * For good measure, it also performs an fstat on the standard input, | ||
110 | * usually your tty, throws that into the buffer, creates a file in | ||
111 | * /tmp (the inode is unpredictable on a busy system), and runs stat() | ||
112 | * on that before deleting it. | ||
113 | * | ||
114 | * The entire buffer is run once through SHA to obtain the final result. | ||
115 | */ | ||
116 | static void | ||
117 | t_fshash(unsigned char * out) | ||
118 | { | ||
119 | char dotpath[128]; | ||
120 | struct stat st; | ||
121 | SHA1_CTX ctxt; | ||
122 | int i, pinode; | ||
123 | dev_t pdev; | ||
124 | |||
125 | SHA1Init(&ctxt); | ||
126 | if(stat(".", &st) >= 0) { | ||
127 | SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st)); | ||
128 | pinode = st.st_ino; | ||
129 | pdev = st.st_dev; | ||
130 | strcpy(dotpath, ".."); | ||
131 | for(i = 0; i < 40; ++i) { | ||
132 | if(stat(dotpath, &st) < 0) | ||
133 | break; | ||
134 | if(st.st_ino == pinode && st.st_dev == pdev) | ||
135 | break; | ||
136 | SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st)); | ||
137 | pinode = st.st_ino; | ||
138 | pdev = st.st_dev; | ||
139 | strcat(dotpath, "/.."); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | if(fstat(0, &st) >= 0) | ||
144 | SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st)); | ||
145 | |||
146 | sprintf(dotpath, "/tmp/rnd.%d", getpid()); | ||
147 | if(creat(dotpath, 0600) >= 0 && stat(dotpath, &st) >= 0) | ||
148 | SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st)); | ||
149 | unlink(dotpath); | ||
150 | |||
151 | SHA1Final(out, &ctxt); | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Generate a high-entropy seed for the strong random number generator. | ||
156 | * This uses a wide variety of quickly gathered and somewhat unpredictable | ||
157 | * system information. The 'preseed' structure is assembled from: | ||
158 | * | ||
159 | * The system time in seconds | ||
160 | * The system time in microseconds | ||
161 | * The current process ID | ||
162 | * The parent process ID | ||
163 | * A hash of the user's environment | ||
164 | * A hash gathered from the file system | ||
165 | * Input from a random device, if available | ||
166 | * Timings of system interrupts | ||
167 | * | ||
168 | * The entire structure (60 bytes on most systems) is fed to SHA to produce | ||
169 | * a 160-bit seed for the strong random number generator. It is believed | ||
170 | * that in the worst case (on a quiet system with no random device versus | ||
171 | * an attacker who has access to the system already), the seed contains at | ||
172 | * least about 80 bits of entropy. Versus an attacker who does not have | ||
173 | * access to the system, the entropy should be slightly over 128 bits. | ||
174 | */ | ||
175 | static char initialized = 0; | ||
176 | |||
177 | static struct { | ||
178 | unsigned int trand1; | ||
179 | time_t sec; | ||
180 | time_t subsec; | ||
181 | short pid; | ||
182 | short ppid; | ||
183 | unsigned char envh[SHA_DIGESTSIZE]; | ||
184 | unsigned char fsh[SHA_DIGESTSIZE]; | ||
185 | unsigned char devrand[20]; | ||
186 | unsigned int trand2; | ||
187 | } preseed; | ||
188 | |||
189 | unsigned long raw_truerand(); | ||
190 | |||
191 | static void | ||
192 | t_initrand() | ||
193 | { | ||
194 | SHA1_CTX ctxt; | ||
195 | #ifdef USE_FTIME | ||
196 | struct timeb t; | ||
197 | #else | ||
198 | struct timeval t; | ||
199 | #endif | ||
200 | int i, r=0; | ||
201 | |||
202 | if(initialized) | ||
203 | return; | ||
204 | |||
205 | initialized = 1; | ||
206 | |||
207 | #if defined(OPENSSL) /* OpenSSL has nifty win32 entropy-gathering code */ | ||
208 | #if OPENSSL_VERSION_NUMBER >= 0x00905100 | ||
209 | r = RAND_status(); | ||
210 | #if defined(WINDOWS) || defined(WIN32) | ||
211 | if(r) /* Don't do the Unix-y stuff on Windows if possible */ | ||
212 | return; | ||
213 | #else | ||
214 | #endif | ||
215 | #endif | ||
216 | |||
217 | #elif defined(TOMCRYPT) | ||
218 | yarrow_start(&g_rng); | ||
219 | r = rng_get_bytes(entropy, sizeof(entropy), NULL); | ||
220 | if(r > 0) { | ||
221 | yarrow_add_entropy(entropy, r, &g_rng); | ||
222 | memset(entropy, 0, sizeof(entropy)); | ||
223 | # if defined(WINDOWS) || defined(WIN32) | ||
224 | /* Don't do the Unix-y stuff on Windows if possible */ | ||
225 | yarrow_ready(&g_rng); | ||
226 | return; | ||
227 | # endif | ||
228 | } | ||
229 | #endif | ||
230 | |||
231 | #if !defined(WINDOWS) && !defined(WIN32) | ||
232 | i = open("/dev/urandom", O_RDONLY); | ||
233 | if(i > 0) { | ||
234 | r += read(i, preseed.devrand, sizeof(preseed.devrand)); | ||
235 | close(i); | ||
236 | } | ||
237 | #endif /* !WINDOWS && !WIN32 */ | ||
238 | |||
239 | /* Resort to truerand only if desperate for some Real entropy */ | ||
240 | if(r == 0) | ||
241 | preseed.trand1 = raw_truerand(); | ||
242 | |||
243 | #ifdef USE_FTIME | ||
244 | ftime(&t); | ||
245 | preseed.sec = t.time; | ||
246 | preseed.subsec = t.millitm; | ||
247 | #else | ||
248 | gettimeofday(&t, NULL); | ||
249 | preseed.sec = t.tv_sec; | ||
250 | preseed.subsec = t.tv_usec; | ||
251 | #endif | ||
252 | preseed.pid = getpid(); | ||
253 | #ifndef WIN32 | ||
254 | preseed.ppid = getppid(); | ||
255 | #endif | ||
256 | t_envhash(preseed.envh); | ||
257 | t_fshash(preseed.fsh); | ||
258 | |||
259 | if(r == 0) | ||
260 | preseed.trand2 = raw_truerand(); | ||
261 | |||
262 | #ifdef OPENSSL | ||
263 | RAND_seed((unsigned char *)&preseed, sizeof(preseed)); | ||
264 | #elif defined(TOMCRYPT) | ||
265 | yarrow_add_entropy((unsigned char *)&preseed, sizeof(preseed), &g_rng); | ||
266 | yarrow_ready(&g_rng); | ||
267 | #elif defined(CRYPTOLIB) | ||
268 | t_mgf1(crpool, sizeof(crpool), (unsigned char *) &preseed, sizeof(preseed)); | ||
269 | seedDesRandom(crpool, sizeof(crpool)); | ||
270 | memset(crpool, 0, sizeof(crpool)); | ||
271 | #elif defined(GCRYPT) | ||
272 | gcry_random_add_bytes((unsigned char *)&preseed, sizeof(preseed), -1); | ||
273 | #else | ||
274 | SHA1Init(&ctxt); | ||
275 | SHA1Update(&ctxt, (unsigned char *) &preseed, sizeof(preseed)); | ||
276 | SHA1Final(randpool, &ctxt); | ||
277 | memset((unsigned char *) &ctxt, 0, sizeof(ctxt)); | ||
278 | outpos = 0; | ||
279 | #endif /* OPENSSL */ | ||
280 | memset((unsigned char *) &preseed, 0, sizeof(preseed)); | ||
281 | } | ||
282 | |||
283 | #define NUM_RANDOMS 12 | ||
284 | |||
285 | _TYPE( void ) | ||
286 | t_stronginitrand() | ||
287 | { | ||
288 | #if 1 /* t_initrand() has been improved enough to make this unnecessary */ | ||
289 | t_initrand(); | ||
290 | #else | ||
291 | SHA1_CTX ctxt; | ||
292 | unsigned int rawrand[NUM_RANDOMS]; | ||
293 | int i; | ||
294 | |||
295 | if(!initialized) | ||
296 | t_initrand(); | ||
297 | for(i = 0; i < NUM_RANDOMS; ++i) | ||
298 | rawrand[i] = raw_truerand(); | ||
299 | SHA1Init(&ctxt); | ||
300 | SHA1Update(&ctxt, (unsigned char *) rawrand, sizeof(rawrand)); | ||
301 | SHA1Final(randkey2, &ctxt); | ||
302 | memset(rawrand, 0, sizeof(rawrand)); | ||
303 | #endif | ||
304 | } | ||
305 | |||
306 | /* | ||
307 | * The strong random number generator. This uses a 160-bit seed | ||
308 | * and uses SHA-1 in a feedback configuration to generate successive | ||
309 | * outputs. If S[0] is set to the initial seed, then: | ||
310 | * | ||
311 | * S[i+1] = SHA-1(i || S[i]) | ||
312 | * A[i] = SHA-1(S[i]) | ||
313 | * | ||
314 | * where the A[i] are the output blocks starting with i=0. | ||
315 | * Each cycle generates 20 bytes of new output. | ||
316 | */ | ||
317 | _TYPE( void ) | ||
318 | t_random(unsigned char * data, unsigned size) | ||
319 | { | ||
320 | if(!initialized) | ||
321 | t_initrand(); | ||
322 | |||
323 | if(size <= 0) /* t_random(NULL, 0) forces seed initialization */ | ||
324 | return; | ||
325 | |||
326 | #ifdef OPENSSL | ||
327 | RAND_bytes(data, size); | ||
328 | #elif defined(TOMCRYPT) | ||
329 | yarrow_read(data, size, &g_rng); | ||
330 | #elif defined(GCRYPT) | ||
331 | gcry_randomize(data, size, GCRY_STRONG_RANDOM); | ||
332 | #elif defined(CRYPTOLIB) | ||
333 | randomBytes(data, size, PSEUDO); | ||
334 | #else | ||
335 | while(size > outpos) { | ||
336 | if(outpos > 0) { | ||
337 | memcpy(data, randout + (sizeof(randout) - outpos), outpos); | ||
338 | data += outpos; | ||
339 | size -= outpos; | ||
340 | } | ||
341 | |||
342 | /* Recycle */ | ||
343 | SHA1Init(&randctxt); | ||
344 | SHA1Update(&randctxt, randpool, sizeof(randpool)); | ||
345 | SHA1Final(randout, &randctxt); | ||
346 | SHA1Init(&randctxt); | ||
347 | SHA1Update(&randctxt, (unsigned char *) &randcnt, sizeof(randcnt)); | ||
348 | SHA1Update(&randctxt, randpool, sizeof(randpool)); | ||
349 | SHA1Final(randpool, &randctxt); | ||
350 | ++randcnt; | ||
351 | outpos = sizeof(randout); | ||
352 | } | ||
353 | |||
354 | if(size > 0) { | ||
355 | memcpy(data, randout + (sizeof(randout) - outpos), size); | ||
356 | outpos -= size; | ||
357 | } | ||
358 | #endif | ||
359 | } | ||
360 | |||
361 | /* | ||
362 | * The interleaved session-key hash. This separates the even and the odd | ||
363 | * bytes of the input (ignoring the first byte if the input length is odd), | ||
364 | * hashes them separately, and re-interleaves the two outputs to form a | ||
365 | * single 320-bit value. | ||
366 | */ | ||
367 | _TYPE( unsigned char * ) | ||
368 | t_sessionkey(unsigned char * key, unsigned char * sk, unsigned sklen) | ||
369 | { | ||
370 | unsigned i, klen; | ||
371 | unsigned char * hbuf; | ||
372 | unsigned char hout[SHA_DIGESTSIZE]; | ||
373 | SHA1_CTX ctxt; | ||
374 | |||
375 | while(sklen > 0 && *sk == 0) { /* Skip leading 0's */ | ||
376 | --sklen; | ||
377 | ++sk; | ||
378 | } | ||
379 | |||
380 | klen = sklen / 2; | ||
381 | if((hbuf = malloc(klen * sizeof(char))) == 0) | ||
382 | return 0; | ||
383 | |||
384 | for(i = 0; i < klen; ++i) | ||
385 | hbuf[i] = sk[sklen - 2 * i - 1]; | ||
386 | SHA1Init(&ctxt); | ||
387 | SHA1Update(&ctxt, hbuf, klen); | ||
388 | SHA1Final(hout, &ctxt); | ||
389 | for(i = 0; i < sizeof(hout); ++i) | ||
390 | key[2 * i] = hout[i]; | ||
391 | |||
392 | for(i = 0; i < klen; ++i) | ||
393 | hbuf[i] = sk[sklen - 2 * i - 2]; | ||
394 | SHA1Init(&ctxt); | ||
395 | SHA1Update(&ctxt, hbuf, klen); | ||
396 | SHA1Final(hout, &ctxt); | ||
397 | for(i = 0; i < sizeof(hout); ++i) | ||
398 | key[2 * i + 1] = hout[i]; | ||
399 | |||
400 | memset(hout, 0, sizeof(hout)); | ||
401 | memset(hbuf, 0, klen); | ||
402 | free(hbuf); | ||
403 | return key; | ||
404 | } | ||
405 | |||
406 | _TYPE( void ) | ||
407 | t_mgf1(unsigned char * mask, unsigned masklen, const unsigned char * seed, unsigned seedlen) | ||
408 | { | ||
409 | SHA1_CTX ctxt; | ||
410 | unsigned i = 0; | ||
411 | unsigned pos = 0; | ||
412 | unsigned char cnt[4]; | ||
413 | unsigned char hout[SHA_DIGESTSIZE]; | ||
414 | |||
415 | while(pos < masklen) { | ||
416 | cnt[0] = (i >> 24) & 0xFF; | ||
417 | cnt[1] = (i >> 16) & 0xFF; | ||
418 | cnt[2] = (i >> 8) & 0xFF; | ||
419 | cnt[3] = i & 0xFF; | ||
420 | SHA1Init(&ctxt); | ||
421 | SHA1Update(&ctxt, seed, seedlen); | ||
422 | SHA1Update(&ctxt, cnt, 4); | ||
423 | |||
424 | if(pos + SHA_DIGESTSIZE > masklen) { | ||
425 | SHA1Final(hout, &ctxt); | ||
426 | memcpy(mask + pos, hout, masklen - pos); | ||
427 | pos = masklen; | ||
428 | } | ||
429 | else { | ||
430 | SHA1Final(mask + pos, &ctxt); | ||
431 | pos += SHA_DIGESTSIZE; | ||
432 | } | ||
433 | |||
434 | ++i; | ||
435 | } | ||
436 | |||
437 | memset(hout, 0, sizeof(hout)); | ||
438 | memset((unsigned char *)&ctxt, 0, sizeof(ctxt)); | ||
439 | } | ||