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

📄 os_spec.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
	switch( dwReason )
		{
		case DLL_PROCESS_ATTACH:
			/* Disable thread-attach notifications, which we don't do
			   anything with and therefore don't need */
			DisableThreadLibraryCalls( hinstDLL );

			/* Set up the initialisation lock in the kernel */
			preInit();
			break;

		case DLL_PROCESS_DETACH:
			/* Delete the initialisation lock in the kernel */
			postShutdown();
			break;

		case DLL_THREAD_ATTACH:
		case DLL_THREAD_DETACH:
			break;
		}

	return( TRUE );
	}
#endif /* OS-specific support */

/****************************************************************************
*																			*
*						Minimal Safe String Function Support				*
*																			*
****************************************************************************/

#ifdef NO_NATIVE_STRLCPY

/* Copy and concatenate a string, truncating it if necessary to fit the 
   destination buffer.  Unfortunately the TR 24731 functions don't do this,
   while the OpenBSD safe-string functions do (but don't implement any of
   the rest of the TR 24731 functionality).  Because the idiot maintainer
   of glibc objects to these functions (even Microsoft recognise their
   utility with the _TRUNCATE semantics for strcpy_s/strcat_s), everyone has 
   to manually implement them in their code, as we do here.  Note that these
   aren't completely identical to the OpenBSD functions, in order to fit the 
   TR 24731 pattern we make the length the second paramter, and give them a
   TR 24731-like _s suffix to make them distinct from the standard OpenBSD
   ones (a macro in os_spec.h is sufficient to map this to the proper 
   functions where they're available in libc) */

int strlcpy_s( char *dest, const int destLen, const char *src )
	{
	int i;

	assert( isWritePtr( dest, destLen ) );
	assert( isReadPtr( src, 1 ) );

	/* Copy as much as we can of the source string onto the end of the 
	   destination string */
	for( i = 0; i < destLen - 1 && *src != '\0'; i++ )
		dest[ i ] = *src++;
	dest[ i ] = '\0';

	return( 1 );
	}

int strlcat_s( char *dest, const int destLen, const char *src )
	{
	int i;

	assert( isWritePtr( dest, destLen ) );

	/* See how long the existing destination string is */
	for( i = 0; i < destLen && dest[ i ] != '\0'; i++ );
	if( i >= destLen )
		{
		assert( DEBUG_WARN );
		dest[ destLen - 1 ] = '\0';

		return( 1 );
		}

	/* Copy as much as we can of the source string onto the end of the 
	   destination string */
	while( i < destLen - 1 && *src != '\0' )
		dest[ i++ ] = *src++;
	dest[ i ] = '\0';

	return( 1 );
	}
#endif /* NO_NATIVE_STRLCPY */

/****************************************************************************
*																			*
*								SysVars Support								*
*																			*
****************************************************************************/

#if defined( __WIN32__ )  && !defined( NO_ASM )

CHECK_RETVAL \
static int getHWInfo( void )
	{
	BOOLEAN hasAdvFeatures = 0;
	char vendorID[ 12 + 8 ];
	unsigned long processorID;
	int sysCaps = 0;

	/* 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 */
		mov [sysCaps], HWCAP_FLAG_RDTSC	/* Remember that we have 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: Get vendor ID */
		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: Get processor info */
		cpuid
		mov [processorID], eax	/* Save processor ID */
#if 0	/* No crypto-related features are reported in these flags */
		mov [featureFlags], edx	/* Save processor feature info */
#endif /* 0 */
	noCPUID:
		}

	/* If there's no CPUID support, there are no special HW capabilities
	   available */
	if( !hasAdvFeatures )
		return( HWCAP_FLAG_NONE );

	/* 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 endCheck			/* No extended info available */
		mov eax, 0xC0000001	/* Centaur extended feature flags */
		cpuid
		mov eax, edx		/* Save a copy of the feature flags */
		and edx, 01100b
		cmp edx, 01100b		/* Check for RNG present + enabled flags */
		jz noRNG			/* No, RNG not present or enabled */
		or [sysCaps], HWCAP_FLAG_XSTORE	/* Remember that we have a HW RNG */
	noRNG:
		mov eax, edx
		and eax, 011000000b
		cmp eax, 011000000b	/* Check for ACE present + enabled flags */
		jz noACE			/* No, ACE not present or enabled */
		or [sysCaps], HWCAP_FLAG_XCRYPT	/* Remember that we have HW AES */
	noACE:
		mov eax, edx
		and eax, 0110000000000b
		cmp eax, 0110000000000b	/* Check for PHE present + enabled flags */
		jz noPHE			/* No, PHE not present or enabled */
		or [sysCaps], HWCAP_FLAG_XSHA	/* Remember that we have HW SHA-1/SHA-2 */
	noPHE:
		mov eax, edx
		and eax, 011000000000000b
		cmp eax, 011000000000000b /* Check for PMM present + enabled flags */
		jz endCheck			/* No, PMM not present or enabled */
		or [sysCaps], HWCAP_FLAG_MONTMUL	/* Remember that we have HW bignum */
	endCheck:
		}
		}
	if( hasAdvFeatures && !memcmp( vendorID, "AuthenticAMD", 12 ) )
		{
		/* Check for AMD Geode LX, family 0x5 = Geode, model 0xA = LX */
		if( ( processorID & 0x05A0 ) == 0x05A0 )
			sysCaps |= HWCAP_FLAG_TRNG;
		}

	return( sysCaps );
	}

#elif defined( __GNUC__ ) && defined( __i386__ ) && !defined( NO_ASM )

#if HWCAP_FLAG_RDTSC != 0x01
  #error Need to sync HWCAP_FLAG_RDTSC with equivalent asm definition
#endif /* HWCAP_FLAG_RDTSC */

CHECK_RETVAL \
static int getHWInfo( void )
	{
	char vendorID[ 12 + 8 ];
	unsigned long processorID;
	int hasAdvFeatures = 0, sysCaps = 0;

	/* Check whether the CPU supports extended features like CPUID and
	   RDTSC, and get any info we need related to this.  The use of ebx is a
	   bit problematic because gcc (via the IA32 ABI) uses ebx to store the
	   address of the global offset table and gets rather upset if it gets
	   changed, so we have to save/restore it around the cpuid call.  We
	   have to be particularly careful here because ebx is used implicitly
	   in references to sysCaps (which is a static int), so we save it as
	   close to the cpuid instruction as possible and restore it immediately
	   afterwards, away from any memory-referencing instructions that 
	   implicitly use ebx */
	asm volatile( "pushf\n\t"
		"popl %%eax\n\t"
		"movl %%eax, %%ecx\n\t"
		"xorl $0x200000, %%eax\n\t"
		"pushl %%eax\n\t"
		"popf\n\t"
		"pushf\n\t"
		"popl %%eax\n\t"
		"pushl %%ecx\n\t"
		"popf\n\t"
		"xorl %%ecx, %%eax\n\t"
		"jz noCPUID\n\t"
		"movl $1, %0\n\t"	/* hasAdvFeatures = TRUE */
		"movl $1, %1\n\t"	/* sysCaps = HWCAP_FLAG_RDTSC */
		"pushl %%ebx\n\t"	/* Save PIC register */
		"xorl %%eax, %%eax\n\t"	/* CPUID function 0: Get vendor ID */
		"cpuid\n\t"
		"leal %2, %%eax\n\t"
		"movl %%ebx, (%%eax)\n\t"
		"movl %%edx, 4(%%eax)\n\t"
		"movl %%ecx, 8(%%eax)\n\t"
		"movl $1, %%eax\n\t"	/* CPUID function 1: Get processor info */
		"cpuid\n\t"
		"leal %3, %%ecx\n\t"
		"movl %%eax, (%%ecx)\n\t"	/* processorID */
		"popl %%ebx\n"		/* Restore PIC register */
	"noCPUID:\n\n"
#if 0	/* See comment in tools/ccopts.sh for why this is disabled */
		".section .note.GNU-stack, \"\", @progbits; .previous\n"
							/* Mark the stack as non-executable.  This is
							   undocumented outside of mailing-list postings
							   and a bit hit-and-miss, but having at least
							   one of these in included asm code doesn't
							   hurt */
#endif /* 0 */
		: "=m"(hasAdvFeatures), "=m"(sysCaps),
			"=m"(vendorID), "=m"(processorID)	/* Output */
		: 										/* Input */
		: "%eax", "%ecx", "%edx"				/* Registers clobbered */
		);

	/* If there's no CPUID support, there are no special HW capabilities
	   available */
	if( !hasAdvFeatures )
		return( HWCAP_FLAG_NONE );

	/* If there's a vendor ID present, check for vendor-specific special
	   features.  Again, we have to be extremely careful with ebx */
	if( hasAdvFeatures && !memcmp( vendorID, "CentaurHauls", 12 ) )
		{
	asm volatile( "pushl %%ebx\n\t"	/* Save PIC register */
		"movl $0xC0000000, %%eax\n\t"
		"cpuid\n\t"
		"popl %%ebx\n\t"	/* Restore PIC register */
		"cmpl $0xC0000001, %%eax\n\t"
		"jb endCheck\n\t"
		"pushl %%ebx\n\t"	/* Re-save PIC register */
		"movl $0xC0000001, %%eax\n\t"
		"cpuid\n\t"
		"popl %%ebx\n\t"	/* Re-restore PIC register */
		"movl %%edx, %%eax\n\t"
		"andl $0xC, %%edx\n\t"
		"cmpl $0xC, %%edx\n\t"
		"jz noRNG\n\t"
		"orl $2, %0\n"		/* HWCAP_FLAG_XSTORE */
	"noRNG:\n\t"
		"movl %%edx, %%eax\n\t"
		"andl $0xC0, %%eax\n\t"
		"cmpl $0xC0, %%eax\n\t"
		"jz noACE\n\t"
		"orl $4, %0\n"		/* HWCAP_FLAG_XCRYPT */
	"noACE:\n\t"
		"movl %%edx, %%eax\n\t"
		"andl $0xC00, %%eax\n\t"
		"cmpl $0xC00, %%eax\n\t"
		"jz noPHE\n\t"
		"orl $8, %0\n"		/* HWCAP_FLAG_XSHA */
	"noPHE:\n\t"
		"movl %%edx, %%eax\n\t"
		"andl $0x3000, %%eax\n\t"
		"cmpl $0x3000, %%eax\n\t"
		"jz endCheck\n\t"
		"orl $10, %0\n"		/* HWCAP_FLAG_MONTMUL */
	"endCheck:\n\n"
		 : "=m"(sysCaps)					/* Output */
		 :
		 : "%eax", "%ecx", "%edx"	/* Registers clobbered */
		);
		}
	if( hasAdvFeatures && !memcmp( vendorID, "AuthenticAMD", 12 ) )
		{
		/* Check for AMD Geode LX, family 0x5 = Geode, model 0xA = LX */
		if( ( processorID & 0x05A0 ) == 0x05A0 )
			sysCaps |= HWCAP_FLAG_TRNG;
		}

	return( sysCaps );
	}
#endif /* OS-specific support */

/* Initialise OS-specific constants.  This is a bit ugly because the values 
   are often specific to one cryptlib module but there's no (clean) way to
   perform any complex per-module initialisation so we have to know about 
   all of the module-specific sysVar requirements here */

#define MAX_SYSVARS		8

static int sysVars[ MAX_SYSVARS ];

#if ( defined( __WIN32__ ) || defined( __WINCE__ ) )

int initSysVars( void )
	{
	OSVERSIONINFO osvi = { sizeof( OSVERSIONINFO ) };
	SYSTEM_INFO systemInfo;

	assert( SYSVAR_LAST < MAX_SYSVARS );

	/* Reset the system variable information */
	memset( sysVars, 0, MAX_SYSVARS );

	/* Figure out which version of Windows we're running under */
	if( !GetVersionEx( &osvi ) )
		{
		/* If for any reason the call fails, just use the most likely 
		   values */
		osvi.dwMajorVersion = 5;	/* Win2K and higher */
		osvi.dwPlatformId = VER_PLATFORM_WIN32_NT;
		}
	sysVars[ SYSVAR_OSVERSION ] = osvi.dwMajorVersion;
	sysVars[ SYSVAR_ISWIN95 ] = \
					( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) ? \
					TRUE : FALSE;

	/* Check for Win32s just in case someone ever tries to load cryptlib under 
	   it */
	if( osvi.dwPlatformId == VER_PLATFORM_WIN32s )
		{
		assert( DEBUG_WARN );
		return( CRYPT_ERROR_NOTAVAIL );
		}

	/* Get the system page size */
	GetSystemInfo( &systemInfo );
	sysVars[ SYSVAR_PAGESIZE ] = systemInfo.dwPageSize;

#if defined( __WIN32__ )  && !defined( NO_ASM )
	/* Get system hardware capabilities */
	sysVars[ SYSVAR_HWCAP ] = getHWInfo();
#endif /* __WIN32__ && !NO_ASM */

	return( CRYPT_OK );
	}

#elif defined( __UNIX__ )

#include <unistd.h>

int initSysVars( void )
	{
	assert( SYSVAR_LAST < MAX_SYSVARS );

	/* Reset the system variable information */
	memset( sysVars, 0, MAX_SYSVARS );

	/* Get the system page size */
#if defined( _CRAY ) || defined( __hpux ) || defined( _M_XENIX ) || \
	defined( __aux )
  #if defined( _SC_PAGESIZE )
	sysVars[ SYSVAR_PAGESIZE ] = sysconf( _SC_PAGESIZE );
  #elif defined( _SC_PAGE_SIZE )
	sysVars[ SYSVAR_PAGESIZE ] = sysconf( _SC_PAGE_SIZE );
  #else
	sysVars[ SYSVAR_PAGESIZE ] = 4096;	/* Close enough for most systems */
  #endif /* Systems without getpagesize() */
#else
	sysVars[ SYSVAR_PAGESIZE ] = getpagesize();
#endif /* Unix variant-specific brokenness */
	if( sysVars[ SYSVAR_PAGESIZE ] < 1024 )
		{
		assert( DEBUG_WARN );

		/* Suspiciously small reported page size, just assume a sensible 
		   value */
		sysVars[ SYSVAR_PAGESIZE ] = 4096;
		}

#if defined( __GNUC__ ) && defined( __i386__ ) && !defined( NO_ASM )
	/* Get system hardware capabilities */
	sysVars[ SYSVAR_HWCAP ] = getHWInfo();
#endif /* __GNUC__ && __i386__ */

#if defined( __IBMC__ ) || defined( __IBMCPP__ )
	/* VisualAge C++ doesn't set the TZ correctly */
	tzset();
#endif /* VisualAge C++ */

	return( CRYPT_OK );
	}

#else

int initSysVars( void )
	{
	/* Reset the system variable information */
	memset( sysVars, 0, MAX_SYSVARS );

	return( CRYPT_OK );
	}
#endif /* OS-specific support */

int getSysVar( const SYSVAR_TYPE type )
	{
	REQUIRES( type > SYSVAR_NONE && type < SYSVAR_LAST );

	return( sysVars[ type ] );
	}

⌨️ 快捷键说明

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