⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win32.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*						  Win32 Randomness-Gathering Code					*
*	Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-2007	*
*																			*
****************************************************************************/

/* This module is part of the cryptlib continuously seeded pseudorandom number
   generator.  For usage conditions, see random.c */

/* General includes */

#include "crypt.h"
#include "random/random.h"

/* 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.  BC++ can only handle the
   emit directive outside an asm block, so we have to terminate the current
   block, emit the opcode, and then restart the asm block.  In addition
   while the 16-bit versions of BC++ had built-in asm support, the 32-bit
   versions removed it and generate a temporary asm file which is passed
   to Tasm32.  This is only included with some high-end versions of BC++,
   and it's not possible to order it separately, so if you're building with
   BC++ and get error messages about a missing tasm32.exe, add NO_ASM to
   Project Options | Compiler | Defines */

#if defined( _MSC_VER )
  #if _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
#endif /* VC++ */
#if defined __BORLANDC__
  #define cpuid			} __emit__( 0x0F, 0xA2 ); __asm {
  #define rdtsc			} __emit__( 0x0F, 0x31 ); __asm {
  #define xstore_rng	} __emit__( 0x0F, 0xA7, 0xC0 ); __asm {
#endif /* BC++ */

/* Map a value that may be 32 or 64 bits depending on the platform to a 
   long */

#if defined( _MSC_VER ) && ( _MSC_VER >= 1400 )
  #define addRandomHandle( randomState, handle ) \
		  addRandomLong( randomState, PtrToUlong( handle ) )
#else
  #define addRandomHandle	addRandomValue
#endif /* 32- vs. 64-bit VC++ */

/* The size of the intermediate buffer used to accumulate polled data */

#define RANDOM_BUFSIZE	4096
#if RANDOM_BUFSIZE > MAX_INTLENGTH_SHORT
  #error RANDOM_BUFSIZE exceeds randomness accumulator size
#endif /* RANDOM_BUFSIZE > MAX_INTLENGTH_SHORT */

/* 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 */

/****************************************************************************
*																			*
*							System RNG Interface							*
*																			*
****************************************************************************/

/* The number of bytes to read from the system RNG on each slow poll */

#define SYSTEMRNG_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 );

/* Somewhat alternative functionality available as a direct call, for 
   Windows XP and newer.  This is the CryptoAPI RNG, which isn't anywhere
   near as good as the HW RNG, but we use it if it's present on the basis
   that at least it can't make things any worse.  This direct access version 
   is only available under Windows XP and newer, we don't go out of our way 
   to access the more general CryptoAPI one since the main purpose of using 
   it is to take advantage of any possible future hardware RNGs that may be 
   added, for example via TCPA devices */

typedef BOOL ( WINAPI *RTLGENRANDOM )( PVOID RandomBuffer, 
									   ULONG RandomBufferLength );

/* 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;
static RTLGENRANDOM pRtlGenRandom = NULL;

/* Handle to the RNG CSP */

static BOOLEAN systemRngAvailable;	/* Whether system RNG is available */
static HCRYPTPROV hProv;			/* Handle to Intel RNG CSP */

/* Try and connect to the system RNG if there's one present */

static void initSystemRNG( void )
	{
	systemRngAvailable = FALSE;
	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" );

	/* Get a pointer to the native randomness function if it's available.  
	   This isn't exported by name, so we have to get it by ordinal */
	pRtlGenRandom = ( RTLGENRANDOM ) GetProcAddress( hAdvAPI32,
													"SystemFunction036" );

	/* 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.  OTOH the Intel RNG is also effectively dead 
	   as well, mostly due to virtually nonexistant support/marketing by 
	   Intel, it's included here mostly for form's sake */
	if( ( pCryptAcquireContext == NULL || \
		  pCryptGenRandom == NULL || pCryptReleaseContext == NULL || \
		  pCryptAcquireContext( &hProv, NULL, INTEL_DEF_PROV,
								PROV_INTEL_SEC, 0 ) == FALSE ) && \
		( pRtlGenRandom == NULL ) )
		{
		hAdvAPI32 = NULL;
		hProv = NULL;
		}
	else
		{
		/* Remember that we have a system RNG available for use */
		systemRngAvailable = TRUE;
		}
	}

/* Read data from the system RNG, in theory the PIII hardware RNG but in
   practice more likely the CryptoAPI software RNG */

static void readSystemRNG( void )
	{
	BYTE buffer[ SYSTEMRNG_BYTES + 8 ];
	int quality = 0;

	if( !systemRngAvailable )
		return;

	/* Read SYSTEMRNG_BYTES bytes from the system RNG.  Rather presciently, 
	   the code up until late 2007 stated that "We don't rely on this for 
	   all our randomness requirements (particularly the software RNG) in 
	   case it's broken in some way", and in November 2007 an analysis paper
	   by Leo Dorrendorf, Zvi Gutterman, and Benny Pinkas showed that the
	   CryptoAPI RNG is indeed broken, being neither forwards- nor 
	   backwards-secure, being reseeded far too infrequently, and (as far as
	   their reverse-engineering was able to tell) using far less entropy
	   sources than cryptlib's built-in mechanisms even though the CryptoAPI
	   one is deeply embedded in the OS.

	   The way the CryptoAPI RNG works is that a system RNG is used to key 
	   a set of eight RC4 ciphers, each of which is used in turn in a round-
	   robin fashion to output 20 bytes of randomness which are then hashed 
	   with SHA1, with the operation being approximately:

		output[  0...19 ] = SHA1( RC4[ i++ % 8 ] );
		output[ 20...39 ] = SHA1( RC4[ i++ % 8 ] );
		[...]

	   Each RC4 cipher is re-keyed every 16KB of output, so for 8 ciphers
	   the rekey interval is every 128KB of output.  Furthermore, although
	   the kernel RNG used to key the RC4 ciphers stores its state in-
	   kernel, the RC4 cipher state is stored in user-space and per-process.
	   This means that in most cases the RNG is never re-keyed.  Finally,
	   the way the RNG works means that it's possible to recover earlier
	   state in O( 2^23 ).  See "Cryptanalysis of the Random Number 
	   Generator of the Windows Operating System" for details */
	if( hProv != NULL )
		{
		if( pCryptGenRandom( hProv, SYSTEMRNG_BYTES, buffer ) )
			quality = 70;
		}
	else
		{
		if( pRtlGenRandom( buffer, SYSTEMRNG_BYTES ) )
			quality = 30;
		}
	if( quality > 0 )
		{
		MESSAGE_DATA msgData;
		int status;

		setMessageData( &msgData, buffer, SYSTEMRNG_BYTES );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  IMESSAGE_SETATTRIBUTE_S, &msgData, 
								  CRYPT_IATTRIBUTE_ENTROPY );
		if( cryptStatusOK( status ) )
			{
			( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
									  IMESSAGE_SETATTRIBUTE,
									  ( void * ) &quality,
									  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );
			}
		zeroise( buffer, SYSTEMRNG_BYTES );
		}
	}

/* Clean up the system RNG access */

static void endSystemRNG( void )
	{
	if( hProv != NULL )
		{
		pCryptReleaseContext( hProv, 0 );
		hProv = NULL;
		}
	}

/****************************************************************************
*																			*
*							Hardware Monitoring Interface					*
*																			*
****************************************************************************/

/* These interfaces currently support data supplied by MBM, Everest, 
   SysTool, RivaTuner, HMonitor, and ATI Tray Tools.  Two notable omissions
   are SVPro and HWMonitor, unfortunately the authors haven't responded to 
   any requests for interfacing information */

/* MBM data structures, originally by Alexander van Kaam, converted to C by
   Anders@Majland.org, finally updated by Chris Zahrt <techn0@iastate.edu>.
   The __int64 values below are actually (64-bit) doubles, but we overlay 
   them with __int64s since we don't care about the values */

#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 */
	__int64 /*double*/ ssCurrent;/* Current value */
	__int64 /*double*/ ssLow;	/* Lowest readout */
	__int64 /*double*/ ssHigh;	/* Highest readout */
	long ssCount;				/* Total number of readout */
	char sspadding2[ 4 ];		/* Padding of 4 bytes */
	BYTE /*long double*/ ssTotal[ 8 ];	/* Total amout of all readouts */
	char sspadding3[ 6 ];		/* Padding of 6 bytes */
	__int64 /*double*/ ssAlarm1;/* Temp & fan: high alarm; voltage: % off */
	__int64 /*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 {
	__int64 /*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 via the shared-memory interface */

static void readMBMData( void )
	{
	HANDLE hMBMData;
	const SharedData *mbmDataPtr;

	if( ( hMBMData = OpenFileMapping( FILE_MAP_READ, FALSE,
									  "$M$B$M$5$S$D$" ) ) == NULL )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -