📄 cryptapi.c
字号:
/****************************************************************************
* *
* cryptlib External API Interface *
* Copyright Peter Gutmann 1997-2003 *
* *
****************************************************************************/
/* NSA motto: In God we trust... all others we monitor.
-- Stanley Miller */
#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 that could be
busy rather than the status of an associated object (e.g.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 ], MESSAGE_GETATTRIBUTE, &dummy,
CRYPT_CTXINFO_ALGO );
if( status != CRYPT_OK && status != CRYPT_ERROR_TIMEOUT )
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 ], 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 ], 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 ], MESSAGE_KEY_CERTMGMT,
&certMgmtInfo, cmd->arg[ 1 ] );
if( cryptStatusOK( status ) && cmd->flags != COMMAND_FLAG_RET_NONE )
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 ], 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 || \
cmd->arg[ 2 ] == CRYPT_DEVICE_CRYPTOAPI )
{
if( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \
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 ] < MIN_NAME_LENGTH || \
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_EXTERNAL )
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 ] < MIN_NAME_LENGTH || \
cmd->strArgLen[ 0 ] >= CRYPT_MAX_TEXTSIZE )
return( CRYPT_ARGERROR_STR1 );
if( cmd->strArgLen[ 1 ] < MIN_NAME_LENGTH || \
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,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
cmd->arg[ 1 ] );
else
status = krnlSendMessage( cmd->arg[ 0 ], 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, IMESSAGE_GETATTRIBUTE, &ownerID,
CRYPT_PROPERTY_OWNER );
if( cryptStatusOK( status ) )
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE, &ownerID,
CRYPT_PROPERTY_OWNER );
if( cryptStatusError( status ) && status != CRYPT_ERROR_NOTINITED )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
}
/* Make the newly-created object externally visible */
krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_INTERNAL );
cmd->arg[ 0 ] = createInfo.cryptHandle;
return( CRYPT_OK );
}
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 ],
CRYPT_CERTTYPE_NONE );
if( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
else
status = krnlSendMessage( cmd->arg[ 0 ],
MESSAGE_DEV_CREATEOBJECT_INDIRECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( status );
/* Make the newly-created object externally visible */
krnlSendMessage( createInfo.cryptHandle, 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_TYPE cryptAlgo;
CRYPT_MODE_TYPE 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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -