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

📄 utils.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*					  cryptlib Self-test Utility Routines					*
*						Copyright Peter Gutmann 1997-2004					*
*																			*
****************************************************************************/

#ifdef _MSC_VER
  #include "../cryptlib.h"
  #include "test.h"
#else
  #include "cryptlib.h"
  #include "test/test.h"
#endif /* Braindamaged MSC include handling */

#if defined( __MVS__ ) || defined( __VMCMS__ )
  /* Suspend conversion of literals to ASCII. */
  #pragma convlit( suspend )
#endif /* IBM big iron */
#if defined( __ILEC400__ )
  #pragma convert( 0 )
#endif /* IBM medium iron */

/****************************************************************************
*																			*
*							Import/Export Functions							*
*																			*
****************************************************************************/

/* Check that a file is accessible.  This is a generic sanity check to make
   sure that access to keyset files is functioning */

int checkFileAccess( void )
	{
	CRYPT_KEYSET cryptKeyset;
	FILE *filePtr;
	int status;

	/* First, check that the file actually exists so that we can return an 
	   appropriate error message */
	if( ( filePtr = fopen( convertFileName( CA_PRIVKEY_FILE ), 
						   "rb" ) ) == NULL )
		{
		printf( "Couldn't access cryptlib keyset file %s.  Please make "
				"sure\nthat all the cryptlib files have been installed "
				"correctly, and the cryptlib\nself-test is being run from "
				"the correct directory.\n", CA_PRIVKEY_FILE );
		return( FALSE );
		}
	fclose( filePtr );

	/* The file exists and is accessible, now try and open it using the
	   cryptlib file access functions */
	status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
							  CA_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );
	if( cryptStatusError( status ) )
		{
		printf( "Couldn't access cryptlib keyset file %s even though the "
				"file\nexists and is readable.  Please make sure that the "
				"cryptlib self-test is\nbeing run from the correct "
				"directory.\n", CA_PRIVKEY_FILE );
		return( FALSE );
		}
	cryptKeysetClose( cryptKeyset );

	return( TRUE );
	}

/* Import a certificate object */

int importCertFile( CRYPT_CERTIFICATE *cryptCert, const C_STR fileName )
	{
	FILE *filePtr;
	BYTE buffer[ BUFFER_SIZE ];
	int count;

	if( ( filePtr = fopen( convertFileName( fileName ), "rb" ) ) == NULL )
		return( CRYPT_ERROR_OPEN );
	count = fread( buffer, 1, BUFFER_SIZE, filePtr );
	fclose( filePtr );
    if( count == BUFFER_SIZE )	/* Item too large for buffer */
		return( CRYPT_ERROR_OVERFLOW );

	/* Import the certificate */
	return( cryptImportCert( buffer, count, CRYPT_UNUSED, cryptCert ) );
	}

int importCertFromTemplate( CRYPT_CERTIFICATE *cryptCert,
							const C_STR fileTemplate, const int number )
	{
	BYTE filenameBuffer[ FILENAME_BUFFER_SIZE ];
#ifdef UNICODE_STRINGS
	wchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];
#endif /* UNICODE_STRINGS */

	filenameFromTemplate( filenameBuffer, fileTemplate, number );
#ifdef UNICODE_STRINGS
	mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
	return( importCertFile( cryptCert, wcBuffer ) );
#else
	return( importCertFile( cryptCert, filenameBuffer ) );
#endif /* UNICODE_STRINGS */
	}

/* Get a line of text from the user */

static void getText( char *input, const char *prompt )
	{
	printf( "Enter %s: ", prompt );
	fflush( stdout );
	fgets( input, CRYPT_MAX_TEXTSIZE - 1, stdin );
	putchar( '\n' );
	}

/* Read a key from a key file */

int getPublicKey( CRYPT_CONTEXT *cryptContext, const C_STR keysetName,
				  const C_STR keyName )
	{
	CRYPT_KEYSET cryptKeyset;
	int status;

	/* Read the key from the keyset */
	status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
							  keysetName, CRYPT_KEYOPT_READONLY );
	if( cryptStatusError( status ) )
		return( status );
	status = cryptGetPublicKey( cryptKeyset, cryptContext, CRYPT_KEYID_NAME,
								keyName );
	cryptKeysetClose( cryptKeyset );
	return( status );
	}

int getPrivateKey( CRYPT_CONTEXT *cryptContext, const C_STR keysetName,
				   const C_STR keyName, const C_STR password )
	{
	CRYPT_KEYSET cryptKeyset;
	time_t validFrom, validTo;
	int dummy, status;

	/* Read the key from the keyset */
	status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
							  keysetName, CRYPT_KEYOPT_READONLY );
	if( cryptStatusError( status ) )
		return( status );
	status = cryptGetPrivateKey( cryptKeyset, cryptContext, CRYPT_KEYID_NAME,
								 keyName, password );
	cryptKeysetClose( cryptKeyset );
	if( cryptStatusError( status ) )
		return( status );

	/* If the key has a cert attached, make sure it's still valid before we 
	   hand it back to the self-test functions that will report the problem 
	   as being with the self-test rather than with the cert */
	status = cryptGetAttributeString( *cryptContext,
					CRYPT_CERTINFO_VALIDFROM, &validFrom, &dummy );
	if( cryptStatusError( status ) )
		/* There's no cert there, this isn't an error */
		return( CRYPT_OK );
	cryptGetAttributeString( *cryptContext,
					CRYPT_CERTINFO_VALIDTO, &validTo, &dummy );
#ifndef _WIN32_WCE
	if( ( validTo - validFrom > ( 86400 * 30 ) ) && \
		validTo - time( NULL ) <= ( 86400 * 30 ) )
		{
		puts( "                         ********************" );
		if( validTo <= time( NULL ) )
			puts( "Warning: This key has expired.  Certificate-related "
				  "operations may fail or\n         result in error "
				  "messages from the test code." );
		else
			if( validTo - time( NULL ) <= 86400 )
				puts( "Warning: This key expires today.  Certificate-"
					  "related operations may fail\n         or result in "
					  "error messages from the test code." );
			else
				printf( "Warning: This key will expire in %ld days.  "
						"Certificate-related operations\n         may fail "
						"or result in error messages from the test code.\n",
						( validTo - time( NULL ) ) / 86400 );
		puts( "                         ********************" );
		}
#endif /* _WIN32_WCE */
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							OS Helper Functions								*
*																			*
****************************************************************************/

#if defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x310 )

/* BC++ 3.x doesn't have mbstowcs() in the default library, and also defines
   wchar_t as char (!!) so we fake it here */

size_t mbstowcs( char *pwcs, const char *s, size_t n )
	{
	memcpy( pwcs, s, n );
	return( n );
	}
#endif /* BC++ 3.1 or lower */

/* When using multiple threads we need to delay one thread for a small
   amount of time, unfortunately there's no easy way to do this with pthreads
   so we have to provide the following wrapper function that makes an
   (implementation-specific) attempt at it */

#if defined( UNIX_THREADS ) || defined( WINDOWS_THREADS ) || defined( OS2_THREADS )

#if defined( UNIX_THREADS )
  /* This include must be outside the function to avoid weird compiler errors
	 on some systems */
  #include <sys/time.h>
#endif /* UNIX_THREADS */

void delayThread( const int seconds )
	{
#if defined( UNIX_THREADS )
	struct timeval tv = { 0 };

	/* The following should put a thread to sleep for a second on most
	   systems since the select() should be a thread-safe one in the
	   presence of pthreads */
	tv.tv_sec = seconds;
	select( 1, NULL, NULL, NULL, &tv );
#elif defined( WINDOWS_THREADS )
	Sleep( seconds * 1000 );
#endif /* Threading system-specific delay functions */
	}
#endif /* Systems with threading support */

/* Helper functions to make tracking down errors on systems with no console 
   a bit less painful.  These just use the debug console as stdout */

#ifdef _WIN32_WCE

void wcPrintf( const char *format, ... )
	{
	wchar_t wcBuffer[ 1024 ];
	char buffer[ 1024 ];
	va_list argPtr;

	va_start( argPtr, format );
	vsprintf( buffer, format, argPtr ); 
	va_end( argPtr );
	mbstowcs( wcBuffer, buffer, strlen( buffer ) + 1 );
	NKDbgPrintfW( wcBuffer );
	}

void wcPuts( const char *string )
	{
	wcPrintf( "%s\n", string );
	}
#endif /* Console-less environments */

/* Conversion functions used to get Unicode input into generic ASCII 
   output */

#ifdef UNICODE_STRINGS

/* Get a filename in an appropriate format for the C runtime library */

const char *convertFileName( const C_STR fileName )
	{
	static char fileNameBuffer[ FILENAME_BUFFER_SIZE ];

	wcstombs( fileNameBuffer, fileName, wcslen( fileName ) + 1 );
	return( fileNameBuffer );
	}

/* Map a filename template to an actual filename, input in Unicode, output in
   ASCII */

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 */

/****************************************************************************
*																			*
*							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;
		}
	printf( "  Extended error code = %d (0x%X)", errorCode, errorCode );
	if( cryptStatusOK( msgStatus ) )
		{
		errorMessage[ errorMessageLength ] = '\0';
		printf( ", error message = %s'%s'.\n",
				( errorMessageLength > 40 ) ? "\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 (that the given algorithms are always
   available, which is virtually guaranteed, and that they have the same
   general properties as the algorithms they're replacing, which is also
   usually the case - Blowfish for IDEA, RC2, or RC5, and MD5 for MD4) */

CRYPT_ALGO_TYPE selectCipher( const CRYPT_ALGO_TYPE algorithm )
	{
	if( cryptStatusOK( cryptQueryCapability( algorithm, NULL ) ) )
		return( algorithm );
	return( CRYPT_ALGO_BLOWFISH );
	}

/* Add a collection of fields to a certificate */

int addCertFields( const CRYPT_CERTIFICATE certificate,
				   const CERT_DATA *certData )
	{
	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 field ID %d, value %d, "
							"failed with error code %d, line %d.\n",
							certData[ i ].type, certData[ i ].numericValue,
							status, __LINE__ );
				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 ) )
					printf( "cryptSetAttributeString() for field ID %d,\n"
							"value '%s', failed with error code %d, line %d.\n",
							certData[ i ].type, 
							( char * ) certData[ i ].stringValue, status,  
							__LINE__ );
				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 field ID %d,\n"

⌨️ 快捷键说明

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