📄 cryptapi.c
字号:
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->flags == COMMAND_FLAG_NONE && cmd->noStrArgs == 1 ) || \
( ( cmd->noArgs == 2 || cmd->flags == COMMAND_FLAG_RET_LENGTH ) && \
cmd->noStrArgs == 0 ) );
UNUSED( stateInfo );
/* Perform basic server-side error checking */
if( !isHandleRangeValid( 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 );
/* 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.
This is further complicated by the fact that the kernel checks that
the destination memory is writeable and either returns an error (for
an external message) or throws an exception (for the internal message
required to access the user object) if it isn't. Since the external
API doesn't allow the specification of the returned data length, it
uses a worst-case estimate which may be much larger than the actual
buffer size, which the kernel will refuse to write to. To handle
this we first read the actual length and then ask for only that much
data, which the caller should have made available for the output */
if( cmd->noArgs == 2 )
{
if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
return( krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE, &cmd->arg[ 0 ],
cmd->arg[ 1 ] ) );
return( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,
&cmd->arg[ 0 ], cmd->arg[ 1 ] ) );
}
setMessageData( &msgData, NULL, 0 );
if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &msgData,
cmd->arg[ 1 ] );
else
status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE_S,
&msgData, cmd->arg[ 1 ] );
if( cryptStatusError( status ) )
return( status );
if( cmd->flags == COMMAND_FLAG_RET_LENGTH )
{
cmd->arg[ 0 ] = msgData.length;
return( CRYPT_OK );
}
msgData.data = cmd->strArg[ 0 ];
if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &msgData,
cmd->arg[ 1 ] );
else
status = krnlSendMessage( cmd->arg[ 0 ], 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 ) ? \
MESSAGE_KEY_GETNEXTCERT : 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( !isHandleRangeValid( 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 ] < MIN_NAME_LENGTH || \
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 ], MESSAGE_GETATTRIBUTE, &owner,
CRYPT_PROPERTY_OWNER );
if( cryptStatusOK( status ) )
status = krnlSendMessage( getkeyInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE, &owner,
CRYPT_PROPERTY_OWNER );
if( cryptStatusError( status ) && status != CRYPT_ERROR_NOTINITED )
{
krnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
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( !isHandleRangeValid( 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 */
setMessageData( &msgData, cmd->strArg[ 0 ], cmd->arg[ 1 ] );
status = krnlSendMessage( cmd->arg[ 0 ], 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( !isHandleRangeValid( 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 */
setMessageData( &msgData, cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : NULL,
cmd->strArgLen[ 0 ] );
status = krnlSendMessage( cmd->arg[ 0 ], 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->flags == COMMAND_FLAG_NONE && cmd->noStrArgs == 1 ) || \
( cmd->flags == COMMAND_FLAG_RET_LENGTH && cmd->noStrArgs == 0 ) );
assert( cmd->flags == COMMAND_FLAG_RET_LENGTH || \
cmd->strArg[ 0 ] != NULL );
UNUSED( 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 ] < 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,
IMESSAGE_DEV_QUERYCAPABILITY, &queryInfo,
cmd->arg[ 1 ] );
else
status = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_DEV_QUERYCAPABILITY,
&queryInfo, cmd->arg[ 1 ] );
if( cryptStatusOK( status ) )
{
/* Return either the length or the full capability into 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 );
}
#ifdef USE_RPCAPI
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, IMESSAGE_GETATTRIBUTE,
&value, CRYPT_OPTION_INFO_MAJORVERSION );
krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE,
&value, CRYPT_OPTION_INFO_MINORVERSION );
return( CRYPT_OK );
}
#endif /* USE_RPCAPI */
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( !isHandleRangeValid( 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,
IMESSAGE_SETATTRIBUTE,
( void * ) &cmd->arg[ 2 ],
cmd->arg[ 1 ] ) );
return( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_SETATTRIBUTE,
( void * ) &cmd->arg[ 2 ], cmd->arg[ 1 ] ) );
}
setMessageData( &msgData, cmd->strArg[ 0 ], cmd->strArgLen[ 0 ] );
if( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )
return( krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
IMESSAGE_SETATTRIBUTE_S, &msgData,
cmd->arg[ 1 ] ) );
return( krnlSendMessage( cmd->arg[ 0 ], 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( !isHandleRangeValid( cmd->arg[ 0 ] ) )
return( CRYPT_ARGERROR_OBJECT );
if( !isHandleRangeValid( cmd->arg[ 1 ] ) )
return( CRYPT_ARGERROR_NUM1 );
if( cmd->noStrArgs == 1 && \
( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \
cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -