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

📄 devices.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
			cryptDestroyContext( cryptContext );
		if( status == CRYPT_ERROR_PERMISSION )
			isWriteProtected = TRUE;
		}

	/* To force the code not to try to create keys and certs in a writeable
	   device, uncomment the following line of code.  This requires that keys/
	   certs of the required type are already present in the device */
/*	KLUDGE_WARN( "write-protect status" );
	isWriteProtected = TRUE; */
	if( !isWriteProtected && TEST_KEYGEN )
		{
		/* If it's a device that we can initialise, go through a full
		   initialisation */
		if( deviceType != CRYPT_DEVICE_CRYPTOAPI && TEST_INITIALISE_CARD )
			{
			status = initialiseDevice( cryptDevice, deviceType,
									   deviceInfo );
			if( status == FALSE )
				{
				cryptDeviceClose( cryptDevice );
				return( FALSE );
				}
			}
		else
			{
			/* There may be test keys lying around from an earlier run, in
			   which case we try to delete them to make sure they won't
			   interfere with the current one */
			deleteTestKey( cryptDevice, "Test CA key", "CA" );
			deleteTestKey( cryptDevice, deviceInfo->keyLabel, "user" );
			if( deviceType == CRYPT_DEVICE_PKCS11 )
				{
				deleteTestKey( cryptDevice, RSA_PUBKEY_LABEL, "RSA public" );
				deleteTestKey( cryptDevice, RSA_PRIVKEY_LABEL, "RSA private" );
				deleteTestKey( cryptDevice, DSA_PUBKEY_LABEL, "DSA public" );
				deleteTestKey( cryptDevice, DSA_PRIVKEY_LABEL, "DSA private" );
				deleteTestKey( cryptDevice, SYMMETRIC_KEY_LABEL, "symmetric" );
				}
			if( deviceType == CRYPT_DEVICE_FORTEZZA )
				deleteTestKey( cryptDevice, "Test KEA key", "KEA" );
			if( deviceType == CRYPT_DEVICE_CRYPTOAPI )
				{
				deleteTestKey( cryptDevice, "Encryption key", "RSA private" );
				deleteTestKey( cryptDevice, "Signature key", "secondary RSA private" );
				}
			}
		}

#ifdef TEST_DH
	return( testLowlevel( cryptDevice, CRYPT_ALGO_DH, FALSE ) );
#endif /* TEST_DH */

	/* Report what the device can do.  This is intended mostly for simple
	   crypto accelerators and may fail with for devices that work only
	   with the higher-level functions centered around certificates,
	   signatures,and key wrapping, so we skip the tests for devices that
	   allow only high-level access */
#if TEST_ALGORITHMS
	if( deviceType != CRYPT_DEVICE_FORTEZZA )
		testResult = testDeviceCapabilities( cryptDevice, deviceName,
											 isWriteProtected );
#else
	puts( "Skipping device algorithm tests." );
#endif /* TEST_ALGORITHMS */

	/* If it's a smart device, try various device-specific operations */
	if( deviceType == CRYPT_DEVICE_FORTEZZA || \
		deviceType == CRYPT_DEVICE_PKCS11 || \
		deviceType == CRYPT_DEVICE_CRYPTOAPI )
		partialSuccess = testDeviceHighlevel( cryptDevice, deviceType,
								deviceInfo->keyLabel, deviceInfo->password,
								isWriteProtected );

	/* Clean up */
	status = cryptDeviceClose( cryptDevice );
	if( cryptStatusError( status ) )
		{
		printf( "cryptDeviceClose() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}
	if( !testResult && !partialSuccess )
		return( FALSE );
	if( testResult && partialSuccess )
		printf( "%s tests succeeded.\n\n", deviceName );
	else
		printf( "Some %s tests succeeded.\n\n", deviceName );
	return( TRUE );
	}

int testDevices( void )
	{
	int i, status;

	/* Test Fortezza devices */
#if 0
	status = testCryptoDevice( CRYPT_DEVICE_FORTEZZA, "Fortezza card",
							   &fortezzaDeviceInfo );
	if( cryptStatusError( status ) && status != CRYPT_ERROR_NOTAVAIL )
		return( status );
#endif /* 0 */

	/* Test PKCS #11 devices */
#if 1
	for( i = 0; pkcs11DeviceInfo[ i ].name != NULL; i++ )
		{
		status = testCryptoDevice( CRYPT_DEVICE_PKCS11, "PKCS #11 crypto token",
								   &pkcs11DeviceInfo[ i ] );
		if( cryptStatusError( status ) && \
			!( status == CRYPT_ERROR_NOTAVAIL || \
			   ( i == 0 && status == CRYPT_ERROR_WRONGKEY ) ) )
			return( status );
		}
#endif /* 0 */

#if 0	/* For test purposes only to check CAPI data, don't use the CAPI code */
#ifdef __WINDOWS__
	for( i = 0; capiDeviceInfo[ i ].name != NULL; i++ )
		{
		status = testCryptoDevice( CRYPT_DEVICE_CRYPTOAPI, "Microsoft CryptoAPI",
								   &capiDeviceInfo[ i ] );
		if( cryptStatusError( status ) && \
			!( status == CRYPT_ERROR_NOTAVAIL || \
			   ( i == 0 && status == CRYPT_ERROR_WRONGKEY ) ) )
			return( status );
		}
#endif /* __WINDOWS__ */
#endif /* 0 */
	putchar( '\n' );
	return( TRUE );
	}

/****************************************************************************
*																			*
*						Full Device Initialisation Test						*
*																			*
****************************************************************************/

/* The following code takes two unitialised devices and turns one into a
   fully initialised CA device, which then runs a PnP PKI session that turns
   the other into a fully initialised user device.

   The following configuration options can be used to change the beaviour of
   the self-test, for example to run it on the local machine in loopback mode
   vs. running on two distinct machines.  Defining an IP address (or host
   name) for SERVER_MACHINE_ADDRESS will have the client connect to that
   address instead of running a local loopback test */

#if 0
  #define SERVER_MACHINE_ADDRESS	"161.5.99.22"
  #define SERVER_MACHINE_PORT		4080
  #define CLIENT_DEVICE_TYPE		CRYPT_DEVICE_FORTEZZA
  #define SERVER_DEVICE_TYPE		CRYPT_DEVICE_FORTEZZA
  #define CLIENT_ID					"25CHS-UDQBU-BPASM"
  #define CLIENT_AUTHENTICATOR		"5ZCJ8-34A5C-YSXRD-C9EME"
  #define CLIENT_TOKEN_SLOT			CRYPT_USE_DEFAULT
  #define NET_TIMEOUT				300
#else
  #define SERVER_MACHINE_ADDRESS	"localhost"
  #define SERVER_MACHINE_PORT		80
  #define CLIENT_DEVICE_TYPE		CRYPT_DEVICE_FORTEZZA
  #define SERVER_DEVICE_TYPE		CRYPT_DEVICE_FORTEZZA
  #define CLIENT_TOKEN_SLOT			1
  #define NET_TIMEOUT				CRYPT_USE_DEFAULT
#endif /* Loopback vs. general test */

/* Default PIN values */

#if CLIENT_DEVICE_TYPE == CRYPT_DEVICE_FORTEZZA
  #define DEFAULT_SSO_PIN	FORTEZZA_SSO_DEFAULT_PIN
#else
  #define DEFAULT_SSO_PIN	"0000"
#endif /* Fortezza vs. PKCS #11 default SSO PINs */
#define SSO_PIN			"0000"
#define USER_PIN		"0000"

/* Set up a client/server to connect locally (usually) or to a custom
   address and port if we're running on distinct machines.  For the client
   this simply tells it where to connect, for the server in loopback mode
   this binds it to the local address so that we don't inadvertently open
   up outside ports */

static BOOLEAN setConnectInfo( const CRYPT_SESSION cryptSession,
							   const char *address, const int port,
							   const int timeout )
	{
	int status;

	status = cryptSetAttributeString( cryptSession,
									  CRYPT_SESSINFO_SERVER_NAME,
									  address,  strlen( address ) );
	if( cryptStatusOK( status ) )
		status = cryptSetAttribute( cryptSession,
									CRYPT_SESSINFO_SERVER_PORT, port );
	if( cryptStatusOK( status ) && timeout != CRYPT_USE_DEFAULT )
		{
		cryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT,
						   NET_TIMEOUT );
		status = cryptSetAttribute( cryptSession,
									CRYPT_OPTION_NET_WRITETIMEOUT,
									NET_TIMEOUT );
		}
	if( cryptStatusError( status ) )
		{
		printf( "cryptSetAttribute/AttributeString() failed with error code "
				"%d, line %d.\n", status, __LINE__ );
		return( FALSE );
		}

	return( TRUE );
	}

/* Create a CA cert in a device */

static const CERT_DATA rootCACertData[] = {
	/* Identification information */
	{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, "AT" },
	{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, "IAEA" },
	{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, "SGTIE" },
	{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, "IAEA CA root" },

	/* Self-signed X.509v3 CA certificate */
	{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },
	{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },
	{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,
	  CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },

	/* Access information */
	{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_AUTHORITYINFO_RTCS },
	{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, "http://localhost" },

	{ CRYPT_ATTRIBUTE_NONE, IS_VOID }
	};

static int createCACert( const CRYPT_DEVICE cryptDevice )
	{
	CRYPT_CONTEXT cryptContext;
	CRYPT_CERTIFICATE cryptCert;
	int status;

	/* Generate a key in the device */
	printf( "Generating a CA key in the device..." );
	status = cryptDeviceCreateContext( cryptDevice, &cryptContext,
						( SERVER_DEVICE_TYPE == CRYPT_DEVICE_FORTEZZA ) ? \
							CRYPT_ALGO_DSA : CRYPT_ALGO_RSA );
	if( cryptStatusError( status ) )
		{
		printf( "\ncryptDeviceCreateContext() failed with error code %d, "
				"line %d.\n", status, __LINE__ );
		return( FALSE );
		}
	status = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,
									  "CA key", strlen( "CA key" ) );
	if( cryptStatusOK( status ) )
		status = cryptGenerateKey( cryptContext );
	if( cryptStatusError( status ) )
		{
		cryptDestroyContext( cryptContext );
		printf( "\ncryptGenerateKey() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}
	puts( " done." );

	/* Create a certificate for the key */
	printf( "Generating a CA certificate for the key..." );
	status = cryptCreateCert( &cryptCert, CRYPT_UNUSED, 
							  CRYPT_CERTTYPE_CERTIFICATE );
	if( cryptStatusError( status ) )
		return( FALSE );
	status = cryptSetAttribute( cryptCert,
						CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
	if( cryptStatusOK( status ) && \
		!addCertFields( cryptCert, rootCACertData, __LINE__ ) )
		return( FALSE );
	if( cryptStatusOK( status ) )
		status = cryptSignCert( cryptCert, cryptContext );
	cryptDestroyContext( cryptContext );
	if( cryptStatusError( status ) )
		{
		cryptDestroyCert( cryptCert );
		printf( "\nCreation of certificate failed with error code %d, "
				"line %d.\n", status, __LINE__ );
		return( FALSE );
		}
	puts( " done." );

	/* Update the key with the CA cert */
	printf( "Updating device with certificate..." );
	status = cryptAddPublicKey( cryptDevice, cryptCert );
	cryptDestroyCert( cryptCert );
	if( cryptStatusError( status ) )
		{
		printf( "\ncryptAddPublicKey() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}
	puts( " done." );

	return( TRUE );
	}

/* Connect to a device */

static int connectDevice( CRYPT_DEVICE *cryptDevice, CRYPT_DEVICE_TYPE type,
						  const int slotNo )
	{
	char buffer[ 128 ];
	int status;

	/* Clear return value */
	*cryptDevice = -1;

	/* Connect to the device */
	if( slotNo == CRYPT_USE_DEFAULT )
		{
		printf( "Connecting to crypto device in default slot..." );
		strcpy( buffer, "[Autodetect]" );
		}
	else
		{
		printf( "Connecting to crypto device in slot %d...", slotNo );
		sprintf( buffer, "[Autodetect]::%d", slotNo );
		}
	status = cryptDeviceOpen( cryptDevice, CRYPT_UNUSED, type, buffer );
	if( cryptStatusError( status ) )
		{
		if( status == CRYPT_ERROR_PARAM3 || status == CRYPT_ERROR_NOTFOUND )
			puts( "\nDevice not detected, skipping test." );
		else
			printf( "\ncryptDeviceOpen() failed with error code %d, line "
					"%d.\n", status, __LINE__ );
		return( FALSE );
		}
	puts( " done." );

	return( TRUE );
	}

/* Log on to a device */

static int logonDevice( const CRYPT_DEVICE cryptDevice, const char *userPIN )
	{
	char tokenLabel[ CRYPT_MAX_TEXTSIZE + 1 ];
	int loggedOn, tokenLabelSize, status;

	/* Tell the user what we're talking to */
	status = cryptGetAttributeString( cryptDevice, CRYPT_DEVINFO_LABEL,
									  tokenLabel, &tokenLabelSize );
	if( cryptStatusError( status ) )
		puts( "(Device doesn't appear to have a label)." );
	else
		{
		tokenLabel[ tokenLabelSize ] = '\0';

⌨️ 快捷键说明

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