/* This is the thread function which will poll the system for randomness */ static unsigned __stdcall PeriodicFastPollThreadProc (void *dummy) { UNREFERENCED_PARAMETER (dummy); /* Remove unused parameter warning */ for (;;) { EnterCriticalSection (&critRandProt); if (bThreadTerminate) { bThreadTerminate = FALSE; LeaveCriticalSection (&critRandProt); _endthreadex (0); } else if (bFastPollEnabled) { FastPoll (); } LeaveCriticalSection (&critRandProt); Sleep (FASTPOLL_INTERVAL); } }
/* Get len random bytes from the pool. * If allowAnyLength is FALSE, then len must be less or equal to RNG_POOL_SIZE * If allowAnyLength is TRUE, then len can have any positive value */ BOOL RandgetBytesFull ( void* hwndDlg, unsigned char *buf , int len, BOOL forceSlowPoll , BOOL allowAnyLength) { int i, looplen; BOOL ret = TRUE; if (!bRandDidInit || HashFunction == 0) TC_THROW_FATAL_EXCEPTION; EnterCriticalSection (&critRandProt); if (bDidSlowPoll == FALSE || forceSlowPoll) { if (!SlowPoll ()) { handleError ((HWND) hwndDlg, ERR_CAPI_INIT_FAILED, SRC_POS); ret = FALSE; } else bDidSlowPoll = TRUE; } if (!FastPoll ()) { handleError ((HWND) hwndDlg, ERR_CAPI_INIT_FAILED, SRC_POS); ret = FALSE; } /* There's never more than RNG_POOL_SIZE worth of randomess */ if ( (!allowAnyLength) && (len > RNG_POOL_SIZE)) { Error ("ERR_NOT_ENOUGH_RANDOM_DATA", (HWND) hwndDlg); len = RNG_POOL_SIZE; LeaveCriticalSection (&critRandProt); return FALSE; } while (len > 0) { if (len > RNG_POOL_SIZE) { looplen = RNG_POOL_SIZE; len -= RNG_POOL_SIZE; } else { looplen = len; len = 0; } // this loop number of bytes is copied from pool to output buffer, // pool is rehashed, and output buffer is XORed with new data from pool for (i = 0; i < looplen; i++) { buf[i] = pRandPool[randPoolReadIndex++]; if (randPoolReadIndex == RNG_POOL_SIZE) randPoolReadIndex = 0; } /* Invert the pool */ for (i = 0; i < RNG_POOL_SIZE / 4; i++) { ((unsigned __int32 *) pRandPool)[i] = ~((unsigned __int32 *) pRandPool)[i]; } // Mix the pool if (!FastPoll ()) ret = FALSE; // XOR the current pool content into the output buffer to prevent pool state leaks for (i = 0; i < looplen; i++) { buf[i] ^= pRandPool[randPoolReadIndex++]; if (randPoolReadIndex == RNG_POOL_SIZE) randPoolReadIndex = 0; } // increment the pointer for the next loop buf += looplen; } LeaveCriticalSection (&critRandProt); if (!ret) TC_THROW_FATAL_EXCEPTION; return ret; }
/* Get len random bytes from the pool (max. RNG_POOL_SIZE bytes per a single call) */ BOOL RandgetBytes (unsigned char *buf, int len, BOOL forceSlowPoll) { int i; BOOL ret = TRUE; if (!bRandDidInit || HashFunction == 0) TC_THROW_FATAL_EXCEPTION; EnterCriticalSection (&critRandProt); if (bDidSlowPoll == FALSE || forceSlowPoll) { if (!SlowPoll ()) ret = FALSE; else bDidSlowPoll = TRUE; } if (!FastPoll ()) ret = FALSE; /* There's never more than RNG_POOL_SIZE worth of randomess */ if (len > RNG_POOL_SIZE) { Error ("ERR_NOT_ENOUGH_RANDOM_DATA"); len = RNG_POOL_SIZE; return FALSE; } // Requested number of bytes is copied from pool to output buffer, // pool is rehashed, and output buffer is XORed with new data from pool for (i = 0; i < len; i++) { buf[i] = pRandPool[randPoolReadIndex++]; if (randPoolReadIndex == RNG_POOL_SIZE) randPoolReadIndex = 0; } /* Invert the pool */ for (i = 0; i < RNG_POOL_SIZE / 4; i++) { ((unsigned __int32 *) pRandPool)[i] = ~((unsigned __int32 *) pRandPool)[i]; } // Mix the pool if (!FastPoll ()) ret = FALSE; // XOR the current pool content into the output buffer to prevent pool state leaks for (i = 0; i < len; i++) { buf[i] ^= pRandPool[randPoolReadIndex++]; if (randPoolReadIndex == RNG_POOL_SIZE) randPoolReadIndex = 0; } LeaveCriticalSection (&critRandProt); if (!ret) TC_THROW_FATAL_EXCEPTION; return ret; }