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