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