📄 utils.c
字号:
void filenameFromTemplate( char *buffer, const wchar_t *fileTemplate,
const int count )
{
wchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];
int length;
length = _snwprintf( wcBuffer, FILENAME_BUFFER_SIZE, fileTemplate,
count );
wcstombs( buffer, wcBuffer, length + 1 );
}
void filenameParamFromTemplate( wchar_t *buffer,
const wchar_t *fileTemplate,
const int count )
{
int length;
length = _snwprintf( buffer, FILENAME_BUFFER_SIZE, fileTemplate,
count );
}
#endif /* UNICODE_STRINGS */
/****************************************************************************
* *
* Thread Support Functions *
* *
****************************************************************************/
#if defined( WINDOWS_THREADS )
static HANDLE hMutex;
void createMutex( void )
{
hMutex = CreateMutex( NULL, FALSE, NULL );
}
void acquireMutex( void )
{
if( WaitForSingleObject( hMutex, 30000 ) == WAIT_TIMEOUT )
{
puts( "Warning: Couldn't acquire mutex after 30s wait. Press a "
"key to continue." );
getchar();
}
}
int waitMutex( void )
{
if( WaitForSingleObject( hMutex, 30000 ) == WAIT_TIMEOUT )
return( CRYPT_ERROR_TIMEOUT );
/* Since this is merely a synchronisation operation in which a later
thread waits to catch up to an earlier one, we release the mutex again
so other threads can get in */
releaseMutex();
return( CRYPT_OK );
}
void releaseMutex( void )
{
if( !ReleaseMutex( hMutex ) )
{
puts( "Warning: Couldn't release mutex. Press a key to continue." );
getchar();
}
}
void destroyMutex( void )
{
CloseHandle( hMutex );
}
void waitForThread( const HANDLE hThread )
{
if( WaitForSingleObject( hThread, 15000 ) == WAIT_TIMEOUT )
{
puts( "Warning: Server thread is still active due to session "
"negotiation failure,\n this will cause an error "
"condition when cryptEnd() is called due\n to "
"resources remaining allocated. Press a key to continue." );
getchar();
}
CloseHandle( hThread );
}
#elif defined( UNIX_THREADS )
static pthread_mutex_t mutex;
void createMutex( void )
{
pthread_mutex_init( &mutex, NULL );
}
void acquireMutex( void )
{
pthread_mutex_lock( &mutex );
}
int waitMutex( void )
{
pthread_mutex_lock( &mutex );
/* Since this is merely a synchronisation operation in which a later
thread waits to catch up to an earlier one, we release the mutex again
so other threads can get in */
releaseMutex();
return( CRYPT_OK );
}
void releaseMutex( void )
{
pthread_mutex_unlock( &mutex );
}
void destroyMutex( void )
{
pthread_mutex_destroy( &mutex );
}
void waitForThread( const pthread_t hThread )
{
if( pthread_join( hThread, NULL ) < 0 )
{
puts( "Warning: Server thread is still active due to session "
"negotiation failure,\n this will cause an error "
"condition when cryptEnd() is called due\n to "
"resources remaining allocated. Press a key to continue." );
getchar();
}
}
#else
void createMutex( void )
{
}
void acquireMutex( void )
{
}
void releaseMutex( void )
{
}
int waitMutex( void )
{
return( CRYPT_OK );
}
void destroyMutex( void )
{
}
#endif /* WINDOWS_THREADS */
#if defined( WINDOWS_THREADS ) || defined( UNIX_THREADS )
/* Dispatch multiple client and server threads and wait for them to exit */
int multiThreadDispatch( THREAD_FUNC clientFunction,
THREAD_FUNC serverFunction, const int noThreads )
{
THREAD_HANDLE hClientThreads[ MAX_NO_THREADS ];
THREAD_HANDLE hServerThreads[ MAX_NO_THREADS ];
int sessionID[ MAX_NO_THREADS ];
int i;
assert( noThreads <= MAX_NO_THREADS );
/* Set up the session ID values */
for( i = 0; i < MAX_NO_THREADS; i++ )
sessionID[ i ] = i;
/* Start the sessions and wait for them initialise. We have to wait for
some time since the multiple private key reads can take awhile */
for( i = 0; i < noThreads; i++ )
{
#ifdef WINDOWS_THREADS
unsigned int threadID;
hServerThreads[ i ] = ( HANDLE ) \
_beginthreadex( NULL, 0, serverFunction,
&sessionID[ i ], 0, &threadID );
#else
pthread_t threadHandle;
hServerThreads[ i ] = 0;
if( pthread_create( &threadHandle, NULL, serverFunction,
&sessionID[ i ] ) == 0 )
hServerThreads[ i ] = threadHandle;
#endif /* Windows vs. pthreads */
}
delayThread( 3 );
/* Connect to the local server */
for( i = 0; i < noThreads; i++ )
{
#ifdef WINDOWS_THREADS
unsigned int threadID;
hClientThreads[ i ] = ( HANDLE ) \
_beginthreadex( NULL, 0, clientFunction,
&sessionID[ i ], 0, &threadID );
#else
pthread_t threadHandle;
hServerThreads[ i ] = 0;
if( pthread_create( &threadHandle, NULL, clientFunction,
&sessionID[ i ] ) == 0 )
hClientThreads[ i ] = threadHandle;
#endif /* Windows vs. pthreads */
}
#ifdef WINDOWS_THREADS
if( WaitForMultipleObjects( noThreads, hServerThreads, TRUE,
60000 ) == WAIT_TIMEOUT || \
WaitForMultipleObjects( noThreads, hClientThreads, TRUE,
60000 ) == WAIT_TIMEOUT )
#else
/* Posix doesn't have an ability to wait for multiple threads for mostly
religious reasons ("That's not how we do things around here") so we
just wait for two token threads */
pthread_join( hServerThreads[ 0 ], NULL );
pthread_join( hClientThreads[ 0 ], NULL );
#endif /* Windows vs. pthreads */
{
puts( "Warning: Server threads are still active due to session "
"negotiation failure,\n this will cause an error "
"condition when cryptEnd() is called due\n to "
"resources remaining allocated. Press a key to continue." );
getchar();
}
#ifdef WINDOWS_THREADS
for( i = 0; i < noThreads; i++ )
if( hServerThreads[ i ] != 0 )
CloseHandle( hServerThreads[ i ] );
for( i = 0; i < noThreads; i++ )
if( hClientThreads[ i ] != 0 )
CloseHandle( hClientThreads[ i ] );
#endif /* Windows vs. pthreads */
return( TRUE );
}
#endif /* Windows/Unix threads */
/****************************************************************************
* *
* Error-handling Functions *
* *
****************************************************************************/
/* Print extended error attribute information */
void printErrorAttributeInfo( const CRYPT_HANDLE cryptHandle )
{
int errorType, errorLocus;
int status;
status = cryptGetAttribute( cryptHandle, CRYPT_ATTRIBUTE_ERRORTYPE,
&errorType );
cryptGetAttribute( cryptHandle, CRYPT_ATTRIBUTE_ERRORLOCUS, &errorLocus );
if( cryptStatusOK( status ) && errorType != CRYPT_ERRTYPE_NONE )
printf( " Error info attributes report locus %d, type %d.\n",
errorLocus, errorType );
}
/* Print extended object error information */
void printExtError( const CRYPT_HANDLE cryptHandle,
const char *functionName, const int functionStatus,
const int lineNo )
{
char errorMessage[ 512 ];
int errorCode, errorMessageLength, status, msgStatus;
printf( "%s failed with error code %d, line %d.\n", functionName,
functionStatus, lineNo );
status = cryptGetAttribute( cryptHandle, CRYPT_ATTRIBUTE_INT_ERRORCODE,
&errorCode );
msgStatus = cryptGetAttributeString( cryptHandle,
CRYPT_ATTRIBUTE_INT_ERRORMESSAGE,
errorMessage, &errorMessageLength );
if( cryptStatusError( status ) )
{
printf( "Read of error attributes failed with error code %d, "
"line %d.\n", status, __LINE__ );
return;
}
if( !errorCode && cryptStatusError( msgStatus ) )
{
puts( " No extended error information available." );
printErrorAttributeInfo( cryptHandle );
return;
}
if( errorCode )
printf( " Extended error code = %d (0x%X).\n", errorCode,
errorCode );
if( cryptStatusOK( msgStatus ) )
{
errorMessage[ errorMessageLength ] = '\0';
printf( " Error message = %s'%s'.\n",
( errorMessageLength > ( 80 - 21 ) ) ? "\n " : "",
errorMessage );
}
else
puts( "." );
printErrorAttributeInfo( cryptHandle );
}
/* Exit with an error message. attrErrorExit() prints the locus and type,
extErrorExit() prints the extended error code and message */
BOOLEAN attrErrorExit( const CRYPT_HANDLE cryptHandle,
const char *functionName, const int errorCode,
const int lineNumber )
{
printf( "%s failed with error code %d, line %d.\n", functionName,
errorCode, lineNumber );
printErrorAttributeInfo( cryptHandle );
return( FALSE );
}
BOOLEAN extErrorExit( const CRYPT_HANDLE cryptHandle,
const char *functionName, const int errorCode,
const int lineNumber )
{
printExtError( cryptHandle, functionName, errorCode, lineNumber );
cryptDestroyObject( cryptHandle );
return( FALSE );
}
/****************************************************************************
* *
* Misc. Functions *
* *
****************************************************************************/
/* Some algorithms can be disabled to eliminate patent problems or reduce the
size of the code. The following functions are used to select generally
equivalent alternatives if the required algorithm isn't available. These
selections make certain assumptions, namely that at least one of the
algorithms in the fallback chain is always available (which is guaranteed,
3DES is used internally), and that they have the same general properties
as the algorithms they're replacing, which is also usually the case,
with Blowfish being a first-instance substitute for IDEA, RC2, or RC5, and
then 3DES as the fallback if Blowfish isn't available */
CRYPT_ALGO_TYPE selectCipher( const CRYPT_ALGO_TYPE algorithm )
{
if( cryptStatusOK( cryptQueryCapability( algorithm, NULL ) ) )
return( algorithm );
if( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_BLOWFISH, NULL ) ) )
return( CRYPT_ALGO_BLOWFISH );
return( CRYPT_ALGO_3DES );
}
/* Add a collection of fields to a certificate */
int addCertFields( const CRYPT_CERTIFICATE certificate,
const CERT_DATA *certData, const int lineNo )
{
int i;
for( i = 0; certData[ i ].type != CRYPT_ATTRIBUTE_NONE; i++ )
{
int status;
switch( certData[ i ].componentType )
{
case IS_NUMERIC:
status = cryptSetAttribute( certificate,
certData[ i ].type, certData[ i ].numericValue );
if( cryptStatusError( status ) )
printf( "cryptSetAttribute() for entry %d, field ID %d,\n"
" value %d, failed with error code %d, line %d.\n",
i + 1, certData[ i ].type, certData[ i ].numericValue,
status, lineNo );
break;
case IS_STRING:
status = cryptSetAttributeString( certificate,
certData[ i ].type, certData[ i ].stringValue,
certData[ i ].numericValue ? \
certData[ i ].numericValue : \
paramStrlen( certData[ i ].stringValue ) );
if( cryptStatusError( status ) )
{
#if defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && !defined( NDEBUG )
if( status == CRYPT_ERROR_INVALID && \
paramStrlen( certData[ i ].stringValue ) == 2 && \
!memcmp( certData[ i ].stringValue, "NZ", 2 ) )
{
/* Warn about BoundsChecker-induced Heisenbugs */
puts( " ********************" );
puts( "If you're running this under BoundsChecker "
"you need to disable it to complete\nthe test "
"since it causes errors in the cert "
"string-checking code. The\nfollowing error "
"is caused by BoundsChecker, not by the "
"self-test failing." );
puts( " ********************" );
}
#endif /* VC++ 6 */
printf( "cryptSetAttributeString() for entry %d, field ID %d,\n"
" value '%s', failed with error code %d, line %d.\n",
i + 1, certData[ i ].type,
( char * ) certData[ i ].stringValue, status,
lineNo );
}
break;
#ifdef HAS_WIDECHAR
case IS_WCSTRING:
status = cryptSetAttributeString( certificate,
certData[ i ].type, certData[ i ].stringValue,
wcslen( certData[ i ].stringValue ) * sizeof( wchar_t ) );
if( cryptStatusError( status ) )
printf( "cryptSetAttributeString() for entry %d, field ID %d,\n"
" value '%s', failed with error code %d, line %d.\n",
i + 1, certData[ i ].type,
( char * ) certData[ i ].stringValue, status,
lineNo );
break;
#endif /* HAS_WIDECHAR */
case IS_TIME:
status = cryptSetAttributeString( certificate,
certData[ i ].type, &certData[ i ].timeValue,
sizeof( time_t ) );
if( cryptStatusError( status ) )
printf( "cryptSetAttributeString() for entry %d, field ID %d,\n"
" value 0x%lX, failed with error code %d, line %d.\n",
i + 1, certData[ i ].type, certData[ i ].timeValue,
status, lineNo );
break;
default:
assert( FALSE );
return( FALSE );
}
if( cryptStatusError( status ) )
{
printErrorAttributeInfo( certificate );
return( FALSE );
}
}
return( TRUE );
}
/* Populate a key database with the contents of a directory. This is a
rather OS-specific utility function for setting up test databases that
only works under Win32 (in fact it's not used at all at the moment) */
#if defined( _MSC_VER ) && defined( _WIN32 ) && !defined( _WIN32_WCE ) && 0
void loadCertificates( void )
{
WIN32_FIND_DATA findData;
HANDLE searchHandle;
searchHandle = FindFirstFile( "d:/tmp/certs/*.der", &findData );
if( searchHandle == INVALID_HANDLE_VALUE )
return;
do
{
CRYPT_CERTIFICATE cryptCert;
int status;
printf( "Adding cert %s.\n", findData.cFileName );
status = importCertFile( &cryptCert, findData.cFileName );
if( cryptStatusOK( status ) )
{
cryptDestroyCert( cryptCert );
}
}
while( FindNextFile( searchHandle, &findData ) );
FindClose( searchHandle );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -