cryptapi.c

来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,895 行 · 第 1/5 页

C
1,895
字号
	status = krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_GETATTRIBUTE,
							  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( status );
	if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )
		{
		status = krnlSendMessage( cmd->arg[ 0 ], 
								  RESOURCE_MESSAGE_GETATTRIBUTE,
								  &cryptMode, CRYPT_CTXINFO_MODE );
		if( cryptStatusError( status ) )
				return( status );
		}
	else
		if( cryptAlgo <= CRYPT_ALGO_LAST_PKC )
			{
			int blockSize;

			status = krnlSendMessage( cmd->arg[ 0 ], 
									  RESOURCE_MESSAGE_GETATTRIBUTE,
									  &blockSize, CRYPT_CTXINFO_KEYSIZE );
			if( cryptStatusOK( status ) && cmd->strArgLen[ 0 ] != blockSize )
				status = CRYPT_ARGERROR_NUM1;
			if( cryptStatusError( status ) )
				return( status );
			}
	if( cmd->strArgLen[ 0 ] < 0 )
		return( CRYPT_ARGERROR_NUM1 );
	if( cryptMode == CRYPT_MODE_ECB || cryptMode == CRYPT_MODE_CBC )
		{
		int blockSize;

		status = krnlSendMessage( cmd->arg[ 0 ], 
								  RESOURCE_MESSAGE_GETATTRIBUTE,
								  &blockSize, CRYPT_CTXINFO_BLOCKSIZE );
		if( cryptStatusOK( status ) && cmd->strArgLen[ 0 ] % blockSize )
			status = CRYPT_ARGERROR_NUM1;
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Make sure the IV has been set */
	if( needsIV( cryptMode ) && !isStreamCipher( cryptAlgo ) )
		{
		RESOURCE_DATA msgData;

		setResourceData( &msgData, NULL, 0 );
		status = krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_IV );
		if( cryptStatusError( status ) )
			return( status );
		}

	status = krnlSendMessage( cmd->arg[ 0 ], ( cryptAlgo >= CRYPT_ALGO_FIRST_HASH ) ? \
							  RESOURCE_MESSAGE_CTX_HASH : RESOURCE_MESSAGE_CTX_DECRYPT, 
							  cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : "", 
							  cmd->strArgLen[ 0 ] );
	if( cryptAlgo >= CRYPT_ALGO_FIRST_HASH )
		/* There's no data to return since the hashing doesn't change it */
		cmd->strArgLen[ 0 ] = 0;
	return( status );
	}

static int cmdDeleteAttribute( void *stateInfo, COMMAND_INFO *cmd )
	{
	assert( cmd->type == COMMAND_DELETEATTRIBUTE );
	assert( cmd->flags == COMMAND_FLAG_NONE );
	assert( cmd->noArgs == 2 );
	assert( cmd->noStrArgs == 0 );

	UNUSED( stateInfo );

	/* Perform basic server-side error checking */
	if( !checkHandleRange( cmd->arg[ 0 ] ) && \
		cmd->arg[ 0 ] != DEFAULTUSER_OBJECT_HANDLE )
		return( CRYPT_ARGERROR_OBJECT );
	if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
		{
		if( cmd->arg[ 1 ] <= CRYPT_OPTION_FIRST || \
			cmd->arg[ 1 ] >= CRYPT_OPTION_LAST )
			return( CRYPT_ARGERROR_NUM1 );
		}
	else
		if( cmd->arg[ 1 ] <= CRYPT_ATTRIBUTE_NONE || \
			cmd->arg[ 1 ] >= CRYPT_ATTRIBUTE_LAST )
			return( CRYPT_ARGERROR_NUM1 );

	/* Delete the attribute.  Since we're usually doing this via the default 
	   user object which is invisible to the user, we have to use an internal 
	   message for this one case */
	if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
		return( krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, 
								 RESOURCE_IMESSAGE_DELETEATTRIBUTE, NULL, 
								 cmd->arg[ 1 ] ) );
	return( krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_DELETEATTRIBUTE,
							 NULL, cmd->arg[ 1 ] ) );
	}

static int cmdDeleteKey( void *stateInfo, COMMAND_INFO *cmd )
	{
	MESSAGE_KEYMGMT_INFO deletekeyInfo;

	assert( cmd->type == COMMAND_DELETEKEY );
	assert( cmd->flags == COMMAND_FLAG_NONE );
	assert( cmd->noArgs == 2 );
	assert( cmd->noStrArgs == 1 );

	UNUSED( stateInfo );

	/* Perform basic server-side error checking */
	if( !checkHandleRange( cmd->arg[ 0 ] ) )
		return( CRYPT_ARGERROR_OBJECT );
	if( cmd->arg[ 1 ] <= CRYPT_KEYID_NONE || \
		cmd->arg[ 1 ] >= CRYPT_KEYID_LAST_EXTERNAL )
		return( CRYPT_ARGERROR_NUM1 );
	if( cmd->strArgLen[ 0 ] < 2 || \
		cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )
		return( CRYPT_ARGERROR_STR1 );

	/* Delete the key from the keyset.  We set the item type to delete to
	   public key since private-key keysets will interpret this correctly
	   to mean they should also delete the associated private key */
	setMessageKeymgmtInfo( &deletekeyInfo, cmd->arg[ 1 ], cmd->strArg[ 0 ], 
						   cmd->strArgLen[ 0 ], NULL, 0, KEYMGMT_FLAG_NONE );
	return( krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_KEY_DELETEKEY, 
							 &deletekeyInfo, KEYMGMT_ITEM_PUBLICKEY ) );
	}

static int cmdDestroyObject( void *stateInfo, COMMAND_INFO *cmd )
	{
	int dummy, status;

	assert( cmd->type == COMMAND_DESTROYOBJECT );
	assert( cmd->flags == COMMAND_FLAG_NONE );
	assert( cmd->noArgs == 1 );
	assert( cmd->noStrArgs == 0 );

	UNUSED( stateInfo );

	/* Perform basic server-side error checking */
	if( !checkHandleRange( cmd->arg[ 0 ] ) )
		return( CRYPT_ARGERROR_OBJECT );

	/* Since we're about to access an internal attribute which can only be 
	   done through an internal message, we have to explicitly make sure the 
	   object is externally visible.  We do this by reading it's locked 
	   property (which is valid for all objects) */
	status = krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_GETATTRIBUTE,
							  &dummy, CRYPT_PROPERTY_LOCKED );
	if( cryptStatusError( status ) )
		return( status );

	/* Make the object internal, which marks it as invalid for any external
	   access (to the caller, it looks like it's been destroyed).  After
	   this, decrement its reference count (which may or may not actually
	   destroy it) */
	krnlSendMessage( cmd->arg[ 0 ], RESOURCE_IMESSAGE_SETATTRIBUTE, 
					 MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_INTERNAL );
	return( krnlSendNotifier( cmd->arg[ 0 ], RESOURCE_IMESSAGE_DECREFCOUNT ) );
	}

static int cmdEncrypt( void *stateInfo, COMMAND_INFO *cmd )
	{
	CRYPT_ALGO cryptAlgo;
	CRYPT_MODE cryptMode = CRYPT_MODE_NONE;
	int status;

	assert( cmd->type == COMMAND_ENCRYPT );
	assert( cmd->flags == COMMAND_FLAG_NONE );
	assert( cmd->noArgs == 1 );
	assert( cmd->noStrArgs == 1 );

	UNUSED( stateInfo );

	/* Perform basic server-side error checking */
	status = krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_GETATTRIBUTE,
							  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( status );
	if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )
		{
		status = krnlSendMessage( cmd->arg[ 0 ], 
								  RESOURCE_MESSAGE_GETATTRIBUTE,
								  &cryptMode, CRYPT_CTXINFO_MODE );
		if( cryptStatusError( status ) )
				return( status );
		}
	else
		if( cryptAlgo <= CRYPT_ALGO_LAST_PKC )
			{
			int blockSize;

			status = krnlSendMessage( cmd->arg[ 0 ], 
									  RESOURCE_MESSAGE_GETATTRIBUTE,
									  &blockSize, CRYPT_CTXINFO_KEYSIZE );
			if( cryptStatusOK( status ) && cmd->strArgLen[ 0 ] != blockSize )
				status = CRYPT_ARGERROR_NUM1;
			if( cryptStatusError( status ) )
				return( status );
			}
	if( cmd->strArgLen[ 0 ] < 0 )
		return( CRYPT_ARGERROR_NUM1 );
	if( cryptMode == CRYPT_MODE_ECB || cryptMode == CRYPT_MODE_CBC )
		{
		int blockSize;

		status = krnlSendMessage( cmd->arg[ 0 ], 
								  RESOURCE_MESSAGE_GETATTRIBUTE,
								  &blockSize, CRYPT_CTXINFO_BLOCKSIZE );
		if( cryptStatusOK( status ) && cmd->strArgLen[ 0 ] % blockSize )
			status = CRYPT_ARGERROR_NUM1;
		if( cryptStatusError( status ) )
			return( status );
		}

	/* If there's no IV set, generate one ourselves */
	if( needsIV( cryptMode ) && !isStreamCipher( cryptAlgo ) )
		{
		RESOURCE_DATA msgData;

		setResourceData( &msgData, NULL, 0 );
		status = krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_IV );
		if( cryptStatusError( status ) )
			if( status == CRYPT_ERROR_NOTINITED )
				krnlSendNotifier( cmd->arg[ 0 ], RESOURCE_MESSAGE_CTX_GENIV );
			else
				return( status );
		}

	status = krnlSendMessage( cmd->arg[ 0 ], ( cryptAlgo >= CRYPT_ALGO_FIRST_HASH ) ? \
							  RESOURCE_MESSAGE_CTX_HASH : RESOURCE_MESSAGE_CTX_ENCRYPT, 
							  cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : "", 
							  cmd->strArgLen[ 0 ] );
	if( cryptAlgo >= CRYPT_ALGO_FIRST_HASH )
		/* There's no data to return since the hashing doesn't change it */
		cmd->strArgLen[ 0 ] = 0;
	return( status );
	}

static int cmdExportObject( void *stateInfo, COMMAND_INFO *cmd )
	{
	CRYPT_ATTRIBUTE_TYPE formatType;
	RESOURCE_DATA msgData;
	int type, status;

	assert( cmd->type == COMMAND_EXPORTOBJECT );
	assert( cmd->flags == COMMAND_FLAG_NONE || \
			cmd->flags == COMMAND_FLAG_RET_LENGTH );
	assert( cmd->noArgs == 2 );
	assert( cmd->noStrArgs >= 0 && cmd->noStrArgs <= 1 );

	UNUSED( stateInfo );

	/* Perform basic server-side error checking */
	if( !checkHandleRange( cmd->arg[ 0 ] ) )
		return( CRYPT_ARGERROR_OBJECT );
	if( cmd->arg[ 1 ] <= CRYPT_CERTFORMAT_NONE || \
		cmd->arg[ 1 ] >= CRYPT_CERTFORMAT_LAST )
		/* At the moment the only object we can export is a cert, so we
		   make sure the format type is valid for this */
		return( CRYPT_ARGERROR_NUM1 );
	
	/* Convert the format type into the appropriate attribute type to read
	   from the object */
	formatType = ( cmd->arg[ 1 ] == CRYPT_CERTFORMAT_CERTIFICATE ) ? \
				 CRYPT_IATTRIBUTE_ENC_CERT : \
				 ( cmd->arg[ 1 ] == CRYPT_CERTFORMAT_CERTCHAIN ) ? \
				 CRYPT_IATTRIBUTE_ENC_CERTCHAIN : \
				 ( cmd->arg[ 1 ] == CRYPT_CERTFORMAT_TEXT_CERTIFICATE ) ? \
				 CRYPT_IATTRIBUTE_TEXT_CERT : CRYPT_IATTRIBUTE_TEXT_CERTCHAIN;

	/* Since we're about to access an internal attribute (which can only be 
	   done through an internal message), we have to explicitly make sure 
	   the object is externally visible.  We do this by reading its cert
	   type, which is a cert-only attribute which ensures that any possible
	   error status which will be reported is that of the cert rather than 
	   that of an associated object.  If that succeeds, we read the encoded
	   cert attribute */
	status = krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_GETATTRIBUTE,
							  &type, CRYPT_CERTINFO_CERTTYPE );
	if( cryptStatusError( status ) )
		return( status );
	if( cmd->flags == COMMAND_FLAG_RET_LENGTH )
		{
		setResourceData( &msgData, NULL, 0 );
		status = krnlSendMessage( cmd->arg[ 0 ], 
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, formatType );
		if( cryptStatusOK( status ) )
			cmd->arg[ 0 ] = msgData.length;
		}
	else
		{
		setResourceData( &msgData, cmd->strArg[ 0 ], cmd->strArgLen[ 0 ] );
		status = krnlSendMessage( cmd->arg[ 0 ], 
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, formatType );
		if( cryptStatusOK( status ) )
			cmd->strArgLen[ 0 ] = msgData.length;
		}

	/* If we try and read a disallowed attribute value (eg an ENC_CERTCHAIN
	   from a cert request) we'll get an argument value error which we need
	   to convert into something more sensible.  The error type to report is
	   somewhat debatable since either the attribute value or the object can
	   be regarded as being wrong, for example when exporting a cert request
	   as a cert chain the value is wrong but when exporting a data-only
	   object as anything the object is wrong.  To handle this, we report an
	   argument value error as a numeric parameter error for cases where the
	   value is incorrect for the object type, and a permission error for 
	   cases where the object can't be exported externally */
	if( status == CRYPT_ARGERROR_VALUE )
		status = ( type == CRYPT_CERTTYPE_CERTIFICATE || \
				   type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
				   type == CRYPT_CERTTYPE_CERTCHAIN || \
				   type == CRYPT_CERTTYPE_CERTREQUEST || \
				   type == CRYPT_CERTTYPE_CRL ) ? \
				 CRYPT_ARGERROR_NUM1 : CRYPT_ERROR_PERMISSION;

	return( status );
	}

static int cmdFlushData( void *stateInfo, COMMAND_INFO *cmd )
	{
	RESOURCE_DATA msgData;
	int status;

	assert( cmd->type == COMMAND_FLUSHDATA );
	assert( cmd->flags == COMMAND_FLAG_NONE );
	assert( cmd->noArgs == 1 );
	assert( cmd->noStrArgs == 0 );

	UNUSED( stateInfo );

	/* Perform basic server-side error checking */
	if( !checkHandleRange( cmd->arg[ 0 ] ) )
		return( CRYPT_ARGERROR_OBJECT );

	/* Send the flush data command to the object */
	setResourceData( &msgData, NULL, 0 );
	status = krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_ENV_PUSHDATA,
							  &msgData, 0 );
	return( status );
	}

static int cmdGenKey( void *stateInfo, COMMAND_INFO *cmd )
	{
	assert( cmd->type == COMMAND_GENKEY );
	assert( cmd->flags == COMMAND_FLAG_NONE );
	assert( cmd->noArgs >= 1 && cmd->noArgs <= 2 );
	assert( cmd->noStrArgs == 0 );

	UNUSED( stateInfo );

	/* Perform basic server-side error checking */
	if( !checkHandleRange( cmd->arg[ 0 ] ) )
		return( CRYPT_ARGERROR_OBJECT );

	return( krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_CTX_GENKEY, 
							 NULL, ( cmd->noArgs > 1 ) ? \
							 ( cmd->arg[ 1 ] ? TRUE : FALSE ) : FALSE ) );
	}

static int cmdGetAttribute( void *stateInfo, COMMAND_INFO *cmd )
	{
	RESOURCE_DATA msgData;
	int status;

	assert( cmd->type == COMMAND_GETATTRIBUTE );
	assert( cmd->flags == COMMAND_FLAG_NONE || \
			cmd->flags == COMMAND_FLAG_RET_LENGTH );
	assert( cmd->noArgs >= 2 && cmd->noArgs <= 3 );
	assert( cmd->noStrArgs >= 0 && cmd->noStrArgs <= 1 );

	UNUSED( stateInfo );

	/* Perform basic server-side error checking */
	if( !checkHandleRange( cmd->arg[ 0 ] ) && \
		cmd->arg[ 0 ] != DEFAULTUSER_OBJECT_HANDLE )

⌨️ 快捷键说明

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