📄 rndwin32.c
字号:
/****************************************************************************
* *
* Win32 Randomness-Gathering Code *
* Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-2003 *
* *
****************************************************************************/
/* This module is part of the cryptlib continuously seeded pseudorandom number
generator. For usage conditions, see dev_sys.c.
From the "Peter giveth and Microsoft taketh away" department: The default
NT setup has Everyone:Read permissions for the
\\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\PerfLib
key, which is the key for the performance counters. This means that
everyone on the network can read your machine's performance counters,
significantly reducing their usefulness (although since they only contain
a snapshot, network users should never see exactly what you're seeing).
If you're worried about the native API call that's normally used failing
(which falls back to using the registry performance counters), delete the
Everyone:Read ACL and replace it with Interactive:Read, which only allows
access to locally logged on users. This means that an attacker will have
to go to the effort of planting a trojan to get your crypto keys rather
than getting them over the net.
"Windows NT is a thing of genuine beauty, if you're seriously into genuine
ugliness. It's like a woman with a history of insanity in the family,
only worse" -- Hans Chloride, "Why I Love Windows NT" */
/* General includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef INC_CHILD
#include "../crypt.h"
#else
#include "crypt.h"
#endif /* Compiler-specific includes */
/* OS-specific includes */
#include <tlhelp32.h>
#include <winperf.h>
#include <winioctl.h>
#include <process.h>
/* Some new CPU opcodes aren't supported by all compiler versions, if
they're not available we define them here */
#if defined( _MSC_VER ) && ( _MSC_VER <= 1100 )
#define cpuid __asm _emit 0x0F __asm _emit 0xA2
#define rdtsc __asm _emit 0x0F __asm _emit 0x31
#endif /* VC++ 5.0 or earlier */
#define xstore_rng __asm _emit 0x0F __asm _emit 0xA7 __asm _emit 0xC0
/* The size of the intermediate buffer used to accumulate polled data */
#define RANDOM_BUFSIZE 4096
/* When we're running a background poll, the main thread can ask it to
terminate if cryptlib is shutting down. The following macro checks
whether the background thread should exit prematurely */
#define checkPollExit() \
{ \
BOOLEAN exitFlag; \
\
enterMutex( MUTEX_RANDOMPOLLING ); \
exitFlag = exitNow; \
exitMutex( MUTEX_RANDOMPOLLING ); \
if( exitFlag ) \
return; \
}
/* A flag telling the randomness polling thread to exit. This is set on
shutdown to indicate that it should bail out as quickly as possible so as
not to hold up the shutdown */
static BOOLEAN exitNow;
/* Handles to various randomness objects */
static HANDLE hAdvAPI32; /* Handle to misc.library */
static HANDLE hNetAPI32; /* Handle to networking library */
static HANDLE hNTAPI; /* Handle to NT kernel library */
static HANDLE hThread; /* Background polling thread handle */
static DWORD threadID; /* Background polling thread ID */
/****************************************************************************
* *
* Misc Randomness Sources *
* *
****************************************************************************/
/* The number of bytes to read from the PIII RNG on each slow poll */
#define PIIIRNG_BYTES 64
/* Intel Chipset CSP type and name */
#define PROV_INTEL_SEC 22
#define INTEL_DEF_PROV "Intel Hardware Cryptographic Service Provider"
/* A mapping from CryptoAPI to standard data types */
#define HCRYPTPROV HANDLE
/* Type definitions for function pointers to call CryptoAPI functions */
typedef BOOL ( WINAPI *CRYPTACQUIRECONTEXT )( HCRYPTPROV *phProv,
LPCTSTR pszContainer,
LPCTSTR pszProvider, DWORD dwProvType,
DWORD dwFlags );
typedef BOOL ( WINAPI *CRYPTGENRANDOM )( HCRYPTPROV hProv, DWORD dwLen,
BYTE *pbBuffer );
typedef BOOL ( WINAPI *CRYPTRELEASECONTEXT )( HCRYPTPROV hProv, DWORD dwFlags );
/* Global function pointers. These are necessary because the functions need
to be dynamically linked since older versions of Win95 and NT don't contain
them */
static CRYPTACQUIRECONTEXT pCryptAcquireContext = NULL;
static CRYPTGENRANDOM pCryptGenRandom = NULL;
static CRYPTRELEASECONTEXT pCryptReleaseContext = NULL;
/* Handle to the RNG CSP */
static HCRYPTPROV hProv; /* Handle to Intel RNG CSP */
/* Try and connect to the PIII RNG CSP. The AMD 768 southbridge (from the
760 MP chipset) also has a hardware RNG, but there doesn't appear to be
any driver support for this as there is for the Intel RNG so we can't do
much with it */
static void initPIIIRng( void )
{
hProv = NULL;
if( ( hAdvAPI32 = GetModuleHandle( "AdvAPI32.dll" ) ) == NULL )
return;
/* Get pointers to the CSP functions. Although the acquire context
function looks like a standard function, it's actually a macro which
is mapped to (depending on the build type) CryptAcquireContextA or
CryptAcquireContextW, so we access it under the straight-ASCII-
function name */
pCryptAcquireContext = ( CRYPTACQUIRECONTEXT ) GetProcAddress( hAdvAPI32,
"CryptAcquireContextA" );
pCryptGenRandom = ( CRYPTGENRANDOM ) GetProcAddress( hAdvAPI32,
"CryptGenRandom" );
pCryptReleaseContext = ( CRYPTRELEASECONTEXT ) GetProcAddress( hAdvAPI32,
"CryptReleaseContext" );
/* Make sure we got valid pointers for every CryptoAPI function and that
the required CSP is present */
if( pCryptAcquireContext == NULL || \
pCryptGenRandom == NULL || pCryptReleaseContext == NULL || \
pCryptAcquireContext( &hProv, NULL, INTEL_DEF_PROV,
PROV_INTEL_SEC, 0 ) == FALSE )
{
hAdvAPI32 = NULL;
hProv = NULL;
}
}
/* Read data from the PIII hardware RNG */
static void readPIIIRng( void )
{
BYTE buffer[ PIIIRNG_BYTES ];
if( hProv == NULL )
return;
/* Read 128 bytes from the PIII RNG. We don't rely on this for all our
randomness requirements in case it's broken in some way */
if( pCryptGenRandom( hProv, PIIIRNG_BYTES, buffer ) )
{
RESOURCE_DATA msgData;
static const int quality = 90;
setMessageData( &msgData, buffer, PIIIRNG_BYTES );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_ENTROPY );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,
( void * ) &quality,
CRYPT_IATTRIBUTE_ENTROPY_QUALITY );
zeroise( buffer, PIIIRNG_BYTES );
}
}
/* MBM data structures, originally by Alexander van Kaam, converted to C by
Anders@Majland.org, finally updated by Chris Zahrt <techn0@iastate.edu> */
#define BusType char
#define SMBType char
#define SensorType char
typedef struct {
SensorType iType; /* Type of sensor */
int Count; /* Number of sensor for that type */
} SharedIndex;
typedef struct {
SensorType ssType; /* Type of sensor */
unsigned char ssName[ 12 ]; /* Name of sensor */
char sspadding1[ 3 ]; /* Padding of 3 bytes */
double ssCurrent; /* Current value */
double ssLow; /* Lowest readout */
double ssHigh; /* Highest readout */
long ssCount; /* Total number of readout */
char sspadding2[ 4 ]; /* Padding of 4 bytes */
long double ssTotal; /* Total amout of all readouts */
char sspadding3[ 6 ]; /* Padding of 6 bytes */
double ssAlarm1; /* Temp & fan: high alarm; voltage: % off */
double ssAlarm2; /* Temp: low alarm */
} SharedSensor;
typedef struct {
short siSMB_Base; /* SMBus base address */
BusType siSMB_Type; /* SMBus/Isa bus used to access chip */
SMBType siSMB_Code; /* SMBus sub type, Intel, AMD or ALi */
char siSMB_Addr; /* Address of sensor chip on SMBus */
unsigned char siSMB_Name[ 41 ]; /* Nice name for SMBus */
short siISA_Base; /* ISA base address of sensor chip on ISA */
int siChipType; /* Chip nr, connects with Chipinfo.ini */
char siVoltageSubType; /* Subvoltage option selected */
} SharedInfo;
typedef struct {
double sdVersion; /* Version number (example: 51090) */
SharedIndex sdIndex[ 10 ]; /* Sensor index */
SharedSensor sdSensor[ 100 ]; /* Sensor info */
SharedInfo sdInfo; /* Misc.info */
unsigned char sdStart[ 41 ]; /* Start time */
/* We don't use the next two fields both because they're not random and
because it provides a nice safety margin in case of data size mis-
estimates (we always under-estimate the buffer size) */
/* unsigned char sdCurrent[ 41 ]; /* Current time */
/* unsigned char sdPath[ 256 ]; /* MBM path */
} SharedData;
/* Read data from MBM. This communicates via shared memory, so all we need
to do is map a file and read the data out */
static void readMBMData( void )
{
HANDLE hMBMData;
SharedData *mbmDataPtr;
if( ( hMBMData = OpenFileMapping( FILE_MAP_READ, FALSE,
"$M$B$M$5$S$D$" ) ) != NULL )
{
if( ( mbmDataPtr = ( SharedData * ) \
MapViewOfFile( hMBMData, FILE_MAP_READ, 0, 0, 0 ) ) != NULL )
{
RESOURCE_DATA msgData;
static const int quality = 20;
setMessageData( &msgData, mbmDataPtr, sizeof( SharedData ) );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_ENTROPY );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,
( void * ) &quality,
CRYPT_IATTRIBUTE_ENTROPY_QUALITY );
UnmapViewOfFile( mbmDataPtr );
}
CloseHandle( hMBMData );
}
}
/****************************************************************************
* *
* Fast Poll *
* *
****************************************************************************/
/* The shared Win32 fast poll routine */
void fastPoll( void )
{
static BOOLEAN addedFixedItems = FALSE;
static BOOLEAN hasAdvFeatures = FALSE, hasHardwareRNG = FALSE;
FILETIME creationTime, exitTime, kernelTime, userTime;
DWORD minimumWorkingSetSize, maximumWorkingSetSize;
LARGE_INTEGER performanceCount;
MEMORYSTATUS memoryStatus;
HANDLE handle;
POINT point;
RANDOM_STATE randomState;
BYTE buffer[ RANDOM_BUFSIZE ];
int bufIndex = 0;
checkPollExit();
initRandomData( randomState, buffer, RANDOM_BUFSIZE );
/* Get various basic pieces of system information: Handle of active
window, handle of window with mouse capture, handle of clipboard owner
handle of start of clpboard viewer list, pseudohandle of current
process, current process ID, pseudohandle of current thread, current
thread ID, handle of desktop window, handle of window with keyboard
focus, whether system queue has any events, cursor position for last
message, 1 ms time for last message, handle of window with clipboard
open, handle of process heap, handle of procs window station, types of
events in input queue, and milliseconds since Windows was started */
addRandomValue( randomState, GetActiveWindow() );
addRandomValue( randomState, GetCapture() );
addRandomValue( randomState, GetClipboardOwner() );
addRandomValue( randomState, GetClipboardViewer() );
addRandomValue( randomState, GetCurrentProcess() );
addRandomValue( randomState, GetCurrentProcessId() );
addRandomValue( randomState, GetCurrentThread() );
addRandomValue( randomState, GetCurrentThreadId() );
addRandomValue( randomState, GetDesktopWindow() );
addRandomValue( randomState, GetFocus() );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -