diff options
Diffstat (limited to '3rd_party/libsrp6a-sha512/t_misc.c')
| -rw-r--r-- | 3rd_party/libsrp6a-sha512/t_misc.c | 444 |
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" | ||
| 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 | #ifdef __APPLE__ | ||
| 81 | #include <crt_externs.h> | ||
| 82 | #define environ (*_NSGetEnviron()) | ||
| 83 | #else | ||
| 84 | extern char ** environ; | ||
| 85 | #endif | ||
| 86 | |||
| 87 | static void | ||
| 88 | t_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 | */ | ||
| 121 | static void | ||
| 122 | t_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 | */ | ||
| 180 | static char initialized = 0; | ||
| 181 | |||
| 182 | static 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 | |||
| 194 | unsigned long raw_truerand(); | ||
| 195 | |||
| 196 | static void | ||
| 197 | t_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 ) | ||
| 291 | t_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 ) | ||
| 323 | t_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 * ) | ||
| 373 | t_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 ) | ||
| 412 | t_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 | } | ||
