1 /* portable way to get secure random bits to feed a PRNG */
5 /* on *NIX read /dev/random */
6 static unsigned long rng_nix(unsigned char *buf, unsigned long len,
7 void (*callback)(void))
14 #ifdef TRY_URANDOM_FIRST
15 f = fopen("/dev/urandom", "rb");
17 #endif /* TRY_URANDOM_FIRST */
18 f = fopen("/dev/random", "rb");
24 /* disable buffering */
25 if (setvbuf(f, NULL, _IONBF, 0) != 0) {
30 x = (unsigned long)fread(buf, 1, (size_t)len, f);
36 #endif /* DEVRANDOM */
41 #define min(a,b) ((a) < (b) ? (a) : (b))
42 // Very simple/stupid MD5-based RNG that samples "entropy" from various PS2 control registers
43 static unsigned long rng_ps2(unsigned char *buf, unsigned long len,
44 void (*callback)(void))
46 static unsigned long lastx[2] = { 0xaab7cb4b2fd3b2b9, 0xcec58aff72afe49f }; // md5sum of bits.c
48 unsigned int samples[10]; // number of sample data sources
52 for (j = 0; j < len; j += sizeof(lastx)) {
54 samples[0] = *T2_COUNT;
55 samples[1] = *T3_COUNT;
56 samples[2] = *IPU_TOP;
57 samples[3] = *GIF_TAG0;
58 samples[4] = *GIF_TAG1;
59 samples[5] = *GIF_TAG2;
60 samples[6] = *VIF1_CODE;
61 samples[7] = *VIF0_CODE;
62 samples[8] = *D0_MADR;
63 samples[9] = *D1_MADR;
64 md5_process(&md, (unsigned char *)(&samples[0]), sizeof(samples));
65 // include previous round
66 md5_process(&md, (unsigned char *)(&lastx[0]), sizeof(lastx));
67 md5_done(&md, (unsigned char *)(&lastx[0]));
68 l = min(sizeof(lastx), len-j);
69 memcpy(buf+j, &lastx[0], l); //min(sizeof(lastx), len-j));
75 /* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */
76 #if !defined(SONY_PS2) && defined(CLOCKS_PER_SEC)
80 static unsigned long rng_ansic(unsigned char *buf, unsigned long len,
81 void (*callback)(void))
84 int l, acc, bits, a, b;
86 if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) {
94 if (callback != NULL) callback();
97 t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
98 t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
100 acc = (acc << 1) | a;
106 acc = bits = a = b = 0;
112 /* Try the Microsoft CSP */
114 #define _WIN32_WINNT 0x0400
116 #include <wincrypt.h>
118 static unsigned long rng_win32(unsigned char *buf, unsigned long len,
119 void (*callback)(void))
121 HCRYPTPROV hProv = 0;
122 if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
123 (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
124 !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
125 CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
128 if (CryptGenRandom(hProv, len, buf) == TRUE) {
129 CryptReleaseContext(hProv, 0);
132 CryptReleaseContext(hProv, 0);
139 unsigned long rng_get_bytes(unsigned char *buf, unsigned long len,
140 void (*callback)(void))
144 _ARGCHK(buf != NULL);
147 x = rng_ps2(buf, len, callback); if (x != 0) { return x; }
148 #elif defined(DEVRANDOM)
149 x = rng_nix(buf, len, callback); if (x != 0) { return x; }
152 x = rng_win32(buf, len, callback); if (x != 0) { return x; }
155 x = rng_ansic(buf, len, callback); if (x != 0) { return x; }
160 int rng_make_prng(int bits, int wprng, prng_state *prng,
161 void (*callback)(void))
163 unsigned char buf[256];
166 _ARGCHK(prng != NULL);
168 /* check parameter */
169 if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
173 if (bits < 64 || bits > 1024) {
174 return CRYPT_INVALID_PRNGSIZE;
177 if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) {
181 bits = ((bits/8)+((bits&7)!=0?1:0)) * 2;
182 if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) {
183 return CRYPT_ERROR_READPRNG;
186 if ((err = prng_descriptor[wprng].add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) {
190 if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) {
195 zeromem(buf, sizeof(buf));