bits.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /* portable way to get secure random bits to feed a PRNG */
  2. #include <fcntl.h>
  3. #include <unistd.h>
  4. #include "mycrypt.h"
  5. #ifdef DEVRANDOM
  6. /* on *NIX read /dev/random */
  7. static unsigned long rng_nix(unsigned char *buf, unsigned long len,
  8. void (*callback)(void))
  9. {
  10. #ifdef NO_FILE
  11. return 0;
  12. #else
  13. int src;
  14. unsigned long x;
  15. #ifdef TRY_URANDOM_FIRST
  16. src = open("/dev/urandom", O_RDONLY);
  17. if (src == -1)
  18. #endif /* TRY_URANDOM_FIRST */
  19. src = open("/dev/random", O_RDONLY);
  20. if (src == -1) {
  21. return 0;
  22. }
  23. x = (unsigned long)read(src, buf, (size_t)len);
  24. close(src);
  25. return x;
  26. #endif /* NO_FILE */
  27. }
  28. #endif /* DEVRANDOM */
  29. #ifdef SONY_PS2
  30. #include <eetypes.h>
  31. #include <eeregs.h>
  32. #define min(a,b) ((a) < (b) ? (a) : (b))
  33. // Very simple/stupid MD5-based RNG that samples "entropy" from various PS2 control registers
  34. static unsigned long rng_ps2(unsigned char *buf, unsigned long len,
  35. void (*callback)(void))
  36. {
  37. static unsigned long lastx[2] = { 0xaab7cb4b2fd3b2b9, 0xcec58aff72afe49f }; // md5sum of bits.c
  38. unsigned long j;
  39. unsigned int samples[10]; // number of sample data sources
  40. int l;
  41. hash_state md;
  42. for (j = 0; j < len; j += sizeof(lastx)) {
  43. md5_init(&md);
  44. samples[0] = *T2_COUNT;
  45. samples[1] = *T3_COUNT;
  46. samples[2] = *IPU_TOP;
  47. samples[3] = *GIF_TAG0;
  48. samples[4] = *GIF_TAG1;
  49. samples[5] = *GIF_TAG2;
  50. samples[6] = *VIF1_CODE;
  51. samples[7] = *VIF0_CODE;
  52. samples[8] = *D0_MADR;
  53. samples[9] = *D1_MADR;
  54. md5_process(&md, (unsigned char *)(&samples[0]), sizeof(samples));
  55. // include previous round
  56. md5_process(&md, (unsigned char *)(&lastx[0]), sizeof(lastx));
  57. md5_done(&md, (unsigned char *)(&lastx[0]));
  58. l = min(sizeof(lastx), len-j);
  59. memcpy(buf+j, &lastx[0], l); //min(sizeof(lastx), len-j));
  60. }
  61. return len;
  62. }
  63. #endif /* SONY_PS2 */
  64. /* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */
  65. #if !defined(SONY_PS2) && defined(CLOCKS_PER_SEC)
  66. #define ANSI_RNG
  67. static unsigned long rng_ansic(unsigned char *buf, unsigned long len,
  68. void (*callback)(void))
  69. {
  70. clock_t t1;
  71. int l, acc, bits, a, b;
  72. if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) {
  73. return 0;
  74. }
  75. l = len;
  76. bits = 8;
  77. acc = a = b = 0;
  78. while (len--) {
  79. if (callback != NULL) callback();
  80. while (bits--) {
  81. do {
  82. t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
  83. t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
  84. } while (a == b);
  85. acc = (acc << 1) | a;
  86. }
  87. *buf++ = acc;
  88. acc = 0;
  89. bits = 8;
  90. }
  91. acc = bits = a = b = 0;
  92. return l;
  93. }
  94. #endif
  95. /* Try the Microsoft CSP */
  96. #ifdef WIN32
  97. #define _WIN32_WINNT 0x0400
  98. #include <windows.h>
  99. #include <wincrypt.h>
  100. static unsigned long rng_win32(unsigned char *buf, unsigned long len,
  101. void (*callback)(void))
  102. {
  103. HCRYPTPROV hProv = 0;
  104. if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
  105. (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
  106. !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
  107. CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
  108. return 0;
  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. #endif /* WIN32 */
  118. unsigned long rng_get_bytes(unsigned char *buf, unsigned long len,
  119. void (*callback)(void))
  120. {
  121. unsigned long x;
  122. _ARGCHK(buf != NULL);
  123. #ifdef SONY_PS2
  124. x = rng_ps2(buf, len, callback); if (x != 0) { return x; }
  125. #elif defined(DEVRANDOM)
  126. x = rng_nix(buf, len, callback); if (x != 0) { return x; }
  127. #endif
  128. #ifdef WIN32
  129. x = rng_win32(buf, len, callback); if (x != 0) { return x; }
  130. #endif
  131. #ifdef ANSI_RNG
  132. x = rng_ansic(buf, len, callback); if (x != 0) { return x; }
  133. #endif
  134. return 0;
  135. }
  136. int rng_make_prng(int bits, int wprng, prng_state *prng,
  137. void (*callback)(void))
  138. {
  139. unsigned char buf[256];
  140. int err;
  141. _ARGCHK(prng != NULL);
  142. /* check parameter */
  143. if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
  144. return err;
  145. }
  146. if (bits < 64 || bits > 1024) {
  147. return CRYPT_INVALID_PRNGSIZE;
  148. }
  149. if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) {
  150. return err;
  151. }
  152. bits = ((bits/8)+((bits&7)!=0?1:0)) * 2;
  153. if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) {
  154. return CRYPT_ERROR_READPRNG;
  155. }
  156. if ((err = prng_descriptor[wprng].add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) {
  157. return err;
  158. }
  159. if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) {
  160. return err;
  161. }
  162. #ifdef CLEAN_STACK
  163. zeromem(buf, sizeof(buf));
  164. #endif
  165. return CRYPT_OK;
  166. }