📄 os_spec.c
字号:
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 + -