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

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

unix.superglobalmegacorp.com

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