#include #include #include #include /* PKCS#11 Definitions for the local platform */ #define CK_PTR * #define CK_DECLARE_FUNCTION(rv, func) rv func #define CK_DECLARE_FUNCTION_POINTER(rv, func) rv (CK_PTR func) #define CK_CALLBACK_FUNCTION(rv, func) CK_DECLARE_FUNCTION_POINTER(rv, func) #define CK_NULL_PTR ((void *) 0) #include "pkcs11.h" #ifndef TCLPKCS11_MAX_HANDLES # define TCLPKCS11_MAX_HANDLES 32 #endif struct tclpkcs11_interpdata { /* Handle Hash Table */ Tcl_HashTable handles; unsigned long handles_idx; }; struct tclpkcs11_handle { void *base; CK_FUNCTION_LIST_PTR pkcs11; }; static int tclpkcs11_load_module(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { CK_RV (*getFuncList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList); CK_FUNCTION_LIST_PTR pkcs11_function_list; struct tclpkcs11_interpdata *interpdata; struct tclpkcs11_handle *new_handle; const char *pathname; Tcl_HashEntry *tcl_handle_entry; Tcl_Obj *tcl_handle; void *handle; char handle_buf[32]; int snprintf_ret; int is_new_entry; CK_RV getFuncList_ret; if (!cd) { Tcl_SetResult(interp, "invalid clientdata\n", TCL_STATIC); return(TCL_ERROR); } if (objc != 2) { Tcl_SetResult(interp, "wrong # args: should be \"pki::pkcs11::loadmodule filename\"", TCL_STATIC); return(TCL_ERROR); } pathname = Tcl_GetString(objv[1]); if (!pathname) { Tcl_SetResult(interp, "invalid pathname", TCL_STATIC); return(TCL_ERROR); } handle = dlopen(pathname, RTLD_LAZY | RTLD_LOCAL); if (!handle) { Tcl_SetResult(interp, "unable to load", TCL_STATIC); return(TCL_ERROR); } getFuncList = dlsym(handle, "C_GetFunctionList"); if (!getFuncList) { Tcl_SetResult(interp, "unable to locate C_GetFunctionList symbol in PKCS#11 module", TCL_STATIC); return(TCL_ERROR); } getFuncList_ret = getFuncList(&pkcs11_function_list); if (getFuncList_ret != CKR_OK) { Tcl_SetResult(interp, "C_GetFunctionList returned in failure", TCL_STATIC); return(TCL_ERROR); } if (!pkcs11_function_list) { Tcl_SetResult(interp, "C_GetFunctionList returned invalid data", TCL_STATIC); return(TCL_ERROR); } if (!pkcs11_function_list->C_Initialize) { Tcl_SetResult(interp, "C_GetFunctionList returned incomplete data", TCL_STATIC); return(TCL_ERROR); } interpdata = (struct tclpkcs11_interpdata *) cd; snprintf_ret = snprintf(handle_buf, sizeof(handle_buf), "pkcsmod%lu", interpdata->handles_idx); (interpdata->handles_idx)++; if (snprintf_ret >= sizeof(handle_buf)) { snprintf_ret = sizeof(handle_buf) - 1; } tcl_handle = Tcl_NewStringObj(handle_buf, snprintf_ret); if (!tcl_handle) { Tcl_SetResult(interp, "unable to create new string obj", TCL_STATIC); return(TCL_ERROR); } tcl_handle_entry = Tcl_CreateHashEntry(&interpdata->handles, (const char *) tcl_handle, &is_new_entry); if (!tcl_handle_entry) { Tcl_SetResult(interp, "unable to create new hash entry", TCL_STATIC); return(TCL_ERROR); } new_handle = malloc(sizeof(*new_handle)); if (!new_handle) { Tcl_SetResult(interp, "unable to allocate internal handle structure", TCL_STATIC); return(TCL_ERROR); } new_handle->base = handle; new_handle->pkcs11 = pkcs11_function_list; Tcl_SetHashValue(tcl_handle_entry, (ClientData) new_handle); Tcl_SetObjResult(interp, tcl_handle); return(TCL_OK); } int Tclpkcs11_Init(Tcl_Interp *interp) { struct tclpkcs11_interpdata *interpdata; Tcl_Command tclCreatComm_ret; int tclPkgProv_ret; interpdata = malloc(sizeof(*interpdata)); if (!interpdata) { Tcl_SetResult(interp, "failed to allocate interpdata structure", TCL_STATIC); return(TCL_ERROR); } /* Initialize InterpData structure */ Tcl_InitObjHashTable(&interpdata->handles); interpdata->handles_idx = 0; tclCreatComm_ret = Tcl_CreateObjCommand(interp, "pki::pkcs11::loadmodule", tclpkcs11_load_module, interpdata, NULL); if (!tclCreatComm_ret) { Tcl_SetResult(interp, "failed to create required commands", TCL_STATIC); return(TCL_ERROR); } tclPkgProv_ret = Tcl_PkgProvide(interp, "pki::pkcs11", "1.0"); if (tclPkgProv_ret != TCL_OK) { Tcl_SetResult(interp, "failed to provide package pki::pkcs11", TCL_STATIC); return(tclPkgProv_ret); } return(TCL_OK); }