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

📄 testdev.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 3 页
字号:
	   order to work */
	if( isAutoDetect )
		{
		int i;

		for( i = 1; pkcs11DeviceInfo[ i ].name != NULL; i++ )
			if( tokenLabelSize == \
							( int ) strlen( pkcs11DeviceInfo[ i ].name ) && \
				!memcmp( pkcs11DeviceInfo[ i ].name, tokenLabel, 
						 tokenLabelSize ) )
				{
				printf( "Found a match for pre-defined device '%s', using\n"
						"  pre-set parameters.\n", 
						pkcs11DeviceInfo[ i ].description );
				deviceInfo = &pkcs11DeviceInfo[ i ];
				break;
				}
			}

	/* See if we need to authenticate ourselves */
	status = cryptGetAttribute( cryptDevice, CRYPT_DEVINFO_LOGGEDIN, 
								&loggedOn );
	if( cryptStatusError( status ) )
		{
		puts( "Couldn't obtain device login status." );
		return( NULL );
		}
	if( loggedOn )
		{
		/* Device may not require a login, or has already been logged in
		   via a keypad or similar mechanism */
		puts( "Device is already logged in, skipping login." );
		return( deviceInfo );
		}

	/* Try and log in */
	printf( "Logging on to the device..." );
	status = cryptSetAttributeString( cryptDevice,
							CRYPT_DEVINFO_AUTHENT_USER, deviceInfo->password,
							strlen( deviceInfo->password ) );
	if( status == CRYPT_ERROR_NOTINITED )
		{
		/* It's an uninitialised device, tell the user and exit */
		puts( " device needs to be initialised." );
		printf( "cryptlib will not automatically initialise the device "
				"during the self-test\n  in case it contains data that "
				"needs to be preserved or requires special\n  steps to be "
				"taken before the initialisation is performed.  If you want "
				"to\n  initialise it, set TEST_INITIALISE_CARD at the top "
				"of " __FILE__ "\n  to a nonzero value.\n" );
		return( NULL );
		}
	if( cryptStatusError( status ) )
		{
		printf( "\nDevice %s failed with error code %d, line %d.\n",
				( status == CRYPT_ERROR_WRONGKEY ) ? \
				"login" : "initialisation/setup", status, __LINE__ );
		if( isAutoDetect )
			puts( "This may be because the auto-detection test uses a fixed "
				  "login value rather\n  than one specific to the device "
				  "type." );
		else
			if( status == CRYPT_ERROR_WRONGKEY && willInitialise )
				{
				/* If we're going to initialise the card, being in the wrong
				   (or even totally uninitialised) state isn't an error */
				puts( "This may be because the device isn't in the user-"
					  "initialised state, in which\n  case the standard "
					  "user PIN can't be used to log on to it." );
				return( deviceInfo );
				}
		return( NULL );
		}
	puts( " succeeded." );
	return( deviceInfo );
	}

/* Initialise a device.  Note that when doing this with a Fortezza card,
   these operations have to be done in a more or less continuous sequence 
   (i.e. without an intervening device open call) because it's not possible 
   to escape from some of the states if the card is closed and reopened in
   between.  In addition the PKCS #11 interface maps some of the 
   initialisation steps differently than the CI interface, so we have to
   special-case this below */

static BOOLEAN initialiseDevice( const CRYPT_DEVICE cryptDevice,
								 const CRYPT_DEVICE_TYPE deviceType,
								 const DEVICE_CONFIG_INFO *deviceInfo )
	{
	const char *defaultSSOPIN = ( deviceType == CRYPT_DEVICE_FORTEZZA ) ? \
								FORTEZZA_SSO_DEFAULT_PIN : \
								deviceInfo->password;
	const char *ssoPIN = ( deviceType == CRYPT_DEVICE_FORTEZZA ) ? \
						 FORTEZZA_SSO_PIN : deviceInfo->password;
	const char *userPIN = deviceInfo->password;
	int status;

	/* PKCS #11 doesn't distinguish between zeroisation and initialisation, 
	   so we only perform the zeroise test if it's a Fortezza card */
	if( deviceType == CRYPT_DEVICE_FORTEZZA )
		{
		printf( "Zeroising device..." );
		status = cryptSetAttributeString( cryptDevice,
						CRYPT_DEVINFO_ZEROISE, FORTEZZA_ZEROISE_PIN,
						strlen( FORTEZZA_ZEROISE_PIN ) );
		if( cryptStatusError( status ) )
			{
			printf( "\nZeroise failed with error code %d, line %d.\n", 
					status, __LINE__ );
			return( FALSE );
			}
		puts( " succeeded." );
		}

	/* Initialise the device and set the SO PIN.   */
	printf( "Initialising device..." );
	status = cryptSetAttributeString( cryptDevice, CRYPT_DEVINFO_INITIALISE, 
									  defaultSSOPIN, strlen( defaultSSOPIN ) );
	if( cryptStatusError( status ) )
		{
		printf( "\nCouldn't initialise device, status = %d, line %d.\n", 
				status, __LINE__ );
		return( FALSE );
		}
	puts( " succeeded." );
	printf( "Setting SO PIN to '%s'...", ssoPIN );
	status = cryptSetAttributeString( cryptDevice, 
									  CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR,
									  ssoPIN, strlen( ssoPIN ) );
	if( cryptStatusError( status ) )
		{
		printf( "\nCouldn't set SO PIN, status = %d, line %d.\n", status, 
				__LINE__ );
		return( FALSE );
		}
	puts( " succeeded." );

	/* If it's a Fortezza card, create a CA root key and install its cert.
	   We have to do it at this point because the operation is only allowed
	   in the SSO initialised state.  In addition we can't use the card for 
	   this operation because cert slot 0 is a data-only slot (that is, it 
	   can't correspond to a key held on the card), so we create a dummy 
	   external cert and use that */
	if( deviceType == CRYPT_DEVICE_FORTEZZA )
		{
		CRYPT_CERTIFICATE cryptCert;
		CRYPT_CONTEXT signContext;

		printf( "Loading PAA certificate..." );
		if( !loadDSAContexts( CRYPT_UNUSED, &signContext, NULL ) )
			return( FALSE );
		cryptCreateCert( &cryptCert, CRYPT_UNUSED, 
						 CRYPT_CERTTYPE_CERTIFICATE );
		status = cryptSetAttribute( cryptCert,
						CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, signContext );
		if( cryptStatusOK( status ) && \
			!addCertFields( cryptCert, paaCertData ) )
			return( FALSE );
		if( cryptStatusOK( status ) )
			status = cryptSignCert( cryptCert, signContext );
		cryptDestroyContext( signContext );
		if( cryptStatusError( status ) )
			{
			cryptDestroyCert( cryptCert );
			printf( "\nCreation of certificate failed with error code %d, "
					"line %d.\n", status, __LINE__ );
			return( FALSE );
			}
		status = cryptAddPublicKey( cryptDevice, cryptCert );
		cryptDestroyCert( cryptCert );
		if( cryptStatusError( status ) )
			{
			printf( "\ncryptAddPublicKey() failed with error code %d, line "
					"%d.\n", status, __LINE__ );
			return( FALSE );
			}
		puts( " succeeded." );
		}

	/* Set the user PIN and log on as the user */
	printf( "Setting user PIN to '%s'...", userPIN );
	status = cryptSetAttributeString( cryptDevice, 
									  CRYPT_DEVINFO_SET_AUTHENT_USER,
									  userPIN, strlen( userPIN ) );
	if( cryptStatusOK( status ) )
		status = cryptSetAttributeString( cryptDevice, 
										  CRYPT_DEVINFO_AUTHENT_USER,
										  userPIN, strlen( userPIN ) );
	if( cryptStatusError( status ) )
		{
		printf( "Couldn't set user PIN/log on as user, status = %d, line "
				"%d.\n", status, __LINE__ );
		return( FALSE );
		}
	puts( " succeeded." );

	return( TRUE );
	}

/****************************************************************************
*																			*
*									Device Tests							*
*																			*
****************************************************************************/

/* Test the general capabilities of a device */

static BOOLEAN testDeviceCapabilities( const CRYPT_DEVICE cryptDevice,
									   const char *deviceName,
									   const BOOLEAN isWriteProtected )
	{
	CRYPT_ALGO_TYPE cryptAlgo;
	int testCount = 0, failCount = 0;

	printf( "Checking %s capabilities...\n", deviceName );
	for( cryptAlgo = CRYPT_ALGO_FIRST_CONVENTIONAL;
		 cryptAlgo <= CRYPT_ALGO_LAST; cryptAlgo++ )
		if( cryptStatusOK( cryptDeviceQueryCapability( cryptDevice,
													   cryptAlgo, NULL ) ) )
			{
			testCount++;
			if( !testLowlevel( cryptDevice, cryptAlgo, isWriteProtected ) )
				/* The test failed, we don't exit at this point but only 
				   remember that there was a problem since we want to test 
				   every possible algorithm */
				failCount++;
			}

	if( isWriteProtected )
		puts( "No tests were performed since the device is write-protected." );
	else
		if( failCount )
			printf( "%d of %d test%s failed.\n", failCount, testCount,
					( testCount > 1 ) ? "s" : "" );
		else
			puts( "Device capabilities test succeeded." );

	return( ( failCount == testCount ) ? FALSE : TRUE );
	}

/* Test the high-level functionality provided by a device */

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_PKCS11 ) ? \
						CRYPT_ALGO_RSA : CRYPT_ALGO_DSA;

		/* 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, "Test CA key",
									 NULL );
		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 );
		}

	/* 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 reuse a private key context
	   for both public and private operations, some devices or drivers (and
	   by extension 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 public key certificate is invalid, "
						"line %d.\n", __LINE__ );
				return( FALSE );
				}
			cryptSetAttribute( pubKeyContext, 
							   CRYPT_CERTINFO_TRUSTED_IMPLICIT, value );
			}
		}
	else
		{

⌨️ 快捷键说明

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