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

📄 utils.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************
*																			*
*					  cryptlib Self-test Utility Routines					*
*						Copyright Peter Gutmann 1997-2007					*
*																			*
****************************************************************************/

#include "cryptlib.h"
#include "test/test.h"

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

#ifdef HAS_WIDECHAR
  #include <wchar.h>
#endif /* HAS_WIDECHAR */

/* The keys used with the test code have associated certs that expire at
   some point.  The following value defines the number of days before the
   expiry at which we start printing warnings */

#if defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && !defined( NDEBUG )
  #define EXPIRY_WARN_DAYS		90
#else
  #define EXPIRY_WARN_DAYS		30
#endif /* VC 6 debug/development, give some advance warning */

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

#ifndef _WIN32_WCE

/* Since ctime() adds a '\n' to the string and may return NULL, we wrap it
   in something that behaves as required */

static char *getTimeString( const time_t theTime, const int bufNo )
	{
	static char timeString[ 2 ][ 64 ], *timeStringPtr;

	assert( bufNo == 0 || bufNo == 1 );

	timeStringPtr = ctime( &theTime );
	if( timeStringPtr == NULL )
		return( "(Not available)" );
	strcpy( timeString[ bufNo ], timeStringPtr );
	timeString[ bufNo ][ strlen( timeStringPtr ) - 1 ] = '\0';	/* Stomp '\n' */

	return( timeString[ bufNo ] );
	}
#else
  #define getTimeString( theTime, bufNo )	"(No time data available)"
#endif /* _WIN32_WCE */

/****************************************************************************
*																			*
*							General Checking 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;
	BYTE buffer[ BUFFER_SIZE ];
	int length, 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 );

	/* Now read the test files and see if there's any problem due to data 
	   conversion evident */
	filenameFromTemplate( buffer, TESTDATA_FILE_TEMPLATE, 1 );
	if( ( filePtr = fopen( buffer, "rb" ) ) == NULL )
		{
		puts( "Couldn't open binary data test file to check for data "
			  "conversion problems." );
		return( FALSE );
		}
	length = fread( buffer, 1, BUFFER_SIZE, filePtr );
	fclose( filePtr );
	if( length != 16 || \
		memcmp( buffer, "\x30\x82\x02\x56\x30\x82\x02\x52\r\n\x08\x40\n" "tqz", 16 ) )
		{
		puts( "Binary data is corrupt, probably due to being unzipped or "
			  "copied onto the\nsystem in a mode that tries to translate "
			  "text data during processing/copying." );
		return( FALSE );
		}
#ifdef __UNIX__
	filenameFromTemplate( buffer, TESTDATA_FILE_TEMPLATE, 2 );
	if( ( filePtr = fopen( buffer, "rb" ) ) == NULL )
		{
		puts( "Couldn't open text data test file to check for data "
			  "conversion problems." );
		return( FALSE );
		}
	length = fread( buffer, 1, BUFFER_SIZE, filePtr );
	fclose( filePtr );
	if( length != 10 || memcmp( buffer, "test\ntest\n" , 10 ) )
		{
		puts( "Text data is still in CRLF-delimited format, probably due "
			  "to being unzipped\nwithout the '-a' option to translate "
			  "text files for Unix systems." );
		return( FALSE );
		}
#endif /* __UNIX__ */

	/* The file exists and is accessible and was copied/installed correctly, 
	   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 ) )
		{
		/* If file keyset access isn't available, the inability to access
		   the keyset isn't an error */
		if( status == CRYPT_ERROR_NOTAVAIL )
			return( TRUE );

		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 );
	}

/* Check that external network sites are accessible, used to detect 
   potential problems with machines stuck behind firewalls */

int checkNetworkAccess( void )
	{
	CRYPT_KEYSET cryptKeyset;
	int status;

	status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_HTTP,
							  TEXT( "www.amazon.com" ), CRYPT_KEYOPT_READONLY );
	if( cryptStatusError( status ) )
		return( FALSE );
	cryptKeysetClose( cryptKeyset );

	return( TRUE );
	}

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

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

/* 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.  We check not
	   just the expiry date but also the expiry interval, to make sure that
	   we don't get false positives on short-validity certs */
	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 * EXPIRY_WARN_DAYS ) ) && \
		validTo - time( NULL ) <= ( 86400 * EXPIRY_WARN_DAYS ) )
		{
		const time_t currentTime = time( NULL );

		puts( "                         ********************" );
		if( validTo <= currentTime )
			{
			puts( "Warning: This key has expired.  Certificate-related "
				  "operations will fail or\n         result in error "
				  "messages from the test code." );
			}
		else
			{
			if( validTo - currentTime <= 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 - currentTime ) / 86400 );
				}
			}
		puts( "                         ********************" );
		printf( "Hit a key..." );
		getchar();
		putchar( '\r' );
		}
#endif /* _WIN32_WCE */
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Key File Access Routines						*
*																			*
****************************************************************************/

/* Key file and password-handling access routines */

const C_STR getKeyfileName( const KEYFILE_TYPE type,
							const BOOLEAN isPrivKey )
	{
	switch( type )
		{
		case KEYFILE_X509:
			return( USER_PRIVKEY_FILE );
		case KEYFILE_PGP:
			return( isPrivKey ? PGP_PRIVKEY_FILE : PGP_PUBKEY_FILE );
		case KEYFILE_OPENPGP:
			return( isPrivKey ? OPENPGP_PRIVKEY_FILE : OPENPGP_PUBKEY_FILE );
		case KEYFILE_OPENPGP_HASH:
			return( isPrivKey ? OPENPGP_PRIVKEY_HASH_FILE : OPENPGP_PUBKEY_HASH_FILE );
		case KEYFILE_OPENPGP_AES:
			return( isPrivKey ? OPENPGP_PRIVKEY_AES_FILE : OPENPGP_PUBKEY_AES_FILE );
		case KEYFILE_OPENPGP_RSA:
			return( isPrivKey ? OPENPGP_PRIVKEY_RSA_FILE : OPENPGP_PUBKEY_RSA_FILE );
		case KEYFILE_OPENPGP_PARTIAL:
			return( OPENPGP_PRIVKEY_PART_FILE );
		case KEYFILE_NAIPGP:
			return( isPrivKey ? NAIPGP_PRIVKEY_FILE : NAIPGP_PUBKEY_FILE );
		}
	assert( 0 );
	return( TEXT( "notfound" ) );
	}

const C_STR getKeyfilePassword( const KEYFILE_TYPE type )
	{
	switch( type )
		{
		case KEYFILE_X509:
			return( TEST_PRIVKEY_PASSWORD );
		case KEYFILE_PGP:
		case KEYFILE_OPENPGP:
		case KEYFILE_OPENPGP_HASH:
		case KEYFILE_OPENPGP_RSA:
			return( TEXT( "test1" ) );
		case KEYFILE_NAIPGP:
			return( TEXT( "test10" ) );
		case KEYFILE_OPENPGP_AES:
			return( TEXT( "testkey" ) );
		case KEYFILE_OPENPGP_PARTIAL:
			return( TEXT( "def" ) );
		}
	assert( 0 );
	return( TEXT( "notfound" ) );
	}

const C_STR getKeyfileUserID( const KEYFILE_TYPE type,
							  const BOOLEAN isPrivKey )
	{
	/* If possible we specify user IDs for keys in the middle of the keyring
	   to make sure that we test the ability to correctly handle multiple
	   keys */
	switch( type )
		{
		case KEYFILE_X509:
			return( USER_PRIVKEY_LABEL );
		case KEYFILE_PGP:
			return( TEXT( "test" ) );
		case KEYFILE_NAIPGP:
			return( isPrivKey ? TEXT( "test" ) : TEXT( "test cryptlib" ) );
		case KEYFILE_OPENPGP:
		case KEYFILE_OPENPGP_HASH:
		case KEYFILE_OPENPGP_RSA:
			return( TEXT( "test1" ) );
		case KEYFILE_OPENPGP_AES:
			return( TEXT( "Max Mustermann" ) );
		}
	assert( 0 );
	return( TEXT( "notfound" ) );
	}

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

⌨️ 快捷键说明

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