📄 random.c
字号:
/* The source code contained in this file has been derived from the source code
of Encryption for the Masses 2.02a by Paul Le Roux. Modifications and
additions to that source code contained in this file are Copyright (c) 2004-2005
TrueCrypt Foundation and Copyright (c) 2004 TrueCrypt Team. Unmodified
parts are Copyright (c) 1998-99 Paul Le Roux. This is a TrueCrypt Foundation
release. Please see the file license.txt for full license details. */
#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, randPoolReadIndex = 0;
int hashFunction = SHA1;
/* 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;
// CryptoAPI
HCRYPTPROV hCryptProv;
unsigned __int8 buffer[POOLSIZE];
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);
VirtualLock (pRandPool, RANDOMPOOL_ALLOCSIZE);
hKeyboard = SetWindowsHookEx (WH_KEYBOARD, (HOOKPROC)&KeyboardProc, NULL, GetCurrentThreadId ());
if (hKeyboard == 0) handleWin32Error (0);
hMouse = SetWindowsHookEx (WH_MOUSE, (HOOKPROC)&MouseProc, NULL, GetCurrentThreadId ());
if (hMouse == 0)
{
handleWin32Error (0);
goto error;
}
if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)
&& !CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
hCryptProv = 0;
}
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;
}
if (hCryptProv)
{
CryptReleaseContext (hCryptProv, 0);
hCryptProv = 0;
}
hMouse = NULL;
hKeyboard = NULL;
nRandIndex = 0;
bThreadTerminate = FALSE;
DeleteCriticalSection (&critRandProt);
bRandDidInit = FALSE;
}
void RandSetHashFunction (int hash)
{
hashFunction = hash;
}
/* 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];
if (hashFunction == SHA1)
SHA1TRANSFORM ((unsigned long *) (pRandPool + i), inputBuffer);
else
RMD160Transform ((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 (unsigned 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 (unsigned char *buf, int len, BOOL forceSlowPoll)
{
int i;
EnterCriticalSection (&critRandProt);
if (bDidSlowPoll == FALSE || forceSlowPoll)
{
bDidSlowPoll = TRUE;
SlowPollWinNT ();
}
FastPoll ();
/* There's never more than POOLSIZE worth of randomess */
if (len > POOLSIZE)
len = POOLSIZE;
// 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 == POOLSIZE) randPoolReadIndex = 0;
}
/* 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 */
FastPoll ();
for (i = 0; i < len; i++)
{
buf[i] ^= pRandPool[randPoolReadIndex++];
if (randPoolReadIndex == POOLSIZE) randPoolReadIndex = 0;
}
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 ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -