/* * Copyright (C) 2007 Nate Nielsen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef CKCAPI_H #define CKCAPI_H /* -------------------------------------------------------------------- * * Session = CkCapiSession * - A PKCS#11 Session * * Objects = CkCapiObject * - There's a global list of objects in ckcapi-object.c indexed by * object handle. * - The object itself has no attributes or cached data, but knows how * to load data when needed. * - Each object has a unique key which guarantees we don't load the * same object twice with two different object handles. * * Object Data = CkCapiObjectData * - Object Data is owned by the Session * - Loaded data and/or attributes for an object. */ #define WIN32_LEAN_AND_MEAN #define _WIN32_WINNT 0x400 #include #include #define CRYPTOKI_EXPORTS #include "pkcs11/pkcs11.h" #include "ckcapi-util.h" struct _CkCapiObject; struct _CkCapiObjectData; struct _CkCapiSession; typedef struct _CkCapiObject CkCapiObject; typedef struct _CkCapiObjectData CkCapiObjectData; typedef struct _CkCapiSession CkCapiSession; /* ------------------------------------------------------------------ * ckcapi-object.c */ /* A function to get an attribute from ObjectData */ typedef CK_RV (*CkCapiGetAttribute)(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr); /* A function to free some data */ typedef void (*CkCapiRelease)(void* data); /* Object data functions */ typedef struct _CkCapiObjectDataVtable { CkCapiGetAttribute get_bool; CkCapiGetAttribute get_ulong; CkCapiGetAttribute get_bytes; CkCapiGetAttribute get_date; CkCapiRelease release; } CkCapiObjectDataVtable; /* * Base class for object data. Different types of * objects extend this with more detailed data */ struct _CkCapiObjectData { CK_OBJECT_HANDLE object; const CkCapiObjectDataVtable* data_funcs; }; /* Match object data against all the given match attributes */ CK_BBOOL ckcapi_object_data_match (CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR matches, CK_ULONG count); /* Match a single attribute against object data */ CK_BBOOL ckcapi_object_data_match_attr (CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR match); /* Get a bunch of attributes from object data */ CK_RV ckcapi_object_data_get_attrs (CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attrs, CK_ULONG count); /* A function to load data for an object */ typedef CK_RV (*CkCapiLoadData)(CkCapiSession* sess, struct _CkCapiObject* obj, CkCapiObjectData** objdata); /* Object functions */ typedef struct _CkCapiObjectVtable { CkCapiLoadData load_data; CkCapiRelease release; } CkCapiObjectVtable; /* Represents a object we've seen */ struct _CkCapiObject { CK_OBJECT_HANDLE id; const CkCapiObjectVtable* obj_funcs; void* unique_key; size_t unique_len; }; /* Debug print something about an object */ #define DBGO(obj, msg) \ ckcapi_debug("O%d: %s", (obj) ? (obj)->id : 0, (msg)) #define DBGOD(objdata, msg) \ ckcapi_debug("O%d: %s", (objdata) ? (objdata)->obj : 0, (msg)) /* Get the number of the maximum object handle currently in memory */ CK_OBJECT_HANDLE ckcapi_object_get_max_handle (void); /* Lookup an object for a given object handle */ CkCapiObject* ckcapi_object_lookup (CkCapiSession* sess, CK_OBJECT_HANDLE obj); /* Register a new object, a handle will be assigned to obj->id */ CK_RV ckcapi_object_register (CkCapiSession* sess, CkCapiObject* obj); /* Clear all objects. Only done when finalizing */ void ckcapi_object_clear_all (void); /* * Each object has a unique key which guarantees that we're * not loading the same objects over and over again. * Usually these are contiguous members of a struct. These * macros help calculate the address and length of such a * unique key */ /* The unique key starts at the address of the starting struct member */ #define UNIQUE_KEY_AT(obj, mem) \ (void*)(&((obj->mem))) /* Calculates key length between first and last struct members */ #define UNIQUE_KEY_LEN(obj, first, last) \ UNIQUE_KEY_VAR_LEN(obj, first, last, sizeof(obj->last)) /* Calcs key len between first and a certain num of bytes past last struct member */ #define UNIQUE_KEY_VAR_LEN(obj, first, last, len) \ ((((char*)&((obj->last))) - ((char*)&((obj->first)))) + (len)) /* Used internally to have a unique id for different object types */ enum { OBJECT_CERT = 1, OBJECT_BUILTIN = 2, OBJECT_TRUST = 3 }; /* ------------------------------------------------------------------ * cryptoki-capi-session.c */ /* For operation_type in CkCapiSession */ enum { OPERATION_NONE = 0, OPERATION_FIND = 1, }; /* Callback to cancel a current operation */ typedef void (*CkCapiSessionCancel) (struct _CkCapiSession* sess); /* Represents an open session */ typedef struct _CkCapiSession { CK_ULONG id; /* Unique ID for this session */ int in_call; /* Whether this session is use in PKCS#11 function */ int operation_type; /* Whether an operation is happening or not */ void* operation_data; /* Data for this operation */ CkCapiSessionCancel operation_cancel; /* Callback to cancel operation when necessary */ CkCapiHash* object_data; CK_NOTIFY notify_callback; /* Application specified callback */ CK_VOID_PTR user_data; /* Argument for above */ int refs; /* Reference count */ HANDLE mutex; /* Mutex for protecting this structure */ } CkCapiSession; /* Debug print something related to a session */ #define DBGS(sess, msg) \ ckcapi_debug("S%d: %s", (sess) ? (sess)->id : 0, (msg)) /* Create a session */ CkCapiSession* ckcapi_session_create (void); /* Destroy a session */ void ckcapi_session_destroy (CkCapiSession* sess); /* Register a new session */ CK_RV ckcapi_session_register (CkCapiSession* sess); /* Get a session from a handle, and lock it */ CK_RV ckcapi_session_get_lock_ref (CK_ULONG id, int remove, CkCapiSession **sess); /* Unlock and unreference a session */ void ckcapi_session_unref_unlock (CkCapiSession* sess); /* Close all sessions */ void ckcapi_session_close_all (void); /* Start a find operation on a session */ CK_RV ckcapi_session_find_init (CkCapiSession* sess, CK_ATTRIBUTE_PTR templ, CK_ULONG count); /* Return results from a find operation */ CK_RV ckcapi_session_find (CkCapiSession* sess, CK_OBJECT_HANDLE_PTR objects, CK_ULONG max_object_count, CK_ULONG_PTR object_count); /* End a find operation */ CK_RV ckcapi_session_find_final (CkCapiSession* sess); /* Get object data for an object */ CK_RV ckcapi_session_get_object_data (CkCapiSession* sess, CkCapiObject* obj, CkCapiObjectData** objdata); /* Get object data for an object handle */ CK_RV ckcapi_session_get_object_data_for (CkCapiSession* sess, CK_OBJECT_HANDLE hand, CkCapiObjectData** objdata); /* Set object data for an object */ void ckcapi_session_take_object_data (CkCapiSession* sess, CkCapiObject* obj, CkCapiObjectData* objdata); /* Clear object data for an object */ void ckcapi_session_clear_object_data (CkCapiSession* sess, CkCapiObject* obj); /* Enumerate object data for all objects */ typedef void (*CkCapiEnumObjectData) (CkCapiSession* sess, CkCapiObject* obj, CkCapiObjectData* data, void* arg); void ckcapi_session_enum_object_data (CkCapiSession* sess, CkCapiEnumObjectData enum_func, void* arg); /* ------------------------------------------------------------------- * ckcapi-cert.c */ /* Find certificates matching criteria */ CK_RV ckcapi_cert_find (CkCapiSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR match, CK_ULONG count, CkCapiArray* arr); /* Called by trust stuff */ CK_RV ckcapi_cert_certificate_get_bytes (PCCERT_CONTEXT cert, CK_ATTRIBUTE_PTR attr); PCCERT_CONTEXT ckcapi_cert_object_data_get_certificate (CkCapiObjectData* objdata); /* ------------------------------------------------------------------- * ckcapi-builtin.c */ /* Find builtin objects matching criteria */ CK_RV ckcapi_builtin_find (CkCapiSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR match, CK_ULONG count, CkCapiArray* arr); /* ------------------------------------------------------------------- * ckcapi-trust.c */ /* Find trust objects matching criteria */ CK_RV ckcapi_trust_find (CkCapiSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR match, CK_ULONG count, CkCapiArray* arr); /* ------------------------------------------------------------------ * cryptoki-capi.c * * Module helper and logging functions. */ #define DBG(args) \ ckcapi_debug args void ckcapi_debug (const char* msg, ...); /* * Protect global data with these. */ void ckcapi_lock_global (void); void ckcapi_unlock_global (void); /* * Convert a GetLastError() windows error to a * PKCS#11 return code. */ CK_RV ckcapi_winerr_to_ckr (DWORD werr); /* * This stores data in the output buffer with appropriate * PKCS#11 codes when the buffer is too short, or the caller * just wants to know the length, etc. */ CK_RV ckcapi_return_data (CK_VOID_PTR dst, CK_ULONG_PTR dlen, CK_VOID_PTR src, DWORD slen); /* ------------------------------------------------------------------ */ #ifndef ASSERT #include "assert.h" #define ASSERT assert #endif /* Represents 'any' class in searches */ #define CKO_ANY CK_INVALID_HANDLE #endif /* CRYPTOKI_CAPI_H */