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

📄 fortezza.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
		initPIN( oldPIN, fortezzaInfo->initPIN, 
				 strlen( fortezzaInfo->initPIN ) );
		initPIN( newPIN, data, dataLength );
		status = pCI_ChangePIN( CI_SSO_PIN, oldPIN, newPIN );
		zeroise( fortezzaInfo->initPIN, CRYPT_MAX_TEXTSIZE );
		return( ( status == CI_FAIL ) ? CRYPT_ERROR_WRONGKEY : \
				mapError( status, CRYPT_ERROR_WRONGKEY ) );
		}
	if( type == CRYPT_DEVINFO_SET_AUTHENT_USER )
		{
		CI_PIN oldPIN, newPIN;

		/* This assumes that we're in the SSO initialised state and are 
		   setting the initial user PIN to move us into the user initialised
		   state, for which oldPIN == newPIN */
		initPIN( oldPIN, data, dataLength );
		initPIN( newPIN, data, dataLength );
		status = pCI_ChangePIN( CI_USER_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 that 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, data, dataLength );
		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 that 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 );

		/* Remember the initialisation PIN for a future CI_ChangePIN() */
		memcpy( fortezzaInfo->initPIN, data, dataLength );
		fortezzaInfo->initPIN[ dataLength ] = '\0';

		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 );

		/* Clear any in-memory state information that we were holding about 
		   the card */
		memset( fortezzaInfo->personalities, 0, 
				fortezzaInfo->personalityCount * sizeof( CI_PERSON ) );
		memset( fortezzaInfo->certHashes, 0, 
				fortezzaInfo->personalityCount * sizeof( CI_HASHVALUE ) );
		fortezzaInfo->certHashesInitialised = FALSE;
		fortezzaInfo->currentPersonality = CRYPT_ERROR;

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

	/* Handle high-reliability time */
	if( type == CRYPT_IATTRIBUTE_TIME )
		{
		CI_TIME cardTime;
		time_t *timePtr = ( time_t * ) data, theTime;

		status = pCI_GetTime( cardTime );
		if( status != CI_OK )
			return( mapError( status, CRYPT_ERROR_FAILED ) );
		if( ( theTime = getTokenTime( cardTime ) ) < MIN_TIME_VALUE )
			return( CRYPT_ERROR_NOTAVAIL );
		*timePtr = getTime();
		return( CRYPT_OK );
		}

	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 )
	{
	CRYPT_CERTIFICATE iCryptCert;
	CRYPT_ALGO_TYPE cryptAlgo;
	static const int keySize = 128;
	const CAPABILITY_INFO *capabilityInfoPtr;
	FORTEZZA_INFO *fortezzaInfo = deviceInfo->deviceFortezza;
	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 = findCertificateFromLabel( fortezzaInfo, 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( fortezzaInfo, 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->capabilityInfoList, 
											cryptAlgo );
	if( capabilityInfoPtr == NULL )
		return( CRYPT_ERROR_NOTAVAIL );
	
	/* If we're after a private key, make sure that 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 that 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 ];

				setMessageData( &msgData, keyDataBuffer, 1024 );
				status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S, 
										  &msgData, CRYPT_IATTRIBUTE_SPKI );
				if( cryptStatusOK( status ) )
					status = krnlSendMessage( iCryptCert, 
											  IMESSAGE_SETATTRIBUTE_S, 
											  &msgData, CRYPT_IATTRIBUTE_KEY_SPKI );
				if( cryptStatusError( status ) )
					{
					krnlSendNotifier( iCryptCert, 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 (i.e. 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, IMESSAGE_DECREFCOUNT );
		return( status );
		}
	krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
					 &deviceInfo->objectHandle, SETDEP_OPTION_INCREF );
	krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, &certIndex, 
					 CRYPT_IATTRIBUTE_DEVICEOBJECT );
	setMessageData( &msgData, personality->CertLabel + 8,
					 strlen( personality->CertLabel + 8 ) );
	krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData, 
					 CRYPT_CTXINFO_LABEL );
	krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
					 ( void * ) &keySize, CRYPT_IATTRIBUTE_KEYSIZE );
	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 */
		setMessageData( &msgData, keyDataBuffer, 1024 );
		status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_SPKI );
		if( cryptStatusOK( status ) )
			status = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE_S, 
									  &msgData, CRYPT_IATTRIBUTE_KEY_SPKI );
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );
			*iCryptContext = CRYPT_ERROR;
			return( status );
			}
		}
	else
		/* If we don't set keying the info, we have to manually move the 

⌨️ 快捷键说明

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