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

📄 rndwin32.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
	checkPollExit();

	initRandomData( randomState, buffer, BIG_RANDOM_BUFSIZE );

	/* Take a snapshot of everything we can get to that's currently in the 
	   system */
	hSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPALL, 0 );
	if( !hSnapshot )
		return;

	/* Walk through the local heap.  We have to be careful to not spend 
	   excessive amounts of time on this if we're linked into a large 
	   application with a great many heaps and/or heap blocks, since the
	   heap-traversal functions are rather slow.  Fortunately this is 
	   quite rare under Win95/98, since it implies a large/long-running
	   server app that would be run under NT/Win2K/XP rather than Win95
	   (the performance of the mapped ToolHelp32 helper functions under
	   these OSes is even worse than under Win95, fortunately we don't
	   have to use them there).
	   
	   Ideally in order to prevent excessive delays we'd count the number 
	   of heaps and ensure that no_heaps * no_heap_blocks doesn't exceed 
	   some maximum value, however this requires two passes of (slow) heap 
	   traversal rather than one, which doesn't help the situation much.
	   To provide at least some protection, we limit the total number of
	   heaps and heap entries traversed, although this leads to slightly
	   suboptimal performance if we have a small number of deep heaps 
	   rather than the current large number of shallow heaps.

	   There is however a second consideration that needs to be taken into
	   account when doing this, which is that the heap-management functions 
	   aren't completely thread-safe, so that under (very rare) conditions 
	   of heavy allocation/deallocation this can cause problems when calling 
	   HeapNext().  By limiting the amount of time that we spend in each 
	   heap, we can reduce our exposure somewhat */
	hl32.dwSize = sizeof( HEAPLIST32 );
	if( pHeap32ListFirst( hSnapshot, &hl32 ) )
		do
			{
			HEAPENTRY32 he32;
			int entryCount = 0;

			/* First add the information from the basic Heaplist32
			   structure */
			checkPollExit();
			addRandomData( randomState, &hl32, sizeof( HEAPLIST32 ) );

			/* Now walk through the heap blocks getting information
			   on each of them */
			he32.dwSize = sizeof( HEAPENTRY32 );
			if( pHeap32First( &he32, hl32.th32ProcessID, hl32.th32HeapID ) )
				do
					{
					checkPollExit();
					addRandomData( randomState, &he32, 
								   sizeof( HEAPENTRY32 ) );
					}
				while( entryCount++ < 20 && pHeap32Next( &he32 ) );
			}
		while( listCount++ < 20 && pHeap32ListNext( hSnapshot, &hl32 ) );

	/* Walk through all processes */
	pe32.dwSize = sizeof( PROCESSENTRY32 );
	if( pProcess32First( hSnapshot, &pe32 ) )
		do
			{
			checkPollExit();
			addRandomData( randomState, &pe32, sizeof( PROCESSENTRY32 ) );
			}
		while( pProcess32Next( hSnapshot, &pe32 ) );

	/* Walk through all threads */
	te32.dwSize = sizeof( THREADENTRY32 );
	if( pThread32First( hSnapshot, &te32 ) )
		do
			{
			checkPollExit();
			addRandomData( randomState, &te32, sizeof( THREADENTRY32 ) );
			}
	while( pThread32Next( hSnapshot, &te32 ) );

	/* Walk through all modules associated with the process */
	me32.dwSize = sizeof( MODULEENTRY32 );
	if( pModule32First( hSnapshot, &me32 ) )
		do
			{
			checkPollExit();
			addRandomData( randomState, &me32, sizeof( MODULEENTRY32 ) );
			}
	while( pModule32Next( hSnapshot, &me32 ) );

	/* Clean up the snapshot */
	CloseHandle( hSnapshot );
	checkPollExit();

	/* Flush any remaining data through */
	endRandomData( randomState, 100 );
	}

/* Perform a thread-safe slow poll for Windows 95 */

unsigned __stdcall threadSafeSlowPollWin95( void *dummy )
	{
	UNUSED( dummy );

	slowPollWin95();
	_endthreadex( 0 );
	return( 0 );
	}

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

/* Type definitions for functions to call native NT functions */

typedef DWORD ( WINAPI *NTQUERYSYSTEMINFO )( DWORD dwType, DWORD dwData,
											 DWORD dwMaxSize, DWORD dwDataSize );

/* Global function pointers. These are necessary because the functions need to
   be dynamically linked since only the WinNT kernel currently contains them.
   Explicitly linking to them will make the program unloadable under Win95 */

static NETSTATISTICSGET pNetStatisticsGet = NULL;
static NETAPIBUFFERSIZE pNetApiBufferSize = NULL;
static NETAPIBUFFERFREE pNetApiBufferFree = NULL;
static NTQUERYSYSTEMINFO pNtQuerySystemInfo = NULL;

/* When we query the performance counters, we allocate an initial buffer and
   then reallocate it as required until RegQueryValueEx() stops returning
   ERROR_MORE_DATA.  The following values define the initial buffer size and
   step size by which the buffer is increased */

#define PERFORMANCE_BUFFER_SIZE		65536	/* Start at 64K */
#define PERFORMANCE_BUFFER_STEP		16384	/* Step by 16K */

static void slowPollWinNT( void )
	{
	static int isWorkstation = CRYPT_ERROR;
	static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
	RESOURCE_DATA msgData;
	PPERF_DATA_BLOCK pPerfData;
	HANDLE hDevice;
	LPBYTE lpBuffer;
	DWORD dwSize, status;
	int nDrive, iterations = 0;

	/* Find out whether this is an NT server or workstation if necessary */
	if( isWorkstation == CRYPT_ERROR )
		{
		HKEY hKey;

		if( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
						  "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
						  0, KEY_READ, &hKey ) == ERROR_SUCCESS )
			{
			BYTE szValue[ 32 ];
			dwSize = sizeof( szValue );

			isWorkstation = TRUE;
			status = RegQueryValueEx( hKey, "ProductType", 0, NULL,
									  szValue, &dwSize );
			if( status == ERROR_SUCCESS && stricmp( szValue, "WinNT" ) )
				/* Note: There are (at least) three cases for ProductType:
				   WinNT = NT Workstation, ServerNT = NT Server, LanmanNT =
				   NT Server acting as a Domain Controller */
				isWorkstation = FALSE;

			RegCloseKey( hKey );
			}
		}

	/* Initialize the NetAPI32 function pointers if necessary */
	if( hNetAPI32 == NULL )
		{
		/* Obtain a handle to the module containing the Lan Manager functions */
		if( ( hNetAPI32 = LoadLibrary( "NETAPI32.DLL" ) ) != NULL )
			{
			/* Now get pointers to the functions */
			pNetStatisticsGet = ( NETSTATISTICSGET ) GetProcAddress( hNetAPI32,
														"NetStatisticsGet" );
			pNetApiBufferSize = ( NETAPIBUFFERSIZE ) GetProcAddress( hNetAPI32,
														"NetApiBufferSize" );
			pNetApiBufferFree = ( NETAPIBUFFERFREE ) GetProcAddress( hNetAPI32,
														"NetApiBufferFree" );

			/* Make sure we got valid pointers for every NetAPI32 function */
			if( pNetStatisticsGet == NULL ||
				pNetApiBufferSize == NULL ||
				pNetApiBufferFree == NULL )
				{
				/* Free the library reference and reset the static handle */
				FreeLibrary( hNetAPI32 );
				hNetAPI32 = NULL;
				}
			}
		}

	/* Initialize the NT kernel native API function pointers if necessary */
	if( hNTAPI == NULL && \
		( hNTAPI = GetModuleHandle( "NTDll.dll" ) ) != NULL )
		{
		/* Get a pointer to the NT native information query function */
		pNtQuerySystemInfo = ( NTQUERYSYSTEMINFO ) GetProcAddress( hNTAPI,
												"NtQuerySystemInformation" );
		if( pNtQuerySystemInfo == NULL )
			hNTAPI = NULL;
		}
	checkPollExit();

	/* Get network statistics.  Note: Both NT Workstation and NT Server by
	   default will be running both the workstation and server services.  The
	   heuristic below is probably useful though on the assumption that the
	   majority of the network traffic will be via the appropriate service. In
	   any case the network statistics return almost no randomness */
	if( hNetAPI32 != NULL &&
		pNetStatisticsGet( NULL,
						   isWorkstation ? L"LanmanWorkstation" : L"LanmanServer",
						   0, 0, &lpBuffer ) == 0 )
		{
		pNetApiBufferSize( lpBuffer, &dwSize );
		setMessageData( &msgData, lpBuffer, dwSize );
		krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,
						 &msgData, CRYPT_IATTRIBUTE_ENTROPY );
		pNetApiBufferFree( lpBuffer );
		}

	/* Get disk I/O statistics for all the hard drives */
	for( nDrive = 0;; nDrive++ )
		{
		BYTE diskPerformance[ 256 ];
		char szDevice[ 24 ];

		/* Check whether we can access this device */
		sprintf( szDevice, "\\\\.\\PhysicalDrive%d", nDrive );
		hDevice = CreateFile( szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
							  NULL, OPEN_EXISTING, 0, NULL );
		if( hDevice == INVALID_HANDLE_VALUE )
			break;

		/* Note: This only works if the user has turned on the disk
		   performance counters with 'diskperf -y'.  These counters are 
		   usually disabled, although they appear to be enabled in newer
		   installs of Win2K and XP.  In addition using the documented 
		   DISK_PERFORMANCE data structure to contain the returned data 
		   returns ERROR_INSUFFICIENT_BUFFER (which is wrong) and doesn't 
		   change dwSize (which is also wrong), so we pass in a larger 
		   buffer and pre-set dwSize to a safe value.  Finally, there is a 
		   bug in pre-SP4 Win2K in which enabling diskperf, installing a 
		   file system filter driver, and then disabling diskperf, causes 
		   diskperf to corrupt the registry key HKEY_LOCAL_MACHINE\SYSTEM\
		   CurrentControlSet\Control\Class\{71A27CDD-812A-11D0-BEC7-
		   08002BE2092F}\Upper Filters, resulting in a Stop 0x7B bugcheck */
		dwSize = sizeof( diskPerformance );
		if( DeviceIoControl( hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
							 &diskPerformance, sizeof( diskPerformance ),
							 &dwSize, NULL ) )
			{
			checkPollExit();
			setMessageData( &msgData, &diskPerformance, dwSize );
			krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S, 
							 &msgData, CRYPT_IATTRIBUTE_ENTROPY );
			}
		CloseHandle( hDevice );
		}
	checkPollExit();

	/* In theory we should be using the Win32 performance query API to obtain
	   unpredictable data from the system, however this is so unreliable (see
	   the multiple sets of comments further down) that it's too risky to 
	   rely on it except as a fallback in emergencies.  Instead, we rely 
	   mostly on an NT native API function that has the dual advantages that 
	   it doesn't have as many (known) problems as the Win32 equivalent, and 
	   that it doesn't access the data indirectly via pseudo-registry keys, 
	   which means that it's much faster.  Note that the Win32 equivalent 
	   actually works almost all of the time, the problem is that on one or 
	   two systems it can fail in strange ways that are never the same and 
	   can't be reproduced on any other system, which is why we use the 
	   native API here.  Microsoft officially documented this function in 
	   early 2003, so it'll be fairly safe to use */
	if( hNTAPI != NULL )
		{
		void *buffer = clAlloc( "slowPollNT", PERFORMANCE_BUFFER_SIZE );

		if( buffer != NULL )
			{
			DWORD dwSize = PERFORMANCE_BUFFER_SIZE, dwType;
			int noResults = 0;

			/* Scan the first 64 possible information types (we don't bother
			   with increasing the buffer size as we do with the Win32 version
			   of the performance data read, we may miss a few classes but
			   it's no big deal).  In addition the returned size value for
			   some classes is wrong (e.g. 23 and 24 return a size of 0) so we
			   miss a few more things, but again it's no big deal.  This scan
			   typically yields around 20 pieces of data, there's nothing in
			   the range 65...128 so chances are there won't be anything above
			   there either */
			for( dwType = 0; dwType < 64; dwType++ )
				{
				status = pNtQuerySystemInfo( dwType, ( DWORD ) buffer,
											 32768, ( DWORD ) &dwSize );
				if( status == ERROR_SUCCESS && dwSize > 0 )
					{
					checkPollExit();
					setMessageData( &msgData, buffer, dwSize );
					status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
										IMESSAGE_SETATTRIBUTE_S, &msgData, 
										CRYPT_IATTRIBUTE_ENTROPY );
					if( cryptStatusOK( status ) )
						noResults++;

⌨️ 快捷键说明

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