📄 random.c
字号:
/* Copyright (C) 2004 TrueCrypt Team, truecrypt.org
This product uses components written by Paul Le Roux <pleroux@swprofessionals.com> */
#include "TCdefs.h"
#include <tlhelp32.h>
#include "crypto.h"
#include "crc.h"
#include "random.h"
#include "apidrvr.h"
#include "dlgcode.h"
/* random management defines & pool pointers */
#define POOLSIZE 256
#define RANDOMPOOL_ALLOCSIZE ( ( POOLSIZE + SHA_DIGESTSIZE - 1 ) \
/ SHA_DIGESTSIZE ) * SHA_DIGESTSIZE
unsigned char *pRandPool = NULL;
int nRandIndex = 0;
/* Macro to add a single byte to the pool */
#define RandaddByte(x) {\
if (nRandIndex==POOLSIZE) nRandIndex = 0;\
pRandPool[nRandIndex] = (unsigned char) ((unsigned char)x + pRandPool[nRandIndex]); \
nRandIndex++; \
Randmix(); \
}
/* Macro to add four bytes to the pool */
#define RandaddLong(x) _RandaddLong((unsigned long)x);
#pragma warning( disable : 4710 ) /* inline func. not expanded warning */
_inline void _RandaddLong(unsigned long x)
{
RandaddByte(x);
RandaddByte((x >> 8));
RandaddByte((x >> 16));
RandaddByte((x >> 24));
}
HHOOK hMouse = NULL; /* Mouse hook for the random number generator */
HHOOK hKeyboard = NULL; /* Keyboard hook for the random number
generator */
/* Variables for thread control, the thread is used to gather up info about
the system in in the background */
CRITICAL_SECTION critRandProt; /* The critical section */
BOOL volatile bThreadTerminate = FALSE; /* This variable is shared among
thread's so its made volatile */
BOOL bDidSlowPoll = FALSE; /* We do the slow poll only once */
/* Network library handle for the slowPollWinNT function */
HANDLE hNetAPI32 = NULL;
BOOL bRandDidInit = FALSE;
/* Init the random number generator, setup the hooks, and start the thread */
int
Randinit ()
{
HANDLE threadID;
if(bRandDidInit == TRUE) return 0;
InitializeCriticalSection (&critRandProt);
bRandDidInit = TRUE;
pRandPool = (unsigned char *) TCalloc (RANDOMPOOL_ALLOCSIZE);
if (pRandPool == NULL)
goto error;
else
memset (pRandPool, 0, RANDOMPOOL_ALLOCSIZE);
hMouse = SetWindowsHookEx (WH_MOUSE, (HOOKPROC)&MouseProc, NULL, GetCurrentThreadId ());
hKeyboard = SetWindowsHookEx (WH_KEYBOARD, (HOOKPROC)&KeyboardProc, NULL, GetCurrentThreadId ());
if (hMouse == 0 || hKeyboard == 0)
goto error;
threadID = (HANDLE) _beginthread (ThreadSafeThreadFunction, 8192, NULL);
if (threadID == (HANDLE) - 1)
goto error;
return 0;
error:
Randfree ();
return 1;
}
/* Close everything down, including the thread which is closed down by
setting a flag which eventually causes the thread function to exit */
void
Randfree ()
{
if (bRandDidInit == FALSE)
return;
EnterCriticalSection (&critRandProt);
if (hMouse != 0)
UnhookWindowsHookEx (hMouse);
if (hKeyboard != 0)
UnhookWindowsHookEx (hKeyboard);
bThreadTerminate = TRUE;
LeaveCriticalSection (&critRandProt);
for (;;)
{
Sleep (250);
EnterCriticalSection (&critRandProt);
if (bThreadTerminate == FALSE)
{
LeaveCriticalSection (&critRandProt);
break;
}
LeaveCriticalSection (&critRandProt);
}
if (pRandPool != NULL)
{
burn (pRandPool, RANDOMPOOL_ALLOCSIZE);
TCfree (pRandPool);
pRandPool = NULL;
}
if (hNetAPI32 != 0)
{
FreeLibrary (hNetAPI32);
hNetAPI32 = NULL;
}
hMouse = NULL;
hKeyboard = NULL;
nRandIndex = 0;
bThreadTerminate = FALSE;
DeleteCriticalSection (&critRandProt);
bRandDidInit = FALSE;
}
/* Mix random pool with the hash function */
void
Randmix ()
{
int i;
for (i = 0; i < POOLSIZE; i += SHA_DIGESTSIZE)
{
unsigned char inputBuffer[SHA_BLOCKSIZE];
int j;
/* Copy SHA_BLOCKSIZE bytes from the circular buffer into the
hash data buffer, hash the data, and copy the result back
into the random pool */
for (j = 0; j < SHA_BLOCKSIZE; j++)
inputBuffer[j] = pRandPool[(i + j) % POOLSIZE];
SHA1TRANSFORM ((unsigned long *) (pRandPool + i), inputBuffer);
memset (inputBuffer, 0, SHA_BLOCKSIZE);
}
}
/* Add a buffer to the pool */
void
RandaddBuf (void *buf, int len)
{
int i;
for (i = 0; i < len; i++)
{
RandaddByte (((unsigned char *) buf)[i]);
}
}
void
RandpeekBytes (char *buf, int len)
{
EnterCriticalSection (&critRandProt);
memcpy (buf, pRandPool, len);
LeaveCriticalSection (&critRandProt);
}
/* Get a certain amount of true random bytes from the pool */
void
RandgetBytes (char *buf, int len)
{
int i;
EnterCriticalSection (&critRandProt);
FastPoll ();
if (bDidSlowPoll == FALSE)
{
bDidSlowPoll = TRUE;
#ifndef _DEBUG
if (nCurrentOS == WIN_NT)
SlowPollWinNT ();
else
SlowPollWin9x ();
#endif
}
/* Then mix the pool */
Randmix ();
/* There's never more than POOLSIZE worth of randomess */
if (len > POOLSIZE)
len = POOLSIZE;
/* Extract out the random bytes needed */
memcpy (buf, pRandPool, len);
/* Now invert the pool */
for (i = 0; i < POOLSIZE / 4; i++)
{
((unsigned long *) pRandPool)[i] = ~((unsigned long *) pRandPool)[i];
}
/* Now remix the pool, creating the new pool */
Randmix ();
LeaveCriticalSection (&critRandProt);
}
/* Capture the mouse, and as long as the event is not the same as the last
two events :- add a crc of the event, and a crc of the time difference
between this event and the last + the current time to the pool */
LRESULT CALLBACK
MouseProc (int nCode, WPARAM wParam, LPARAM lParam)
{
static DWORD dwLastTimer;
static unsigned long lastCrc, lastCrc2;
MOUSEHOOKSTRUCT *lpMouse = (MOUSEHOOKSTRUCT *) lParam;
if (nCode < 0)
return CallNextHookEx (hMouse, nCode, wParam, lParam);
else
{
DWORD dwTimer = GetTickCount ();
DWORD j = dwLastTimer - dwTimer;
unsigned long crc = 0L;
int i;
dwLastTimer = dwTimer;
for (i = 0; i < sizeof (MOUSEHOOKSTRUCT); i++)
{
crc = UPDC32 (((unsigned char *) lpMouse)[i], crc);
}
if (crc != lastCrc && crc != lastCrc2)
{
unsigned long timeCrc = 0L;
for (i = 0; i < 4; i++)
{
timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc);
}
for (i = 0; i < 4; i++)
{
timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc);
}
EnterCriticalSection (&critRandProt);
RandaddLong (timeCrc);
RandaddLong (crc);
LeaveCriticalSection (&critRandProt);
}
lastCrc2 = lastCrc;
lastCrc = crc;
}
return 0;
}
/* Capture the keyboard, as long as the event is not the same as the last two
events :- add a crc of the event to the pool along with a crc of the time
difference between this event and the last */
LRESULT CALLBACK
KeyboardProc (int nCode, WPARAM wParam, LPARAM lParam)
{
static int lLastKey, lLastKey2;
static DWORD dwLastTimer;
int nKey = (lParam & 0x00ff0000) >> 16;
int nCapture = 0;
if (nCode < 0)
return CallNextHookEx (hMouse, nCode, wParam, lParam);
if ((lParam & 0x0000ffff) == 1 && !(lParam & 0x20000000) &&
(lParam & 0x80000000))
{
if (nKey != lLastKey)
nCapture = 1; /* Capture this key */
else if (nKey != lLastKey2)
nCapture = 1; /* Allow for one repeat */
}
if (nCapture)
{
DWORD dwTimer = GetTickCount ();
DWORD j = dwLastTimer - dwTimer;
unsigned long timeCrc = 0L;
int i;
dwLastTimer = dwTimer;
lLastKey2 = lLastKey;
lLastKey = nKey;
for (i = 0; i < 4; i++)
{
timeCrc = UPDC32 (((unsigned char *) &j)[i], timeCrc);
}
for (i = 0; i < 4; i++)
{
timeCrc = UPDC32 (((unsigned char *) &dwTimer)[i], timeCrc);
}
EnterCriticalSection (&critRandProt);
RandaddLong (lParam);
RandaddLong (timeCrc);
LeaveCriticalSection (&critRandProt);
}
return 0;
}
/* This is the thread function which will poll the system for randomness */
void
ThreadSafeThreadFunction (void *dummy)
{
if (dummy); /* Remove unused parameter warning */
for (;;)
{
EnterCriticalSection (&critRandProt);
if (bThreadTerminate == TRUE)
{
bThreadTerminate = FALSE;
LeaveCriticalSection (&critRandProt);
_endthread ();
}
else
{
FastPoll ();
}
LeaveCriticalSection (&critRandProt);
Sleep (250);
}
}
/* Type definitions for function pointers to call NetAPI32 functions */
typedef
DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService,
DWORD dwLevel, DWORD dwOptions,
LPBYTE * lpBuffer);
typedef
DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer);
typedef
DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer);
NETSTATISTICSGET pNetStatisticsGet = NULL;
NETAPIBUFFERSIZE pNetApiBufferSize = NULL;
NETAPIBUFFERFREE pNetApiBufferFree = NULL;
/* This is the slowpoll function which gathers up network/hard drive
performance data for the random pool */
void
SlowPollWinNT (void)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -