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

📄 rndwin32.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*						  Win32 Randomness-Gathering Code					*
*	Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-2001	*
*																			*
****************************************************************************/

/* 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 contain a
   snapshot only, network users will never see exactly what you're seeing). To
   fix this problem, delete the Everyone:Read ACL and replace it with
   Interactive:Read, which only allows access to locally logged on users. This
   means 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>

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

#define RANDOM_BUFSIZE	4096

/* The number of bytes to read from the PIII RNG and serial-port RNG on each
   slow poll */

#define PIIIRNG_BYTES		64
#define SERIALRNG_BYTES		64

/* A mapping from CryptoAPI to standard data types */

#define HCRYPTPROV			HANDLE

/* 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 HANDLE hComm;		/* Handle to serial RNG */
static HCRYPTPROV hProv;	/* Handle to Intel RNG CSP */

/* Intel Chipset CSP type and name */

#define PROV_INTEL_SEC	22
#define INTEL_DEF_PROV	"Intel Hardware Cryptographic Service Provider"

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

/* Initialise a serial-based RNG if there's one present */

static int initSerialRNG( void )
	{
	RESOURCE_DATA msgData;
	COMMPROP commProp;
	DWORD bytesRead;
	DCB dcb;
	char serialPortString[ CRYPT_MAX_TEXTSIZE + 1 ];
	char serialParamString[ CRYPT_MAX_TEXTSIZE + 1 ];
	char buffer[ 10 ];
	int status;

	/* Get the serial-port RNG parameters if there's one being used.  Since
	   this is a general systemwide config option, we always query the built-
	   in default user object */
	setResourceData( &msgData, serialPortString, CRYPT_MAX_TEXTSIZE );
	status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
							  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_OPTION_DEVICE_SERIALRNG );
	if( cryptStatusOK( status ) )
		{
		serialPortString[ msgData.length ] = '\0';
		setResourceData( &msgData, serialParamString, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
								  CRYPT_OPTION_DEVICE_SERIALRNG_PARAMS );
		serialParamString[ msgData.length ] = '\0';
		}
	if( cryptStatusError( status ) )
		return( CRYPT_ERROR );

	/* Open the serial port device and set the port parameters.  We need to
	   call GetCommState() before we call BuildCommDCB() because
	   BuildCommDCB() doesn't touch the DCB fields not affected by the config
	   string, so that they're left with garbage values which causes
	   SetCommState() to fail */
	hComm = CreateFile( serialPortString, GENERIC_READ, 0, NULL,
						OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
	if( hComm == ( HANDLE ) -1 )
		{
		hComm = NULL;
		return( CRYPT_ERROR ) ;
		}
	GetCommState( hComm, &dcb );
	BuildCommDCB( serialParamString, &dcb );
	dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
	if( !SetCommState( hComm, &dcb ) )
		{
		CloseHandle( hComm );
		hComm = NULL;
		return( CRYPT_ERROR );
		}

	/* Set the timeout to return immediately in case there's nothing
	   plugged in */
	commProp.wPacketLength = sizeof( COMMPROP );
	GetCommProperties( hComm, &commProp );
	if( commProp.dwProvCapabilities & PCF_INTTIMEOUTS )
		{
		COMMTIMEOUTS timeouts;

		/* Wait 10ms between chars and per char (which will work even with
		   a 1200bps generator), and 100ms overall (we need to make this
		   fairly short since we don't want to have a long delay every
		   time the library is started up if the RNG is unplugged) */
		GetCommTimeouts( hComm, &timeouts );
		timeouts.ReadIntervalTimeout = 10;
		timeouts.ReadTotalTimeoutMultiplier = 10;
		timeouts.ReadTotalTimeoutConstant = 100;
		SetCommTimeouts( hComm, &timeouts );
		}

	/* The RNG can take awhile to get started so we wait 1/4s before trying
	   to read anything */
	PurgeComm( hComm, PURGE_RXABORT | PURGE_RXCLEAR );
	Sleep( 250 );

	/* Try and read a few bytes to make sure there's something there */
	PurgeComm( hComm, PURGE_RXABORT | PURGE_RXCLEAR );
	if( !ReadFile( hComm, buffer, 10, &bytesRead, NULL ) || bytesRead != 10 )
		{
		CloseHandle( hComm );
		hComm = NULL;
		return( CRYPT_ERROR );
		}

	return( CRYPT_OK );
	}

/* The shared Win32 fast poll routine */

void fastPoll( void )
	{
	static BOOLEAN addedFixedItems = FALSE;
	BYTE buffer[ RANDOM_BUFSIZE ];
	FILETIME  creationTime, exitTime, kernelTime, userTime;
	DWORD minimumWorkingSetSize, maximumWorkingSetSize;
	LARGE_INTEGER performanceCount;
	MEMORYSTATUS memoryStatus;
	HANDLE handle;
	POINT point;
	int quality = 34, bufIndex = 0;	/* Quality = int( 33 1/3 % ) */

	/* 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 */
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetActiveWindow() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetCapture() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetClipboardOwner() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetClipboardViewer() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetCurrentProcess() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetCurrentProcessId() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetCurrentThread() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetCurrentThreadId() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetDesktopWindow() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetFocus() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetInputState() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetMessagePos() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetMessageTime() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetOpenClipboardWindow() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetProcessHeap() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetProcessWindowStation() );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetTickCount() );

	/* Calling the following function can cause problems in some cases in
	   that a calling application eventually stops getting events from its
	   event loop, so we can't (safely) use it as an entropy source */
/*	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE,
			   GetQueueStatus( QS_ALLEVENTS ) ); */

	/* Get multiword system information: Current caret position, current
	   mouse cursor position */
	GetCaretPos( &point );
	addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, &point,
					 sizeof( POINT ) );
	GetCursorPos( &point );
	addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, &point,
					 sizeof( POINT ) );

	/* Get percent of memory in use, bytes of physical memory, bytes of free
	   physical memory, bytes in paging file, free bytes in paging file, user
	   bytes of address space, and free user bytes */
	memoryStatus.dwLength = sizeof( MEMORYSTATUS );
	GlobalMemoryStatus( &memoryStatus );
	addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, &memoryStatus,
					 sizeof( MEMORYSTATUS ) );

	/* Get thread and process creation time, exit time, time in kernel mode,
	   and time in user mode in 100ns intervals */
	handle = GetCurrentThread();
	GetThreadTimes( handle, &creationTime, &exitTime, &kernelTime, &userTime );
	addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE,
					 &creationTime, sizeof( FILETIME ) );
	addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE,
					 &exitTime, sizeof( FILETIME ) );
	addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE,
					 &kernelTime, sizeof( FILETIME ) );
	addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE,
					 &userTime, sizeof( FILETIME ) );
	handle = GetCurrentProcess();
	GetProcessTimes( handle, &creationTime, &exitTime, &kernelTime, &userTime );
	addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE,
					 &creationTime, sizeof( FILETIME ) );
	addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE,
					 &exitTime, sizeof( FILETIME ) );
	addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE,
					 &kernelTime, sizeof( FILETIME ) );
	addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE,
					 &userTime, sizeof( FILETIME ) );

	/* Get the minimum and maximum working set size for the current process */
	GetProcessWorkingSetSize( handle, &minimumWorkingSetSize,
							  &maximumWorkingSetSize );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, minimumWorkingSetSize );
	addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, maximumWorkingSetSize );

	/* The following are fixed for the lifetime of the process so we only
	   add them once */
	if( !addedFixedItems )
		{
		STARTUPINFO startupInfo;

		/* Get name of desktop, console window title, new window position and
		   size, window flags, and handles for stdin, stdout, and stderr */
		startupInfo.cb = sizeof( STARTUPINFO );
		GetStartupInfo( &startupInfo );
		addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, &startupInfo,
						 sizeof( STARTUPINFO ) );
		addedFixedItems = TRUE;
		}

	/* The performance of QPC varies depending on the architecture it's
	   running on and on the OS.  Under NT it reads the CPU's 64-bit timstamp
	   counter (at least on a Pentium and newer '486's, it hasn't been tested
	   on anything without a TSC), under Win95 it reads the 1.193180 MHz PIC
	   timer.  There are vague mumblings in the docs that it may fail if the
	   appropriate hardware isn't available (possibly '386's or MIPS machines
	   running NT), but who's going to run NT on a '386? */
	if( QueryPerformanceCounter( &performanceCount ) )
		addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE,
						 &performanceCount, sizeof( LARGE_INTEGER ) );
	else
		/* Millisecond accuracy at best... */
		addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, GetTickCount() );

	/* Flush any remaining data through */
	addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, NULL, 0 );
	krnlSendMessage( SYSTEM_OBJECT_HANDLE, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 &quality, CRYPT_IATTRIBUTE_RANDOM_QUALITY );
	}

/* Type definitions for function pointers to call Toolhelp32 functions */

typedef BOOL ( WINAPI *MODULEWALK )( HANDLE hSnapshot, LPMODULEENTRY32 lpme );
typedef BOOL ( WINAPI *THREADWALK )( HANDLE hSnapshot, LPTHREADENTRY32 lpte );
typedef BOOL ( WINAPI *PROCESSWALK )( HANDLE hSnapshot, LPPROCESSENTRY32 lppe );
typedef BOOL ( WINAPI *HEAPLISTWALK )( HANDLE hSnapshot, LPHEAPLIST32 lphl );
typedef BOOL ( WINAPI *HEAPFIRST )( LPHEAPENTRY32 lphe, DWORD th32ProcessID, DWORD th32HeapID );
typedef BOOL ( WINAPI *HEAPNEXT )( LPHEAPENTRY32 lphe );
typedef HANDLE ( WINAPI *CREATESNAPSHOT )( DWORD dwFlags, DWORD th32ProcessID );

/* Global function pointers. These are necessary because the functions need to

⌨️ 快捷键说明

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