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

📄 testlib.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
*																			*
****************************************************************************/

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

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

/* The tests that use databases and cert stores require that the user set
   up a suitable ODBC data source (at least when running under Windows).  To
   help people who don't read documentation, we try and create the data
   source if it isn't present */

#if defined( _MSC_VER ) && defined( _WIN32 )

#define DATABASE_AUTOCONFIG

#include <odbcinst.h>

#define DATABASE_ATTR_NAME		"DSN=" DATABASE_KEYSET_NAME "\0" \
								"DESCRIPTION=cryptlib test key database\0" \
								"DBQ="
#define DATABASE_ATTR_CREATE	"DSN=" DATABASE_KEYSET_NAME "\0" \
								"DESCRIPTION=cryptlib test key database\0" \
								"CREATE_DB="
#define DATABASE_ATTR_TAIL		DATABASE_KEYSET_NAME ".mdb\0"
#define CERTSTORE_ATTR_NAME		"DSN=" CERTSTORE_KEYSET_NAME "\0" \
								"DESCRIPTION=cryptlib test key database\0" \
								"DBQ="
#define CERTSTORE_ATTR_CREATE	"DSN=" CERTSTORE_KEYSET_NAME "\0" \
								"DESCRIPTION=cryptlib test key database\0" \
								"CREATE_DB="
#define CERTSTORE_ATTR_TAIL		CERTSTORE_KEYSET_NAME ".mdb\0"
#ifdef USE_SQLSERVER
  #define DRIVER_NAME			"SQL Server"
#else
  #define DRIVER_NAME			"Microsoft Access Driver (*.MDB)"
#endif /* USE_SQLSERVER */

static void buildDBString( char *buffer, const char *attrName,
						   const int attrNameSize,
						   const char *attrTail, const char *path )
	{
	const int attrTailSize = strlen( attrTail ) + 2;
	const int pathSize = strlen( path );

	memcpy( buffer, attrName, attrNameSize + 1 );
	memcpy( buffer + attrNameSize - 1, path, pathSize );
	memcpy( buffer + attrNameSize - 1 + pathSize, attrTail, attrTailSize );
	}

static void checkCreateDatabaseKeysets( void )
	{
	CRYPT_KEYSET cryptKeyset;
	char tempPathBuffer[ 512 ];
	int length, status;

	if( !( length = GetTempPath( 512, tempPathBuffer ) ) )
		{
		strcpy( tempPathBuffer, "C:\\Temp\\" );
		length = 8;
		}

	/* Try and open the test keyset */
	status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
							  CRYPT_KEYSET_ODBC, DATABASE_KEYSET_NAME,
							  CRYPT_KEYOPT_READONLY );
	if( cryptStatusOK( status ) )
		cryptKeysetClose( cryptKeyset );
	else
		{
		if( status == CRYPT_ERROR_OPEN )
			{
			char attrBuffer[ 1024 ];

			/* Try and create the DSN.  This is a two-step process, first we
			   create the DSN and then the underlying file that contains the
			   database */
			puts( "Database keyset " DATABASE_KEYSET_NAME " not found, "
				  "attempting to create data source..." );
			buildDBString( attrBuffer, DATABASE_ATTR_NAME,
						   sizeof( DATABASE_ATTR_NAME ),
						   DATABASE_ATTR_TAIL, tempPathBuffer );
			status = SQLConfigDataSource( NULL, ODBC_ADD_DSN, DRIVER_NAME,
										  attrBuffer );
			if( status == 1 )
				{
				buildDBString( attrBuffer, DATABASE_ATTR_CREATE,
							   sizeof( DATABASE_ATTR_CREATE ),
							   DATABASE_ATTR_TAIL, tempPathBuffer );
				status = SQLConfigDataSource( NULL, ODBC_ADD_DSN,
											  DRIVER_NAME, attrBuffer );
				}
			puts( ( status == 1 ) ? "Data source creation succeeded." : \
				  "Data source creation failed.\n\nYou need to create the "
				  "keyset data source as described in the cryptlib manual\n"
				  "for the database keyset tests to run." );
			}
		}

	/* Try and open the test cert store.  This can return a
	   CRYPT_ARGERROR_PARAM3 as a normal condition since a freshly-created
	   database is empty and therefore can't be identified as a cert store
	   until data is written to it */
	status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
							  CRYPT_KEYSET_ODBC_STORE, CERTSTORE_KEYSET_NAME,
							  CRYPT_KEYOPT_READONLY );
	if( cryptStatusOK( status ) )
		cryptKeysetClose( cryptKeyset );
	else
		{
		if( status == CRYPT_ERROR_OPEN )
			{
			char attrBuffer[ 1024 ];

			/* Try and create the DSN.  As before, this is a two-step
			   process */
			puts( "Certificate store " CERTSTORE_KEYSET_NAME " not found, "
				  "attempting to create data source..." );
			buildDBString( attrBuffer, CERTSTORE_ATTR_NAME,
						   sizeof( CERTSTORE_ATTR_NAME ),
						   CERTSTORE_ATTR_TAIL, tempPathBuffer );
			status = SQLConfigDataSource( NULL, ODBC_ADD_DSN, DRIVER_NAME,
										  attrBuffer );
			if( status == 1 )
				{
				buildDBString( attrBuffer, CERTSTORE_ATTR_CREATE,
							   sizeof( CERTSTORE_ATTR_CREATE ),
							   CERTSTORE_ATTR_TAIL, tempPathBuffer );
				status = SQLConfigDataSource( NULL, ODBC_ADD_DSN,
											  DRIVER_NAME, attrBuffer );
				}
			puts( ( status == 1 ) ? "Data source creation succeeded.\n" : \
				  "Data source creation failed.\n\nYou need to create the "
				  "certificate store data source as described in the\n"
				  "cryptlib manual for the certificate management tests to "
				  "run.\n" );
			}
		}
	}
#endif /* Win32 with VC++ */

/****************************************************************************
*																			*
*								Key Load Routines							*
*																			*
****************************************************************************/

/* Set the label for a device object */

static BOOLEAN setLabel( const CRYPT_CONTEXT cryptContext, const char *label )
	{
	if( cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,
								 label, strlen( label ) ) == CRYPT_ERROR_DUPLICATE )
		{
		printf( "A key object with the label '%s' already exists inside the\n"
				"device.  To perform this test, you need to delete the "
				"existing object so\nthat cryptlib can create a new one.\n",
				label );
		return( FALSE );
		}

	return( TRUE );
	}

/* Load RSA, DSA, and Elgamal PKC encrytion contexts */

static int loadRSAPublicKey( const CRYPT_DEVICE cryptDevice,
							 CRYPT_CONTEXT *cryptContext,
							 const char *cryptContextLabel,
							 CRYPT_PKCINFO_RSA *rsaKey,
							 const BOOLEAN isDevice,
							 const BOOLEAN useLargeKey )
	{
	const RSA_KEY *rsaKeyTemplate = useLargeKey ? \
								&rsa1024TestKey : &rsa512TestKey;
	int status;

	if( isDevice )
		status = cryptDeviceCreateContext( cryptDevice, cryptContext,
										   CRYPT_ALGO_RSA );
	else
		status = cryptCreateContext( cryptContext, CRYPT_UNUSED,
									 CRYPT_ALGO_RSA );
	if( cryptStatusError( status ) )
		{
		printf( "crypt%sCreateContext() failed with error code %d.\n",
				isDevice ? "Device" : "", status );
		return( status );
		}
	if( !setLabel( *cryptContext, cryptContextLabel ) )
		{
		cryptDestroyContext( *cryptContext );
		return( status );
		}
	cryptInitComponents( rsaKey, CRYPT_KEYTYPE_PUBLIC );
	cryptSetComponent( rsaKey->n, rsaKeyTemplate->n, rsaKeyTemplate->nLen );
	cryptSetComponent( rsaKey->e, rsaKeyTemplate->e, rsaKeyTemplate->eLen );
	status = cryptSetAttributeString( *cryptContext,
								CRYPT_CTXINFO_KEY_COMPONENTS, rsaKey,
								sizeof( CRYPT_PKCINFO_RSA ) );
	cryptDestroyComponents( rsaKey );
	if( cryptStatusError( status ) )
		cryptDestroyContext( *cryptContext );
	return( status );
	}

BOOLEAN loadRSAContextsEx( const CRYPT_DEVICE cryptDevice,
						   CRYPT_CONTEXT *cryptContext,
						   CRYPT_CONTEXT *decryptContext,
						   const char *cryptContextLabel,
						   const char *decryptContextLabel )
	{
	CRYPT_PKCINFO_RSA *rsaKey;
	const RSA_KEY *rsaKeyTemplate = &rsa512TestKey;
	const BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;
	BOOLEAN useLargeKey = FALSE;
	int status;

	/* Allocate room for the public-key components */
	if( ( rsaKey = ( CRYPT_PKCINFO_RSA * ) malloc( sizeof( CRYPT_PKCINFO_RSA ) ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );

	/* Some devices only support a single key size that isn't the same as
	   the built-in one so we adjust the key size being used if necessary */
	if( isDevice )
		{
		CRYPT_QUERY_INFO cryptQueryInfo;

		status = cryptDeviceQueryCapability( cryptDevice, CRYPT_ALGO_RSA,
											 &cryptQueryInfo );
		if( cryptStatusError( status ) )
			return( FALSE );
		if( cryptQueryInfo.keySize != 64 )
			{
			if( cryptQueryInfo.keySize != 128 )
				{
				printf( "Device requires a %d-bit key, which doesn't "
						"correspond to any built-in\ncryptlib key.\n",
						cryptQueryInfo.keySize );
				return( FALSE );
				}
			rsaKeyTemplate = &rsa1024TestKey;
			useLargeKey = TRUE;
			}
		}

	/* Create the encryption context */
	if( cryptContext != NULL )
		{
		status = loadRSAPublicKey( cryptDevice, cryptContext,
								   cryptContextLabel, rsaKey, isDevice,
								   useLargeKey );
		if( status == CRYPT_ERROR_NOTAVAIL && isDevice )
			{
			/* The device doesn't support public-key ops, use a native
			   context for the public key */
			puts( "  Warning: Device doesn't support public-key operations, "
				  "using a cryptlib\n  native context instead." );
			status = loadRSAPublicKey( CRYPT_UNUSED, cryptContext,
									   cryptContextLabel, rsaKey, FALSE,
									   useLargeKey );
			}
		if( cryptStatusError( status ) )
			{
			free( rsaKey );
			printf( "Key load failed with error code %d.\n", status );
			return( FALSE );
			}
		if( decryptContext == NULL )
			{
			/* We're only using a public-key context, return */
			free( rsaKey );
			return( TRUE );
			}
		}

	/* Create the decryption context */
	if( isDevice )
		status = cryptDeviceCreateContext( cryptDevice, decryptContext,
										   CRYPT_ALGO_RSA );
	else
		status = cryptCreateContext( decryptContext, CRYPT_UNUSED,
									 CRYPT_ALGO_RSA );
	if( cryptStatusError( status ) )
		{
		free( rsaKey );
		if( cryptContext != NULL )
			{
			cryptDestroyContext( *cryptContext );
			if( isDevice )
				cryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,
								cryptContextLabel );
			}
		printf( "crypt%sCreateContext() failed with error code %d.\n",
				isDevice ? "Device" : "", status );
		return( FALSE );
		}
	if( !setLabel( *decryptContext, decryptContextLabel ) )
		{
		free( rsaKey );
		cryptDestroyContext( *decryptContext );
		if( cryptContext != NULL )
			{
			cryptDestroyContext( *cryptContext );
			if( isDevice )
				cryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,
								cryptContextLabel );
			}
		return( FALSE );
		}
	cryptInitComponents( rsaKey, CRYPT_KEYTYPE_PRIVATE );
	cryptSetComponent( rsaKey->n, rsaKeyTemplate->n, rsaKeyTemplate->nLen );
	cryptSetComponent( rsaKey->e, rsaKeyTemplate->e, rsaKeyTemplate->eLen );
	cryptSetComponent( rsaKey->d, rsaKeyTemplate->d, rsaKeyTemplate->dLen );
	cryptSetComponent( rsaKey->p, rsaKeyTemplate->p, rsaKeyTemplate->pLen );
	cryptSetComponent( rsaKey->q, rsaKeyTemplate->q, rsaKeyTemplate->qLen );
	cryptSetComponent( rsaKey->u, rsaKeyTemplate->u, rsaKeyTemplate->uLen );
	cryptSetComponent( rsaKey->e1, rsaKeyTemplate->e1, rsaKeyTemplate->e1Len );
	cryptSetComponent( rsaKey->e2, rsaKeyTemplate->e2, rsaKeyTemplate->e2Len );
	status = cryptSetAttributeString( *decryptContext,
									  CRYPT_CTXINFO_KEY_COMPONENTS, rsaKey,
									  sizeof( CRYPT_PKCINFO_RSA ) );
	cryptDestroyComponents( rsaKey );
	free( rsaKey );

⌨️ 快捷键说明

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