win_rand.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #include "secrng.h"
  5. #ifdef XP_WIN
  6. #include <windows.h>
  7. #include <time.h>
  8. static BOOL
  9. CurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow)
  10. {
  11. LARGE_INTEGER liCount;
  12. if (!QueryPerformanceCounter(&liCount))
  13. return FALSE;
  14. *lpdwHigh = liCount.u.HighPart;
  15. *lpdwLow = liCount.u.LowPart;
  16. return TRUE;
  17. }
  18. size_t
  19. RNG_GetNoise(void *buf, size_t maxbuf)
  20. {
  21. DWORD dwHigh, dwLow, dwVal;
  22. int n = 0;
  23. int nBytes;
  24. time_t sTime;
  25. if (maxbuf <= 0)
  26. return 0;
  27. CurrentClockTickTime(&dwHigh, &dwLow);
  28. // get the maximally changing bits first
  29. nBytes = sizeof(dwLow) > maxbuf ? maxbuf : sizeof(dwLow);
  30. memcpy((char *)buf, &dwLow, nBytes);
  31. n += nBytes;
  32. maxbuf -= nBytes;
  33. if (maxbuf <= 0)
  34. return n;
  35. nBytes = sizeof(dwHigh) > maxbuf ? maxbuf : sizeof(dwHigh);
  36. memcpy(((char *)buf) + n, &dwHigh, nBytes);
  37. n += nBytes;
  38. maxbuf -= nBytes;
  39. if (maxbuf <= 0)
  40. return n;
  41. // get the number of milliseconds that have elapsed since Windows started
  42. dwVal = GetTickCount();
  43. nBytes = sizeof(dwVal) > maxbuf ? maxbuf : sizeof(dwVal);
  44. memcpy(((char *)buf) + n, &dwVal, nBytes);
  45. n += nBytes;
  46. maxbuf -= nBytes;
  47. if (maxbuf <= 0)
  48. return n;
  49. // get the time in seconds since midnight Jan 1, 1970
  50. time(&sTime);
  51. nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime);
  52. memcpy(((char *)buf) + n, &sTime, nBytes);
  53. n += nBytes;
  54. return n;
  55. }
  56. void
  57. RNG_SystemInfoForRNG(void)
  58. {
  59. DWORD dwVal;
  60. char buffer[256];
  61. int nBytes;
  62. MEMORYSTATUS sMem;
  63. HANDLE hVal;
  64. DWORD dwSerialNum;
  65. DWORD dwComponentLen;
  66. DWORD dwSysFlags;
  67. char volName[128];
  68. DWORD dwSectors, dwBytes, dwFreeClusters, dwNumClusters;
  69. nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
  70. RNG_RandomUpdate(buffer, nBytes);
  71. sMem.dwLength = sizeof(sMem);
  72. GlobalMemoryStatus(&sMem); // assorted memory stats
  73. RNG_RandomUpdate(&sMem, sizeof(sMem));
  74. dwVal = GetLogicalDrives();
  75. RNG_RandomUpdate(&dwVal, sizeof(dwVal)); // bitfields in bits 0-25
  76. dwVal = sizeof(buffer);
  77. if (GetComputerName(buffer, &dwVal))
  78. RNG_RandomUpdate(buffer, dwVal);
  79. hVal = GetCurrentProcess(); // 4 or 8 byte pseudo handle (a
  80. // constant!) of current process
  81. RNG_RandomUpdate(&hVal, sizeof(hVal));
  82. dwVal = GetCurrentProcessId(); // process ID (4 bytes)
  83. RNG_RandomUpdate(&dwVal, sizeof(dwVal));
  84. dwVal = GetCurrentThreadId(); // thread ID (4 bytes)
  85. RNG_RandomUpdate(&dwVal, sizeof(dwVal));
  86. volName[0] = '\0';
  87. buffer[0] = '\0';
  88. GetVolumeInformation(NULL,
  89. volName,
  90. sizeof(volName),
  91. &dwSerialNum,
  92. &dwComponentLen,
  93. &dwSysFlags,
  94. buffer,
  95. sizeof(buffer));
  96. RNG_RandomUpdate(volName, strlen(volName));
  97. RNG_RandomUpdate(&dwSerialNum, sizeof(dwSerialNum));
  98. RNG_RandomUpdate(&dwComponentLen, sizeof(dwComponentLen));
  99. RNG_RandomUpdate(&dwSysFlags, sizeof(dwSysFlags));
  100. RNG_RandomUpdate(buffer, strlen(buffer));
  101. if (GetDiskFreeSpace(NULL, &dwSectors, &dwBytes, &dwFreeClusters,
  102. &dwNumClusters)) {
  103. RNG_RandomUpdate(&dwSectors, sizeof(dwSectors));
  104. RNG_RandomUpdate(&dwBytes, sizeof(dwBytes));
  105. RNG_RandomUpdate(&dwFreeClusters, sizeof(dwFreeClusters));
  106. RNG_RandomUpdate(&dwNumClusters, sizeof(dwNumClusters));
  107. }
  108. nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes
  109. RNG_RandomUpdate(buffer, nBytes);
  110. }
  111. /*
  112. * The RtlGenRandom function is declared in <ntsecapi.h>, but the
  113. * declaration is missing a calling convention specifier. So we
  114. * declare it manually here.
  115. */
  116. #define RtlGenRandom SystemFunction036
  117. DECLSPEC_IMPORT BOOLEAN WINAPI RtlGenRandom(
  118. PVOID RandomBuffer,
  119. ULONG RandomBufferLength);
  120. size_t
  121. RNG_SystemRNG(void *dest, size_t maxLen)
  122. {
  123. size_t bytes = 0;
  124. if (RtlGenRandom(dest, maxLen)) {
  125. bytes = maxLen;
  126. }
  127. return bytes;
  128. }
  129. #endif /* is XP_WIN */