/**************************************************************************** * * * cryptlib RPC Header File * * Copyright Peter Gutmann 1997-2001 * * * ****************************************************************************/ #ifndef _RPC_DEFINED #define _RPC_DEFINED /* Each message when encoded looks as follows: type : 8 flags : 8 noArgs : 8 noStringArgs : 8 length : 32 arg * 0..n : 32 * n stringArg * 0..n: 32 + data * n The fixed header consists of a 32-bit type+format information value and length (to allow the entire message to be read using only two read calls) followed by 1 - MAX_ARGS integer args and 0 - MAX_STRING_ARGS variable- length data args. The protocol is completely stateless, the client sends COMMAND_xxx requests to the server and the server responds with COMMAND_RESULT messages */ /* cryptlib API commands */ typedef enum { COMMAND_NONE, /* No command type */ COMMAND_RESULT, /* Result from server */ COMMAND_SERVERQUERY, /* Get info on server */ COMMAND_CREATEOBJECT, /* Create an object */ COMMAND_CREATEOBJECT_INDIRECT, /* Create an object indirectly */ COMMAND_EXPORTOBJECT, /* Export object in encoded form */ COMMAND_DESTROYOBJECT, /* Destroy an object */ COMMAND_QUERYCAPABILITY, /* Query capabilities */ COMMAND_GENKEY, /* Generate key */ COMMAND_ENCRYPT, /* Encrypt/sign/hash */ COMMAND_DECRYPT, /* Decrypt/sig check/hash */ COMMAND_GETATTRIBUTE, /* Get/set/delete attribute */ COMMAND_SETATTRIBUTE, COMMAND_DELETEATTRIBUTE, COMMAND_GETKEY, /* Get/set/delete key */ COMMAND_SETKEY, COMMAND_DELETEKEY, COMMAND_PUSHDATA, COMMAND_POPDATA, COMMAND_FLUSHDATA, /* Push/pop/flush data */ COMMAND_CERTSIGN, /* Sign certificate */ COMMAND_CERTCHECK, /* Check signature on certificate */ COMMAND_CERTMGMT, /* CA cert management operation */ COMMAND_ASYNCOP, /* Async keygen op */ COMMAND_LAST /* Last command type */ } COMMAND_TYPE; /* Database shim commands */ typedef enum { DBX_COMMAND_NONE, /* No command type */ DBX_COMMAND_RESULT, /* Result from server (== COMAND_RESULT) */ DBX_COMMAND_OPEN, /* Open session with database */ DBX_COMMAND_CLOSE, /* Close session with database */ DBX_COMMAND_QUERY, /* Perform data fetch/check */ DBX_COMMAND_UPDATE, /* Perform data update */ DBX_COMMAND_GETERRORINFO, /* Sent if another command fails */ DBX_COMMAND_LAST /* Last command type */ } DBX_COMMAND_TYPE; /* The command formats are as follows (arguments in square brackets are implied arguments whose values are supplied at the C function level but that aren't passed over the wire, this is used to handle reads of string values): COMMAND_SERVERQUERY word: status word: protocol version word: max.fragment size COMMAND_CREATEOBJECT word: handle word: status word: object type word: new handle word(s) | str(s): params COMMAND_CREATEOBJECT_INDIRECT word: handle word: status word: object type word: new handle str : encoded object data COMMAND_EXPORTOBJECT word: handle word: status word(s): params word: str_length | str: data COMMAND_DESTROYOBJECT word: handle word: status COMMAND_QUERYCAPABILITY word: handle word: status word: algo word: str_length | str : data word: mode [str: return buffer] COMMAND_GENKEY word: handle word: status word: is_async (optional) COMMAND_ENCRYPT word: handle word: status str : data str : data COMMAND_DECRYPT word: handle word: status str : data str : data COMMAND_GETATTRIBUTE word: handle word: status word: attribute type word: value | word: str_length | str: data word: get_str_data (optional) [str: return buffer for str_data] COMMAND_SETATTRIBUTE word: handle word: status word: attribute type word: value | str : value COMMAND_DELETEATTRIBUTE word: handle word: status word: attribute type COMMAND_GETKEY word: handle word: status word: itemType word: handle word: key ID type str : key ID (optional) str : password (optional) COMMAND_SETKEY word: handle word: status word: key handle word: caItemType (optional) str : password (optional) COMMAND_DELETEKEY word: handle word: status word: key ID type word: caItemType (optional) str : key ID COMMAND_PUSHDATA word: handle word: status str : data word: length COMMAND_POPDATA word: handle word: status word: length str : data [str: return buffer] COMMAND_CERTSIGN word: handle word: status word: sig.key handle COMMAND_CERTCHECK word: handle word: status word: check key handle COMMAND_CERTMGMT word: handle word: status word: caKey word: new cert (optional) word: certRequest COMMAND_ASYNCOP word: handle word: status word: get status/cancel op DBX_COMMAND_OPEN: word: options word: status str : name word: featureFlags DBX_COMMAND_CLOSE DBX_COMMAND_UPDATE: word: type word: status str : command str : date (optional) str : data (optional) DBX_COMMAND_QUERY: word: type word: status word: query entry (opt.) str : data str : command str : date (optional) str : data (optional) [str: return buffer] DBX_COMMAND_GETERRORINFO word: errorCode str : errorMessage */ /* The maximum number of integer and string args, and the amount of space to allocate in the COMMAND_INFO to store all possible args */ #define MAX_ARGS 4 #define MAX_STRING_ARGS 2 #define DBX_MAX_ARGS 2 #define DBX_MAX_STRING_ARGS 3 #define ALLOC_MAX_ARGS MAX_ARGS #define ALLOC_MAX_STRING_ARGS DBX_MAX_STRING_ARGS /* The possible command flags */ #define COMMAND_FLAG_NONE 0x00 /* No command flag */ #define COMMAND_FLAG_RET_NONE 0x01 /* Don't return any data */ #define COMMAND_FLAG_RET_LENGTH 0x02 /* Return only length of string arg */ /* The size of an integer as encoded in a message, the size of the fixed- length fields, and the offsets of the data fields in the message */ #define COMMAND_WORDSIZE 4 #define COMMAND_FIXED_DATA_SIZE ( COMMAND_WORDSIZE * 2 ) #define COMMAND_WORD1_OFFSET COMMAND_FIXED_DATA_SIZE #define COMMAND_WORD2_OFFSET ( COMMAND_FIXED_DATA_SIZE + COMMAND_WORDSIZE ) #define COMMAND_WORD3_OFFSET ( COMMAND_FIXED_DATA_SIZE + ( COMMAND_WORDSIZE * 2 ) ) #define COMMAND_WORD4_OFFSET ( COMMAND_FIXED_DATA_SIZE + ( COMMAND_WORDSIZE * 3 ) ) /* Macros to encode/decode a message type value */ #define putMessageType( buffer, type, flags, noInt, noString ) \ { \ buffer[ 0 ] = ( BYTE ) ( type & 0xFF ); \ buffer[ 1 ] = ( BYTE ) ( flags & 0xFF ); \ buffer[ 2 ] = noInt; \ buffer[ 3 ] = noString; \ } #define getMessageType( buffer, type, flags, noInt, noString ) \ type = buffer[ 0 ]; flags = buffer[ 1 ]; \ noInt = buffer[ 2 ]; noString = buffer[ 3 ] /* Macros to encode/decode an integer value and a length */ #define putMessageWord( buffer, word ) \ { \ ( buffer )[ 0 ] = ( BYTE ) ( ( ( word ) >> 24 ) & 0xFF ); \ ( buffer )[ 1 ] = ( BYTE ) ( ( ( word ) >> 16 ) & 0xFF ); \ ( buffer )[ 2 ] = ( BYTE ) ( ( ( word ) >> 8 ) & 0xFF ); \ ( buffer )[ 3 ] = ( BYTE ) ( ( word ) & 0xFF ); \ } #define getMessageWord( buffer ) \ ( ( ( ( long ) ( buffer )[ 0 ] ) << 24 ) | \ ( ( ( long ) ( buffer )[ 1 ] ) << 16 ) | \ ( ( ( long ) ( buffer )[ 2 ] ) << 8 ) | \ ( long ) ( buffer )[ 3 ] ) #define getMessageLength getMessageWord #define putMessageLength putMessageWord /* A structure to contain the command elements */ typedef struct { COMMAND_TYPE type; /* Command type */ int flags; /* Command flags */ int noArgs, noStrArgs; /* Number of int, string args */ int arg[ ALLOC_MAX_ARGS ]; /* Integer arguments */ void *strArg[ ALLOC_MAX_STRING_ARGS ]; /* String args */ int strArgLen[ ALLOC_MAX_STRING_ARGS ]; } COMMAND_INFO; /* Function pointers for a generic dispatch function that dispatches the marshalled data to a receiver, and command handlers that process each command type */ typedef void ( *DISPATCH_FUNCTION )( void *stateInfo, BYTE *buffer ); typedef int ( *COMMAND_HANDLER )( void *stateInfo, COMMAND_INFO *cmd ); /* The full RPC interface (with marshalling and everything) provides complete isolation of input and output, however it resuls in a slight performance decrease due to copying, and can't handle large objects atomically due to limits on message size (this specifically applies to mega-CRLs). Because of this, we also allow a direct interface that just forwards the data without marshalling/unmarshalling. Because of the change in arg handling for returned data in RPC vs. direct calls (the RPC returns the data in the return message, the direct call requires an extra parameter to specify the location of the returned data) we also need a macro RETURN_VALUE() to no-op out the extra parameter in case we're using the RPC form */ #ifdef USE_RPCAPI #define DISPATCH_COMMAND( function, command ) \ dispatchCommand( &command ) #define DISPATCH_COMMAND_DBX( function, command, dbmsInfo ) \ dispatchCommand( &command, ( dbmsInfo )->stateInfo, ( dbmsInfo )->dispatchFunction ) #define RETURN_VALUE( value ) 0 #else #define DISPATCH_COMMAND( function, command ) \ function( NULL, &command ) #define DISPATCH_COMMAND_DBX( function, command, dbmsInfo ) \ function( ( dbmsInfo )->stateInfo, &command ) #define RETURN_VALUE( value ) value #endif /* USE_RPCAPI */ /* Check whether a decoded command header contains valid data for the different RPC types */ #define checkCommandInfo( cmd, length ) \ ( ( cmd )->type > COMMAND_NONE && \ ( cmd )->type < COMMAND_LAST && \ ( ( cmd )->flags == COMMAND_FLAG_NONE || \ ( cmd )->flags == COMMAND_FLAG_RET_NONE || \ ( cmd )->flags == COMMAND_FLAG_RET_LENGTH ) && \ ( cmd )->noArgs >= 1 && ( cmd )->noArgs <= MAX_ARGS && \ ( cmd )->noStrArgs >= 0 && ( cmd )->noStrArgs <= MAX_STRING_ARGS && \ ( cmd )->strArgLen[ 0 ] >= 0 && \ ( cmd )->strArgLen[ 1 ] >= 0 && \ ( length ) >= 0 && ( length ) <= RPC_IO_BUFSIZE ) #define checkCommandConsistency( cmd, length ) \ ( ( ( cmd )->strArgLen[ 0 ] + ( cmd )->strArgLen[ 1 ] ) == \ ( length - ( COMMAND_WORDSIZE * ( ( cmd )->noArgs + ( cmd )->noStrArgs ) ) ) ) #define dbxCheckCommandInfo( cmd, length ) \ ( ( cmd )->type > DBX_COMMAND_NONE && \ ( cmd )->type < DBX_COMMAND_LAST && \ ( cmd )->flags == COMMAND_FLAG_NONE && \ ( cmd )->noArgs >= 0 && ( cmd )->noArgs <= DBX_MAX_ARGS && \ ( cmd )->noStrArgs >= 0 && ( cmd )->noStrArgs <= DBX_MAX_STRING_ARGS && \ ( cmd )->strArgLen[ 0 ] >= 0 && \ ( cmd )->strArgLen[ 1 ] >= 0 && \ ( cmd )->strArgLen[ 2 ] >= 0 && \ ( length ) >= 0 && ( length ) <= DBX_IO_BUFSIZE ) #define dbxCheckCommandConsistency( cmd, length ) \ ( ( ( cmd )->strArgLen[ 0 ] + ( cmd )->strArgLen[ 1 ] + ( cmd )->strArgLen[ 2 ] ) == \ ( length - ( COMMAND_WORDSIZE * ( ( cmd )->noArgs + ( cmd )->noStrArgs ) ) ) ) /* The maximum size of a message fragment. Messages containing more data than this are broken up into fragments. On systems with very restricted amounts of memory we make the size rather small to limit the size of the intermediate buffers used */ #ifdef CONFIG_CONSERVE_MEMORY #define MAX_FRAGMENT_SIZE 8192 #else #define MAX_FRAGMENT_SIZE 32768 #endif /* CONSERVER_MEMORY */ /* The size of the I/O buffer used to assemble messages. This is equal to the maximum fragment size plus the maximum header size for commands that require fragmentation (COMMAND_ENCRYPT/COMMAND_DECRYPT and COMMAND_PUSHDATA/COMMAND_POPDATA). We define a separate version for database RPC since this uses much smaller buffers */ #define RPC_IO_BUFSIZE MAX_FRAGMENT_SIZE + 32 #define DBX_IO_BUFSIZE 4096 #endif /* _RPC_DEFINED */