?? cryptapi.c
字號(hào):
/****************************************************************************
* *
* cryptlib External API Interface *
* Copyright Peter Gutmann 1997-2007 *
* *
****************************************************************************/
/* NSA motto: In God we trust... all others we monitor.
-- Stanley Miller */
#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 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_ARG( stateInfo );
/* Perform basic server-side error checking */
if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
return( CRYPT_ARGERROR_OBJECT );
if( !isHandleRangeValid( 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_ARG( stateInfo );
/* Perform basic server-side error checking */
if( !isHandleRangeValid( 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( !isHandleRangeValid( 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( !isHandleRangeValid( 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_ARG( stateInfo );
/* Perform basic server-side error checking */
if( !isHandleRangeValid( cmd->arg[ 0 ] ) )
return( CRYPT_ARGERROR_OBJECT );
if( !isHandleRangeValid( 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 = DUMMY_INIT, 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_ARG( stateInfo );
/* Perform basic server-side error checking */
if( !isHandleRangeValid( 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:
retIntError();
}
/* 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;
}
/* 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 if necessary. This
is only required when we're creating the object via the system
handle, which requires an internal message that leaves the object
internal */
if( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )
{
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_ARG( 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 || \
cmd->strArgLen[ 0 ] >= MAX_INTLENGTH )
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_ARG( stateInfo );
/* Perform basic server-side error checking */
status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( status );
if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )
{
status = krnlSendMessage( cmd->arg[ 0 ], 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 ], 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 ], 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 ) )
{
MESSAGE_DATA msgData;
setMessageData( &msgData, NULL, 0 );
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -