Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
3.4 KiB

  1. // osrng.cpp - written and placed in the public domain by Wei Dai
  2. // Thanks to Leonard Janke for the suggestion for AutoSeededRandomPool.
  3. #include "pch.h"
  4. #ifndef CRYPTOPP_IMPORTS
  5. #include "osrng.h"
  6. #ifdef OS_RNG_AVAILABLE
  7. #include "rng.h"
  8. #ifdef CRYPTOPP_WIN32_AVAILABLE
  9. #ifndef _WIN32_WINNT
  10. #define _WIN32_WINNT 0x0400
  11. #endif
  12. #include <windows.h>
  13. #include <wincrypt.h>
  14. #endif
  15. #ifdef CRYPTOPP_UNIX_AVAILABLE
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <unistd.h>
  19. #endif
  20. NAMESPACE_BEGIN(CryptoPP)
  21. #if defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE)
  22. OS_RNG_Err::OS_RNG_Err(const std::string &operation)
  23. : Exception(OTHER_ERROR, "OS_Rng: " + operation + " operation failed with error " +
  24. #ifdef CRYPTOPP_WIN32_AVAILABLE
  25. "0x" + IntToString(GetLastError(), 16)
  26. #else
  27. IntToString(errno)
  28. #endif
  29. )
  30. {
  31. }
  32. #endif
  33. #ifdef NONBLOCKING_RNG_AVAILABLE
  34. #ifdef CRYPTOPP_WIN32_AVAILABLE
  35. MicrosoftCryptoProvider::MicrosoftCryptoProvider()
  36. {
  37. if(!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
  38. throw OS_RNG_Err("CryptAcquireContext");
  39. }
  40. MicrosoftCryptoProvider::~MicrosoftCryptoProvider()
  41. {
  42. CryptReleaseContext(m_hProvider, 0);
  43. }
  44. #endif
  45. NonblockingRng::NonblockingRng()
  46. {
  47. #ifndef CRYPTOPP_WIN32_AVAILABLE
  48. m_fd = open("/dev/urandom",O_RDONLY);
  49. if (m_fd == -1)
  50. throw OS_RNG_Err("open /dev/urandom");
  51. #endif
  52. }
  53. NonblockingRng::~NonblockingRng()
  54. {
  55. #ifndef CRYPTOPP_WIN32_AVAILABLE
  56. close(m_fd);
  57. #endif
  58. }
  59. void NonblockingRng::GenerateBlock(byte *output, size_t size)
  60. {
  61. #ifdef CRYPTOPP_WIN32_AVAILABLE
  62. # ifdef WORKAROUND_MS_BUG_Q258000
  63. const MicrosoftCryptoProvider &m_Provider = Singleton<MicrosoftCryptoProvider>().Ref();
  64. # endif
  65. if (!CryptGenRandom(m_Provider.GetProviderHandle(), (DWORD)size, output))
  66. throw OS_RNG_Err("CryptGenRandom");
  67. #else
  68. if (read(m_fd, output, size) != size)
  69. throw OS_RNG_Err("read /dev/urandom");
  70. #endif
  71. }
  72. #endif
  73. // *************************************************************
  74. #ifdef BLOCKING_RNG_AVAILABLE
  75. #ifndef CRYPTOPP_BLOCKING_RNG_FILENAME
  76. #ifdef __OpenBSD__
  77. #define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/srandom"
  78. #else
  79. #define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/random"
  80. #endif
  81. #endif
  82. BlockingRng::BlockingRng()
  83. {
  84. m_fd = open(CRYPTOPP_BLOCKING_RNG_FILENAME,O_RDONLY);
  85. if (m_fd == -1)
  86. throw OS_RNG_Err("open " CRYPTOPP_BLOCKING_RNG_FILENAME);
  87. }
  88. BlockingRng::~BlockingRng()
  89. {
  90. close(m_fd);
  91. }
  92. void BlockingRng::GenerateBlock(byte *output, size_t size)
  93. {
  94. while (size)
  95. {
  96. // on some systems /dev/random will block until all bytes
  97. // are available, on others it will returns immediately
  98. ssize_t len = read(m_fd, output, size);
  99. if (len < 0)
  100. throw OS_RNG_Err("read " CRYPTOPP_BLOCKING_RNG_FILENAME);
  101. size -= len;
  102. output += len;
  103. if (size)
  104. sleep(1);
  105. }
  106. }
  107. #endif
  108. // *************************************************************
  109. void OS_GenerateRandomBlock(bool blocking, byte *output, size_t size)
  110. {
  111. #ifdef NONBLOCKING_RNG_AVAILABLE
  112. if (blocking)
  113. #endif
  114. {
  115. #ifdef BLOCKING_RNG_AVAILABLE
  116. BlockingRng rng;
  117. rng.GenerateBlock(output, size);
  118. #endif
  119. }
  120. #ifdef BLOCKING_RNG_AVAILABLE
  121. if (!blocking)
  122. #endif
  123. {
  124. #ifdef NONBLOCKING_RNG_AVAILABLE
  125. NonblockingRng rng;
  126. rng.GenerateBlock(output, size);
  127. #endif
  128. }
  129. }
  130. void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize)
  131. {
  132. SecByteBlock seed(seedSize);
  133. OS_GenerateRandomBlock(blocking, seed, seedSize);
  134. IncorporateEntropy(seed, seedSize);
  135. }
  136. NAMESPACE_END
  137. #endif
  138. #endif