📄 cryptmis.c
字号:
setMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_AUTO );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_ENVELOPE );
if( cryptStatusError( status ) )
return( status );
iCryptEnvelope = createInfo.cryptHandle;
krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &minBufferSize, CRYPT_ATTRIBUTE_BUFFERSIZE );
krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_ATTRONLY );
setMessageData( &msgData, ( void * ) inData, inDataLength );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,
&msgData, 0 );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,
&msgData, 0 );
}
if( cryptStatusOK( status ) && iSigCheckKey != CRYPT_UNUSED )
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &iSigCheckKey,
CRYPT_ENVINFO_SIGNATURE );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_GETATTRIBUTE,
sigResult, CRYPT_ENVINFO_SIGNATURE_RESULT );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, outData, outDataMaxLength );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_POPDATA,
&msgData, 0 );
}
if( cryptStatusOK( status ) && iSigningCert != NULL )
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_GETATTRIBUTE,
iSigningCert,
CRYPT_ENVINFO_SIGNATURE );
if( cryptStatusOK( status ) && iCmsAttributes != NULL )
{
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_GETATTRIBUTE,
iCmsAttributes,
CRYPT_ENVINFO_SIGNATURE_EXTRADATA );
if( cryptStatusError( status ) && iSigningCert != NULL )
krnlSendNotifier( *iSigningCert, IMESSAGE_DECREFCOUNT );
}
krnlSendNotifier( iCryptEnvelope, IMESSAGE_DECREFCOUNT );
if( cryptStatusOK( status ) )
*outDataLength = msgData.length;
return( status );
}
/****************************************************************************
* *
* Extended libc Functions *
* *
****************************************************************************/
/* Match a given substring against a string in a case-insensitive manner.
If possible we use native calls to handle this since they deal with
charset-specific issues such as collating sequences, however a few OSes
don't provide this functionality so we have to do it ourselves */
#if defined( __SYMBIAN32__ ) || defined( __BEOS__ )
int strnicmp( const char *src, const char *dest, int length )
{
while( length-- )
{
char srcCh = *src++, destCh = *dest++;
/* Need to be careful with toupper() side-effects */
srcCh = toUpper( srcCh );
destCh = toUpper( destCh );
if( srcCh != destCh )
return( srcCh - destCh );
}
return( 0 );
}
int stricmp( const char *src, const char *dest )
{
const int length = strlen( src );
if( length != strlen( dest ) )
return( 1 ); /* Lengths differ */
return( strnicmp( src, dest, length ) );
}
#endif /* OSes without case-insensitive string compares */
/* Debugging malloc() that dumps memory usage diagnostics to stdout */
#ifdef CONFIG_DEBUG_MALLOC
#ifdef __WIN32__
#include <direct.h>
#endif /* __WIN32__ */
static int clAllocIndex = 0;
void *clAllocFn( const char *fileName, const char *fnName,
const int lineNo, size_t size )
{
char buffer[ 512 ];
BYTE *memPtr;
int length;
/* Strip off the leading path components if we can to reduce the amount
of noise in the output */
#if defined( __WIN32__ ) || defined( __UNIX__ )
if( getcwd( buffer, 512 ) != NULL )
fileName += strlen( buffer ) + 1; /* Skip leading path + '/' */
#endif /* __WIN32__ || __UNIX__ */
length = printf( "ALLOC: %s:%s:%d", fileName, fnName, lineNo );
while( length < 46 )
{
putchar( ' ' );
length++;
}
printf( " %4d - %d bytes.\n", clAllocIndex, size );
if( ( memPtr = malloc( size + 4 ) ) == NULL )
return( NULL );
mputLong( memPtr, clAllocIndex );
clAllocIndex++;
return( memPtr );
}
void clFreeFn( const char *fileName, const char *fnName,
const int lineNo, void *memblock )
{
char buffer[ 512 ];
BYTE *memPtr = ( BYTE * ) memblock - 4;
int length, index;
/* Strip off the leading path components if we can to reduce the amount
of noise in the output */
#if defined( __WIN32__ ) || defined( __UNIX__ )
if( getcwd( buffer, 512 ) != NULL )
fileName += strlen( buffer ) + 1; /* Skip leading path + '/' */
#endif /* __WIN32__ || __UNIX__ */
index = mgetLong( memPtr );
length = printf( "ALLOC: %s:%s:%d", fileName, fnName, lineNo );
while( length < 46 )
{
putchar( ' ' );
length++;
}
printf( " %4d.\n", index );
free( memPtr - 4 );
}
#endif /* CONFIG_DEBUG_MALLOC */
/****************************************************************************
* *
* OS-specific Helper Functions *
* *
****************************************************************************/
/* For performance evaluation purposes we provide the following function,
which returns ticks of the 3.579545 MHz hardware timer (see the long
comment in rndwin32.c for more details on Win32 timing issues) */
#if defined( __WIN32__ ) && !defined( NDEBUG )
unsigned long getTickCount( unsigned long startTime )
{
LARGE_INTEGER performanceCount;
unsigned long timeLSB;
/* Sensitive to context switches */
QueryPerformanceCounter( &performanceCount );
timeLSB = performanceCount.LowPart;
if( !startTime )
return( timeLSB );
if( startTime < timeLSB )
return( timeLSB - startTime );
return( ( 0xFFFFFFFF - startTime ) + 1 + timeLSB );
}
#endif /* __WIN32__ debug build */
/* WinNT and its derivatives support ACL-based access control mechanisms for
system objects (modulo a great many holes), so when we create objects such
as files and threads we give them an ACL that allows only the creator
access. The following functions return the security info needed when
creating objects. The interface for this has changed in every major NT
release, although it never got any better, just differently ugly. The
following code uses the original NT 3.1 interface, which works for all OS
versions */
#if defined( __WIN32__ )
/* The size of the buffer for ACLs and the user token */
#define ACL_BUFFER_SIZE 1024
#define TOKEN_BUFFER_SIZE 256
/* A composite structure to contain the various ACL structures. This is
required because ACL handling is a complex, multistage operation that
requires first creating an ACL and security descriptor to contain it,
adding an access control entry (ACE) to the ACL, adding the ACL as the
DACL of the security descriptor, and finally, wrapping the security
descriptor up in a security attributes structure that can be passed to
an object-creation function.
The handling of the TOKEN_INFO is extraordinarily ugly because although
the TOKEN_USER struct as defined is only 8 bytes long, Windoze allocates
an extra 24 bytes after the end of the struct into which it stuffs data
that the SID pointer in the TOKEN_USER struct points to. This means we
can't statically allocate memory of the size of the TOKEN_USER struct but
have to make it a pointer into a larger buffer that can contain the
additional invisible data tacked onto the end */
typedef struct {
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR pSecurityDescriptor;
PACL pAcl;
PTOKEN_USER pTokenUser;
BYTE aclBuffer[ ACL_BUFFER_SIZE ];
BYTE tokenBuffer[ TOKEN_BUFFER_SIZE ];
} SECURITY_INFO;
/* Initialise an ACL allowing only the creator access and return it to the
caller as an opaque value */
void *initACLInfo( const int access )
{
SECURITY_INFO *securityInfo;
HANDLE hToken = INVALID_HANDLE_VALUE; /* See comment below */
BOOLEAN tokenOK = FALSE;
/* Win95 doesn't have any security, return null security info */
if( isWin95 )
return( NULL );
/* Allocate and initialise the composite security info structure */
if( ( securityInfo = \
clAlloc( "initACLInfo", sizeof( SECURITY_INFO ) ) ) == NULL )
return( NULL );
memset( securityInfo, 0, sizeof( SECURITY_INFO ) );
securityInfo->pAcl = ( PACL ) securityInfo->aclBuffer;
securityInfo->pTokenUser = ( PTOKEN_USER ) securityInfo->tokenBuffer;
/* Get the security token for this thread. First we try for the thread
token (which it typically only has when impersonating), if we don't
get that we use the token associated with the process. We also
initialise the hToken even though it shouldn't be necessary because
Windows tries to read its contents, which indicates there might be
problems if it happens to start out with the wrong value */
if( OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken ) || \
OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) )
{
DWORD cbTokenUser;
tokenOK = GetTokenInformation( hToken, TokenUser,
securityInfo->pTokenUser,
TOKEN_BUFFER_SIZE, &cbTokenUser );
CloseHandle( hToken );
}
if( !tokenOK )
{
clFree( "initACLInfo", securityInfo );
return( NULL );
}
/* Set a security descriptor owned by the current user */
if( !InitializeSecurityDescriptor( &securityInfo->pSecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION ) || \
!SetSecurityDescriptorOwner( &securityInfo->pSecurityDescriptor,
securityInfo->pTokenUser->User.Sid,
FALSE ) )
{
clFree( "initACLInfo", securityInfo );
return( NULL );
}
/* Set up the discretionary access control list (DACL) with one access
control entry (ACE) for the current user */
if( !InitializeAcl( securityInfo->pAcl, ACL_BUFFER_SIZE,
ACL_REVISION ) || \
!AddAccessAllowedAce( securityInfo->pAcl, ACL_REVISION, access,
securityInfo->pTokenUser->User.Sid ) )
{
clFree( "initACLInfo", securityInfo );
return( NULL );
}
/* Bind the DACL to the security descriptor */
if( !SetSecurityDescriptorDacl( &securityInfo->pSecurityDescriptor, TRUE,
securityInfo->pAcl, FALSE ) )
{
clFree( "initACLInfo", securityInfo );
return( NULL );
}
assert( IsValidSecurityDescriptor( &securityInfo->pSecurityDescriptor ) );
/* Finally, set up the security attributes structure */
securityInfo->sa.nLength = sizeof( SECURITY_ATTRIBUTES );
securityInfo->sa.bInheritHandle = FALSE;
securityInfo->sa.lpSecurityDescriptor = &securityInfo->pSecurityDescriptor;
return( securityInfo );
}
void freeACLInfo( void *securityInfoPtr )
{
SECURITY_INFO *securityInfo = ( SECURITY_INFO * ) securityInfoPtr;
if( securityInfo == NULL )
return;
clFree( "freeACLInfo", securityInfo );
}
/* Extract the security info needed in Win32 API calls from the collection of
security data we set up earlier */
void *getACLInfo( void *securityInfoPtr )
{
SECURITY_INFO *securityInfo = ( SECURITY_INFO * ) securityInfoPtr;
return( ( securityInfo == NULL ) ? NULL : &securityInfo->sa );
}
#endif /* __WIN32__ */
/* SCO creates threads with a ridiculously small default stack size of a few
KB or so, which means the thread can't even start. To work around this we
use a wrapper that sets a slightly larger thread stack size */
#if defined( __SCO_VERSION__ ) && defined( USE_THREADS )
int int createThread( void *( *function )( void * ), void *arg,
pthread_t *handle )
{
pthread_attr_t attr;
pthread_t dummy;
int status;
/* Create the thread, setting the stack size to a sensible value
rather than the default used by SCO */
pthread_attr_init( &attr );
pthread_attr_setstacksize( &attr, 32768 );
status = pthread_create( &handle, &attr, function, arg );
pthread_attr_destroy( &attr );
return( status ? CRYPT_ERROR : CRYPT_OK );
}
#endif /* UnixWare/SCO with threading */
/* VM/CMS, MVS, and AS/400 systems need to convert characters from ASCII <->
EBCDIC before/after they're read/written to external formats, the
following functions perform the necessary conversion using the latin-1
code tables for systems that don't have etoa/atoe */
#ifdef EBCDIC_CHARS
#include <stdarg.h>
#ifndef USE_ETOA
/* ISO 8859-1 to IBM Latin-1 Code Page 01047 (EBCDIC). */
static const BYTE asciiToEbcdicTbl[] = {
0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 00 - 07 */
0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */
0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /* 10 - 17 */
0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -