Annotation of truecrypt/common/random.c, revision 1.1.1.6

1.1.1.6 ! root        1: /* Legal Notice: The source code contained in this file has been derived from
        !             2:    the source code of Encryption for the Masses 2.02a, which is Copyright (c)
        !             3:    1998-99 Paul Le Roux and which is covered by the 'License Agreement for
        !             4:    Encryption for the Masses'. Modifications and additions to that source code
        !             5:    contained in this file are Copyright (c) 2004-2005 TrueCrypt Foundation and
        !             6:    Copyright (c) 2004 TrueCrypt Team, and are covered by TrueCrypt License 2.0
        !             7:    the full text of which is contained in the file License.txt included in
        !             8:    TrueCrypt binary and source code distribution archives.  */
1.1       root        9: 
1.1.1.6 ! root       10: #include "Tcdefs.h"
1.1       root       11: 
                     12: #include <tlhelp32.h>
                     13: 
1.1.1.6 ! root       14: #include "Crc.h"
        !            15: #include "Random.h"
        !            16: #include "Apidrvr.h"
        !            17: #include "Dlgcode.h"
1.1       root       18: 
                     19: unsigned char *pRandPool = NULL;
1.1.1.2   root       20: int nRandIndex = 0, randPoolReadIndex = 0;
1.1       root       21: 
1.1.1.6 ! root       22: int hashFunction = DEFAULT_HASH_ALGORITHM;
1.1.1.3   root       23: 
1.1       root       24: /* Macro to add a single byte to the pool */
                     25: #define RandaddByte(x) {\
1.1.1.6 ! root       26:        if (nRandIndex == RNG_POOL_SIZE) nRandIndex = 0;\
1.1       root       27:        pRandPool[nRandIndex] = (unsigned char) ((unsigned char)x + pRandPool[nRandIndex]); \
1.1.1.6 ! root       28:        if (nRandIndex % 8 == 0) Randmix();\
1.1       root       29:        nRandIndex++; \
                     30:        }
                     31: 
                     32: /* Macro to add four bytes to the pool */
1.1.1.6 ! root       33: #define RandaddInt32(x) _RandaddInt32((unsigned __int32)x);
1.1       root       34: 
                     35: #pragma warning( disable : 4710 ) /* inline func. not expanded warning */
                     36: 
1.1.1.6 ! root       37: _inline void _RandaddInt32(unsigned __int32 x)
1.1       root       38: {
                     39:        RandaddByte(x); 
                     40:        RandaddByte((x >> 8)); 
                     41:        RandaddByte((x >> 16));
                     42:        RandaddByte((x >> 24));
                     43: }
                     44: 
                     45: HHOOK hMouse = NULL;           /* Mouse hook for the random number generator */
1.1.1.6 ! root       46: HHOOK hKeyboard = NULL;                /* Keyboard hook for the random number generator */
1.1       root       47: 
                     48: /* Variables for thread control, the thread is used to gather up info about
                     49:    the system in in the background */
                     50: CRITICAL_SECTION critRandProt; /* The critical section */
1.1.1.6 ! root       51: BOOL volatile bThreadTerminate = FALSE;        /* This variable is shared among thread's so its made volatile */
1.1       root       52: BOOL bDidSlowPoll = FALSE;     /* We do the slow poll only once */
1.1.1.6 ! root       53: BOOL volatile bFastPollEnabled = TRUE; /* Used to reduce CPU load when performing benchmarks and formatting */
        !            54: BOOL volatile bRandmixEnabled = TRUE;  /* Used to reduce CPU load when performing benchmarks and formatting */
1.1       root       55: 
                     56: /* Network library handle for the slowPollWinNT function */
                     57: HANDLE hNetAPI32 = NULL;
                     58: 
1.1.1.4   root       59: // CryptoAPI
                     60: HCRYPTPROV hCryptProv;
1.1.1.6 ! root       61: unsigned __int8 buffer[RNG_POOL_SIZE];
1.1.1.4   root       62: 
1.1       root       63: BOOL bRandDidInit = FALSE;
                     64: 
                     65: /* Init the random number generator, setup the hooks, and start the thread */
                     66: int
                     67: Randinit ()
                     68: {
                     69:        HANDLE threadID;
                     70: 
1.1.1.6 ! root       71:        if(bRandDidInit) return 0;
1.1       root       72: 
                     73:        InitializeCriticalSection (&critRandProt);
                     74: 
                     75:        bRandDidInit = TRUE;
                     76: 
                     77:        pRandPool = (unsigned char *) TCalloc (RANDOMPOOL_ALLOCSIZE);
                     78:        if (pRandPool == NULL)
                     79:                goto error;
                     80:        else
                     81:                memset (pRandPool, 0, RANDOMPOOL_ALLOCSIZE);
                     82: 
1.1.1.2   root       83:        VirtualLock (pRandPool, RANDOMPOOL_ALLOCSIZE);
                     84: 
1.1       root       85:        hKeyboard = SetWindowsHookEx (WH_KEYBOARD, (HOOKPROC)&KeyboardProc, NULL, GetCurrentThreadId ());
1.1.1.4   root       86:        if (hKeyboard == 0) handleWin32Error (0);
                     87: 
                     88:        hMouse = SetWindowsHookEx (WH_MOUSE, (HOOKPROC)&MouseProc, NULL, GetCurrentThreadId ());
                     89:        if (hMouse == 0)
                     90:        {
                     91:                handleWin32Error (0);
1.1       root       92:                goto error;
1.1.1.4   root       93:        }
                     94: 
                     95:        if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)
                     96:                && !CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
                     97:        {
1.1.1.6 ! root       98:                hCryptProv = 0;
1.1.1.4   root       99:        }
1.1       root      100: 
                    101:        threadID = (HANDLE) _beginthread (ThreadSafeThreadFunction, 8192, NULL);
                    102:        if (threadID == (HANDLE) - 1)
                    103:                goto error;
                    104: 
                    105:        return 0;
                    106: 
1.1.1.4   root      107: error:
1.1       root      108:        Randfree ();
                    109:        return 1;
                    110: }
                    111: 
                    112: /* Close everything down, including the thread which is closed down by
                    113:    setting a flag which eventually causes the thread function to exit */
                    114: void
                    115: Randfree ()
                    116: {
                    117:        if (bRandDidInit == FALSE)
                    118:                return;
                    119: 
                    120:        EnterCriticalSection (&critRandProt);
                    121: 
                    122:        if (hMouse != 0)
                    123:                UnhookWindowsHookEx (hMouse);
                    124:        if (hKeyboard != 0)
                    125:                UnhookWindowsHookEx (hKeyboard);
                    126: 
                    127:        bThreadTerminate = TRUE;
                    128: 
                    129:        LeaveCriticalSection (&critRandProt);
                    130: 
                    131:        for (;;)
                    132:        {
                    133:                Sleep (250);
                    134:                EnterCriticalSection (&critRandProt);
                    135:                if (bThreadTerminate == FALSE)
                    136:                {
                    137:                        LeaveCriticalSection (&critRandProt);
                    138:                        break;
                    139:                }
                    140:                LeaveCriticalSection (&critRandProt);
                    141:        }
                    142: 
                    143:        if (pRandPool != NULL)
                    144:        {
                    145:                burn (pRandPool, RANDOMPOOL_ALLOCSIZE);
                    146:                TCfree (pRandPool);
                    147:                pRandPool = NULL;
                    148:        }
                    149: 
                    150:        if (hNetAPI32 != 0)
                    151:        {
                    152:                FreeLibrary (hNetAPI32);
                    153:                hNetAPI32 = NULL;
                    154:        }
                    155: 
1.1.1.4   root      156:        if (hCryptProv)
                    157:        {
                    158:                CryptReleaseContext (hCryptProv, 0);
                    159:                hCryptProv = 0;
                    160:        }
                    161: 
1.1       root      162:        hMouse = NULL;
                    163:        hKeyboard = NULL;
                    164:        nRandIndex = 0;
                    165:        bThreadTerminate = FALSE;
                    166:        DeleteCriticalSection (&critRandProt);
                    167:        bRandDidInit = FALSE;
                    168: }
                    169: 
1.1.1.6 ! root      170: void RandSetHashFunction (int hash_algo_id)
1.1.1.3   root      171: {
1.1.1.6 ! root      172:        hashFunction = hash_algo_id;
1.1.1.3   root      173: }
                    174: 
1.1.1.6 ! root      175: int RandGetHashFunction (void)
        !           176: {
        !           177:        return hashFunction;
        !           178: }
        !           179: 
        !           180: /* The random pool mixing function */
1.1       root      181: void
                    182: Randmix ()
                    183: {
1.1.1.6 ! root      184:        if (bRandmixEnabled)
1.1       root      185:        {
1.1.1.6 ! root      186:                unsigned char hashOutputBuffer [MAX_DIGESTSIZE];
        !           187:                WHIRLPOOL_CTX   wctx;
        !           188:                RMD160_CTX              rctx;
        !           189:                sha1_ctx                sctx;
        !           190:                int poolIndex, digestIndex, digestSize;
        !           191: 
        !           192:                switch (hashFunction)
        !           193:                {
        !           194:                case SHA1:
        !           195:                        digestSize = SHA1_DIGESTSIZE;
        !           196:                        break;
1.1       root      197: 
1.1.1.6 ! root      198:                case RIPEMD160:
        !           199:                        digestSize = RIPEMD160_DIGESTSIZE;
        !           200:                        break;
        !           201: 
        !           202:                case WHIRLPOOL:
        !           203:                        digestSize = WHIRLPOOL_DIGESTSIZE;
        !           204:                        break;
        !           205:                }
1.1.1.3   root      206: 
1.1.1.6 ! root      207:                for (poolIndex = 0; poolIndex < RNG_POOL_SIZE; poolIndex += digestSize)         
        !           208:                {
        !           209:                        /* Compute the message digest of the entire pool using the selected hash function. */
        !           210:                        switch (hashFunction)
        !           211:                        {
        !           212:                        case SHA1:
        !           213:                                sha1_begin (&sctx);
        !           214:                                sha1_hash (pRandPool, RNG_POOL_SIZE, &sctx);
        !           215:                                sha1_end (hashOutputBuffer, &sctx);
        !           216:                                break;
        !           217: 
        !           218:                        case RIPEMD160:
        !           219:                                RMD160Init(&rctx);
        !           220:                                RMD160Update(&rctx, pRandPool, RNG_POOL_SIZE);
        !           221:                                RMD160Final(hashOutputBuffer, &rctx);
        !           222:                                break;
        !           223: 
        !           224:                        case WHIRLPOOL:
        !           225:                                WHIRLPOOL_init (&wctx);
        !           226:                                WHIRLPOOL_add (pRandPool, RNG_POOL_SIZE * 8, &wctx);
        !           227:                                WHIRLPOOL_finalize (&wctx, hashOutputBuffer);
        !           228:                                break;
        !           229:                        }
        !           230: 
        !           231:                        /* XOR the resultant message digest to the pool at the poolIndex position. */
        !           232:                        for (digestIndex = 0; digestIndex < digestSize; digestIndex++)
        !           233:                        {
        !           234:                                pRandPool [poolIndex + digestIndex] ^= hashOutputBuffer [digestIndex];
        !           235:                        }
        !           236:                }
        !           237: 
        !           238:                /* Prevent leaks */
        !           239:                memset (hashOutputBuffer, 0, MAX_DIGESTSIZE);   
        !           240:                switch (hashFunction)
        !           241:                {
        !           242:                case SHA1:
        !           243:                        memset (&sctx, 0, sizeof(sctx));                
        !           244:                        break;
        !           245: 
        !           246:                case RIPEMD160:
        !           247:                        memset (&rctx, 0, sizeof(rctx));                
        !           248:                        break;
        !           249: 
        !           250:                case WHIRLPOOL:
        !           251:                        memset (&wctx, 0, sizeof(wctx));                
        !           252:                        break;
        !           253:                }
1.1       root      254:        }
                    255: }
                    256: 
                    257: /* Add a buffer to the pool */
                    258: void
                    259: RandaddBuf (void *buf, int len)
                    260: {
                    261:        int i;
                    262:        for (i = 0; i < len; i++)
                    263:        {
                    264:                RandaddByte (((unsigned char *) buf)[i]);
                    265:        }
                    266: }
                    267: 
                    268: void
1.1.1.4   root      269: RandpeekBytes (unsigned char *buf, int len)
1.1       root      270: {
1.1.1.6 ! root      271:        if (len > RNG_POOL_SIZE)
        !           272:                len = RNG_POOL_SIZE;
        !           273: 
1.1       root      274:        EnterCriticalSection (&critRandProt);
                    275:        memcpy (buf, pRandPool, len);
                    276:        LeaveCriticalSection (&critRandProt);
                    277: }
                    278: 
1.1.1.6 ! root      279: /* Get len random bytes from the pool (max. RNG_POOL_SIZE bytes per a single call) */
1.1       root      280: void
1.1.1.4   root      281: RandgetBytes (unsigned char *buf, int len, BOOL forceSlowPoll)
1.1       root      282: {
                    283:        int i;
                    284: 
                    285:        EnterCriticalSection (&critRandProt);
                    286: 
1.1.1.2   root      287:        if (bDidSlowPoll == FALSE || forceSlowPoll)
1.1       root      288:        {
                    289:                bDidSlowPoll = TRUE;
1.1.1.2   root      290:                SlowPollWinNT ();
1.1       root      291:        }
1.1.1.2   root      292: 
                    293:        FastPoll ();
1.1       root      294: 
1.1.1.6 ! root      295:        /* There's never more than RNG_POOL_SIZE worth of randomess */
        !           296:        if (len > RNG_POOL_SIZE)
        !           297:        {
        !           298:                Error ("ERR_NOT_ENOUGH_RANDOM_DATA");   
        !           299:                len = RNG_POOL_SIZE;
        !           300:        }
1.1       root      301: 
1.1.1.2   root      302:        // Requested number of bytes is copied from pool to output buffer,
                    303:        // pool is rehashed, and output buffer is XORed with new data from pool
                    304:        for (i = 0; i < len; i++)
                    305:        {
                    306:                buf[i] = pRandPool[randPoolReadIndex++];
1.1.1.6 ! root      307:                if (randPoolReadIndex == RNG_POOL_SIZE) randPoolReadIndex = 0;
1.1.1.2   root      308:        }
                    309: 
1.1.1.6 ! root      310:        /* Invert the pool */
        !           311:        for (i = 0; i < RNG_POOL_SIZE / 4; i++)
1.1       root      312:        {
1.1.1.6 ! root      313:                ((unsigned __int32 *) pRandPool)[i] = ~((unsigned __int32 *) pRandPool)[i];
1.1       root      314:        }
                    315: 
1.1.1.6 ! root      316:        // Mix the pool
1.1.1.4   root      317:        FastPoll ();
                    318: 
1.1.1.6 ! root      319:        // XOR the current pool content into the output buffer to prevent pool state leaks
1.1.1.4   root      320:        for (i = 0; i < len; i++)
                    321:        {
                    322:                buf[i] ^= pRandPool[randPoolReadIndex++];
1.1.1.6 ! root      323:                if (randPoolReadIndex == RNG_POOL_SIZE) randPoolReadIndex = 0;
1.1.1.4   root      324:        }
1.1       root      325: 
                    326:        LeaveCriticalSection (&critRandProt);
                    327: }
                    328: 
                    329: /* Capture the mouse, and as long as the event is not the same as the last
1.1.1.6 ! root      330:    two events, add the crc of the event, and the crc of the time difference
1.1       root      331:    between this event and the last + the current time to the pool */
                    332: LRESULT CALLBACK
                    333: MouseProc (int nCode, WPARAM wParam, LPARAM lParam)
                    334: {
                    335:        static DWORD dwLastTimer;
1.1.1.6 ! root      336:        static unsigned __int32 lastCrc, lastCrc2;
1.1       root      337:        MOUSEHOOKSTRUCT *lpMouse = (MOUSEHOOKSTRUCT *) lParam;
                    338: 
                    339:        if (nCode < 0)
                    340:                return CallNextHookEx (hMouse, nCode, wParam, lParam);
                    341:        else
                    342:        {
                    343:                DWORD dwTimer = GetTickCount ();
                    344:                DWORD j = dwLastTimer - dwTimer;
1.1.1.6 ! root      345:                unsigned __int32 crc = 0L;
1.1       root      346:                int i;
                    347: 
                    348:                dwLastTimer = dwTimer;
                    349: 
                    350:                for (i = 0; i < sizeof (MOUSEHOOKSTRUCT); i++)
                    351:                {
                    352:                        crc = UPDC32 (((unsigned char *) lpMouse)[i], crc);
                    353:                }
                    354: 
                    355:                if (crc != lastCrc && crc != lastCrc2)
                    356:                {
1.1.1.6 ! root      357:                        unsigned __int32 timeCrc = 0L;
1.1       root      358: 
                    359:                        for (i = 0; i < 4; i++)
                    360:                        {
                    361:                                timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc);
                    362:                        }
                    363: 
                    364:                        for (i = 0; i < 4; i++)
                    365:                        {
                    366:                                timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc);
                    367:                        }
                    368: 
                    369:                        EnterCriticalSection (&critRandProt);
1.1.1.6 ! root      370:                        RandaddInt32 ((unsigned __int32) (crc + timeCrc));
1.1       root      371:                        LeaveCriticalSection (&critRandProt);
                    372:                }
                    373:                lastCrc2 = lastCrc;
                    374:                lastCrc = crc;
                    375: 
                    376:        }
                    377:        return 0;
                    378: }
                    379: 
                    380: /* Capture the keyboard, as long as the event is not the same as the last two
1.1.1.6 ! root      381:    events, add the crc of the event to the pool along with the crc of the time
1.1       root      382:    difference between this event and the last */
                    383: LRESULT CALLBACK
                    384: KeyboardProc (int nCode, WPARAM wParam, LPARAM lParam)
                    385: {
                    386:        static int lLastKey, lLastKey2;
                    387:        static DWORD dwLastTimer;
                    388:        int nKey = (lParam & 0x00ff0000) >> 16;
                    389:        int nCapture = 0;
                    390: 
                    391:        if (nCode < 0)
                    392:                return CallNextHookEx (hMouse, nCode, wParam, lParam);
                    393: 
                    394:        if ((lParam & 0x0000ffff) == 1 && !(lParam & 0x20000000) &&
                    395:            (lParam & 0x80000000))
                    396:        {
                    397:                if (nKey != lLastKey)
                    398:                        nCapture = 1;   /* Capture this key */
                    399:                else if (nKey != lLastKey2)
                    400:                        nCapture = 1;   /* Allow for one repeat */
                    401:        }
                    402:        if (nCapture)
                    403:        {
                    404:                DWORD dwTimer = GetTickCount ();
                    405:                DWORD j = dwLastTimer - dwTimer;
1.1.1.6 ! root      406:                unsigned __int32 timeCrc = 0L;
1.1       root      407:                int i;
                    408: 
                    409:                dwLastTimer = dwTimer;
                    410:                lLastKey2 = lLastKey;
                    411:                lLastKey = nKey;
                    412: 
                    413:                for (i = 0; i < 4; i++)
                    414:                {
                    415:                        timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc);
                    416:                }
                    417: 
                    418:                for (i = 0; i < 4; i++)
                    419:                {
                    420:                        timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc);
                    421:                }
                    422: 
                    423:                EnterCriticalSection (&critRandProt);
1.1.1.6 ! root      424:                RandaddInt32 ((unsigned __int32) (crc32int(&lParam) + timeCrc));
1.1       root      425:                LeaveCriticalSection (&critRandProt);
                    426:        }
                    427:        return 0;
                    428: }
                    429: 
                    430: /* This is the thread function which will poll the system for randomness */
                    431: void
                    432: ThreadSafeThreadFunction (void *dummy)
                    433: {
                    434:        if (dummy);             /* Remove unused parameter warning */
                    435: 
                    436:        for (;;)
                    437:        {
                    438:                EnterCriticalSection (&critRandProt);
                    439: 
1.1.1.6 ! root      440:                if (bThreadTerminate)
1.1       root      441:                {
                    442:                        bThreadTerminate = FALSE;
                    443:                        LeaveCriticalSection (&critRandProt);
                    444:                        _endthread ();
                    445:                }
1.1.1.6 ! root      446:                else if (bFastPollEnabled)
1.1       root      447:                {
                    448:                        FastPoll ();
                    449:                }
                    450: 
                    451:                LeaveCriticalSection (&critRandProt);
                    452: 
1.1.1.6 ! root      453:                Sleep (500);
1.1       root      454:        }
                    455: }
                    456: 
                    457: /* Type definitions for function pointers to call NetAPI32 functions */
                    458: 
                    459: typedef
                    460:   DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService,
                    461:                                     DWORD dwLevel, DWORD dwOptions,
                    462:                                     LPBYTE * lpBuffer);
                    463: typedef
                    464:   DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer);
                    465: typedef
                    466:   DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer);
                    467: 
                    468: NETSTATISTICSGET pNetStatisticsGet = NULL;
                    469: NETAPIBUFFERSIZE pNetApiBufferSize = NULL;
                    470: NETAPIBUFFERFREE pNetApiBufferFree = NULL;
                    471: 
                    472: /* This is the slowpoll function which gathers up network/hard drive
                    473:    performance data for the random pool */
                    474: void
                    475: SlowPollWinNT (void)
                    476: {
                    477:        static int isWorkstation = -1;
                    478:        static int cbPerfData = 0x10000;
                    479:        HANDLE hDevice;
                    480:        LPBYTE lpBuffer;
                    481:        DWORD dwSize, status;
                    482:        LPWSTR lpszLanW, lpszLanS;
1.1.1.4   root      483:        int i, nDrive;
1.1       root      484: 
                    485:        /* Find out whether this is an NT server or workstation if necessary */
                    486:        if (isWorkstation == -1)
                    487:        {
                    488:                HKEY hKey;
                    489: 
                    490:                if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
                    491:                       "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
                    492:                                  0, KEY_READ, &hKey) == ERROR_SUCCESS)
                    493:                {
                    494:                        unsigned char szValue[32];
                    495:                        dwSize = sizeof (szValue);
                    496: 
                    497:                        isWorkstation = TRUE;
                    498:                        status = RegQueryValueEx (hKey, "ProductType", 0, NULL,
                    499:                                                  szValue, &dwSize);
                    500: 
                    501:                        if (status == ERROR_SUCCESS && _stricmp ((char *) szValue, "WinNT"))
                    502:                                /* Note: There are (at least) three cases for
                    503:                                   ProductType: WinNT = NT Workstation,
                    504:                                   ServerNT = NT Server, LanmanNT = NT Server
                    505:                                   acting as a Domain Controller */
                    506:                                isWorkstation = FALSE;
                    507: 
                    508:                        RegCloseKey (hKey);
                    509:                }
                    510:        }
                    511:        /* Initialize the NetAPI32 function pointers if necessary */
                    512:        if (hNetAPI32 == NULL)
                    513:        {
                    514:                /* Obtain a handle to the module containing the Lan Manager
                    515:                   functions */
                    516:                hNetAPI32 = LoadLibrary ("NETAPI32.DLL");
                    517:                if (hNetAPI32 != NULL)
                    518:                {
                    519:                        /* Now get pointers to the functions */
                    520:                        pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32,
                    521:                                                        "NetStatisticsGet");
                    522:                        pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32,
                    523:                                                        "NetApiBufferSize");
                    524:                        pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32,
                    525:                                                        "NetApiBufferFree");
                    526: 
                    527:                        /* Make sure we got valid pointers for every NetAPI32
                    528:                           function */
                    529:                        if (pNetStatisticsGet == NULL ||
                    530:                            pNetApiBufferSize == NULL ||
                    531:                            pNetApiBufferFree == NULL)
                    532:                        {
                    533:                                /* Free the library reference and reset the
                    534:                                   static handle */
                    535:                                FreeLibrary (hNetAPI32);
                    536:                                hNetAPI32 = NULL;
                    537:                        }
                    538:                }
                    539:        }
                    540: 
                    541:        /* Get network statistics.  Note: Both NT Workstation and NT Server
                    542:           by default will be running both the workstation and server
                    543:           services.  The heuristic below is probably useful though on the
                    544:           assumption that the majority of the network traffic will be via
                    545:           the appropriate service */
                    546:        lpszLanW = (LPWSTR) WIDE ("LanmanWorkstation");
                    547:        lpszLanS = (LPWSTR) WIDE ("LanmanServer");
                    548:        if (hNetAPI32 &&
                    549:            pNetStatisticsGet (NULL,
                    550:                               isWorkstation ? lpszLanW : lpszLanS,
                    551:                               0, 0, &lpBuffer) == 0)
                    552:        {
                    553:                pNetApiBufferSize (lpBuffer, &dwSize);
                    554:                RandaddBuf ((unsigned char *) lpBuffer, dwSize);
                    555:                pNetApiBufferFree (lpBuffer);
                    556:        }
                    557: 
                    558:        /* Get disk I/O statistics for all the hard drives */
                    559:        for (nDrive = 0;; nDrive++)
                    560:        {
                    561:                DISK_PERFORMANCE diskPerformance;
                    562:                char szDevice[24];
                    563: 
                    564:                /* Check whether we can access this device */
                    565:                sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive);
                    566:                hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
                    567:                                      NULL, OPEN_EXISTING, 0, NULL);
                    568:                if (hDevice == INVALID_HANDLE_VALUE)
                    569:                        break;
                    570: 
                    571: 
                    572:                /* Note: This only works if you have turned on the disk
                    573:                   performance counters with 'diskperf -y'.  These counters
                    574:                   are off by default */
                    575:                if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
                    576:                                &diskPerformance, sizeof (DISK_PERFORMANCE),
                    577:                                     &dwSize, NULL))
                    578:                {
                    579:                        RandaddBuf ((unsigned char *) &diskPerformance, dwSize);
                    580:                }
                    581:                CloseHandle (hDevice);
                    582:        }
                    583: 
1.1.1.4   root      584:        // CryptoAPI
1.1.1.6 ! root      585:        for (i = 0; i < 25; i++)
1.1.1.4   root      586:        {
1.1.1.6 ! root      587:                if (hCryptProv && CryptGenRandom(hCryptProv, sizeof (buffer), buffer)) 
1.1.1.4   root      588:                        RandaddBuf (buffer, sizeof (buffer));
1.1       root      589:        }
                    590: 
1.1.1.6 ! root      591:        Randmix();
1.1       root      592: }
                    593: 
                    594: 
1.1.1.6 ! root      595: /* This is the fastpoll function which gathers up info by calling various api's */
1.1       root      596: void
                    597: FastPoll (void)
                    598: {
                    599:        static BOOL addedFixedItems = FALSE;
                    600:        FILETIME creationTime, exitTime, kernelTime, userTime;
                    601:        DWORD minimumWorkingSetSize, maximumWorkingSetSize;
                    602:        LARGE_INTEGER performanceCount;
                    603:        MEMORYSTATUS memoryStatus;
                    604:        HANDLE handle;
                    605:        POINT point;
1.1.1.6 ! root      606:        int nOriginalRandIndex = nRandIndex;
1.1       root      607: 
                    608:        /* Get various basic pieces of system information */
1.1.1.6 ! root      609:        RandaddInt32 (GetActiveWindow ());      /* Handle of active window */
        !           610:        RandaddInt32 (GetCapture ());   /* Handle of window with mouse
1.1       root      611:                                           capture */
1.1.1.6 ! root      612:        RandaddInt32 (GetClipboardOwner ());    /* Handle of clipboard owner */
        !           613:        RandaddInt32 (GetClipboardViewer ());   /* Handle of start of
1.1       root      614:                                                   clpbd.viewer list */
1.1.1.6 ! root      615:        RandaddInt32 (GetCurrentProcess ());    /* Pseudohandle of current
1.1       root      616:                                                   process */
1.1.1.6 ! root      617:        RandaddInt32 (GetCurrentProcessId ());  /* Current process ID */
        !           618:        RandaddInt32 (GetCurrentThread ());     /* Pseudohandle of current
1.1       root      619:                                                   thread */
1.1.1.6 ! root      620:        RandaddInt32 (GetCurrentThreadId ());   /* Current thread ID */
        !           621:        RandaddInt32 (GetCurrentTime ());       /* Milliseconds since Windows
1.1       root      622:                                                   started */
1.1.1.6 ! root      623:        RandaddInt32 (GetDesktopWindow ());     /* Handle of desktop window */
        !           624:        RandaddInt32 (GetFocus ());     /* Handle of window with kb.focus */
        !           625:        RandaddInt32 (GetInputState ());        /* Whether sys.queue has any events */
        !           626:        RandaddInt32 (GetMessagePos ());        /* Cursor pos.for last message */
        !           627:        RandaddInt32 (GetMessageTime ());       /* 1 ms time for last message */
        !           628:        RandaddInt32 (GetOpenClipboardWindow ());       /* Handle of window with
1.1       root      629:                                                           clpbd.open */
1.1.1.6 ! root      630:        RandaddInt32 (GetProcessHeap ());       /* Handle of process heap */
        !           631:        RandaddInt32 (GetProcessWindowStation ());      /* Handle of procs
1.1       root      632:                                                           window station */
1.1.1.6 ! root      633:        RandaddInt32 (GetQueueStatus (QS_ALLEVENTS));   /* Types of events in
1.1       root      634:                                                           input queue */
                    635: 
                    636:        /* Get multiword system information */
                    637:        GetCaretPos (&point);   /* Current caret position */
                    638:        RandaddBuf ((unsigned char *) &point, sizeof (POINT));
                    639:        GetCursorPos (&point);  /* Current mouse cursor position */
                    640:        RandaddBuf ((unsigned char *) &point, sizeof (POINT));
                    641: 
                    642:        /* Get percent of memory in use, bytes of physical memory, bytes of
                    643:           free physical memory, bytes in paging file, free bytes in paging
                    644:           file, user bytes of address space, and free user bytes */
                    645:        memoryStatus.dwLength = sizeof (MEMORYSTATUS);
                    646:        GlobalMemoryStatus (&memoryStatus);
                    647:        RandaddBuf ((unsigned char *) &memoryStatus, sizeof (MEMORYSTATUS));
                    648: 
                    649:        /* Get thread and process creation time, exit time, time in kernel
                    650:           mode, and time in user mode in 100ns intervals */
                    651:        handle = GetCurrentThread ();
                    652:        GetThreadTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime);
                    653:        RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME));
                    654:        RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME));
                    655:        RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME));
                    656:        RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME));
                    657:        handle = GetCurrentProcess ();
                    658:        GetProcessTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime);
                    659:        RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME));
                    660:        RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME));
                    661:        RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME));
                    662:        RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME));
                    663: 
                    664:        /* Get the minimum and maximum working set size for the current
                    665:           process */
                    666:        GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
                    667:                                  &maximumWorkingSetSize);
1.1.1.6 ! root      668:        RandaddInt32 (minimumWorkingSetSize);
        !           669:        RandaddInt32 (maximumWorkingSetSize);
1.1       root      670: 
                    671:        /* The following are fixed for the lifetime of the process so we only
                    672:           add them once */
                    673:        if (addedFixedItems == 0)
                    674:        {
                    675:                STARTUPINFO startupInfo;
                    676: 
                    677:                /* Get name of desktop, console window title, new window
                    678:                   position and size, window flags, and handles for stdin,
                    679:                   stdout, and stderr */
                    680:                startupInfo.cb = sizeof (STARTUPINFO);
                    681:                GetStartupInfo (&startupInfo);
                    682:                RandaddBuf ((unsigned char *) &startupInfo, sizeof (STARTUPINFO));
                    683:                addedFixedItems = TRUE;
                    684:        }
                    685:        /* The docs say QPC can fail if appropriate hardware is not
                    686:           available. It works on 486 & Pentium boxes, but hasn't been tested
                    687:           for 386 or RISC boxes */
                    688:        if (QueryPerformanceCounter (&performanceCount))
                    689:                RandaddBuf ((unsigned char *) &performanceCount, sizeof (LARGE_INTEGER));
                    690:        else
                    691:        {
                    692:                /* Millisecond accuracy at best... */
                    693:                DWORD dwTicks = GetTickCount ();
                    694:                RandaddBuf ((unsigned char *) &dwTicks, sizeof (dwTicks));
                    695:        }
1.1.1.4   root      696: 
                    697:        // CryptoAPI
1.1.1.6 ! root      698:        if (hCryptProv && CryptGenRandom(hCryptProv, sizeof (buffer), buffer)) 
1.1.1.4   root      699:                RandaddBuf (buffer, sizeof (buffer));
1.1.1.6 ! root      700: 
        !           701:        /* Apply the pool mixing function */
        !           702:        Randmix();
        !           703: 
        !           704:        /* Restore the original pool cursor position. If this wasn't done, mouse coordinates
        !           705:           could be written to a limited area of the pool, especially when moving the mouse
        !           706:           uninterruptedly. The severity of the problem would depend on the length of data
        !           707:           written by FastPoll (if it was equal to the size of the pool, mouse coordinates
        !           708:           would be written only to a particular 4-byte area, whenever moving the mouse
        !           709:           uninterruptedly). */
        !           710:        nRandIndex = nOriginalRandIndex;
1.1       root      711: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.