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

📄 rndwin32.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
	addRandomValue( randomState, GetInputState() );
	addRandomValue( randomState, GetMessagePos() );
	addRandomValue( randomState, GetMessageTime() );
	addRandomValue( randomState, GetOpenClipboardWindow() );
	addRandomValue( randomState, GetProcessHeap() );
	addRandomValue( randomState, GetProcessWindowStation() );
	addRandomValue( randomState, GetTickCount() );
	checkPollExit();

	/* 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;
		char vendorID[ 12 ];
		unsigned long processorID, featureFlags;

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

		/* Check whether the CPU supports extended features like CPUID and 
		   RDTSC, and get any info we need related to this.  There is an 
		   IsProcessorFeaturePresent() function, but all that this provides 
		   is an indication of the availability of rdtsc (alongside some 
		   stuff we don't care about, like MMX and 3DNow).  Since we still 
		   need to check for the presence of other features, we do the whole 
		   thing ourselves */
		_asm {
			/* Detect the CPU type */
			pushfd
			pop eax				/* Get EFLAGS in eax */
			mov ebx, eax		/* Save a copy for later */
			xor eax, 0x200000	/* Toggle the CPUID bit */
			push eax
			popfd				/* Update EFLAGS */
			pushfd
			pop eax				/* Get updated EFLAGS back in eax */
			push ebx
			popfd				/* Restore original EFLAGS */
			xor eax, ebx		/* Check if we could toggle CPUID bit */
			jz noCPUID			/* Nope, we can't do anything further */
			mov [hasAdvFeatures], 1	/* Remember that we have CPUID, RDTSC */

			/* We have CPUID, see what we've got */
			xor ecx, ecx
			xor edx, edx		/* Tell VC++ that ECX, EDX will be trashed */
			xor eax, eax		/* CPUID function 0: */
			cpuid
			mov dword ptr [vendorID], ebx
			mov dword ptr [vendorID+4], edx
			mov dword ptr [vendorID+8], ecx	/* Save vendor ID string */
			mov eax, 1			/* CPUID function 1:  */
			cpuid
			mov [processorID], eax	/* Save processor ID */
			mov [featureFlags], edx	/* Save processor feature info */
		noCPUID:
			}

		/* If there's a vendor ID present, check for vendor-specific 
		   special features */
		if( hasAdvFeatures && !memcmp( vendorID, "CentaurHauls", 12 ) )
			{
		_asm {
			xor ebx, ebx
			xor ecx, ecx		/* Tell VC++ that EBX, ECX will be trashed */
			mov eax, 0xC0000000	/* Centaur extended CPUID info */
			cpuid
			cmp eax, 0xC0000001	/* Need at least release 2 ext.feature set */
			jb noRNG			/* No extended info available */
			mov eax, 0xC0000001	/* Centaur extended feature flags */
			cpuid
			and edx, 01100b
			cmp edx, 01100b		/* Check for RNG present + enabled flags */
			jne noRNG			/* No, RNG not present or enabled */
			mov [hasHardwareRNG], 1	/* Remember that we have a hardware RNG */
		noRNG:
			}
			}
		}

	/* 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).  That 
	   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 appears to synchronise the TSCs across CPUs at 
	   boot time (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, Pentiums 
	   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).
	   
	   To make things unambiguous, we detect a CPU new enough to call RDTSC 
	   directly by checking for CPUID capabilities, and fall back to QPC if 
	   this isn't present */
	if( hasAdvFeatures )
		{
		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 );
		}
	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 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 */
	if( hasHardwareRNG )
		{
		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 );
		}

	/* Flush any remaining data through.  Quality = int( 33 1/3 % ) */
	endRandomData( randomState, 34 );
	}

/****************************************************************************
*																			*
*									Slow Poll								*
*																			*
****************************************************************************/

/* 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
   be dynamically linked since only the Win95 kernel currently contains them.
   Explicitly linking to them will make the program unloadable under NT */

static CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL;
static MODULEWALK pModule32First = NULL;
static MODULEWALK pModule32Next = NULL;
static PROCESSWALK pProcess32First = NULL;
static PROCESSWALK pProcess32Next = NULL;
static THREADWALK pThread32First = NULL;
static THREADWALK pThread32Next = NULL;
static HEAPLISTWALK pHeap32ListFirst = NULL;
static HEAPLISTWALK pHeap32ListNext = NULL;
static HEAPFIRST pHeap32First = NULL;
static HEAPNEXT pHeap32Next = NULL;

/* Since there are a significant number of ToolHelp data blocks, we use a
   larger-than-usual intermediate buffer to cut down on kernel traffic */

#define BIG_RANDOM_BUFSIZE	( RANDOM_BUFSIZE * 4 )

static void slowPollWin95( void )
	{
	PROCESSENTRY32 pe32;
	THREADENTRY32 te32;
	MODULEENTRY32 me32;
	HEAPLIST32 hl32;
	HANDLE hSnapshot;
	RANDOM_STATE randomState;
	BYTE buffer[ BIG_RANDOM_BUFSIZE ];
	int bufIndex = 0, listCount = 0;

	/* Initialize the Toolhelp32 function pointers if necessary */
	if( pCreateToolhelp32Snapshot == NULL )
		{
		HANDLE hKernel;

		/* Obtain the module handle of the kernel to retrieve the addresses
		   of the Toolhelp32 functions */
		if( ( hKernel = GetModuleHandle( "Kernel32.dll" ) ) == NULL )
			return;

		/* Now get pointers to the functions */
		pCreateToolhelp32Snapshot = ( CREATESNAPSHOT ) GetProcAddress( hKernel,
													"CreateToolhelp32Snapshot" );
		pModule32First = ( MODULEWALK ) GetProcAddress( hKernel,
													"Module32First" );
		pModule32Next = ( MODULEWALK ) GetProcAddress( hKernel,
													"Module32Next" );
		pProcess32First = ( PROCESSWALK ) GetProcAddress( hKernel,
													"Process32First" );
		pProcess32Next = ( PROCESSWALK ) GetProcAddress( hKernel,
													"Process32Next" );
		pThread32First = ( THREADWALK ) GetProcAddress( hKernel,
													"Thread32First" );
		pThread32Next = ( THREADWALK ) GetProcAddress( hKernel,
													"Thread32Next" );
		pHeap32ListFirst = ( HEAPLISTWALK ) GetProcAddress( hKernel,
													"Heap32ListFirst" );
		pHeap32ListNext = ( HEAPLISTWALK ) GetProcAddress( hKernel,
													"Heap32ListNext" );
		pHeap32First = ( HEAPFIRST ) GetProcAddress( hKernel,
													"Heap32First" );
		pHeap32Next = ( HEAPNEXT ) GetProcAddress( hKernel,
													"Heap32Next" );

		/* Make sure we got valid pointers for every Toolhelp32 function */
		if( pModule32First == NULL || pModule32Next == NULL || \
			pProcess32First == NULL || pProcess32Next == NULL || \
			pThread32First == NULL || pThread32Next == NULL || \
			pHeap32ListFirst == NULL || pHeap32ListNext == NULL || \
			pHeap32First == NULL || pHeap32Next == NULL || \
			pCreateToolhelp32Snapshot == NULL )
			{
			/* Mark the main function as unavailable in case for future
			   reference */
			pCreateToolhelp32Snapshot = NULL;
			return;
			}
		}

⌨️ 快捷键说明

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