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

📄 devices.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:

	/* Make it a persistent object and load a key */
	status = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL, 
									  SYMMETRIC_KEY_LABEL, 
									  strlen( SYMMETRIC_KEY_LABEL ) );
	if( cryptStatusOK( status ) )
		status = cryptSetAttribute( cryptContext, CRYPT_CTXINFO_PERSISTENT, 
									TRUE );
	if( cryptStatusError( status ) )
		{
		printf( "\nCouldn't make device context persistent, status = %d, "
				"line %d.\n", status, __LINE__ );
		return( FALSE );
		}
	status = cryptGenerateKey( cryptContext );
	if( cryptStatusError( status ) )
		{
		printf( "\nCouldn't load key into persistent context, status = %d, "
				"line %d.\n", status, __LINE__ );
		return( FALSE );
		}
	puts( " succeeded." );

	/* Destroy the context.  Since it's persistent, it'll still be present 
	   in the device */
	cryptDestroyContext( cryptContext );

	/* Recreate the object from the device */
	printf( "Reading back symmetric key..." );
	status = cryptGetKey( cryptDevice, &cryptContext, CRYPT_KEYID_NAME,
						  SYMMETRIC_KEY_LABEL, NULL );
	if( cryptStatusError( status ) )
		{
		printf( "\nRead of symmetric key failed, status = %d, line %d.\n", 
				status, __LINE__ );
		return( FALSE );
		}
	puts( " succeeded." );

	/* Re-destroy it and make sure that it's still there afterwards.  This 
	   tests the persistence of read-back objects vs. created objects */
	cryptDestroyContext( cryptContext );
	printf( "Re-reading back symmetric key..." );
	status = cryptGetKey( cryptDevice, &cryptContext, CRYPT_KEYID_NAME,
						  SYMMETRIC_KEY_LABEL, NULL );
	if( cryptStatusError( status ) )
		{
		printf( "\nRe-read of symmetric key failed, status = %d, line %d.\n", 
				status, __LINE__ );
		return( FALSE );
		}
	puts( " succeeded." );

	/* Perform an encrypt/decrypt test with the recreated object */
	printf( "Performing encryption test with recovered key..." );
	status = testCrypt( cryptContext, cryptContext, NULL, TRUE, FALSE );
	if( cryptStatusError( status ) )
		return( FALSE );
	puts( " succeeded." );

	/* Clean up.  Unlike the public/private keys which are reused for 
	   various tests, this object isn't really useful for anything else so 
	   we always clean it up once we're done */
	cryptDestroyContext( cryptContext );
	deleteTestKey( cryptDevice, SYMMETRIC_KEY_LABEL, NULL );
	return( TRUE );
	}

static BOOLEAN testDeviceHighlevel( const CRYPT_DEVICE cryptDevice,
									const CRYPT_DEVICE_TYPE deviceType,
									const char *keyLabel,
									const char *password,
									const BOOLEAN isWriteProtected )
	{
	CRYPT_CONTEXT pubKeyContext, privKeyContext, sigKeyContext;
	int status;

	if( !isWriteProtected && TEST_KEYGEN )
		{
		const CRYPT_ALGO_TYPE cryptAlgo = \
						( deviceType == CRYPT_DEVICE_FORTEZZA ) ? \
						CRYPT_ALGO_DSA : CRYPT_ALGO_RSA;

		if( deviceType != CRYPT_DEVICE_CRYPTOAPI )
			{
			/* Create a CA key in the device */
			if( !createKey( cryptDevice, cryptAlgo, "CA",
							( deviceType == CRYPT_DEVICE_PKCS11 ) ? \
							"dp_cacert" : "df_cacert", CRYPT_UNUSED ) )
				return( FALSE );

			/* Read back the CA key for use in generating end entity certs */
			status = cryptGetPrivateKey( cryptDevice, &sigKeyContext,
										 CRYPT_KEYID_NAME,
										 TEXT( "Test CA key" ), NULL );
			}
		else
			{
			/* CryptoAPI can only store one private key per provider so we
			   can't have both a CA key and user key in the same "device".
			   Because of this we have to use the fixed CA key to issue the
			   cert */
			status = getPrivateKey( &sigKeyContext, CA_PRIVKEY_FILE,
									CA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
			}
		if( cryptStatusError( status ) )
			{
			printf( "\nRead of CA key failed with error code %d, line %d.\n",
					status, __LINE__ );
			return( FALSE );
			}

		/* Create end-entity certificate(s) for keys using the previously-
		   generated CA key.  If it's a Fortezza card and we're using KEA we
		   have to generate two sets of keys/certs, one for signing and one
		   for encryption */
		status = createKey( cryptDevice, cryptAlgo, "user",
							( deviceType == CRYPT_DEVICE_PKCS11 ) ? \
							"dp_usrcert" : "df_usrcert", sigKeyContext );
#ifdef USE_KEA
		if( status && deviceType == CRYPT_DEVICE_FORTEZZA )
			status = createKey( cryptDevice, CRYPT_ALGO_KEA, "KEA",
								"df_keacert", sigKeyContext );
#endif /* USE_KEA */
		cryptDestroyContext( sigKeyContext );
		if( !status )
			return( FALSE );
		}
	else
		puts( "Skipping key generation test, this assumes that the device "
			  "contains pre-\n  existing keys." );

	/* See whether there are any existing keys or certs.  Some tokens have
	   these built in and don't allow anything new to be created, after this
	   point the handling is somewhat special-case but we can at least report
	   their presence.  Although generally we can re-use a private key
	   context for both public and private operations, some devices or drivers
	   (and by logical extension thereof the cryptlib kernel) don't allow
	   public-key ops with private keys so we have to eplicitly handle public
	   and private keys.  This gets somewhat messy because some devices don't
	   have public keys but allow public-key ops with their private keys,
	   while others separate public and private keys and don't allow the
	   private key to do public-key ops */
	status = cryptGetPublicKey( cryptDevice, &pubKeyContext,
								CRYPT_KEYID_NAME, keyLabel );
	if( cryptStatusOK( status ) )
		{
		int value;

		puts( "Found a public key in the device, details follow..." );
		printCertChainInfo( pubKeyContext );
		if( cryptStatusOK( \
				cryptGetAttribute( pubKeyContext,
								   CRYPT_CERTINFO_SELFSIGNED, &value ) ) && \
			value )
			{
			/* It's a self-signed cert/cert chain, make sure that it's
			   valid.  Because it's probably not trusted, we make it
			   temporarily implicitly trusted in order for the sig.check to
			   succeed */
			status = cryptGetAttribute( pubKeyContext,
								CRYPT_CERTINFO_TRUSTED_IMPLICIT, &value );
			if( cryptStatusOK( status ) )
				status = cryptSetAttribute( pubKeyContext,
									CRYPT_CERTINFO_TRUSTED_IMPLICIT, 1 );
			if( cryptStatusOK( status ) )
				status = cryptCheckCert( pubKeyContext, CRYPT_UNUSED );
			if( cryptStatusError( status ) )
				{
				printf( "Signature on certificate is invalid, status %d, "
						"line %d.\n", status, __LINE__ );
				return( FALSE );
				}
			cryptSetAttribute( pubKeyContext,
							   CRYPT_CERTINFO_TRUSTED_IMPLICIT, value );
			}
		}
	else
		{
		puts( "Error: Couldn't locate public key in device." );
		pubKeyContext = CRYPT_UNUSED;
		}
	status = cryptGetPrivateKey( cryptDevice, &privKeyContext,
								 CRYPT_KEYID_NAME, keyLabel, NULL );
	if( cryptStatusOK( status ) )
		{
		puts( "Found a private key in the device, details follow..." );
		printCertChainInfo( privKeyContext );
		if( pubKeyContext == CRYPT_UNUSED )
			{
			/* No explicit public key found, try using the private key for
			   both key types */
			puts( "No public key found, attempting to continue using the "
				  "private key as both a\n  public and a private key." );
			pubKeyContext = privKeyContext;
			}
		}
	else
		{
		puts( "Error: Couldn't locate private key in device." );
		privKeyContext = CRYPT_UNUSED;
		}
	sigKeyContext = privKeyContext;
	if( deviceType == CRYPT_DEVICE_FORTEZZA )
		{
		cryptDestroyContext( pubKeyContext );	/* pubK is sig.only */
		status = cryptGetPrivateKey( cryptDevice, &privKeyContext,
									 CRYPT_KEYID_NAME, "Test KEA key", NULL );
		if( cryptStatusOK( status ) )
			{
			puts( "Found a key agreement key in the device, details follow..." );
			printCertChainInfo( privKeyContext );
			pubKeyContext = privKeyContext;		/* Fortezza allows both uses */
			}
		else
			{
			pubKeyContext = CRYPT_UNUSED;
			privKeyContext = CRYPT_UNUSED;
			}
		}

	/* If we got something, try some simple operations with it */
	if( pubKeyContext != CRYPT_UNUSED )
		{
		char emailAddress[ CRYPT_MAX_TEXTSIZE + 1 ];
		int length;

		if( !testEnvelopePKCCryptEx( pubKeyContext, cryptDevice ) )
			return( FALSE );
		if( !testCMSEnvelopePKCCryptEx( pubKeyContext, cryptDevice, 
										password, NULL ) )
			return( FALSE );
		cryptSetAttribute( pubKeyContext, CRYPT_ATTRIBUTE_CURRENT, 
						   CRYPT_CERTINFO_SUBJECTALTNAME );
		status = cryptGetAttributeString( pubKeyContext, CRYPT_CERTINFO_EMAIL,
										  emailAddress, &length );
		if( cryptStatusError( status ) )
			{
			printf( "Couldn't read recipient address from certificate, "
					"status %d, line %d.\n", status, __LINE__ );
			return( FALSE );
			}
		emailAddress[ length ] = '\0';
		if( !testCMSEnvelopePKCCryptEx( CRYPT_UNUSED, cryptDevice, 
										password, emailAddress ) )
			return( FALSE );
		}
	else
		puts( "Public-key enveloping tests skipped because no key was "
			  "available.\n" );
	if( sigKeyContext != CRYPT_UNUSED )
		{
		if( !testCMSEnvelopeSignEx( sigKeyContext ) )
			return( FALSE );
		}
	else
		puts( "Signed enveloping tests skipped because no key was "
			  "available." );

	/* Test persistent (non-public-key) object creation */
	if( !isWriteProtected && TEST_KEYGEN )
		{
		if( !testPersistentObject( cryptDevice ) )
			return( FALSE );
		}

	/* Clean up */
	if( pubKeyContext == CRYPT_UNUSED && sigKeyContext == CRYPT_UNUSED )
		return( FALSE );
	if( privKeyContext != CRYPT_UNUSED )
		cryptDestroyContext( privKeyContext );
	if( sigKeyContext != CRYPT_UNUSED && privKeyContext != sigKeyContext )
		cryptDestroyContext( sigKeyContext );
	if( pubKeyContext != CRYPT_UNUSED && pubKeyContext != privKeyContext )
		cryptDestroyContext( pubKeyContext );
	return( TRUE );
	}

/* General device test routine */

static int testCryptoDevice( const CRYPT_DEVICE_TYPE deviceType,
							 const char *deviceName,
							 const DEVICE_CONFIG_INFO *deviceInfo )
	{
	CRYPT_DEVICE cryptDevice;
	BOOLEAN isWriteProtected = FALSE, isAutoDetect = FALSE;
	BOOLEAN testResult = FALSE, partialSuccess = FALSE;
	int status;

	/* Open a connection to the device */
	if( deviceType == CRYPT_DEVICE_PKCS11 || \
		deviceType == CRYPT_DEVICE_CRYPTOAPI )
		{
		if( !memcmp( deviceInfo->name, "[A", 2 ) )
			{
			printf( "\nTesting %s with autodetection...\n", deviceName );
			isAutoDetect = TRUE;
			}
		else
			printf( "\nTesting %s %s...\n", deviceInfo->name, deviceName );
		status = cryptDeviceOpen( &cryptDevice, CRYPT_UNUSED, deviceType,
								  deviceInfo->name );
		}
	else
		{
		printf( "\nTesting %s...\n", deviceName );
		status = cryptDeviceOpen( &cryptDevice, CRYPT_UNUSED, deviceType,
								  deviceName );
		}
	if( status == CRYPT_ERROR_PARAM2 )
		{
		puts( "Support for this device type isn't enabled in this build of "
			  "cryptlib." );
		return( CRYPT_ERROR_NOTAVAIL );	/* Device access not available */
		}
	if( cryptStatusError( status ) )
		{
		if( status == CRYPT_ERROR_PARAM3 || status == CRYPT_ERROR_NOTFOUND )
			puts( "Crypto device not detected, skipping test." );
		else
			printf( "cryptDeviceOpen() failed with error code %d, line %d.\n",
					status, __LINE__ );
		return( FALSE );
		}

	/* If it's one of the smarter classes of device, authenticate ourselves to
	   the device, which is usually required in order to allow it to be used
	   fully */
	if( deviceType == CRYPT_DEVICE_PKCS11 || deviceType == CRYPT_DEVICE_FORTEZZA )
		{
		deviceInfo = checkLogonDevice( cryptDevice, deviceInfo, isAutoDetect, 
									   TEST_INITIALISE_CARD );
		if( deviceInfo == NULL )
			{
			cryptDeviceClose( cryptDevice );
			return( FALSE );
			}
		}

	/* Write-protected devices won't allow contexts to be created in them,
	   before we try the general device capabilities test we make sure that
	   we can actually perform the operation */
	if( deviceType == CRYPT_DEVICE_PKCS11 )
		{
		CRYPT_CONTEXT cryptContext;

		/* Try and create a DES object.  The following check for read-only
		   devices always works because the device object ACL is applied at
		   a much higher level than any device capability checking, the
		   device will never even see the create object message if it's
		   write-protected so all we have to do is make sure that whatever
		   we create is ephemeral */
		status = cryptDeviceCreateContext( cryptDevice, &cryptContext,
										   CRYPT_ALGO_DES );
		if( cryptStatusOK( status ) )

⌨️ 快捷键说明

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