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

📄 devices.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
	if( cryptStatusError( status ) )
		{
		cryptDestroyCert( cryptCert );
		printf( "\nCreation of certificate failed with error code %d, "
				"line %d.\n", status, __LINE__ );
		return( FALSE );
		}
	puts( " succeeded." );

	/* Dump the resulting cert for debugging */
	if( dumpName != NULL )
		{
		status = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,
				isCA ? CRYPT_CERTFORMAT_CERTIFICATE : CRYPT_CERTFORMAT_CERTCHAIN,
				cryptCert );
		if( cryptStatusOK( status ) )
			debugDump( dumpName, certBuffer, certificateLength );
		}

	/* Update the key with the 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( " succeeded." );

	return( TRUE );
	}

/****************************************************************************
*																			*
*							Device Logon/Initialisation						*
*																			*
****************************************************************************/

/* Print information about a device and log in if necessary */

static const DEVICE_CONFIG_INFO *checkLogonDevice( const CRYPT_DEVICE cryptDevice,
												   const DEVICE_CONFIG_INFO *deviceInfo,
												   const BOOLEAN isAutoDetect,
												   const BOOLEAN willInitialise )
	{
	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';
		printf( "Device label is '%s'.\n", tokenLabel );
		}

	/* Check whether the device corresponds to a known device.  We do this
	   because some devices require specific test passwords and whatnot in
	   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',\n"
						"  using 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_INITED )
		{
		/* Some devices may not require any login, in which case we're
		   done */
		puts( " device is already logged in." );
		return( deviceInfo );
		}
	if( status == CRYPT_ERROR_NOTINITED )
		{
		/* It's an uninitialised device, tell the user and exit */
		puts( " device needs to be initialised." );
		if( willInitialise )
			return( deviceInfo );
		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\n  " __FILE__ " 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( 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 );
			}
		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." );
		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 );
		status = cryptCreateCert( &cryptCert, CRYPT_UNUSED,
								  CRYPT_CERTTYPE_CERTIFICATE );
		if( cryptStatusError( status ) )
			return( FALSE );
		status = cryptSetAttribute( cryptCert,
						CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, signContext );
		if( cryptStatusOK( status ) && \
			!addCertFields( cryptCert, paaCertData, __LINE__ ) )
			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 ) )
		{
		int loggedOn;

		/* Some devices automatically log the user in when they set the user
		   password, so we check to see if it's necessary to log in before we
		   actually do it */
		status = cryptGetAttribute( cryptDevice, CRYPT_DEVINFO_LOGGEDIN,
									&loggedOn );
		if( cryptStatusError( status ) )
			{
			puts( "Couldn't obtain device login status." );
			return( FALSE );
			}
		if( !loggedOn )
			status = cryptSetAttributeString( cryptDevice,
											  CRYPT_DEVINFO_AUTHENT_USER,
											  userPIN, strlen( userPIN ) );
		}
	if( cryptStatusError( status ) )
		{
		printf( "\nCouldn'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 testPersistentObject( const CRYPT_DEVICE cryptDevice )
	{
	CRYPT_ALGO_TYPE cryptAlgo = CRYPT_ALGO_HMAC_SHA1;
	CRYPT_CONTEXT cryptContext;
	int status;

	printf( "Loading a persistent symmetric key into the device..." );

	/* Find an encryption algorithm that we can use and create a context in
	   the device */
	status = cryptDeviceQueryCapability( cryptDevice, cryptAlgo, NULL );
	if( cryptStatusError( status ) )
		{
		cryptAlgo = CRYPT_ALGO_DES;
		status = cryptDeviceQueryCapability( cryptDevice, cryptAlgo, NULL );
		}
	if( cryptStatusOK( status ) )
		status = cryptDeviceCreateContext( cryptDevice, &cryptContext, 
										   cryptAlgo );
	if( cryptStatusError( status ) )
		{
		printf( "\nCouldn't create conventional-encryption context in "
				"device, status = %d, line %d.\n", status, __LINE__ );
		return( FALSE );
		}

⌨️ 快捷键说明

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