2014-12-17 03:07:06 +00:00
|
|
|
#define LTC_SOURCE
|
2014-12-10 21:56:49 +00:00
|
|
|
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
|
|
|
*
|
|
|
|
* LibTomCrypt is a library that provides various cryptographic
|
|
|
|
* algorithms in a highly modular and flexible manner.
|
|
|
|
*
|
|
|
|
* The library is free for all purposes without any express
|
|
|
|
* guarantee it works.
|
|
|
|
*/
|
|
|
|
#include "tomcrypt.h"
|
|
|
|
|
2019-06-09 20:44:26 +00:00
|
|
|
#ifdef LTC_RNG_GET_BYTES
|
|
|
|
/**
|
2014-12-10 21:56:49 +00:00
|
|
|
@file rng_get_bytes.c
|
|
|
|
portable way to get secure random bits to feed a PRNG (Tom St Denis)
|
|
|
|
*/
|
|
|
|
|
2019-06-09 20:44:26 +00:00
|
|
|
#if defined(LTC_DEVRANDOM) && !defined(_WIN32)
|
2014-12-10 21:56:49 +00:00
|
|
|
/* on *NIX read /dev/random */
|
2019-06-09 20:44:26 +00:00
|
|
|
static unsigned long _rng_nix(unsigned char *buf, unsigned long len,
|
2014-12-10 21:56:49 +00:00
|
|
|
void (*callback)(void))
|
|
|
|
{
|
|
|
|
#ifdef LTC_NO_FILE
|
2019-06-09 20:44:26 +00:00
|
|
|
LTC_UNUSED_PARAM(callback);
|
|
|
|
LTC_UNUSED_PARAM(buf);
|
|
|
|
LTC_UNUSED_PARAM(len);
|
2014-12-10 21:56:49 +00:00
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
FILE *f;
|
|
|
|
unsigned long x;
|
2019-06-09 20:44:26 +00:00
|
|
|
LTC_UNUSED_PARAM(callback);
|
|
|
|
#ifdef LTC_TRY_URANDOM_FIRST
|
2014-12-10 21:56:49 +00:00
|
|
|
f = fopen("/dev/urandom", "rb");
|
|
|
|
if (f == NULL)
|
2019-06-09 20:44:26 +00:00
|
|
|
#endif /* LTC_TRY_URANDOM_FIRST */
|
2014-12-10 21:56:49 +00:00
|
|
|
f = fopen("/dev/random", "rb");
|
|
|
|
|
|
|
|
if (f == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
2019-06-09 20:44:26 +00:00
|
|
|
|
2014-12-10 21:56:49 +00:00
|
|
|
/* disable buffering */
|
|
|
|
if (setvbuf(f, NULL, _IONBF, 0) != 0) {
|
|
|
|
fclose(f);
|
|
|
|
return 0;
|
2019-06-09 20:44:26 +00:00
|
|
|
}
|
|
|
|
|
2014-12-10 21:56:49 +00:00
|
|
|
x = (unsigned long)fread(buf, 1, (size_t)len, f);
|
|
|
|
fclose(f);
|
|
|
|
return x;
|
|
|
|
#endif /* LTC_NO_FILE */
|
|
|
|
}
|
|
|
|
|
2019-06-09 20:44:26 +00:00
|
|
|
#endif /* LTC_DEVRANDOM */
|
2014-12-10 21:56:49 +00:00
|
|
|
|
2019-06-09 20:44:26 +00:00
|
|
|
#if !defined(_WIN32_WCE)
|
2014-12-10 21:56:49 +00:00
|
|
|
|
|
|
|
#define ANSI_RNG
|
|
|
|
|
2019-06-09 20:44:26 +00:00
|
|
|
static unsigned long _rng_ansic(unsigned char *buf, unsigned long len,
|
2014-12-10 21:56:49 +00:00
|
|
|
void (*callback)(void))
|
|
|
|
{
|
|
|
|
clock_t t1;
|
|
|
|
int l, acc, bits, a, b;
|
|
|
|
|
|
|
|
l = len;
|
|
|
|
bits = 8;
|
|
|
|
acc = a = b = 0;
|
|
|
|
while (len--) {
|
|
|
|
if (callback != NULL) callback();
|
|
|
|
while (bits--) {
|
|
|
|
do {
|
|
|
|
t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
|
|
|
|
t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
|
|
|
|
} while (a == b);
|
|
|
|
acc = (acc << 1) | a;
|
|
|
|
}
|
2019-06-09 20:44:26 +00:00
|
|
|
*buf++ = acc;
|
2014-12-10 21:56:49 +00:00
|
|
|
acc = 0;
|
|
|
|
bits = 8;
|
|
|
|
}
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
2019-06-09 20:44:26 +00:00
|
|
|
#endif
|
2014-12-10 21:56:49 +00:00
|
|
|
|
|
|
|
/* Try the Microsoft CSP */
|
2019-06-09 20:44:26 +00:00
|
|
|
#if defined(_WIN32) || defined(_WIN32_WCE)
|
|
|
|
#ifndef _WIN32_WINNT
|
|
|
|
#define _WIN32_WINNT 0x0400
|
|
|
|
#endif
|
|
|
|
#ifdef _WIN32_WCE
|
2014-12-10 21:56:49 +00:00
|
|
|
#define UNDER_CE
|
|
|
|
#define ARM
|
|
|
|
#endif
|
2019-06-09 20:44:26 +00:00
|
|
|
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
2014-12-10 21:56:49 +00:00
|
|
|
#include <windows.h>
|
|
|
|
#include <wincrypt.h>
|
|
|
|
|
2019-06-09 20:44:26 +00:00
|
|
|
static unsigned long _rng_win32(unsigned char *buf, unsigned long len,
|
2014-12-10 21:56:49 +00:00
|
|
|
void (*callback)(void))
|
|
|
|
{
|
|
|
|
HCRYPTPROV hProv = 0;
|
2019-06-09 20:44:26 +00:00
|
|
|
LTC_UNUSED_PARAM(callback);
|
|
|
|
if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
|
|
|
|
(CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
|
|
|
|
!CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
|
2014-12-10 21:56:49 +00:00
|
|
|
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (CryptGenRandom(hProv, len, buf) == TRUE) {
|
|
|
|
CryptReleaseContext(hProv, 0);
|
|
|
|
return len;
|
|
|
|
} else {
|
|
|
|
CryptReleaseContext(hProv, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* WIN32 */
|
|
|
|
|
|
|
|
/**
|
|
|
|
Read the system RNG
|
|
|
|
@param out Destination
|
|
|
|
@param outlen Length desired (octets)
|
|
|
|
@param callback Pointer to void function to act as "callback" when RNG is slow. This can be NULL
|
|
|
|
@return Number of octets read
|
2019-06-09 20:44:26 +00:00
|
|
|
*/
|
|
|
|
unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen,
|
2014-12-10 21:56:49 +00:00
|
|
|
void (*callback)(void))
|
|
|
|
{
|
|
|
|
unsigned long x;
|
|
|
|
|
|
|
|
LTC_ARGCHK(out != NULL);
|
|
|
|
|
2019-06-09 20:44:26 +00:00
|
|
|
#ifdef LTC_PRNG_ENABLE_LTC_RNG
|
|
|
|
if (ltc_rng) {
|
|
|
|
x = ltc_rng(out, outlen, callback);
|
|
|
|
if (x != 0) {
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
}
|
2014-12-10 21:56:49 +00:00
|
|
|
#endif
|
2019-06-09 20:44:26 +00:00
|
|
|
|
|
|
|
#if defined(_WIN32) || defined(_WIN32_WCE)
|
|
|
|
x = _rng_win32(out, outlen, callback); if (x != 0) { return x; }
|
|
|
|
#elif defined(LTC_DEVRANDOM)
|
|
|
|
x = _rng_nix(out, outlen, callback); if (x != 0) { return x; }
|
2014-12-10 21:56:49 +00:00
|
|
|
#endif
|
|
|
|
#ifdef ANSI_RNG
|
2019-06-09 20:44:26 +00:00
|
|
|
x = _rng_ansic(out, outlen, callback); if (x != 0) { return x; }
|
2014-12-10 21:56:49 +00:00
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
2019-06-09 20:44:26 +00:00
|
|
|
#endif /* #ifdef LTC_RNG_GET_BYTES */
|
2014-12-10 21:56:49 +00:00
|
|
|
|
2019-06-09 20:44:26 +00:00
|
|
|
/* ref: $Format:%D$ */
|
|
|
|
/* git commit: $Format:%H$ */
|
|
|
|
/* commit time: $Format:%ai$ */
|