cryptapi.c

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

C
1,895
字号
		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 );

	/* Get the attribute data from the object.  If it's a config option, 
	   we're usually doing this via the default user object which is 
	   invisible to the user, so we have to use an internal message for this 
	   one case */
	if( cmd->noArgs == 2 )
		{
		if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
			return( krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, 
									 RESOURCE_IMESSAGE_GETATTRIBUTE,
									 &cmd->arg[ 0 ], cmd->arg[ 1 ] ) );
		return( krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_GETATTRIBUTE,
								 &cmd->arg[ 0 ], cmd->arg[ 1 ] ) );
		}
	if( cmd->flags == COMMAND_FLAG_RET_LENGTH )
		{
		setResourceData( &msgData, NULL, 0 );
		if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
			status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, 
									  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
									  &msgData, cmd->arg[ 1 ] );
		else
			status = krnlSendMessage( cmd->arg[ 0 ], 
									  RESOURCE_MESSAGE_GETATTRIBUTE_S,
									  &msgData, cmd->arg[ 1 ] );
		if( cryptStatusOK( status ) )
			cmd->arg[ 0 ] = msgData.length;
		}
	else
		{
		setResourceData( &msgData, cmd->strArg[ 0 ], cmd->strArgLen[ 0 ] );
		if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
			status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, 
									  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
									  &msgData, cmd->arg[ 1 ] );
		else
			status = krnlSendMessage( cmd->arg[ 0 ], 
									  RESOURCE_MESSAGE_GETATTRIBUTE_S,
									  &msgData, cmd->arg[ 1 ] );
		if( cryptStatusOK( status ) )
			cmd->strArgLen[ 0 ] = msgData.length;
		}
	return( status );
	}

static int cmdGetKey( void *stateInfo, COMMAND_INFO *cmd )
	{
	MESSAGE_KEYMGMT_INFO getkeyInfo;
	int itemType = ( cmd->noStrArgs >= 2 ) ? \
				KEYMGMT_ITEM_PRIVATEKEY : KEYMGMT_ITEM_PUBLICKEY;
	int messageType = ( cmd->arg[ 1 ] == CRYPT_KEYID_NONE ) ? \
				RESOURCE_MESSAGE_KEY_GETNEXTCERT : RESOURCE_MESSAGE_KEY_GETKEY;
	int owner, status;

	assert( cmd->type == COMMAND_GETKEY );
	assert( cmd->flags == COMMAND_FLAG_NONE );
	assert( cmd->noArgs >= 2 && cmd->noArgs <= 3 );
	assert( cmd->noStrArgs >= 1 && cmd->noStrArgs <= 2 );

	UNUSED( stateInfo );

	/* Perform basic server-side error checking.  Because of keyset queries 
	   we have to accept CRYPT_KEYID_NONE as well as obviously valid key 
	   ID's.  In addition if we find a missing ID we pass the request in as
	   a keyset query (this is matched to an implicit GetFirstCert performed 
	   by setting the query attribute, this isn't really possible using the 
	   external API) */
	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->arg[ 1 ] == CRYPT_KEYID_NONE )
		{
		if( cmd->strArgLen[ 0 ] )
			return( CRYPT_ARGERROR_NUM1 );
		}
	else
		if( cmd->strArgLen[ 0 ] < 2 || \
			cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )
			return( CRYPT_ARGERROR_STR1 );
	if( cmd->arg[ 2 ] )
		{
		/* It's a special-case object being fetched from a CA store */
		if( cmd->arg[ 2 ] == CRYPT_CERTTYPE_REQUEST_CERT )
			itemType = KEYMGMT_ITEM_REQUEST;
		else
			if( cmd->arg[ 2 ] == CRYPT_CERTTYPE_PKIUSER )
				itemType = KEYMGMT_ITEM_PKIUSER;
			else
				return( CRYPT_ARGERROR_NUM2 );
		}

	/* Read the key from the keyset */
	setMessageKeymgmtInfo( &getkeyInfo, cmd->arg[ 1 ], 
						   cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : NULL, 
							cmd->strArgLen[ 0 ], 
						   cmd->strArgLen[ 1 ] ? cmd->strArg[ 1 ] : NULL, 
							cmd->strArgLen[ 1 ], KEYMGMT_FLAG_NONE );
	status = krnlSendMessage( cmd->arg[ 0 ], messageType, &getkeyInfo, 
							  itemType );
	if( cryptStatusError( status ) )
		return( status );

	/* If the keyset is bound to a thread, bind the key read from it to the 
	   thread as well.  If this fails, we don't return the imported key to 
	   the caller since it would be returned in a potentially unbound state */
	status = krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_GETATTRIBUTE, 
							  &owner, CRYPT_PROPERTY_OWNER );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( getkeyInfo.cryptHandle, RESOURCE_IMESSAGE_DECREFCOUNT );
		return( status );
		}
	krnlSendMessage( getkeyInfo.cryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE, 
					 &owner, CRYPT_PROPERTY_OWNER );

	/* Make the key externally visible */
	krnlSendMessage( getkeyInfo.cryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE, 
					 MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_INTERNAL );
	cmd->arg[ 0 ] = getkeyInfo.cryptHandle;
		
	return( CRYPT_OK );
	}

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

	assert( cmd->type == COMMAND_POPDATA );
	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 ] < 1 )
		return( CRYPT_ARGERROR_NUM1 );

	/* Get the data from the object.  We always copy out the byte count value
	   because it's valid even if an error occurs */
	setResourceData( &msgData, cmd->strArg[ 0 ], cmd->arg[ 1 ] );
	status = krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_ENV_POPDATA,
							  &msgData, 0 );
	cmd->strArgLen[ 0 ] = msgData.length;
	return( status );
	}

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

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

	UNUSED( stateInfo );

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

	/* Send the data to the object.  We always copy out the byte count value
	   because it's valid even if an error occurs */
	setResourceData( &msgData, cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : NULL, 
					 cmd->strArgLen[ 0 ] );
	status = krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_ENV_PUSHDATA,
							  &msgData, 0 );
	cmd->arg[ 0 ] = msgData.length;
	return( status );
	}

static int cmdQueryCapability( void *stateInfo, COMMAND_INFO *cmd )
	{
	CRYPT_QUERY_INFO queryInfo;
	int status;

	assert( cmd->type == COMMAND_QUERYCAPABILITY );
	assert( cmd->flags == COMMAND_FLAG_NONE || \
			cmd->flags == COMMAND_FLAG_RET_LENGTH );
	assert( cmd->noArgs == 2 );
	assert( cmd->noStrArgs >= 0 && cmd->noStrArgs <= 1 );
	assert( cmd->flags == COMMAND_FLAG_RET_LENGTH || \
			cmd->strArg[ 0 ] != NULL );

	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 ] < CRYPT_ALGO_NONE || cmd->arg[ 1 ] >= CRYPT_ALGO_LAST )
		return( CRYPT_ARGERROR_NUM1 );

	/* Query the device for information on the given algorithm and mode.  
	   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 */
	if( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  RESOURCE_IMESSAGE_DEV_QUERYCAPABILITY,
								  &queryInfo, cmd->arg[ 1 ] );
	else
		status = krnlSendMessage( cmd->arg[ 0 ], 
								  RESOURCE_MESSAGE_DEV_QUERYCAPABILITY,
								  &queryInfo, cmd->arg[ 1 ] );
	if( cryptStatusOK( status ) )
		{
		/* Return either the length or the full capability into depending on
		   what the caller has asked for */
		if( cmd->flags == COMMAND_FLAG_RET_LENGTH )
			cmd->arg[ 0 ] = sizeof( CRYPT_QUERY_INFO );
		else
			{
			memcpy( cmd->strArg[ 0 ], &queryInfo, 
					sizeof( CRYPT_QUERY_INFO ) );
			cmd->strArgLen[ 0 ] = sizeof( CRYPT_QUERY_INFO );
			}
		}

	return( status );
	}

static int cmdServerQuery( void *stateInfo, COMMAND_INFO *cmd )
	{
	int value;

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

	UNUSED( stateInfo );

	/* Return information about the server */
	krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, 
					 RESOURCE_IMESSAGE_GETATTRIBUTE, &value, 
					 CRYPT_OPTION_INFO_MAJORVERSION );
	krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, 
					 RESOURCE_IMESSAGE_GETATTRIBUTE, &value, 
					 CRYPT_OPTION_INFO_MINORVERSION );

	return( CRYPT_OK );
	}

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

	assert( cmd->type == COMMAND_SETATTRIBUTE );
	assert( cmd->flags == COMMAND_FLAG_NONE );
	assert( ( cmd->noArgs == 3 && cmd->noStrArgs == 0 ) ||
			( cmd->noArgs == 2 && cmd->noStrArgs == 1 ) );

	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 );
	if( cmd->noStrArgs == 1 )
		{
		if( cmd->arg[ 1 ] == CRYPT_CTXINFO_KEY_COMPONENTS )
			{
			/* Public key components constitute a special case since the 
			   composite structures used are quite large */
			if( cmd->strArgLen[ 0 ] != sizeof( CRYPT_PKCINFO_RSA ) && \
				cmd->strArgLen[ 0 ] != sizeof( CRYPT_PKCINFO_DLP ) ) 
				return( CRYPT_ARGERROR_NUM2 );
			}
		else
			if( cmd->strArgLen[ 0 ] < 1 || \
				cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )
				return( CRYPT_ARGERROR_NUM2 );
		}

	/* Send the attribute data to the object, mapping the return code to the
	   correct value if necessary.  If it's a config option, we're usually 
	   doing this via the default user object which is invisible to the user, 
	   so we have to use an internal message for this one case */
	if( cmd->noStrArgs == 0 )
		{
		if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
			return( krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, 
									 RESOURCE_IMESSAGE_SETATTRIBUTE,
									 ( void * ) &cmd->arg[ 2 ], 
									 cmd->arg[ 1 ] ) );
		return( krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_SETATTRIBUTE,
								 ( void * ) &cmd->arg[ 2 ], cmd->arg[ 1 ] ) );
		}
	setResourceData( &msgData, cmd->strArg[ 0 ], cmd->strArgLen[ 0 ] );
	if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
		return( krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, 
								 RESOURCE_IMESSAGE_SETATTRIBUTE_S, &msgData, 
								 cmd->arg[ 1 ] ) );
	return( krnlSendMessage( cmd->arg[ 0 ], RESOURCE_MESSAGE_SETATTRIBUTE_S,
							 &msgData, cmd->arg[ 1 ] ) );
	}

static int cmdSetKey( void *stateInfo, COMMAND_INFO *cmd )
	{
	MESSAGE_KEYMGMT_INFO setkeyInfo;
	int itemType = ( cmd->noStrArgs == 1 ) ? \
				   KEYMGMT_ITEM_PRIVATEKEY : KEYMGMT_ITEM_PUBLICKEY;

	assert( cmd->type == COMMAND_SETKEY );
	assert( cmd->flags == COMMAND_FLAG_NONE );
	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 ] ) )
		return( CRYPT_ARGERROR_OBJECT );
	if( !checkHandleRange( cmd->arg[ 1 ] ) )
		return( CRYPT_ARGERROR_NUM1 );
	if( cmd->noStrArgs == 1 && \
		( cmd->strArgLen[ 0 ] < 2 || \
		  cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE ) )
		return( CRYPT_ARGERROR_STR1 );
	if( cmd->arg[ 2 ] )
		{
		int value;

		/* It's a cert management item request being added to a CA store,
		   usually this is a request but it may also be PKI user info */
		itemType = KEYMGMT_ITEM_REQUEST;
		if( cryptStatusOK( krnlSendMessage( cmd->arg[ 1 ], 
									RESOURCE_MESSAGE_GETATTRIBUTE, 
									&value, CRYPT_CERTINFO_CERTTYPE ) ) && \
			value == CRYPT_CERTTYPE_PKIUSER )
			itemType = KEYMGMT_ITEM_PKIUSER;
		}
	else
		{
		int value;

		/* If we're adding a CRL, add it as revocation information rather 
		   than as a generic public-key object */
		if( itemType != KEYMGMT_ITEM_PRIVATEKEY && \
			cryptStatusOK( krnlSendMessage( cmd->arg[ 1 ], 
									RESOURCE_MESSAGE_GETATTRIBUTE, 
									&value, CRYPT_CERTINFO_CERTTYPE ) ) && \
			value == CRYPT_CERTTYPE_CRL )
			itemType = KEYMGMT_ITEM_REVOCATIONINFO;
		}

	/* Add the key */
	setMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0, 

⌨️ 快捷键说明

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