security/nss/lib/freebl/win_rand.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial