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.c439
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"
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(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 */
116static void
117t_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 */
175static char initialized = 0;
176
177static 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
189unsigned long raw_truerand();
190
191static void
192t_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 )
286t_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 )
318t_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 * )
368t_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 )
407t_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}