rng_get_bytes.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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, [email protected], http://libtomcrypt.org
  10. */
  11. /* portable way to get secure random bits to feed a PRNG */
  12. #include "mycrypt.h"
  13. #ifdef DEVRANDOM
  14. /* on *NIX read /dev/random */
  15. static unsigned long rng_nix(unsigned char *buf, unsigned long len,
  16. void (*callback)(void))
  17. {
  18. #ifdef NO_FILE
  19. return 0;
  20. #else
  21. FILE *f;
  22. unsigned long x;
  23. #ifdef TRY_URANDOM_FIRST
  24. f = fopen("/dev/urandom", "rb");
  25. if (f == NULL)
  26. #endif /* TRY_URANDOM_FIRST */
  27. f = fopen("/dev/random", "rb");
  28. if (f == NULL) {
  29. return 0;
  30. }
  31. /* disable buffering */
  32. if (setvbuf(f, NULL, _IONBF, 0) != 0) {
  33. fclose(f);
  34. return 0;
  35. }
  36. x = (unsigned long)fread(buf, 1, (size_t)len, f);
  37. fclose(f);
  38. return x;
  39. #endif /* NO_FILE */
  40. }
  41. #endif /* DEVRANDOM */
  42. /* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */
  43. #if defined(CLOCKS_PER_SEC)
  44. #define ANSI_RNG
  45. static unsigned long rng_ansic(unsigned char *buf, unsigned long len,
  46. void (*callback)(void))
  47. {
  48. clock_t t1;
  49. int l, acc, bits, a, b;
  50. if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) {
  51. return 0;
  52. }
  53. l = len;
  54. bits = 8;
  55. acc = a = b = 0;
  56. while (len--) {
  57. if (callback != NULL) callback();
  58. while (bits--) {
  59. do {
  60. t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
  61. t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
  62. } while (a == b);
  63. acc = (acc << 1) | a;
  64. }
  65. *buf++ = acc;
  66. acc = 0;
  67. bits = 8;
  68. }
  69. acc = bits = a = b = 0;
  70. return l;
  71. }
  72. #endif
  73. /* Try the Microsoft CSP */
  74. #ifdef WIN32
  75. #define _WIN32_WINNT 0x0400
  76. #include <windows.h>
  77. #include <wincrypt.h>
  78. static unsigned long rng_win32(unsigned char *buf, unsigned long len,
  79. void (*callback)(void))
  80. {
  81. HCRYPTPROV hProv = 0;
  82. if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
  83. (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
  84. !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
  85. CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
  86. return 0;
  87. if (CryptGenRandom(hProv, len, buf) == TRUE) {
  88. CryptReleaseContext(hProv, 0);
  89. return len;
  90. } else {
  91. CryptReleaseContext(hProv, 0);
  92. return 0;
  93. }
  94. }
  95. #endif /* WIN32 */
  96. unsigned long rng_get_bytes(unsigned char *buf, unsigned long len,
  97. void (*callback)(void))
  98. {
  99. unsigned long x;
  100. _ARGCHK(buf != NULL);
  101. #if defined(DEVRANDOM)
  102. x = rng_nix(buf, len, callback); if (x != 0) { return x; }
  103. #endif
  104. #ifdef WIN32
  105. x = rng_win32(buf, len, callback); if (x != 0) { return x; }
  106. #endif
  107. #ifdef ANSI_RNG
  108. x = rng_ansic(buf, len, callback); if (x != 0) { return x; }
  109. #endif
  110. return 0;
  111. }