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

📄 win32.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
	pSetupDiEnumDeviceInfo = ( SETUPDIENUMDEVICEINFO ) \
				GetProcAddress( hSetupAPI, "SetupDiEnumDeviceInfo" );
	pSetupDiGetClassDevs = ( SETUPDIGETCLASSDEVS ) \
				GetProcAddress( hSetupAPI, "SetupDiGetClassDevsA" );
	pSetupDiGetDeviceRegistryProperty = ( SETUPDIGETDEVICEREGISTRYPROPERTY ) \
				GetProcAddress( hSetupAPI, "SetupDiGetDeviceRegistryPropertyA" );
	if( pSetupDiDestroyDeviceInfoList == NULL || \
		pSetupDiEnumDeviceInfo == NULL || pSetupDiGetClassDevs == NULL || \
		pSetupDiGetDeviceRegistryProperty == NULL )
		{
		FreeLibrary( hSetupAPI );
		return;
		}

	/* Get info on all PnP devices */
	hDevInfo = pSetupDiGetClassDevs( NULL, NULL, NULL,
									 DIGCF_PRESENT | DIGCF_ALLCLASSES );
	if( hDevInfo != INVALID_HANDLE_VALUE )
		{
		SP_DEVINFO_DATA devInfoData;
		RANDOM_STATE randomState;
		BYTE buffer[ RANDOM_BUFSIZE + 8 ];
		BYTE pnpBuffer[ 512 + 8 ];
		DWORD cbPnPBuffer;
		int deviceCount, iterationCount, status;

		/* Enumerate all PnP devices */
		status = initRandomData( randomState, buffer, RANDOM_BUFSIZE );
		if( cryptStatusError( status ) )
			retIntError_Void();
		memset( &devInfoData, 0, sizeof( devInfoData ) );
		devInfoData.cbSize = sizeof( SP_DEVINFO_DATA );
		for( deviceCount = 0, iterationCount = 0;
			 pSetupDiEnumDeviceInfo( hDevInfo, deviceCount, 
									 &devInfoData ) && \
				iterationCount < FAILSAFE_ITERATIONS_MAX; 
			 deviceCount++, iterationCount++ )
			{
			if( pSetupDiGetDeviceRegistryProperty( hDevInfo, &devInfoData,
												   SPDRP_HARDWAREID, NULL,
												   pnpBuffer, 512, &cbPnPBuffer ) )
				addRandomData( randomState, pnpBuffer, cbPnPBuffer );
			}
		ENSURES_V( iterationCount < FAILSAFE_ITERATIONS_MAX );
		pSetupDiDestroyDeviceInfoList( hDevInfo );
		endRandomData( randomState, 5 );
		}

	FreeLibrary( hSetupAPI );
	}

/****************************************************************************
*																			*
*									Fast Poll								*
*																			*
****************************************************************************/

/* The shared Win32 fast poll routine */

void fastPoll( void )
	{
	static BOOLEAN addedFixedItems = 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 + 8 ];
	int status;

	if( krnlIsExiting() )
		return;

	status = initRandomData( randomState, buffer, RANDOM_BUFSIZE );
	if( cryptStatusError( status ) )
		retIntError_Void();

	/* 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.
	   Since a HWND/HANDLE can be a 64-bit value on a 64-bit platform, we 
	   have to use a mapping macro that discards the high 32 bits (which
	   presumably won't be of much interest anyway) */
	addRandomHandle( randomState, GetActiveWindow() );
	addRandomHandle( randomState, GetCapture() );
	addRandomHandle( randomState, GetClipboardOwner() );
	addRandomHandle( randomState, GetClipboardViewer() );
	addRandomHandle( randomState, GetCurrentProcess() );
	addRandomValue( randomState, GetCurrentProcessId() );
	addRandomHandle( randomState, GetCurrentThread() );
	addRandomValue( randomState, GetCurrentThreadId() );
	addRandomHandle( randomState, GetDesktopWindow() );
	addRandomHandle( randomState, GetFocus() );
	addRandomValue( randomState, GetInputState() );
	addRandomValue( randomState, GetMessagePos() );
	addRandomValue( randomState, GetMessageTime() );
	addRandomHandle( randomState, GetOpenClipboardWindow() );
	addRandomHandle( randomState, GetProcessHeap() );
	addRandomHandle( randomState, GetProcessWindowStation() );
	addRandomValue( randomState, GetTickCount() );
	if( krnlIsExiting() )
		return;

	/* 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 */
/*	addRandomValue( randomState, GetQueueStatus( QS_ALLEVENTS ) ); */

	/* Get multiword system information: Current caret position, current
	   mouse cursor position */
	GetCaretPos( &point );
	addRandomData( randomState, &point, sizeof( POINT ) );
	GetCursorPos( &point );
	addRandomData( randomState, &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 );
	addRandomData( randomState, &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 );
	addRandomData( randomState, &creationTime, sizeof( FILETIME ) );
	addRandomData( randomState, &exitTime, sizeof( FILETIME ) );
	addRandomData( randomState, &kernelTime, sizeof( FILETIME ) );
	addRandomData( randomState, &userTime, sizeof( FILETIME ) );
	handle = GetCurrentProcess();
	GetProcessTimes( handle, &creationTime, &exitTime, &kernelTime, &userTime );
	addRandomData( randomState, &creationTime, sizeof( FILETIME ) );
	addRandomData( randomState, &exitTime, sizeof( FILETIME ) );
	addRandomData( randomState, &kernelTime, sizeof( FILETIME ) );
	addRandomData( randomState, &userTime, sizeof( FILETIME ) );

	/* Get the minimum and maximum working set size for the current process */
	GetProcessWorkingSetSize( handle, &minimumWorkingSetSize,
							  &maximumWorkingSetSize );
	addRandomValue( randomState, minimumWorkingSetSize );
	addRandomValue( randomState, 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 );
		addRandomData( randomState, &startupInfo, sizeof( STARTUPINFO ) );

		/* Remember that we've got the fixed info */
		addedFixedItems = TRUE;
		}

	/* The performance of QPC varies depending on the architecture it's
	   running on and on the OS, the MS documentation is vague about the
	   details because it varies so much.  Under Win9x/ME it reads the
	   1.193180 MHz PIC timer.  Under NT/Win2K/XP it may or may not read the
	   64-bit TSC depending on the HAL and assorted other circumstances,
	   generally on machines with a uniprocessor HAL
	   KeQueryPerformanceCounter() uses a 3.579545MHz timer and on machines
	   with a multiprocessor or APIC HAL it uses the TSC (the exact time
	   source is controlled by the HalpUse8254 flag in the kernel).  Since
	   Vista-era machines are generally running on multiprocessor HALs we
	   usually get the TSC under Vista.

	   This choice of time sources is somewhat peculiar because on a
	   multiprocessor machine it's theoretically possible to get completely
	   different TSC readings depending on which CPU you're currently
	   running on, while for uniprocessor machines it's not a problem.
	   However the kernel synchronises the TSCs across CPUs at boot time if 
	   a multiprocessor HAL is used (it resets the TSC as part of its system 
	   init) so this shouldn't really be a problem.  Under WinCE it's 
	   completely platform-dependant, if there's no hardware performance 
	   counter available it uses the 1ms system timer.

	   Another feature of the TSC (although it doesn't really affect us 
	   here) is that mobile CPUs will turn off the TSC when they idle, 
	   newer Pentiums and Athlons with advanced power management/clock
	   throttling will change the rate of the counter when they clock-
	   throttle (to match the current CPU speed), and hyperthreading 
	   Pentiums will turn it off when both threads are idle (this more or 
	   less makes sense since the CPU will be in the halted state and not 
	   executing any instructions to count).  What makes this even more
	   exciting is that the resulting handling of the TSC is almost entirely
	   nondeterministic, the only thing that's guaranteed is that the
	   counter is monotonically incrementing.  For example when a newer
	   processor with power-saving features enabled ramps down its core
	   clock the TSC rate is lowered to correspond to the clock rate
	   (assuming that the BIOS sets this up correctly, which isn't always
	   the case).  However various events like cache probes can cause the
	   core to temporarily return to the original rate to process the
	   event before dropping back to the throttled rate, which can cause
	   TSC drift across multiple cores.  Hardware-specific events like
	   AMDs STPCLK signalling ("shut 'er down ma, she's glowing red") can
	   reach different cores at different times and lead to ramping up
	   and down and different times and for different durations, leading
	   to further drift.  Newer AMD CPUs fix this by providing drift-
	   invariant TSCs if the TscInvariant CPUID feature flag is set.

	   As a result, if we're on a system with multiple cores and it doesn't
	   have the AMD TscInvariant fix then the TSC skew can also be a source
	   of entropy.  To some extent this is just timing the context switch 
	   time across CPUs (which in itself is a source of some entropy), but 
	   what's left is the TSC skew across cores.  If this is if interest we
	   can do it with code something like the following.  Note that this is 
	   only sample code, there are various complications such as the fact 
	   that another thread may change the process affinity mask between the
	   call to the initial GetProcessAffinityMask() and the final
	   SetThreadAffinityMask() to restore the original mask, even if we 
	   insert another GetProcessAffinityMask() just before the 
	   SetThreadAffinityMask() there's still a small race condition present 
	   but no real way to avoid it without OS API-level support:

		DWORD processAfinityMask, systemAffinityMask, mask = 0x10000;

		// Get the available processors that the thread can be scheduled on
		if( !GetProcessAffinityMask( GetCurrentProcess(), processAfinityMask, 
									 systemAffinityMask ) )
			return;

		// Move the thread to each processor and read the TSC
		while( mask != 0 )
			{
			mask >>= 1;
			if( !( mask & processAfinityMask ) )
				continue;

			SetThreadAffinityMask( GetCurrentThread(), mask );
			// RDTSC
			}

		// Restore the original thread affinity
		SetThreadAffinityMask( GetCurrentThread(), processAfinityMask );

	   Finally, there's the HPET, but this is only supported in Vista and
	   it's not clear how to access it from user-level APIs rather than as
	   part of the multimedia subsystem.

	   To make things unambiguous, we call RDTSC directly if possible and 
	   fall back to QPC in the highly unlikely situation where this isn't 
	   present */
#ifndef NO_ASM
	if( getSysVar( SYSVAR_HWCAP ) & HWCAP_FLAG_RDTSC )
		{
		unsigned long value;

		__asm {
			xor eax, eax
			xor edx, edx		/* Tell VC++ that EDX:EAX will be trashed */
			rdtsc
			mov [value], eax	/* Ignore high 32 bits, which are > 1s res */
			}
		addRandomValue( randomState, value );
		}
#endif /* NO_ASM */
	else
		{
		if( QueryPerformanceCounter( &performanceCount ) )
			addRandomData( randomState, &performanceCount,
						   sizeof( LARGE_INTEGER ) );
		else
			{
			/* Millisecond accuracy at best... */
			addRandomValue( randomState, GetTickCount() );
			}
		}

	/* If there's a hardware RNG present, read data from it.  We check that
	   the RNG is still present/enabled on each fetch since it could (at 
	   least in theory) be disabled by the OS between fetches.  We also read 
	   the data into an explicitly dword-aligned buffer (which the standard 
	   buffer should be anyway, but we make it explicit here just to be 
	   safe).  Note that we have to force alignment using a LONGLONG rather 
	   than a #pragma pack, since chars don't need alignment it would have 
	   no effect on the BYTE [] member */
#ifndef NO_ASM
	if( getSysVar( SYSVAR_HWCAP ) & HWCAP_FLAG_XSTORE )
		{
		struct alignStruct {
			LONGLONG dummy1;		/* Force alignment of following member */
			BYTE buffer[ 64 ];
			};
		struct alignStruct *rngBuffer = ( struct alignStruct * ) buffer;
		void *bufPtr = rngBuffer->buffer;	/* Get it into a form asm can handle */
		int byteCount = 0;

		__asm {
			push es
			xor ecx, ecx		/* Tell VC++ that ECX will be trashed */
			mov eax, 0xC0000001	/* Centaur extended feature flags */
			cpuid
			and edx, 01100b
			cmp edx, 01100b		/* Check for RNG present + enabled flags */
			jne rngDisabled		/* RNG was disabled after our initial check */
			push ds
			pop es
			mov edi, bufPtr		/* ES:EDI = buffer */
			xor edx, edx		/* Fetch 8 bytes */
			xstore_rng
			and eax, 011111b	/* Get count of bytes returned */
			jz rngDisabled		/* Nothing read, exit */
			mov [byteCount], eax
		rngDisabled:
			pop es
			}
		if( byteCount > 0 )
			addRandomData( randomState, bufPtr, byteCount );
		}
	if( getSysVar( SYSVAR_HWCAP ) & HWCAP_FLAG_TRNG )
		{
		unsigned long value = 0;

		__asm {

⌨️ 快捷键说明

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