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

📄 dev_fort.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Handle device control functions */

static int controlFunction( DEVICE_INFO *deviceInfo,
							const CRYPT_ATTRIBUTE_TYPE type,
							const void *data1, const int data1Length,
							const void *data2, const int data2Length )
	{
	STATIC_FN int findCertificate( DEVICE_INFO *deviceInfo, const char *label, 
								   const int labelLength );
	int status;

	/* Handle user authorisation */
	if( type == CRYPT_DEVINFO_AUTHENT_USER || \
		type == CRYPT_DEVINFO_AUTHENT_SUPERVISOR )
		{
		CI_PERSON *personalityList = deviceInfo->personalities;
		CI_PIN pin;
		BYTE ivBuffer[ 64 ];	/* For LEAF handling */
		int certIndex;

		initPIN( pin, data1, data1Length );
		status = pCI_CheckPIN( ( type == CRYPT_DEVINFO_AUTHENT_USER ) ? \
							   CI_USER_PIN : CI_SSO_PIN, pin );
		if( status != CI_OK )
			return( ( status == CI_FAIL ) ? CRYPT_ERROR_WRONGKEY : \
					mapError( status, CRYPT_ERROR_WRONGKEY ) );

		/* Get the list of device personalities (skipping the zero-th 
		   personality which can't be selected) and lock the device for our 
		   exclusive use.  We should really do this as soon as we open the 
		   device to make sure the user isn't presented with any nasty 
		   surprises due to state changes caused by other active sessions 
		   with the device, but the driver won't let us do it until we've 
		   authenticated ourselves to the device */
		status = pCI_GetPersonalityList( deviceInfo->personalityCount - 1, 
										 &personalityList[ 1 ] );
		if( status == CI_OK )
			{
			int index;

			/* Set a label for the zero-th personality (which can't be 
			   explicitly accessed but whose cert can be read) to make sure 
			   it isn't treated as an empty personality slot */
			strcpy( personalityList[ 0 ].CertLabel, 
					"PAA1FFFFPersonality 0 dummy label" );

			/* Perform a sanity check for certificate indices.  The 
			   documentation implies that the certificate index always 
			   matches the personality index (skipping the zero-th 
			   personality), but doesn't seem to mandate this anywhere so 
			   we make sure things really are set up this way */
			for( index = 0; index < deviceInfo->personalityCount; index++ )
				{
				CI_PERSON *personality = getPersonality( deviceInfo, index );

				if( personality->CertificateIndex != 0 && \
					personality->CertificateIndex != index )
					{
					status = CI_BAD_TUPLES;
					break;
					}
				}
			}
		if( status == CI_OK )
			status = pCI_Lock( CI_NULL_FLAG );
		if( status != CI_OK )
			{
			pCI_Reset();	/* Log off */
			deviceInfo->errorCode = status;
			return( CRYPT_ERROR_FAILED );
			}
		deviceInfo->flags |= DEVICE_LOGGEDIN;		

		/* Look for the most likely required personality (other than 
		   personality 0, which is a non-personality used for the CA
		   root cert) and set it as the currently active one.  If this 
		   fails we stay with the default personality for lack of any 
		   better way to handle it */
		certIndex = findCertificate( deviceInfo, NULL, 0 );
		if( !cryptStatusError( certIndex ) && certIndex )
			{
			pCI_SetPersonality( certIndex );
			deviceInfo->currentPersonality = certIndex;
			}

		/* Handle LEAF suppression.  On LEAF-suppressed cards the LEAF bytes
		   are replaced by 'THIS IS NOT LEAF', in case there are cards which
		   use a different string we remember it with the device info so we 
		   can load LEAF-less IV's */
		status = pCI_DeleteKey( 1 );
		if( status == CI_OK )
			status = pCI_GenerateMEK( 1, 0 );
		if( status == CI_OK )
			status = pCI_SetKey( 1 );
		if( status == CI_OK )
			status = pCI_GenerateIV( ivBuffer );
		memcpy( deviceInfo->leafString, ( status == CI_OK ) ? \
				ivBuffer : "THIS IS NOT LEAF", 16 );
		pCI_DeleteKey( 1 );

		return( CRYPT_OK );
		}

	/* Handle authorisation value change */
	if( type == CRYPT_DEVINFO_SET_AUTHENT_USER || \
		type == CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR )
		{
		CI_PIN oldPIN, newPIN;

		initPIN( oldPIN, data1, data1Length );
		initPIN( newPIN, data2, data2Length );

		status = pCI_ChangePIN( ( type == CRYPT_DEVINFO_SET_AUTHENT_USER ) ? \
								CI_USER_PIN : CI_SSO_PIN, oldPIN, newPIN );
		return( ( status == CI_FAIL ) ? CRYPT_ERROR_WRONGKEY : \
				mapError( status, CRYPT_ERROR_WRONGKEY ) );
		}

	/* Handle initialisation */
	if( type == CRYPT_DEVINFO_INITIALISE )
		{
		CI_RANDOM randomBuffer;
		CI_STATE deviceState;
		CI_PIN pin;

		/* Make sure the device is in the uninitialised state */
		status = pCI_GetState( &deviceState );
		if( status != CI_OK || deviceState != CI_UNINITIALIZED )
			return( CRYPT_ERROR_INITED );

		/* Log on with the SSO PIN */
		initPIN( pin, data1, data1Length );
		status = pCI_CheckPIN( CI_SSO_PIN, pin );
		if( status != CI_OK )
			return( mapError( status, CRYPT_ERROR_FAILED ) );

		/* Load the random number seed and storage key from the device's
		   RNG output and make sure the card has now in the initialised
		   state */
		status = pCI_GenerateRandom( randomBuffer );
		if( status == CI_OK )
			status = pCI_LoadInitValues( randomBuffer, 
										 randomBuffer + sizeof( CI_RANDSEED ) );
		zeroise( randomBuffer, sizeof( CI_RANDOM ) );
		if( status == CI_OK )
			status = pCI_GetState( &deviceState );
		if( status != CI_OK )
			return( mapError( status, CRYPT_ERROR_FAILED ) );
		if( deviceState != CI_INITIALIZED )
			return( CRYPT_ERROR_FAILED );
		return( CRYPT_OK );
		}

	/* Handle zeroisation */
	if( type == CRYPT_DEVINFO_ZEROISE )
		{
		CI_STATE deviceState;
		CI_PIN pin;

		/* Zeroise the card */
		status = pCI_Zeroize();
		if( status == CI_OK )
			status = pCI_GetState( &deviceState );
		if( status != CI_OK )
			return( mapError( status, CRYPT_ERROR_FAILED ) );
		if( deviceState != CI_ZEROIZED )
			return( CRYPT_ERROR_FAILED );

		/* Log on with the zeroise PIN to move it into the uninitialised 
		   state */
		initPIN( pin, data1, data1Length );
		status = pCI_CheckPIN( CI_SSO_PIN, pin );
		return( mapError( status, CRYPT_ERROR_WRONGKEY ) );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR_NOTAVAIL );	/* Get rid of compiler warning */
	}

/****************************************************************************
*																			*
*						 	Misc.Device Interface Routines					*
*																			*
****************************************************************************/

/* Get random data from the device */

static int getRandomFunction( DEVICE_INFO *deviceInfo, void *buffer,
							  const int length )
	{
	CI_RANDOM randomBuffer;
	BYTE *bufPtr = buffer;
	int count, status;

	/* Get as many 20-byte blocks as required to fill the request */
	for( count = 0; count < length; count += 20 )
		{
		const int noBytes = min( 20, length - count );

		status = pCI_GenerateRandom( randomBuffer );
		if( status != CI_OK )
			break;
	
		memcpy( bufPtr, randomBuffer, noBytes );
		bufPtr += noBytes;
		}
	zeroise( randomBuffer, 20 );

	return( mapError( status, CRYPT_ERROR_FAILED ) );
	}

/* Instantiate an object in a device.  This works like the create context
   function but instantiates a cryptlib object using data already contained
   in the device (for example a stored private key or certificate).  If the
   value being read is a public key and there's a certificate attached, the
   instantiated object is a native cryptlib object rather than a device
   object with a native certificate object attached because there doesn't 
   appear to be any good reason to create the public-key object in the device, 
   and the cryptlib native object will probably be faster anyway */

static int getItemFunction( DEVICE_INFO *deviceInfo,
							CRYPT_CONTEXT *iCryptContext,
							const KEYMGMT_ITEM_TYPE itemType,
							const CRYPT_KEYID_TYPE keyIDtype,
							const void *keyID, const int keyIDlength,
							void *auxInfo, int *auxInfoLength, 
							const int flags )
	{
	static const int keySize = 128;
	const CAPABILITY_INFO *capabilityInfoPtr;
	CRYPT_CERTIFICATE iCryptCert;
	CRYPT_ALGO cryptAlgo;
	CI_PERSON *personality;
	CI_CERTIFICATE certificate;
	RESOURCE_DATA msgData;
	BOOLEAN certPresent = TRUE;
	int certIndex, status;

	assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
			itemType == KEYMGMT_ITEM_PRIVATEKEY );
	assert( keyIDtype == CRYPT_KEYID_NAME );

	/* Find the referenced personality on the device and determine the 
	   algorithm type for the key */
	certIndex = findCertificate( deviceInfo, keyID, keyIDlength );
	if( certIndex == CRYPT_ERROR )
		return( CRYPT_ERROR_NOTFOUND );
	if( flags & KEYMGMT_FLAG_CHECK_ONLY )
		/* If we're just checking whether an object exists, return now */
		return( CRYPT_OK );
	personality = getPersonality( deviceInfo, certIndex );
	if( flags & KEYMGMT_FLAG_LABEL_ONLY )
		{
		/* All we want is the key label, copy it back to the caller and
		   exit */
		*auxInfoLength = strlen( personality->CertLabel + 8 );
		if( auxInfo != NULL )
			memcpy( auxInfo, personality->CertLabel + 8, *auxInfoLength );
		return( CRYPT_OK );
		}
	status = pCI_GetCertificate( certIndex, certificate );
	if( status != CI_OK )
		return( mapError( status, CRYPT_ERROR_READ ) );
	if( !memcmp( personality->CertLabel, "TEMP", 4 ) )
		{
		STREAM stream;

		/* It's a work in progress, read the algorithm from the start of the 
		   public key data */
		sMemConnect( &stream, certificate, 128 );
		status = readSequence( &stream, NULL );
		if( !cryptStatusError( status ) )
			status = readAlgoID( &stream, &cryptAlgo );
		sMemDisconnect( &stream );
		if( cryptStatusError( status ) )
			return( status );

		/* Remember that there's no cert available for this key */
		certPresent = FALSE;
		}
	else
		/* It's a certificate, determine the algorithm type from the label */
		if( !memcmp( personality->CertLabel, "DSA", 3 ) || \
			!memcmp( personality->CertLabel, "CAX", 3 ) || \
			!memcmp( personality->CertLabel, "PCA", 3 ) || \
			!memcmp( personality->CertLabel, "PAA", 3 ) )
			cryptAlgo = CRYPT_ALGO_DSA;
		else
			if( !memcmp( personality->CertLabel, "KEA", 3 ) )
				cryptAlgo = CRYPT_ALGO_KEA;
			else
				return( CRYPT_ERROR_BADDATA );
	capabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfo, 
											cryptAlgo );
	if( capabilityInfoPtr == NULL )
		return( CRYPT_ERROR_NOTAVAIL );
	
	/* If we're after a private key, make sure it really is a private key.  
	   This check isn't completely effective since the CA labels don't
	   identify the presence of a private key */
	if( personality->CertLabel[ 4 ] == 'X' && \
		itemType == KEYMGMT_ITEM_PRIVATEKEY )
		return( CRYPT_ERROR_NOTFOUND );

	/* Try and create a certificate chain which matches the key.  The process 
	   is as follows:

		if public key
			if cert
				create native cert chain (+key) object
			else
				create device pubkey object, mark as "key loaded"
		else
			create device privkey object, mark as "key loaded"
			if cert
				create native data-only cert chain object
				attach cert chain object to key

	   The reason for doing things this way is given in the comment at the 
	   top of this section */
	if( certPresent )
		{
		status = iCryptImportCertIndirect( &iCryptCert, 
						deviceInfo->objectHandle, keyIDtype, keyID, 
						keyIDlength, ( itemType == KEYMGMT_ITEM_PRIVATEKEY ) ? \
						KEYMGMT_FLAG_DATAONLY_CERT : 0 );
		if( cryptStatusError( status ) )
			return( status );

		/* We got the cert, if we're being asked for a public key then we've 
		   created a native object to contain it so we return that */
		if( itemType == KEYMGMT_ITEM_PUBLICKEY )
			{
			/* Set up the keying info in the context based on the data from
			   the cert if necessary */
			if( cryptAlgo == CRYPT_ALGO_KEA )
				{
				BYTE keyDataBuffer[ 1024 ];

				setResourceData( &msgData, keyDataBuffer, 1024 );
				status = krnlSendMessage( iCryptCert, 
										  RESOURCE_IMESSAGE_GETATTRIBUTE_S, 

⌨️ 快捷键说明

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