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

📄 fortezza.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
		   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( fortezzaInfo->leafString, ( status == CI_OK ) ? \
				ivBuffer : "THIS IS NOT LEAF", 16 );
		pCI_DeleteKey( 1 );

		/* The device is now ready for use */
		deviceInfo->flags |= DEVICE_LOGGEDIN;		
		krnlSendMessage( deviceInfo->objectHandle, IMESSAGE_SETATTRIBUTE, 
						 MESSAGE_VALUE_UNUSED, CRYPT_IATTRIBUTE_INITIALISED );
		return( CRYPT_OK );
		}

	/* Handle authorisation value change.  Fortezza uses a multi-stage
	   bootstrap FSM and requires that all of the various intialisation 
	   functions be used one after the other, with no intervening operations 
	   apart from setting the PAA (CA root) certificate in the SSO 
	   initialised state.  Interrupting the process (for example by logging 
	   off/closing the device) requires that it be restarted from scratch:

			   uninitialised
					v
				CI_Zeroize			(enter zeroise PIN)
					v
				 zeroised
					v
				CI_CheckPIN			(enter init PIN)
					v
				initialised
					v
				CI_ChangePIN		(set SSO PIN)
					v
			  SSO initialised
					v
				CI_ChangePIN		(set user PIN)
					v
			  user initialised

	   The single-sequence requirement means that the initialised -> SSO
	   initialised step re-uses the PIN set at initialisation, and the SSO
	   initialised -> user initialised uses the same PIN as the old and new
	   PIN, since there's no user PIN set at that point.  Once we've set the
	   initial user PIN, the card is automagically moved into the user
	   initialised state */
	if( type == CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR )
		{
		CI_PIN oldPIN, newPIN;

		/* Make sure that the PIN is within range */
		if( dataLength < fortezzaInfo->minPinSize || \
			dataLength > fortezzaInfo->maxPinSize )
			return( CRYPT_ARGERROR_NUM1 );

		/* Make sure that there's an SSO PIN present from a previous device
		   initialisation */
		if( fortezzaInfo->initPinLen <= 0 )
			{
			setErrorInfo( deviceInfo, CRYPT_DEVINFO_INITIALISE, 
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			return( CRYPT_ERROR_NOTINITED );
			}

		/* This assumes that we're in the initialised state and are setting 
		   the initial SSO PIN to move us into the SSO initialised state, 
		   for which oldPIN == initialisation PIN.  Once we've done this we
		   clear the initialisation PIN, since it's no longer valid in the 
		   new state */
		initPIN( oldPIN, fortezzaInfo->initPin, fortezzaInfo->initPinLen );
		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;

		/* Make sure that the PIN is within range */
		if( dataLength < fortezzaInfo->minPinSize || \
			dataLength > fortezzaInfo->maxPinSize )
			return( CRYPT_ARGERROR_NUM1 );

		/* 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 PIN is within range */
		if( dataLength < fortezzaInfo->minPinSize || \
			dataLength > fortezzaInfo->maxPinSize )
			return( CRYPT_ARGERROR_NUM1 );

		/* 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->initPinLen = dataLength;

		return( CRYPT_OK );
		}

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

		/* Make sure that the PIN is within range */
		if( dataLength < fortezzaInfo->minPinSize || \
			dataLength > fortezzaInfo->maxPinSize )
			return( CRYPT_ARGERROR_NUM1 );

		/* Zeroise the card */
		status = pCI_Zeroize();
		if( status != CI_OK )
			return( mapError( status, CRYPT_ERROR_FAILED ) );
		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 );
		}

	retIntError();
	}

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

/* Get random data from the device */

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

	/* 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 = DUMMY_INIT;
	CRYPT_ALGO_TYPE cryptAlgo = CRYPT_ALGO_NONE;
	static const int keySize = 128;
	const CAPABILITY_INFO *capabilityInfoPtr;
	FORTEZZA_INFO *fortezzaInfo = deviceInfo->deviceFortezza;
	CI_PERSON *personality;
	CI_CERTIFICATE certificate;
	MESSAGE_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 certificate 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 certificate
				create native certificate chain (+key) object
			else
				create device pubkey object, 

⌨️ 快捷键说明

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