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

📄 cryptctx.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
		MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );
	static const int actionFlagsDH = ACTION_PERM_NONE_EXTERNAL_ALL;
	static const int actionFlagsPGP = \
		MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \
		MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
	const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
	STREAM stream;
	int status;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( contextInfoPtr->type == CONTEXT_PKC );
	assert( needsKey( contextInfoPtr ) || \
			( contextInfoPtr->flags & CONTEXT_DUMMY ) );
	assert( keyType == CRYPT_IATTRIBUTE_KEY_SPKI || \
			keyType == CRYPT_IATTRIBUTE_KEY_PGP || \
			keyType == CRYPT_IATTRIBUTE_KEY_SSH1 || \
			keyType == CRYPT_IATTRIBUTE_KEY_SSH2 || \
			keyType == CRYPT_IATTRIBUTE_KEY_SSL || \
			keyType == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL || \
			keyType == CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL );
	assert( isReadPtr( keyData, keyDataLen ) );

	/* If the keys are held externally (e.g. in a crypto device), copy the 
	   encoded public key data in and set up any other information that we 
	   may need from it.  This information is used when loading a context 
	   from a key contained in a device, where the actual key components 
	   aren't directly available in the context but may be needed in the 
	   future for things like cert requests and certs */
	if( contextInfoPtr->flags & CONTEXT_DUMMY )
		{
		assert( keyType == CRYPT_IATTRIBUTE_KEY_SPKI || \
				keyType == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );

		if( ( contextInfoPtr->ctxPKC->publicKeyInfo = \
				clAlloc( "processSetAttributeS", keyDataLen ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		memcpy( contextInfoPtr->ctxPKC->publicKeyInfo, keyData, keyDataLen );
		contextInfoPtr->ctxPKC->publicKeyInfoSize = keyDataLen;
		return( calculateKeyID( contextInfoPtr ) );
		}

	/* Read the appropriately-formatted key data into the context, applying 
	   a lowest-common-denominator set of usage flags to the loaded key 
	   (more specific usage restrictions will be set by higher-level code) */
	sMemConnect( &stream, keyData, keyDataLen );
	status = contextInfoPtr->ctxPKC->readPublicKeyFunction( &stream,
										contextInfoPtr, 
										attributeToFormatType( keyType ) );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );

	/* If it's a partial load of the initial public portions of a private 
	   key with further key component operations to follow, there's nothing 
	   more to do at this point and we're done */
	if( keyType == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL || \
		keyType == CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL )
		return( calculateKeyID( contextInfoPtr ) );

	/* Perform an internal load that uses the key component values that 
	   we've just read into the context */
	contextInfoPtr->flags |= CONTEXT_ISPUBLICKEY;
	status = contextInfoPtr->loadKeyFunction( contextInfoPtr, NULL, 0 );
	if( cryptStatusError( status ) )
		/* Map the status to a more appropriate code if necessary */
		return( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );
	contextInfoPtr->flags |= CONTEXT_KEY_SET;

	/* Restrict the key usage to public-key-only actions if necessary.  For 
	   PGP key loads (which, apart from the restrictions specified with the 
	   stored key data aren't constrained by the presence of ACLs in the 
	   form of certs) we allow external usage, for DH (whose keys can be 
	   both public and private keys even though technically it's a public 
	   key) we allow both encryption and decryption usage, and for public 
	   keys read from certs we  allow internal usage only */
	status = krnlSendMessage( contextInfoPtr->objectHandle,
						IMESSAGE_SETATTRIBUTE, 
						( keyType == CRYPT_IATTRIBUTE_KEY_PGP ) ? \
							( void * ) &actionFlagsPGP : \
						( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH ) ? \
							( void * ) &actionFlagsDH : \
							( void * ) &actionFlags,
						CRYPT_IATTRIBUTE_ACTIONPERMS );
	if( cryptStatusError( status ) )
		return( status );
	contextInfoPtr->flags |= CONTEXT_KEY_SET;
	return( calculateKeyID( contextInfoPtr ) );
	}

/* Load a composite key into a context */

static int setKeyComponents( CONTEXT_INFO *contextInfoPtr, 
							 const void *keyData, const int keyDataLen )
	{
	static const int actionFlags = \
		MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \
		MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
	const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
	int status;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( contextInfoPtr->type == CONTEXT_PKC );
	assert( needsKey( contextInfoPtr ) );
	assert( isReadPtr( keyData, keyDataLen ) );
	assert( keyDataLen == sizeof( CRYPT_PKCINFO_RSA ) || \
			keyDataLen == sizeof( CRYPT_PKCINFO_DLP ) );

	/* We need to have a key label set before we can continue */
	if( contextInfoPtr->labelSize <= 0 )
		return( exitErrorNotInited( contextInfoPtr, CRYPT_CTXINFO_LABEL ) );

	/* Load the key components into the context */
	status = contextInfoPtr->loadKeyFunction( contextInfoPtr, keyData, 
											  keyDataLen );
	if( cryptStatusError( status ) )
		return( status );
	contextInfoPtr->flags |= CONTEXT_KEY_SET | CONTEXT_EPHEMERAL | CONTEXT_PBO;

	/* Restrict the key usage to public-key-only actions if it's a public 
	   key.  DH keys act as both public and private keys so we don't 
	   restrict their usage */
	if( ( contextInfoPtr->flags & CONTEXT_ISPUBLICKEY ) && \
		( capabilityInfoPtr->cryptAlgo != CRYPT_ALGO_DH ) )
		status = krnlSendMessage( contextInfoPtr->objectHandle,
								  IMESSAGE_SETATTRIBUTE, 
								  ( void * ) &actionFlags,
								  CRYPT_IATTRIBUTE_ACTIONPERMS );
	return( status );
	}

/* Encrypt a block of data */

static int encryptData( CONTEXT_INFO *contextInfoPtr, void *data, 
						const int dataLength )
	{
	BYTE savedData[ ENCRYPT_CHECKSIZE ];
	const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
	const int savedDataLength = min( dataLength, ENCRYPT_CHECKSIZE );
	int status;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( contextInfoPtr->type == CONTEXT_CONV || \
			contextInfoPtr->type == CONTEXT_PKC );
	assert( contextInfoPtr->encryptFunction != NULL );
	assert( isWritePtr( data, dataLength ) );

	if( contextInfoPtr->type == CONTEXT_PKC )
		{
		const BOOLEAN isDLP = isDlpAlgo( capabilityInfoPtr->cryptAlgo );

		/* Key agreement algorithms are treated as a special case since they 
		   don't actually encrypt the data */
		if( isKeyxAlgo( capabilityInfoPtr->cryptAlgo ) )
			{
			assert( dataLength == sizeof( KEYAGREE_PARAMS ) );

			status = contextInfoPtr->encryptFunction( contextInfoPtr, data, 
													  dataLength );
			clearTempBignums( contextInfoPtr->ctxPKC );
			return( status );
			}

		assert( !isDLP || dataLength == sizeof( DLP_PARAMS ) );

		memcpy( savedData, isDLP ? ( ( DLP_PARAMS * ) data )->inParam1 : \
								   data, ENCRYPT_CHECKSIZE );
		status = contextInfoPtr->encryptFunction( contextInfoPtr, data, 
												  dataLength );
		if( cryptStatusError( status ) )
			{
			zeroise( savedData, ENCRYPT_CHECKSIZE );
			clearTempBignums( contextInfoPtr->ctxPKC );
			return( status );
			}

		/* Check for a catastrophic failure of the encryption */
		if( isDLP )
			{
			DLP_PARAMS *dlpParams = ( DLP_PARAMS * ) data;

			if( !memcmp( savedData, dlpParams->outParam, ENCRYPT_CHECKSIZE ) )
				{
				zeroise( dlpParams->outParam, dlpParams->outLen );
				status = CRYPT_ERROR_FAILED;
				}
			}
		else
			if( !memcmp( savedData, data, ENCRYPT_CHECKSIZE ) )
				{
				zeroise( data, dataLength );
				status = CRYPT_ERROR_FAILED;
				}
		zeroise( savedData, ENCRYPT_CHECKSIZE );
		return( status );
		}

	assert( isStreamCipher( capabilityInfoPtr->cryptAlgo ) || \
			!needsIV( contextInfoPtr->ctxConv->mode ) ||
			( contextInfoPtr->flags & CONTEXT_IV_SET ) );
	assert( contextInfoPtr->ctxConv->key == \
			contextInfoPtr->storage + sizeof( CONV_INFO ) );

	memcpy( savedData, data, savedDataLength );
	status = contextInfoPtr->encryptFunction( contextInfoPtr, data, 
											  dataLength );
	if( cryptStatusError( status ) || savedDataLength <= 6 )
		{
		zeroise( savedData, ENCRYPT_CHECKSIZE );
		return( status );
		}

	/* Check for a catastrophic failure of the encryption.  A check of
	   a single block unfortunately isn't completely foolproof for 64-bit
	   blocksize ciphers in CBC mode because of the way the IV is applied to 
	   the input.  For the CBC encryption operation:
					
		out = enc( in ^ IV )
						
	   if out == IV the operation turns into a no-op.  Consider the simple 
	   case where IV == in, so IV ^ in == 0.  Then out = enc( 0 ) == IV, 
	   with the input appearing again at the output.  In fact this can occur 
	   during normal operation once every 2^32 blocks (for a 64-bit block 
	   cipher).  Although the chances of this happening are fairly low (the 
	   collision would have to occur on the first encrypted block in a 
	   message, since that's the one we check), if possible we check the 
	   first two blocks if we're using a 64-bit block cipher in CBC mode in 
	   order to reduce false positives */
	if( !memcmp( savedData, data, savedDataLength ) )
		{
		zeroise( data, dataLength );
		status = CRYPT_ERROR_FAILED;
		}
	zeroise( savedData, ENCRYPT_CHECKSIZE );
	return( status );
	}

/****************************************************************************
*																			*
*						Context Attribute Handling Functions				*
*																			*
****************************************************************************/

/* Handle data sent to or read from a context */

static int processGetAttribute( CONTEXT_INFO *contextInfoPtr,
								void *messageDataPtr, const int messageValue )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
	const CONTEXT_TYPE contextType = contextInfoPtr->type;
	int *valuePtr = ( int * ) messageDataPtr, value;

	switch( messageValue )
		{
		case CRYPT_ATTRIBUTE_ERRORTYPE:
			*valuePtr = contextInfoPtr->errorType;
			return( CRYPT_OK );

		case CRYPT_ATTRIBUTE_ERRORLOCUS:
			*valuePtr = contextInfoPtr->errorLocus;
			return( CRYPT_OK );

		case CRYPT_OPTION_MISC_SIDECHANNELPROTECTION:
			*valuePtr = ( contextInfoPtr->flags & \
						  CONTEXT_SIDECHANNELPROTECTION ) ? TRUE : FALSE;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_ALGO:
			*valuePtr = capabilityInfoPtr->cryptAlgo;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_MODE:
			assert( contextType == CONTEXT_CONV );
			*valuePtr = contextInfoPtr->ctxConv->mode;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_KEYSIZE:
			switch( contextType )
				{
				case CONTEXT_CONV:
					value = contextInfoPtr->ctxConv->userKeyLength;
					break;

				case CONTEXT_PKC:
					value = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );
					break;

				case CONTEXT_MAC:
					value = contextInfoPtr->ctxMAC->userKeyLength;
					break;

				default:
					assert( NOTREACHED );
					return( CRYPT_ERROR );
				}
			if( value <= 0 )
				/* If a key hasn't been loaded yet, we return the default
				   key size */
				value = capabilityInfoPtr->keySize;
			*valuePtr = value;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_BLOCKSIZE:
			if( contextType == CONTEXT_CONV && \
				( contextInfoPtr->ctxConv->mode == CRYPT_MODE_CFB || \
				  contextInfoPtr->ctxConv->mode == CRYPT_MODE_OFB ) )
				*valuePtr = 1;	/* Block cipher in stream mode */
			else
				*valuePtr = capabilityInfoPtr->blockSize;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_IVSIZE:
			assert( contextType == CONTEXT_CONV );
			if( !needsIV( contextInfoPtr->ctxConv->mode ) || \
				isStreamCipher( capabilityInfoPtr->cryptAlgo ) )
				return( CRYPT_ERROR_NOTAVAIL );
			*valuePtr = capabilityInfoPtr->blockSize;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_KEYING_ALGO:
		case CRYPT_OPTION_KEYING_ALGO:
			switch( contextType )
				{
				case CONTEXT_CONV:
					value = contextInfoPtr->ctxConv->keySetupAlgorithm;
					break;

				case CONTEXT_MAC:
					value = contextInfoPtr->ctxMAC->keySetupAlgorithm;
					break;

				default:
					assert( NOTREACHED );
					return( CRYPT_ERROR );
				}
			if( value <= 0 )
				return( exitErrorNotInited( contextInfoPtr,
											CRYPT_CTXINFO_KEYING_ALGO ) );
			*valuePtr = value;
			return( CRYPT_OK );

		case CRYPT_CTXINFO_KEYING_ITERATIONS:
		case CRYPT_OPTION_KEYING_ITERATIONS:
			switch( contextType )
				{
				case CONTEXT_CONV:
					value = contextInfoPtr->ctxConv->keySetupIterations;
					break;

				case CONTEXT_MAC:
					value = contextInfoPtr->ctxMAC->keySetupIterations;
					break;

				default:
					assert( NOTREACHED );
					return( CRYPT_ERROR );
				}
			if( value <= 0 )
				return( exitErrorNotInited( contextInfoPtr,

⌨️ 快捷键说明

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