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

📄 dev_fort.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
										  &msgData, CRYPT_IATTRIBUTE_SPKI );
				if( cryptStatusOK( status ) )
					status = krnlSendMessage( iCryptCert, 
										  RESOURCE_IMESSAGE_SETATTRIBUTE_S, 
										  &msgData, CRYPT_IATTRIBUTE_PUBLICKEY );
				if( cryptStatusError( status ) )
					{
					krnlSendNotifier( iCryptCert, 
									  RESOURCE_IMESSAGE_DECREFCOUNT );
					return( status );
					}
				}

			*iCryptContext = iCryptCert;
			return( CRYPT_OK );
			}
		}

	/* Create a dummy context for the key, remember the device it's contained 
	   in, the index of the device-internal key, and the object's label, mark 
	   it as initialised (ie with a key loaded), and if there's a cert present 
	   attach it to the context.  The cert is an internal object used only by 
	   the context so we tell the kernel to mark it as owned by the context 
	   only */
	status = createContextFromCapability( iCryptContext, deviceInfo->ownerHandle,
										  capabilityInfoPtr, 
										  CREATEOBJECT_FLAG_DUMMY );
	if( cryptStatusError( status ) )
		{
		if( certPresent )
			krnlSendNotifier( iCryptCert, RESOURCE_IMESSAGE_DECREFCOUNT );
		return( status );
		}
	krnlSendMessage( *iCryptContext, RESOURCE_IMESSAGE_SETDEPENDENT,
					 &deviceInfo->objectHandle, SETDEP_OPTION_INCREF );
	krnlSendMessage( *iCryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 &certIndex, CRYPT_IATTRIBUTE_DEVICEOBJECT );
	setResourceData( &msgData, personality->CertLabel + 8,
					 strlen( personality->CertLabel + 8 ) );
	krnlSendMessage( *iCryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
					 &msgData, CRYPT_CTXINFO_LABEL );
	if( certPresent && cryptAlgo == CRYPT_ALGO_KEA )
		{
		BYTE keyDataBuffer[ 1024 ];

		/* Set up the keying info in the context based on the data from the 
		   cert if necessary */
		setResourceData( &msgData, keyDataBuffer, 1024 );
		status = krnlSendMessage( iCryptCert, 
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_SPKI );
		if( cryptStatusOK( status ) )
			status = krnlSendMessage( *iCryptContext, 
								  RESOURCE_IMESSAGE_SETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_PUBLICKEY );
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( *iCryptContext, RESOURCE_IMESSAGE_DECREFCOUNT );
			*iCryptContext = CRYPT_ERROR;
			return( status );
			}
		}
	krnlSendMessage( *iCryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 ( void * ) &keySize, CRYPT_IATTRIBUTE_KEYSIZE );
	krnlSendMessage( *iCryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 MESSAGE_VALUE_UNUSED, CRYPT_IATTRIBUTE_INITIALISED );
	if( certPresent )
		krnlSendMessage( *iCryptContext, RESOURCE_IMESSAGE_SETDEPENDENT, 
						 &iCryptCert, SETDEP_OPTION_NOINCREF );

	return( status );
	}

/* Update a device with a certificate */

static int setItemFunction( DEVICE_INFO *deviceInfo, 
							const CRYPT_HANDLE iCryptHandle )
	{
	CRYPT_CERTIFICATE iCryptCert;
	int certIndex, status;

	/* Read the personality index at which we're adding the certificate */
	krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE, &certIndex, 
					 CRYPT_IATTRIBUTE_DEVICEOBJECT );
	if( certIndex < 0 )
		return( CRYPT_ARGERROR_NUM1 );

	/* Get the cert objects handle, lock it for our exclusive use, update the 
	   card with the cert(s), and unlock it to allow others access */
	krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETDEPENDENT, 
					 &iCryptCert, OBJECT_TYPE_CERTIFICATE );
	status = krnlSendNotifier( iCryptCert, RESOURCE_IMESSAGE_LOCK );
	if( cryptStatusError( status ) )
		return( status );
	status = updateCertChain( deviceInfo, iCryptCert, certIndex );
	krnlSendNotifier( iCryptCert, RESOURCE_IMESSAGE_UNLOCK );

	return( status );
	}

/* Delete an object in a device */

static int deleteItemFunction( DEVICE_INFO *deviceInfo,
							   const KEYMGMT_ITEM_TYPE itemType,
							   const CRYPT_KEYID_TYPE keyIDtype,
							   const void *keyID, const int keyIDlength )
	{
	int certIndex, status;

	assert( itemType == KEYMGMT_ITEM_PUBLICKEY );
	assert( keyIDtype == CRYPT_KEYID_NAME );

	/* Find the item to delete based on the label */
	certIndex = findCertificate( deviceInfo, keyID, keyIDlength );
	if( certIndex == CRYPT_ERROR )
		return( CRYPT_ERROR_NOTFOUND );
	status = pCI_DeleteCertificate( certIndex );
	if( status != CI_OK )
		return( mapError( status, CRYPT_ERROR_WRITE ) );
	updateCertificateInfo( deviceInfo, certIndex, NULL, CRYPT_UNUSED, "" );
	return( CRYPT_OK );
	}

/* Get the sequence of certs in a chain from a device */

static int getFirstItemFunction( DEVICE_INFO *deviceInfo, 
								 CRYPT_CERTIFICATE *iCertificate,
								 int *stateInfo, 
								 const CRYPT_KEYID_TYPE keyIDtype,
								 const void *keyID, const int keyIDlength,
								 const KEYMGMT_ITEM_TYPE itemType, 
								 const int options )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	BYTE buffer[ CI_CERT_SIZE ];
	int status;

	assert( keyIDtype == CRYPT_KEYID_NAME && keyID != NULL );
	assert( stateInfo != NULL );

	/* Find the cert based on the label */
	*stateInfo = findCertificate( deviceInfo, keyID, keyIDlength );
	if( *stateInfo == CRYPT_ERROR )
		return( CRYPT_ERROR_NOTFOUND );

	/* Get the cert at this position */
	status = pCI_GetCertificate( *stateInfo, buffer );
	if( status != CI_OK )
		return( mapError( status, CRYPT_ERROR_READ ) );
	setMessageCreateObjectIndirectInfo( &createInfo, buffer, CI_CERT_SIZE );
	createInfo.arg1 = ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \
					  CERTFORMAT_DATAONLY : CERTFORMAT_NORMAL;
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
							  RESOURCE_IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
							  &createInfo, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusOK( status ) )
		*iCertificate = createInfo.cryptHandle;
	return( status );
	}

static int getNextItemFunction( DEVICE_INFO *deviceInfo, 
								CRYPT_CERTIFICATE *iCertificate,
								int *stateInfo, const int options )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	CI_PERSON *personality;
	BYTE buffer[ CI_CERT_SIZE ];
	int status;

	assert( stateInfo != NULL );
	assert( ( *stateInfo >= 0 && *stateInfo < deviceInfo->personalityCount ) || \
			*stateInfo == CRYPT_ERROR );

	/* If the previous cert was the last one, there's nothing left to fetch */
	if( *stateInfo == CRYPT_ERROR )
		return( CRYPT_ERROR_NOTFOUND );

	/* Find the parent for the last cert we got using the SDN.605 
	   labelling scheme */
	personality = getPersonality( deviceInfo, *stateInfo );
	if( !memcmp( personality->CertLabel + 4, "0999", 4 ) || \
		!memcmp( personality->CertLabel + 6, "FF", 2 ) || \
		sscanf( personality->CertLabel + 6, "%02X", stateInfo ) != 1 )
		*stateInfo = 255;
	*stateInfo = ( *stateInfo == 255 ) ? CRYPT_ERROR : *stateInfo;
	if( *stateInfo == CRYPT_ERROR )
		return( CRYPT_ERROR_NOTFOUND );

	/* Get the cert at this position */
	status = pCI_GetCertificate( *stateInfo, buffer );
	if( status != CI_OK )
		return( mapError( status, CRYPT_ERROR_READ ) );
	setMessageCreateObjectIndirectInfo( &createInfo, buffer, CI_CERT_SIZE );
	createInfo.arg1 = ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \
					  CERTFORMAT_DATAONLY : CERTFORMAT_NORMAL;
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
							  RESOURCE_IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
							  &createInfo, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusOK( status ) )
		*iCertificate = createInfo.cryptHandle;
	return( status );
	}

/****************************************************************************
*																			*
*						 	Capability Interface Routines					*
*																			*
****************************************************************************/

/* Initialise the encryption */

static int initCryptFunction( CRYPT_INFO *cryptInfo )
	{
	int mode, status;

	/* We're encrypting data, set the appropriate mode for future
	   en/decryption */
	switch( cryptInfo->ctxConv.mode )
		{
		case CRYPT_MODE_ECB:
			mode = CI_ECB64_MODE;
			break;

		case CRYPT_MODE_CBC:
			mode = CI_CBC64_MODE;
			break;

		case CRYPT_MODE_CFB:
			mode = CI_CFB64_MODE;
			break;

		case CRYPT_MODE_OFB:
			mode = CI_OFB64_MODE;
			break;
		}
	status = pCI_SetMode( CI_DECRYPT_TYPE, mode );
	if( status == CI_OK )
		status = pCI_SetMode( CI_ENCRYPT_TYPE, mode );
	return( mapError( status, CRYPT_ERROR_FAILED ) );
	}

/* Load an IV.  Handling IV generation/loading is very problematic since we 
   can't generate an IV until the key is generated (since it depends on the 
   key), however implicitly generating a key into the context at this point 
   will change its state so that a future attempt to explicitly generate a key 
   will fail.  This is complicated by the fact that although there are a 
   number of key registers, the cryptologic can only have one active mode and
   one active IV.  To get around this we'd have to do the following:

	initIV:
		if( !key )
			generateKey();
			autoKey = TRUE;
		generateIV();
	
	initKey:
		if( autoKey == TRUE )
			return( OK );
		generateKey()

   but this doesn't work due to the problem mentioned above, so for now we
   just assume we'll be called from within cryptlib, which gets it right (it's
   unlikely users will be able to work with the complex Fortezza key 
   management, so there's little chance the sequencing will become messed up).
   
   In practice it's even worse than this, because the cryptologic on some 
   cards imposes even more limitations than this.  The standard way to use a
   session/content-enryption key is:

	generate session/conetent-encryption key;
	export wrapped key;
	encrypt data with key;

   This doesn't work here because the act of exporting the session key screws
   up the state of the key.  Specifically, after executing the following code
   sequence:

	// Generate the session key
	CI_DeleteKey( mekIndex );
	CI_GenerateMEK( mekIndex, 0 );
	CI_SetKey( mekIndex );
	CI_GenerateIV( ivBuffer );

	// Export the encrypted session key
	CI_SetPersonality( personality );
	CI_GenerateRa( Ra );
	CI_GenerateTEK( CI_INITIATOR_FLAG, tekIndex, Ra, 
					( void * ) Rb, sizeof( CI_RB ), recipientPublicValue );
	CI_WrapKey( tekIndex, mekIndex, wrappedKey );
	CI_DeleteKey( tekIndex );

	// Encrypt data with the key
	CI_Encrypt( length, buffer, buffer );

   the CI_Encrypt() fails with CI_NO_KEY.  Calling CI_SetKey() before 
   CI_Encrypt() causes it to fail with a CI_NO_IV instead.  Calling 
   CI_Encrypt() immediately after CI_GenerateTEK() results in a CI_FAIL.
   This indicates that the TEK wrapping upsets the state of the cryptologic
   which in turn upsets any attempt to use the MEK later on.

   Because of this problem, we can't generate the IV in the initIVFunction()
   but have to wait until after the key wrap operations have been performed.  
   The code kludges this by setting the ivSet flag at this point without
   setting the IV and then generating the real IV as a side-effect of the key
   wrapping.  This only works if we're wrapping the key for a single recipient 
   using a TEK, it doesn't work if we're wrapping using Ks or if there's more
   than one recipient because we can't tell in advance whether this is the 
   last operation before we encrypt (and therefore whether it's safe to 
   generate an IV now).
   
   The problems with IV handling extend even further than this.  The 
   following simple sequence of calls (generating an IV, reading it out, 
   loading it back in, and then attempting to encrypt) produce a "no IV 
   loaded" error even though all the previous calls succeeded:

	CI_SetMode( CI_DECRYPT_TYPE, CI_CBC64_MODE );
	CI_DeleteKey( 5 );
	CI_GenerateMEK( 5, 0 );
	CI_SetKey( 5 );
	CI_GenerateIV( ivBuffer );
	CI_SetKey( 5 );		// Required or the IV load fails with CI_EXEC_FAIL
	CI_LoadIV( ivBuffer );
	CI_Encrypt( 8, ivBuffer, ivBuffer ); // Result = CI_NO_IV

   Presumably this is because of interlocks on the card or Capstone chip 
   which date back to the LEAF period and which ensure that it's not possible
   to fiddle with non-LEAF'd IV's or anything else even if the card firmware 
   is somehow compromised or has unexpected failure modes.  The result is 
   that it's possible to use the device exactly as intended by its original 
   designers but probably not possible (or at least very difficult) to use it 
   in any other way.  The unexpected return codes are <wild speculation> 
   possibly caused by this functionality not being anticipated by the 
   firmware vendors</wild speculation>.  In any case it's a nice failsafe
   design */

static int initIVFunction( CRYPT_INFO *cryptInfo, const void *iv,
						   const int ivLength )
	{
	BYT

⌨️ 快捷键说明

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