1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 * 3 * LibTomCrypt is a library that provides various cryptographic 4 * algorithms in a highly modular and flexible manner. 5 * 6 * The library is free for all purposes without any express 7 * guarantee it works. 8 * 9 * Tom St Denis, tomstdenis (at) gmail.com, http://libtomcrypt.com 10 */ 11 #include "tomcrypt.h" 12 13 /** 14 @file rng_get_bytes.c 15 portable way to get secure random bits to feed a PRNG (Tom St Denis) 16 */ 17 18 #ifdef DEVRANDOM 19 /* on *NIX read /dev/random */ 20 static unsigned long rng_nix(unsigned char *buf, unsigned long len, 21 void (*callback)(void)) 22 { 23 #ifdef LTC_NO_FILE 24 return 0; 25 #else 26 FILE *f; 27 unsigned long x; 28 #ifdef TRY_URANDOM_FIRST 29 f = fopen("/dev/urandom", "rb"); 30 if (f == NULL) 31 #endif /* TRY_URANDOM_FIRST */ 32 f = fopen("/dev/random", "rb"); 33 34 if (f == NULL) { 35 return 0; 36 } 37 38 /* disable buffering */ 39 if (setvbuf(f, NULL, _IONBF, 0) != 0) { 40 fclose(f); 41 return 0; 42 } 43 44 x = (unsigned long)fread(buf, 1, (size_t)len, f); 45 fclose(f); 46 return x; 47 #endif /* LTC_NO_FILE */ 48 } 49 50 #endif /* DEVRANDOM */ 51 52 /* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */ 53 #if defined(CLOCKS_PER_SEC) && !defined(WINCE) 54 55 #define ANSI_RNG 56 57 static unsigned long rng_ansic(unsigned char *buf, unsigned long len, 58 void (*callback)(void)) 59 { 60 clock_t t1; 61 int l, acc, bits, a, b; 62 63 if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) { 64 return 0; 65 } 66 67 l = len; 68 bits = 8; 69 acc = a = b = 0; 70 while (len--) { 71 if (callback != NULL) callback(); 72 while (bits--) { 73 do { 74 t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1; 75 t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1; 76 } while (a == b); 77 acc = (acc << 1) | a; 78 } 79 *buf++ = acc; 80 acc = 0; 81 bits = 8; 82 } 83 acc = bits = a = b = 0; 84 return l; 85 } 86 87 #endif 88 89 /* Try the Microsoft CSP */ 90 #if defined(WIN32) || defined(WINCE) 91 #define _WIN32_WINNT 0x0400 92 #ifdef WINCE 93 #define UNDER_CE 94 #define ARM 95 #endif 96 #include <windows.h> 97 #include <wincrypt.h> 98 99 static unsigned long rng_win32(unsigned char *buf, unsigned long len, 100 void (*callback)(void)) 101 { 102 HCRYPTPROV hProv = 0; 103 if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 104 (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && 105 !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 106 CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) 107 return 0; 108 109 if (CryptGenRandom(hProv, len, buf) == TRUE) { 110 CryptReleaseContext(hProv, 0); 111 return len; 112 } else { 113 CryptReleaseContext(hProv, 0); 114 return 0; 115 } 116 } 117 118 #endif /* WIN32 */ 119 120 /** 121 Read the system RNG 122 @param out Destination 123 @param outlen Length desired (octets) 124 @param callback Pointer to void function to act as "callback" when RNG is slow. This can be NULL 125 @return Number of octets read 126 */ 127 unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen, 128 void (*callback)(void)) 129 { 130 unsigned long x; 131 132 LTC_ARGCHK(out != NULL); 133 134 #if defined(DEVRANDOM) 135 x = rng_nix(out, outlen, callback); if (x != 0) { return x; } 136 #endif 137 #ifdef WIN32 138 x = rng_win32(out, outlen, callback); if (x != 0) { return x; } 139 #endif 140 #ifdef ANSI_RNG 141 x = rng_ansic(out, outlen, callback); if (x != 0) { return x; } 142 #endif 143 return 0; 144 } 145 146 /* $Source: /cvs/libtom/libtomcrypt/src/prngs/rng_get_bytes.c,v $ */ 147 /* $Revision: 1.5 $ */ 148 /* $Date: 2006/12/06 02:01:29 $ */ 149