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

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

unix.superglobalmegacorp.com

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