Counter Strike : Global Offensive Source Code
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.

182 lines
3.8 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. m_hProvider = 0;
  40. }
  41. MicrosoftCryptoProvider::~MicrosoftCryptoProvider()
  42. {
  43. //CryptReleaseContext(m_hProvider, 0);
  44. }
  45. #endif
  46. NonblockingRng::NonblockingRng()
  47. {
  48. #ifndef CRYPTOPP_WIN32_AVAILABLE
  49. m_fd = open("/dev/urandom",O_RDONLY);
  50. if (m_fd == -1)
  51. throw OS_RNG_Err("open /dev/urandom");
  52. #endif
  53. }
  54. NonblockingRng::~NonblockingRng()
  55. {
  56. #ifndef CRYPTOPP_WIN32_AVAILABLE
  57. close(m_fd);
  58. #endif
  59. }
  60. void NonblockingRng::GenerateBlock(byte *output, size_t size)
  61. {
  62. #ifdef CRYPTOPP_WIN32_AVAILABLE
  63. //# ifdef WORKAROUND_MS_BUG_Q258000
  64. // const MicrosoftCryptoProvider &m_Provider = Singleton<MicrosoftCryptoProvider>().Ref();
  65. //# endif
  66. // if (!CryptGenRandom(m_Provider.GetProviderHandle(), (DWORD)size, output))
  67. // throw OS_RNG_Err("CryptGenRandom");
  68. static BOOL (__stdcall * s_pfnRtlGenRandom)( PVOID, ULONG ) = 0;
  69. if ( !s_pfnRtlGenRandom )
  70. {
  71. HMODULE hModAdvApi = ::LoadLibraryA( "advapi32.dll" );
  72. if ( hModAdvApi )
  73. s_pfnRtlGenRandom = (BOOL(__stdcall*)(PVOID,ULONG)) GetProcAddress( hModAdvApi, "SystemFunction036" );
  74. }
  75. _ReadWriteBarrier();
  76. if ( !s_pfnRtlGenRandom || s_pfnRtlGenRandom( output, size ) == 0 )
  77. throw OS_RNG_Err("RtlGenRandom");
  78. #else
  79. if (read(m_fd, output, size) != size)
  80. throw OS_RNG_Err("read /dev/urandom");
  81. #endif
  82. }
  83. #endif
  84. // *************************************************************
  85. #ifdef BLOCKING_RNG_AVAILABLE
  86. #ifndef CRYPTOPP_BLOCKING_RNG_FILENAME
  87. #ifdef __OpenBSD__
  88. #define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/srandom"
  89. #else
  90. #define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/random"
  91. #endif
  92. #endif
  93. BlockingRng::BlockingRng()
  94. {
  95. m_fd = open(CRYPTOPP_BLOCKING_RNG_FILENAME,O_RDONLY);
  96. if (m_fd == -1)
  97. throw OS_RNG_Err("open " CRYPTOPP_BLOCKING_RNG_FILENAME);
  98. }
  99. BlockingRng::~BlockingRng()
  100. {
  101. close(m_fd);
  102. }
  103. void BlockingRng::GenerateBlock(byte *output, size_t size)
  104. {
  105. while (size)
  106. {
  107. // on some systems /dev/random will block until all bytes
  108. // are available, on others it will returns immediately
  109. ssize_t len = read(m_fd, output, size);
  110. if (len < 0)
  111. throw OS_RNG_Err("read " CRYPTOPP_BLOCKING_RNG_FILENAME);
  112. size -= len;
  113. output += len;
  114. if (size)
  115. sleep(1);
  116. }
  117. }
  118. #endif
  119. // *************************************************************
  120. void OS_GenerateRandomBlock(bool blocking, byte *output, size_t size)
  121. {
  122. #ifdef NONBLOCKING_RNG_AVAILABLE
  123. if (blocking)
  124. #endif
  125. {
  126. #ifdef BLOCKING_RNG_AVAILABLE
  127. BlockingRng rng;
  128. rng.GenerateBlock(output, size);
  129. #endif
  130. }
  131. #ifdef BLOCKING_RNG_AVAILABLE
  132. if (!blocking)
  133. #endif
  134. {
  135. #ifdef NONBLOCKING_RNG_AVAILABLE
  136. NonblockingRng rng;
  137. rng.GenerateBlock(output, size);
  138. #endif
  139. }
  140. }
  141. void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize)
  142. {
  143. SecByteBlock seed(seedSize);
  144. OS_GenerateRandomBlock(blocking, seed, seedSize);
  145. IncorporateEntropy(seed, seedSize);
  146. }
  147. NAMESPACE_END
  148. #endif
  149. #endif