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

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

unix.superglobalmegacorp.com

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