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

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

unix.superglobalmegacorp.com

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