tomcrypt/src/prngs/rng_get_bytes.c

160 lines
3.8 KiB
C
Raw Normal View History

2004-01-25 17:40:34 +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
2004-05-12 20:42:16 +00:00
* guarantee it works.
2004-01-25 17:40:34 +00:00
*
2007-07-20 17:48:02 +00:00
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
2004-01-25 17:40:34 +00:00
*/
2004-12-30 23:55:53 +00:00
#include "tomcrypt.h"
#ifdef LTC_RNG_GET_BYTES
2014-01-03 15:16:59 +01:00
/**
2004-12-30 23:55:53 +00:00
@file rng_get_bytes.c
portable way to get secure random bits to feed a PRNG (Tom St Denis)
*/
2003-03-03 00:59:24 +00:00
2007-07-20 17:48:02 +00:00
#ifdef LTC_DEVRANDOM
2003-03-03 00:59:24 +00:00
/* on *NIX read /dev/random */
2014-01-03 15:16:59 +01:00
static unsigned long rng_nix(unsigned char *buf, unsigned long len,
2003-03-03 00:59:24 +00:00
void (*callback)(void))
{
2004-12-30 23:55:53 +00:00
#ifdef LTC_NO_FILE
LTC_UNUSED_PARAM(callback);
2014-08-24 18:24:15 +02:00
LTC_UNUSED_PARAM(buf);
LTC_UNUSED_PARAM(len);
2003-03-03 00:59:24 +00:00
return 0;
#else
2003-07-16 17:43:06 +00:00
FILE *f;
2003-03-03 01:02:42 +00:00
unsigned long x;
LTC_UNUSED_PARAM(callback);
2014-07-17 10:49:05 +02:00
#ifdef LTC_TRY_URANDOM_FIRST
2003-07-16 17:43:06 +00:00
f = fopen("/dev/urandom", "rb");
if (f == NULL)
2014-07-17 10:49:05 +02:00
#endif /* LTC_TRY_URANDOM_FIRST */
2003-07-16 17:43:06 +00:00
f = fopen("/dev/random", "rb");
2003-03-03 00:59:24 +00:00
2003-07-16 17:43:06 +00:00
if (f == NULL) {
2003-03-03 00:59:24 +00:00
return 0;
}
2014-01-03 15:16:59 +01:00
2003-07-16 17:43:06 +00:00
/* disable buffering */
if (setvbuf(f, NULL, _IONBF, 0) != 0) {
fclose(f);
return 0;
2014-01-03 15:16:59 +01:00
}
2003-07-16 17:43:06 +00:00
x = (unsigned long)fread(buf, 1, (size_t)len, f);
fclose(f);
2003-03-03 00:59:24 +00:00
return x;
2004-12-30 23:55:53 +00:00
#endif /* LTC_NO_FILE */
2003-03-03 00:59:24 +00:00
}
2007-07-20 17:48:02 +00:00
#endif /* LTC_DEVRANDOM */
2003-03-03 00:59:24 +00:00
/* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */
2006-12-16 18:10:04 +00:00
#if defined(CLOCKS_PER_SEC) && !defined(WINCE)
2003-03-03 00:59:24 +00:00
#define ANSI_RNG
2014-01-03 15:16:59 +01:00
static unsigned long rng_ansic(unsigned char *buf, unsigned long len,
2003-03-03 00:59:24 +00:00
void (*callback)(void))
{
clock_t t1;
int l, acc, bits, a, b;
if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) {
return 0;
}
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;
}
2014-01-03 15:16:59 +01:00
*buf++ = acc;
2003-03-03 00:59:24 +00:00
acc = 0;
bits = 8;
}
acc = bits = a = b = 0;
return l;
}
2014-01-03 15:16:59 +01:00
#endif
2003-03-03 00:59:24 +00:00
/* Try the Microsoft CSP */
#if defined(WIN32) || defined(_WIN32) || defined(WINCE)
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
2006-12-16 18:10:04 +00:00
#ifdef WINCE
#define UNDER_CE
#define ARM
#endif
#define WIN32_LEAN_AND_MEAN
2003-03-03 00:59:24 +00:00
#include <windows.h>
#include <wincrypt.h>
2014-01-03 15:16:59 +01:00
static unsigned long rng_win32(unsigned char *buf, unsigned long len,
2003-03-03 00:59:24 +00:00
void (*callback)(void))
{
2014-08-24 18:24:15 +02:00
LTC_UNUSED_PARAM(callback);
2003-03-03 00:59:24 +00:00
HCRYPTPROV hProv = 0;
2014-01-03 15:16:59 +01:00
if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
(CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
!CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
2003-03-03 00:59:24 +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 */
2004-12-30 23:55:53 +00:00
/**
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
2014-01-03 15:16:59 +01:00
*/
unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen,
2003-03-03 00:59:24 +00:00
void (*callback)(void))
{
2003-03-03 01:02:42 +00:00
unsigned long x;
2003-03-03 00:59:24 +00:00
2004-12-30 23:55:53 +00:00
LTC_ARGCHK(out != NULL);
2003-03-03 00:59:24 +00:00
2007-07-20 17:48:02 +00:00
#if defined(LTC_DEVRANDOM)
2004-12-30 23:55:53 +00:00
x = rng_nix(out, outlen, callback); if (x != 0) { return x; }
2003-03-03 00:59:24 +00:00
#endif
#if defined(WIN32) || defined(_WIN32) || defined(WINCE)
2004-12-30 23:55:53 +00:00
x = rng_win32(out, outlen, callback); if (x != 0) { return x; }
2003-03-03 00:59:24 +00:00
#endif
#ifdef ANSI_RNG
2004-12-30 23:55:53 +00:00
x = rng_ansic(out, outlen, callback); if (x != 0) { return x; }
2003-03-03 00:59:24 +00:00
#endif
return 0;
}
#endif /* #ifdef LTC_RNG_GET_BYTES */
2005-06-09 00:08:13 +00:00
/* $Source$ */
/* $Revision$ */
/* $Date$ */