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

📄 cryptapi.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*						 cryptlib External API Interface					*
*						Copyright Peter Gutmann 1997-2002					*
*																			*
****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "crypt.h"
#if defined( INC_ALL )
  #include "rpc.h"
#else
  #include "misc/rpc.h"
#endif /* Compiler-specific includes */

/* Handlers for the various commands */

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

	assert( cmd->type == COMMAND_ASYNCOP );
	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 ] ) )
		return( CRYPT_ERROR_PARAM1 );

	/* This command is a kitchen-sink operation used to manage async ops.on
	   contexts.  If the arg is zero, it gets the objects status, otherwise
	   it cancels an async operation.  
	   
	   First, 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 
	   algorithm type, which is a context-only attribute which ensures that
	   what'll be reported is the status of whatever it is which could be
	   busy rather than the status of an associated object (eg an envelope,
	   which is never busy, in any case we can't use a universal object
	   attribute like a property because these are handled by the kernel and
	   aren't affected by the object state).
	   
	   Since the context attribute read returns an error value if the object 
	   is in a non-normal state, we allow some error types through */
	status = krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_GETATTRIBUTE,
							  &dummy, CRYPT_CTXINFO_ALGO );
	if( status != CRYPT_OK && status != CRYPT_ERROR_BUSY )
		return( status );

	/* If we're after the object status or it's in the normal status (ie 
	   there's nothing to do), return now */
	if( !cmd->arg[ 1 ] || status == CRYPT_OK )
		return( status );

	/* If the object is busy, reset its status to non-busy.  If the object is 
	   still busy when the message is received, the abort flag will be set, 
	   otherwise the message won't have any effect */
	return( krnlSendMessage( cmd->arg[ 0 ], RESOURCE_IMESSAGE_SETATTRIBUTE,
							 MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS ) );
	}

static int cmdCertCheck( void *stateInfo, COMMAND_INFO *cmd )
	{
	assert( cmd->type == COMMAND_CERTCHECK );
	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 ] ) )
		return( CRYPT_ARGERROR_OBJECT );
	if( !checkHandleRange( cmd->arg[ 1 ] ) && \
		( cmd->arg[ 1 ] != CRYPT_UNUSED ) )
		return( CRYPT_ARGERROR_NUM1 );

	return( krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_CRT_SIGCHECK, 
							 NULL, cmd->arg[ 1 ] ) );
	}

static int cmdCertMgmt( void *stateInfo, COMMAND_INFO *cmd )
	{
	MESSAGE_CERTMGMT_INFO certMgmtInfo;
	int status;

	assert( cmd->type == COMMAND_CERTMGMT );
	assert( cmd->flags == COMMAND_FLAG_NONE || \
			cmd->flags == COMMAND_FLAG_RET_NONE );
	assert( cmd->noArgs == 4 );
	assert( cmd->noStrArgs == 0 );

	UNUSED( stateInfo );

	/* Perform basic server-side error checking */
	if( !checkHandleRange( cmd->arg[ 0 ] ) )
		return( CRYPT_ARGERROR_OBJECT );
	if( cmd->arg[ 1 ] < CRYPT_CERTACTION_FIRST_USER || \
		cmd->arg[ 1 ] > CRYPT_CERTACTION_LAST_USER )
		return( CRYPT_ARGERROR_VALUE );
	if( !checkHandleRange( cmd->arg[ 2 ] ) && \
		!( ( cmd->arg[ 1 ] == CRYPT_CERTACTION_EXPIRE_CERT || \
			 cmd->arg[ 1 ] == CRYPT_CERTACTION_CLEANUP ) && \
		   cmd->arg[ 2 ] == CRYPT_UNUSED ) )
		return( CRYPT_ARGERROR_NUM1 );
	if( !checkHandleRange( cmd->arg[ 3 ] ) && \
		!( ( cmd->arg[ 1 ] == CRYPT_CERTACTION_ISSUE_CRL || \
			 cmd->arg[ 1 ] == CRYPT_CERTACTION_EXPIRE_CERT || \
			 cmd->arg[ 1 ] == CRYPT_CERTACTION_CLEANUP ) && \
		   cmd->arg[ 3 ] == CRYPT_UNUSED ) )
		return( CRYPT_ARGERROR_NUM2 );

	setMessageCertMgmtInfo( &certMgmtInfo, cmd->arg[ 2 ], cmd->arg[ 3 ] );
	if( cmd->flags == COMMAND_FLAG_RET_NONE )
		/* If we aren't interested in the return value, set the crypt handle 
		   to CRYPT_UNUSED to indicate that there's no need to return the 
		   created cert object */
		certMgmtInfo.cryptCert = CRYPT_UNUSED;
	status = krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_KEY_CERTMGMT, 
							  &certMgmtInfo, cmd->arg[ 1 ] );
	if( cryptStatusOK( status ) && cmd->flags != COMMAND_FLAG_RET_NONE )
		{
		/* Make the newly-created cert externally visible */
		krnlSendMessage( certMgmtInfo.cryptCert, 
						 RESOURCE_IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_FALSE, 
						 CRYPT_IATTRIBUTE_INTERNAL );
		cmd->arg[ 0 ] = certMgmtInfo.cryptCert;
		}
	return( status );
	}

static int cmdCertSign( void *stateInfo, COMMAND_INFO *cmd )
	{
	assert( cmd->type == COMMAND_CERTSIGN );
	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 ] ) )
		return( CRYPT_ARGERROR_OBJECT );
	if( !checkHandleRange( cmd->arg[ 1 ] ) )
		return( CRYPT_ARGERROR_NUM1 );

	return( krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_CRT_SIGN, 
							 NULL, cmd->arg[ 1 ] ) );
	}

static int cmdCreateObject( void *stateInfo, COMMAND_INFO *cmd )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	BOOLEAN bindToOwner = FALSE, hasStrArg = FALSE;
	int owner, status;

	assert( cmd->type == COMMAND_CREATEOBJECT );
	assert( cmd->flags == COMMAND_FLAG_NONE );
	assert( cmd->noArgs >= 2 && cmd->noArgs <= 4 );
	assert( cmd->noStrArgs >= 0 && cmd->noStrArgs <= 2 );

	UNUSED( stateInfo );

	/* Perform basic server-side error checking */
	if( !checkHandleRange( cmd->arg[ 0 ] ) && \
		cmd->arg[ 0 ] != SYSTEM_OBJECT_HANDLE )
		return( CRYPT_ARGERROR_OBJECT );
	if( cmd->arg[ 1 ] <= OBJECT_TYPE_NONE || \
		cmd->arg[ 1 ] >= OBJECT_TYPE_LAST )
		return( CRYPT_ERROR_FAILED );	/* Internal error */
	switch( cmd->arg[ 1 ] )
		{
		case OBJECT_TYPE_CONTEXT:
			assert( cmd->noArgs == 3 );
			assert( cmd->noStrArgs == 0 );
			if( ( cmd->arg[ 2 ] <= CRYPT_ALGO_NONE || \
				  cmd->arg[ 2 ] >= CRYPT_ALGO_LAST ) && \
				cmd->arg[ 2 ] != CRYPT_USE_DEFAULT )
				return( CRYPT_ARGERROR_NUM1 );
			break;

		case OBJECT_TYPE_CERTIFICATE:
			assert( cmd->noArgs == 3 );
			assert( cmd->noStrArgs == 0 );
			if( cmd->arg[ 2 ] <= CRYPT_CERTTYPE_NONE || \
				cmd->arg[ 2 ] >= CRYPT_CERTTYPE_LAST_EXTERNAL )
				return( CRYPT_ARGERROR_NUM1 );
			break;

		case OBJECT_TYPE_DEVICE:
			assert( cmd->noArgs == 3 );
			assert( cmd->noStrArgs == 1 );
			if( cmd->arg[ 2 ] <= CRYPT_DEVICE_NONE || \
				cmd->arg[ 2 ] >= CRYPT_DEVICE_LAST )
				return( CRYPT_ARGERROR_NUM1 );
			if( cmd->arg[ 2 ] == CRYPT_DEVICE_PKCS11 )
				{
				if( cmd->strArgLen[ 0 ] < 2 || \
					cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )
					return( CRYPT_ARGERROR_STR1 );
				hasStrArg = TRUE;
				}
			break;

		case OBJECT_TYPE_KEYSET:
			assert( cmd->noArgs == 4 );
			assert( cmd->noStrArgs >= 0 && cmd->noStrArgs <= 1 );
			if( cmd->arg[ 2 ] <= CRYPT_KEYSET_NONE || \
				cmd->arg[ 2 ] >= CRYPT_KEYSET_LAST )
				return( CRYPT_ARGERROR_NUM1 );
			if( cmd->strArgLen[ 0 ] < 2 || \
				cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )
				return( CRYPT_ARGERROR_STR1 );
			if( cmd->arg[ 3 ] < CRYPT_KEYOPT_NONE || \
				cmd->arg[ 3 ] >= CRYPT_KEYOPT_LAST_EXTERNAL )
				/* CRYPT_KEYOPT_NONE is a valid setting for this parameter */
				return( CRYPT_ARGERROR_NUM2 );
			hasStrArg = TRUE;
			break;

		case OBJECT_TYPE_ENVELOPE:
			assert( cmd->noArgs == 3 );
			assert( cmd->noStrArgs == 0 );
			if( cmd->arg[ 2 ] <= CRYPT_FORMAT_NONE || \
				cmd->arg[ 2 ] >= CRYPT_FORMAT_LAST )
				return( CRYPT_ARGERROR_NUM1 );
			break;

		case OBJECT_TYPE_SESSION:
			assert( cmd->noArgs == 3 );
			assert( cmd->noStrArgs == 0 );
			if( cmd->arg[ 2 ] <= CRYPT_SESSION_NONE || \
				cmd->arg[ 2 ] >= CRYPT_SESSION_LAST )
				return( CRYPT_ARGERROR_NUM1 );
			break;

		case OBJECT_TYPE_USER:
			assert( cmd->noArgs == 2 );
			assert( cmd->noStrArgs == 2 );
			if( cmd->strArgLen[ 0 ] < 2 || \
				cmd->strArgLen[ 0 ] >= CRYPT_MAX_TEXTSIZE )
				return( CRYPT_ARGERROR_STR1 );
			if( cmd->strArgLen[ 1 ] < 2 || \
				cmd->strArgLen[ 1 ] >= CRYPT_MAX_TEXTSIZE )
				return( CRYPT_ARGERROR_STR2 );
			hasStrArg = TRUE;
			break;

		default:
			assert( NOTREACHED );
		}

	/* If we're creating the object via a device, we should set the new 
	   object owner to the device owner */
	if( cmd->arg[ 0 ] != SYSTEM_OBJECT_HANDLE )
		{
		bindToOwner = TRUE;
		owner = cmd->arg[ 0 ];
		}

	/* Create the object via the device.  Since we're usually doing this via 
	   the system object which is invisible to the user, we have to use an
	   internal message for this one case */
	setMessageCreateObjectInfo( &createInfo, cmd->arg[ 2 ] );
	if( cmd->noArgs == 4 )
		createInfo.arg2 = cmd->arg[ 3 ];
	if( hasStrArg )
		{
		createInfo.strArg1 = cmd->strArg[ 0 ];
		createInfo.strArgLen1 = cmd->strArgLen[ 0 ];
		if( cmd->noStrArgs > 1 )
			{
			createInfo.strArg2 = cmd->strArg[ 1 ];
			createInfo.strArgLen2 = cmd->strArgLen[ 1 ];
			}
		}
	if( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
								  &createInfo, cmd->arg[ 1 ] );
	else
		status = krnlSendMessage( cmd->arg[ 0 ], 
								  RESOURCE_MESSAGE_DEV_CREATEOBJECT,
								  &createInfo, cmd->arg[ 1 ] );
	if( cryptStatusError( status ) )
		return( status );

	/* If the device used to create the object is bound to a thread, bind the 
	   created object to the thread as well.  If this fails, we don't return 
	   the object to the caller since it would be returned in a potentially 
	   unbound state */
	if( bindToOwner )
		{
		int ownerID;

		status = krnlSendMessage( owner, RESOURCE_IMESSAGE_GETATTRIBUTE,
								  &ownerID, CRYPT_PROPERTY_OWNER );
		if( cryptStatusOK( status ) )
			status = krnlSendMessage( createInfo.cryptHandle, 
									  RESOURCE_IMESSAGE_SETATTRIBUTE,
									  &ownerID, CRYPT_PROPERTY_OWNER );
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( createInfo.cryptHandle, 
							  RESOURCE_IMESSAGE_DECREFCOUNT );
			return( status );
			}
		}

	/* Make the newly-created object externally visible */
	krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_INTERNAL );
	cmd->arg[ 0 ] = createInfo.cryptHandle;
	return( status );
	}

static int cmdCreateObjectIndirect( void *stateInfo, COMMAND_INFO *cmd )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	int status;

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

	UNUSED( stateInfo );

	/* Perform basic server-side error checking */
	if( cmd->arg[ 0 ] != SYSTEM_OBJECT_HANDLE )
		return( CRYPT_ERROR_FAILED );	/* Internal error */
	if( cmd->arg[ 1 ] != OBJECT_TYPE_CERTIFICATE )
		return( CRYPT_ERROR_FAILED );	/* Internal error */
	if( cmd->strArgLen[ 0 ] < MIN_CERTSIZE )
		return( CRYPT_ARGERROR_STR1 );

	/* Create the object via the device.  Since we're usually doing this via 
	   the system object which is invisible to the user, we have to use an
	   internal message for this one case */
	setMessageCreateObjectIndirectInfo( &createInfo, cmd->strArg[ 0 ],
										cmd->strArgLen[ 0 ] );
	if( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  RESOURCE_IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
								  &createInfo, OBJECT_TYPE_CERTIFICATE );
	else
		status = krnlSendMessage( cmd->arg[ 0 ], 
								  RESOURCE_MESSAGE_DEV_CREATEOBJECT_INDIRECT,
								  &createInfo, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusError( status ) )
		return( status );

	/* Make the newly-created object externally visible */
	krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_INTERNAL );
	cmd->arg[ 0 ] = createInfo.cryptHandle;
	return( status );
	}

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

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

	UNUSED( stateInfo );

	/* Perform basic server-side error checking */

⌨️ 快捷键说明

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