/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* p11-rpc-private.h - various ids and signatures for our protocol Copyright (C) 2008, Stef Walter The Gnome Keyring Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Keyring Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, . Author: Stef Walter */ #ifndef GKM_RPC_CALLS_H #define GKM_RPC_CALLS_H #include #include #include "egg/egg-buffer.h" #include "pkcs11/pkcs11.h" /* Whether to print debug output or not */ #define DEBUG_OUTPUT 0 /* The calls, must be in sync with array below */ enum { GKM_RPC_CALL_ERROR = 0, GKM_RPC_CALL_C_Initialize, GKM_RPC_CALL_C_Finalize, GKM_RPC_CALL_C_GetInfo, GKM_RPC_CALL_C_GetSlotList, GKM_RPC_CALL_C_GetSlotInfo, GKM_RPC_CALL_C_GetTokenInfo, GKM_RPC_CALL_C_GetMechanismList, GKM_RPC_CALL_C_GetMechanismInfo, GKM_RPC_CALL_C_InitToken, GKM_RPC_CALL_C_WaitForSlotEvent, GKM_RPC_CALL_C_OpenSession, GKM_RPC_CALL_C_CloseSession, GKM_RPC_CALL_C_CloseAllSessions, GKM_RPC_CALL_C_GetFunctionStatus, GKM_RPC_CALL_C_CancelFunction, GKM_RPC_CALL_C_GetSessionInfo, GKM_RPC_CALL_C_InitPIN, GKM_RPC_CALL_C_SetPIN, GKM_RPC_CALL_C_GetOperationState, GKM_RPC_CALL_C_SetOperationState, GKM_RPC_CALL_C_Login, GKM_RPC_CALL_C_Logout, GKM_RPC_CALL_C_CreateObject, GKM_RPC_CALL_C_CopyObject, GKM_RPC_CALL_C_DestroyObject, GKM_RPC_CALL_C_GetObjectSize, GKM_RPC_CALL_C_GetAttributeValue, GKM_RPC_CALL_C_SetAttributeValue, GKM_RPC_CALL_C_FindObjectsInit, GKM_RPC_CALL_C_FindObjects, GKM_RPC_CALL_C_FindObjectsFinal, GKM_RPC_CALL_C_EncryptInit, GKM_RPC_CALL_C_Encrypt, GKM_RPC_CALL_C_EncryptUpdate, GKM_RPC_CALL_C_EncryptFinal, GKM_RPC_CALL_C_DecryptInit, GKM_RPC_CALL_C_Decrypt, GKM_RPC_CALL_C_DecryptUpdate, GKM_RPC_CALL_C_DecryptFinal, GKM_RPC_CALL_C_DigestInit, GKM_RPC_CALL_C_Digest, GKM_RPC_CALL_C_DigestUpdate, GKM_RPC_CALL_C_DigestKey, GKM_RPC_CALL_C_DigestFinal, GKM_RPC_CALL_C_SignInit, GKM_RPC_CALL_C_Sign, GKM_RPC_CALL_C_SignUpdate, GKM_RPC_CALL_C_SignFinal, GKM_RPC_CALL_C_SignRecoverInit, GKM_RPC_CALL_C_SignRecover, GKM_RPC_CALL_C_VerifyInit, GKM_RPC_CALL_C_Verify, GKM_RPC_CALL_C_VerifyUpdate, GKM_RPC_CALL_C_VerifyFinal, GKM_RPC_CALL_C_VerifyRecoverInit, GKM_RPC_CALL_C_VerifyRecover, GKM_RPC_CALL_C_DigestEncryptUpdate, GKM_RPC_CALL_C_DecryptDigestUpdate, GKM_RPC_CALL_C_SignEncryptUpdate, GKM_RPC_CALL_C_DecryptVerifyUpdate, GKM_RPC_CALL_C_GenerateKey, GKM_RPC_CALL_C_GenerateKeyPair, GKM_RPC_CALL_C_WrapKey, GKM_RPC_CALL_C_UnwrapKey, GKM_RPC_CALL_C_DeriveKey, GKM_RPC_CALL_C_SeedRandom, GKM_RPC_CALL_C_GenerateRandom, GKM_RPC_CALL_MAX }; typedef struct _GkmRpcCall { int call_id; const char* name; const char* request; const char* response; } GkmRpcCall; /* * a_ = prefix denotes array of _ * A = CK_ATTRIBUTE * f_ = prefix denotes buffer for _ * M = CK_MECHANISM * u = CK_ULONG * s = space padded string * v = CK_VERSION * y = CK_BYTE * z = null terminated string */ static const GkmRpcCall gkm_rpc_calls[] = { { GKM_RPC_CALL_ERROR, "ERROR", NULL, NULL }, { GKM_RPC_CALL_C_Initialize, "C_Initialize", "ay", "" }, { GKM_RPC_CALL_C_Finalize, "C_Finalize", "", "" }, { GKM_RPC_CALL_C_GetInfo, "C_GetInfo", "", "vsusv" }, { GKM_RPC_CALL_C_GetSlotList, "C_GetSlotList", "yfu", "au" }, { GKM_RPC_CALL_C_GetSlotInfo, "C_GetSlotInfo", "u", "ssuvv" }, { GKM_RPC_CALL_C_GetTokenInfo, "C_GetTokenInfo", "u", "ssssuuuuuuuuuuuvvs" }, { GKM_RPC_CALL_C_GetMechanismList, "C_GetMechanismList", "ufu", "au" }, { GKM_RPC_CALL_C_GetMechanismInfo, "C_GetMechanismInfo", "uu", "uuu" }, { GKM_RPC_CALL_C_InitToken, "C_InitToken", "uayz", "" }, { GKM_RPC_CALL_C_WaitForSlotEvent, "C_WaitForSlotEvent", "u", "u" }, { GKM_RPC_CALL_C_OpenSession, "C_OpenSession", "uu", "u" }, { GKM_RPC_CALL_C_CloseSession, "C_CloseSession", "u", "" }, { GKM_RPC_CALL_C_CloseAllSessions, "C_CloseAllSessions", "u", "" }, { GKM_RPC_CALL_C_GetFunctionStatus, "C_GetFunctionStatus", "u", "" }, { GKM_RPC_CALL_C_CancelFunction, "C_CancelFunction", "u", "" }, { GKM_RPC_CALL_C_GetSessionInfo, "C_GetSessionInfo", "u", "uuuu" }, { GKM_RPC_CALL_C_InitPIN, "C_InitPIN", "uay", "" }, { GKM_RPC_CALL_C_SetPIN, "C_SetPIN", "uayay", "" }, { GKM_RPC_CALL_C_GetOperationState, "C_GetOperationState", "ufy", "ay" }, { GKM_RPC_CALL_C_SetOperationState, "C_SetOperationState", "uayuu", "" }, { GKM_RPC_CALL_C_Login, "C_Login", "uuay", "" }, { GKM_RPC_CALL_C_Logout, "C_Logout", "u", "" }, { GKM_RPC_CALL_C_CreateObject, "C_CreateObject", "uaA", "u" }, { GKM_RPC_CALL_C_CopyObject, "C_CopyObject", "uuaA", "u" }, { GKM_RPC_CALL_C_DestroyObject, "C_DestroyObject", "uu", "" }, { GKM_RPC_CALL_C_GetObjectSize, "C_GetObjectSize", "uu", "u" }, { GKM_RPC_CALL_C_GetAttributeValue, "C_GetAttributeValue", "uufA", "aAu" }, { GKM_RPC_CALL_C_SetAttributeValue, "C_SetAttributeValue", "uuaA", "" }, { GKM_RPC_CALL_C_FindObjectsInit, "C_FindObjectsInit", "uaA", "" }, { GKM_RPC_CALL_C_FindObjects, "C_FindObjects", "ufu", "au" }, { GKM_RPC_CALL_C_FindObjectsFinal, "C_FindObjectsFinal", "u", "" }, { GKM_RPC_CALL_C_EncryptInit, "C_EncryptInit", "uMu", "" }, { GKM_RPC_CALL_C_Encrypt, "C_Encrypt", "uayfy", "ay" }, { GKM_RPC_CALL_C_EncryptUpdate, "C_EncryptUpdate", "uayfy", "ay" }, { GKM_RPC_CALL_C_EncryptFinal, "C_EncryptFinal", "ufy", "ay" }, { GKM_RPC_CALL_C_DecryptInit, "C_DecryptInit", "uMu", "" }, { GKM_RPC_CALL_C_Decrypt, "C_Decrypt", "uayfy", "ay" }, { GKM_RPC_CALL_C_DecryptUpdate, "C_DecryptUpdate", "uayfy", "ay" }, { GKM_RPC_CALL_C_DecryptFinal, "C_DecryptFinal", "ufy", "ay" }, { GKM_RPC_CALL_C_DigestInit, "C_DigestInit", "uM", "" }, { GKM_RPC_CALL_C_Digest, "C_Digest", "uayfy", "ay" }, { GKM_RPC_CALL_C_DigestUpdate, "C_DigestUpdate", "uay", "" }, { GKM_RPC_CALL_C_DigestKey, "C_DigestKey", "uu", "" }, { GKM_RPC_CALL_C_DigestFinal, "C_DigestFinal", "ufy", "ay" }, { GKM_RPC_CALL_C_SignInit, "C_SignInit", "uMu", "" }, { GKM_RPC_CALL_C_Sign, "C_Sign", "uayfy", "ay" }, { GKM_RPC_CALL_C_SignUpdate, "C_SignUpdate", "uay", "" }, { GKM_RPC_CALL_C_SignFinal, "C_SignFinal", "ufy", "ay" }, { GKM_RPC_CALL_C_SignRecoverInit, "C_SignRecoverInit", "uMu", "" }, { GKM_RPC_CALL_C_SignRecover, "C_SignRecover", "uayfy", "ay" }, { GKM_RPC_CALL_C_VerifyInit, "C_VerifyInit", "uMu", "" }, { GKM_RPC_CALL_C_Verify, "C_Verify", "uayay", "" }, { GKM_RPC_CALL_C_VerifyUpdate, "C_VerifyUpdate", "uay", "" }, { GKM_RPC_CALL_C_VerifyFinal, "C_VerifyFinal", "uay", "" }, { GKM_RPC_CALL_C_VerifyRecoverInit, "C_VerifyRecoverInit", "uMu", "" }, { GKM_RPC_CALL_C_VerifyRecover, "C_VerifyRecover", "uayfy", "ay" }, { GKM_RPC_CALL_C_DigestEncryptUpdate, "C_DigestEncryptUpdate", "uayfy", "ay" }, { GKM_RPC_CALL_C_DecryptDigestUpdate, "C_DecryptDigestUpdate", "uayfy", "ay" }, { GKM_RPC_CALL_C_SignEncryptUpdate, "C_SignEncryptUpdate", "uayfy", "ay" }, { GKM_RPC_CALL_C_DecryptVerifyUpdate, "C_DecryptVerifyUpdate", "uayfy", "ay" }, { GKM_RPC_CALL_C_GenerateKey, "C_GenerateKey", "uMaA", "u" }, { GKM_RPC_CALL_C_GenerateKeyPair, "C_GenerateKeyPair", "uMaAaA", "uu" }, { GKM_RPC_CALL_C_WrapKey, "C_WrapKey", "uMuufy", "ay" }, { GKM_RPC_CALL_C_UnwrapKey, "C_UnwrapKey", "uMuayaA", "u" }, { GKM_RPC_CALL_C_DeriveKey, "C_DeriveKey", "uMuaA", "u" }, { GKM_RPC_CALL_C_SeedRandom, "C_SeedRandom", "uay", "" }, { GKM_RPC_CALL_C_GenerateRandom, "C_GenerateRandom", "ufy", "ay" }, }; #ifdef _DEBUG #define GKM_RPC_CHECK_CALLS() \ { int i; for (i = 0; i < GKM_RPC_CALL_MAX; ++i) assert (gkm_rpc_calls[i].call_id == i); } #endif #define GKM_RPC_HANDSHAKE \ ((unsigned char*)"PRIVATE-GNOME-KEYRING-PKCS11-PROTOCOL-V-1") #define GKM_RPC_HANDSHAKE_LEN \ (strlen ((char *)GKM_RPC_HANDSHAKE)) #define GKM_RPC_SOCKET_EXT "pkcs11" typedef enum _GkmRpcMessageType { GKM_RPC_REQUEST = 1, GKM_RPC_RESPONSE } GkmRpcMessageType; typedef struct _GkmRpcMessage { int call_id; GkmRpcMessageType call_type; const char *signature; EggBuffer buffer; size_t parsed; const char *sigverify; } GkmRpcMessage; GkmRpcMessage* gkm_rpc_message_new (EggBufferAllocator allocator); void gkm_rpc_message_free (GkmRpcMessage *msg); void gkm_rpc_message_reset (GkmRpcMessage *msg); int gkm_rpc_message_equals (GkmRpcMessage *m1, GkmRpcMessage *m2); #define gkm_rpc_message_is_verified(msg) (!(msg)->sigverify || (msg)->sigverify[0] == 0) #define gkm_rpc_message_buffer_error(msg) (egg_buffer_has_error(&(msg)->buffer)) int gkm_rpc_message_prep (GkmRpcMessage *msg, int call_id, GkmRpcMessageType type); int gkm_rpc_message_parse (GkmRpcMessage *msg, GkmRpcMessageType type); int gkm_rpc_message_verify_part (GkmRpcMessage *msg, const char* part); int gkm_rpc_message_write_byte (GkmRpcMessage *msg, CK_BYTE val); int gkm_rpc_message_write_ulong (GkmRpcMessage *msg, CK_ULONG val); int gkm_rpc_message_write_zero_string (GkmRpcMessage *msg, CK_UTF8CHAR* string); int gkm_rpc_message_write_space_string (GkmRpcMessage *msg, CK_UTF8CHAR* buffer, CK_ULONG length); int gkm_rpc_message_write_byte_buffer (GkmRpcMessage *msg, CK_ULONG count); int gkm_rpc_message_write_byte_array (GkmRpcMessage *msg, CK_BYTE_PTR arr, CK_ULONG num); int gkm_rpc_message_write_ulong_buffer (GkmRpcMessage *msg, CK_ULONG count); int gkm_rpc_message_write_ulong_array (GkmRpcMessage *msg, CK_ULONG_PTR arr, CK_ULONG num); int gkm_rpc_message_write_attribute_buffer (GkmRpcMessage *msg, CK_ATTRIBUTE_PTR arr, CK_ULONG num); int gkm_rpc_message_write_attribute_array (GkmRpcMessage *msg, CK_ATTRIBUTE_PTR arr, CK_ULONG num); int gkm_rpc_message_write_version (GkmRpcMessage *msg, CK_VERSION* version); int gkm_rpc_message_read_byte (GkmRpcMessage *msg, CK_BYTE* val); int gkm_rpc_message_read_ulong (GkmRpcMessage *msg, CK_ULONG* val); int gkm_rpc_message_read_space_string (GkmRpcMessage *msg, CK_UTF8CHAR* buffer, CK_ULONG length); int gkm_rpc_message_read_version (GkmRpcMessage *msg, CK_VERSION* version); void gkm_rpc_log (const char *line); void gkm_rpc_warn (const char* msg, ...); void gkm_rpc_debug (const char* msg, ...); #ifdef G_DISABLE_ASSERT #define assert(x) #else #include #endif /* * PKCS#11 mechanism parameters are not easy to serialize. They're * completely different for so many mechanisms, they contain * pointers to arbitrary memory, and many callers don't initialize * them completely or properly. * * We only support certain mechanisms. * * Also callers do yucky things like leaving parts of the structure * pointing to garbage if they don't think it's going to be used. */ int gkm_rpc_mechanism_is_supported (CK_MECHANISM_TYPE mech); void gkm_rpc_mechanism_list_purge (CK_MECHANISM_TYPE_PTR mechs, CK_ULONG_PTR n_mechs); int gkm_rpc_mechanism_has_sane_parameters (CK_MECHANISM_TYPE type); int gkm_rpc_mechanism_has_no_parameters (CK_MECHANISM_TYPE mech); #endif /* GKM_RPC_CALLS_H */