summaryrefslogtreecommitdiff
path: root/gp11/gp11-slot.c
diff options
context:
space:
mode:
Diffstat (limited to 'gp11/gp11-slot.c')
-rw-r--r--gp11/gp11-slot.c436
1 files changed, 436 insertions, 0 deletions
diff --git a/gp11/gp11-slot.c b/gp11/gp11-slot.c
new file mode 100644
index 00000000..04e6d32a
--- /dev/null
+++ b/gp11/gp11-slot.c
@@ -0,0 +1,436 @@
+
+#include "config.h"
+
+#include "gp11.h"
+#include "gp11-private.h"
+
+#include <string.h>
+
+enum {
+ PROP_0,
+ PROP_MODULE,
+ PROP_HANDLE
+};
+
+G_DEFINE_TYPE (GP11Slot, gp11_slot, G_TYPE_OBJECT);
+
+/* ----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gp11_slot_init (GP11Slot *slot)
+{
+
+}
+
+static void
+gp11_slot_get_property (GObject *obj, guint prop_id, GValue *value,
+ GParamSpec *pspec)
+{
+ GP11Slot *slot = GP11_SLOT (obj);
+
+ switch (prop_id) {
+ case PROP_MODULE:
+ g_value_set_object (value, slot->module);
+ break;
+ case PROP_HANDLE:
+ g_value_set_uint (value, slot->handle);
+ break;
+ }
+}
+
+static void
+gp11_slot_set_property (GObject *obj, guint prop_id, const GValue *value,
+ GParamSpec *pspec)
+{
+ GP11Slot *slot = GP11_SLOT (obj);
+
+ switch (prop_id) {
+ case PROP_MODULE:
+ g_return_if_fail (!slot->module);
+ slot->module = g_value_get_object (value);
+ g_return_if_fail (slot->module);
+ g_object_ref (slot->module);
+ break;
+ case PROP_HANDLE:
+ g_return_if_fail (!slot->handle);
+ slot->handle = g_value_get_uint (value);
+ break;
+ }
+}
+
+static void
+gp11_slot_dispose (GObject *obj)
+{
+ GP11Slot *slot = GP11_SLOT (obj);
+
+ if (slot->module)
+ g_object_unref (slot->module);
+ slot->module = NULL;
+
+ G_OBJECT_CLASS (gp11_slot_parent_class)->dispose (obj);
+}
+
+static void
+gp11_slot_finalize (GObject *obj)
+{
+ GP11Slot *slot = GP11_SLOT (obj);
+
+ g_assert (slot->module == NULL);
+ slot->handle = 0;
+
+ G_OBJECT_CLASS (gp11_slot_parent_class)->finalize (obj);
+}
+
+
+static void
+gp11_slot_class_init (GP11SlotClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass*)klass;
+ gp11_slot_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->get_property = gp11_slot_get_property;
+ gobject_class->set_property = gp11_slot_set_property;
+ gobject_class->dispose = gp11_slot_dispose;
+ gobject_class->finalize = gp11_slot_finalize;
+
+ g_object_class_install_property (gobject_class, PROP_MODULE,
+ g_param_spec_object ("module", "Module", "PKCS11 Module",
+ GP11_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class, PROP_HANDLE,
+ g_param_spec_uint ("handle", "Handle", "PKCS11 Slot ID",
+ 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+void
+gp11_slot_info_free (GP11SlotInfo *slot_info)
+{
+ if (!slot_info)
+ return;
+ g_free (slot_info->slot_description);
+ g_free (slot_info->manufacturer_id);
+ g_free (slot_info);
+}
+
+void
+gp11_token_info_free (GP11TokenInfo *token_info)
+{
+ if (!token_info)
+ return;
+ g_free (token_info->label);
+ g_free (token_info->manufacturer_id);
+ g_free (token_info->model);
+ g_free (token_info->serial_number);
+ g_free (token_info);
+}
+
+void
+gp11_mechanism_info_free (GP11MechanismInfo *mech_info)
+{
+ if (!mech_info)
+ return;
+ g_free (mech_info);
+}
+
+GP11SlotInfo*
+gp11_slot_get_info (GP11Slot *slot)
+{
+ GP11SlotInfo *slotinfo;
+ CK_SLOT_INFO info;
+ CK_RV rv;
+
+ g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+ g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL);
+ g_return_val_if_fail (slot->module->funcs, NULL);
+
+ memset (&info, 0, sizeof (info));
+ rv = (slot->module->funcs->C_GetSlotInfo) (slot->handle, &info);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get slot info: %s", gp11_message_from_rv (rv));
+ return NULL;
+ }
+
+ slotinfo = g_new0 (GP11SlotInfo, 1);
+ slotinfo->slot_description = gp11_string_from_chars (info.slotDescription,
+ sizeof (info.slotDescription));
+ slotinfo->manufacturer_id = gp11_string_from_chars (info.manufacturerID,
+ sizeof (info.manufacturerID));
+ slotinfo->flags = info.flags;
+ slotinfo->hardware_version_major = info.hardwareVersion.major;
+ slotinfo->hardware_version_minor = info.hardwareVersion.minor;
+ slotinfo->firmware_version_major = info.firmwareVersion.major;
+ slotinfo->firmware_version_minor = info.firmwareVersion.minor;
+
+ return slotinfo;
+}
+
+GP11TokenInfo*
+gp11_slot_get_token_info (GP11Slot *slot)
+{
+ GP11TokenInfo *tokeninfo;
+ CK_TOKEN_INFO info;
+ gchar *string;
+ struct tm tm;
+ CK_RV rv;
+
+ g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+ g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL);
+ g_return_val_if_fail (slot->module->funcs, NULL);
+
+ memset (&info, 0, sizeof (info));
+ rv = (slot->module->funcs->C_GetTokenInfo) (slot->handle, &info);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get slot info: %s", gp11_message_from_rv (rv));
+ return NULL;
+ }
+
+ tokeninfo = g_new0 (GP11TokenInfo, 1);
+ tokeninfo->label = gp11_string_from_chars (info.label, sizeof (info.label));
+ tokeninfo->model = gp11_string_from_chars (info.model, sizeof (info.model));
+ tokeninfo->manufacturer_id = gp11_string_from_chars (info.manufacturerID,
+ sizeof (info.manufacturerID));
+ tokeninfo->serial_number = gp11_string_from_chars (info.serialNumber,
+ sizeof (info.serialNumber));
+ tokeninfo->flags = info.flags;
+ tokeninfo->max_session_count = info.ulMaxSessionCount;
+ tokeninfo->session_count = info.ulSessionCount;
+ tokeninfo->max_rw_session_count = info.ulMaxRwSessionCount;
+ tokeninfo->rw_session_count = info.ulRwSessionCount;
+ tokeninfo->max_pin_len = info.ulMaxPinLen;
+ tokeninfo->min_pin_len = info.ulMinPinLen;
+ tokeninfo->total_public_memory = info.ulTotalPublicMemory;
+ tokeninfo->total_private_memory = info.ulTotalPrivateMemory;
+ tokeninfo->free_private_memory = info.ulFreePrivateMemory;
+ tokeninfo->free_public_memory = info.ulFreePublicMemory;
+ tokeninfo->hardware_version_major = info.hardwareVersion.major;
+ tokeninfo->hardware_version_minor = info.hardwareVersion.minor;
+ tokeninfo->firmware_version_major = info.firmwareVersion.major;
+ tokeninfo->firmware_version_minor = info.firmwareVersion.minor;
+
+ /* Parse the time into seconds since epoch */
+ if (info.flags & CKF_CLOCK_ON_TOKEN) {
+ string = g_strndup ((gchar*)info.utcTime, MIN (14, sizeof (info.utcTime)));
+ if (!strptime (string, "%Y%m%d%H%M%S", &tm))
+ tokeninfo->utc_time = -1;
+ else
+ tokeninfo->utc_time = mktime (&tm);
+ } else {
+ tokeninfo->utc_time = -1;
+ }
+
+ return tokeninfo;
+}
+
+GSList*
+gp11_slot_get_mechanisms (GP11Slot *slot)
+{
+ CK_MECHANISM_TYPE_PTR mech_list;
+ CK_ULONG count, i;
+ GSList *result;
+ CK_RV rv;
+
+ g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+ g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL);
+ g_return_val_if_fail (slot->module->funcs, NULL);
+
+ rv = (slot->module->funcs->C_GetMechanismList) (slot->handle, NULL, &count);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get mechanism count: %s", gp11_message_from_rv (rv));
+ return NULL;
+ }
+
+ if (!count)
+ return NULL;
+
+ mech_list = g_new (CK_MECHANISM_TYPE, count);
+ rv = (slot->module->funcs->C_GetMechanismList) (slot->handle, mech_list, &count);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get mechanism list: %s", gp11_message_from_rv (rv));
+ g_free (mech_list);
+ return NULL;
+ }
+
+ result = NULL;
+ for (i = 0; i < count; ++i)
+ result = g_slist_prepend (result, GUINT_TO_POINTER (mech_list[i]));
+
+ g_free (mech_list);
+ return g_slist_reverse (result);
+
+}
+
+GP11MechanismInfo*
+gp11_slot_get_mechanism_info (GP11Slot *slot, guint mech_type)
+{
+ GP11MechanismInfo *mechinfo;
+ CK_MECHANISM_INFO info;
+ struct tm;
+ CK_RV rv;
+
+ g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+ g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL);
+ g_return_val_if_fail (slot->module->funcs, NULL);
+
+ memset (&info, 0, sizeof (info));
+ rv = (slot->module->funcs->C_GetMechanismInfo) (slot->handle, mech_type, &info);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get mechanism info: %s", gp11_message_from_rv (rv));
+ return NULL;
+ }
+
+ mechinfo = g_new0 (GP11MechanismInfo, 1);
+ mechinfo->flags = info.flags;
+ mechinfo->max_key_size = info.ulMaxKeySize;
+ mechinfo->min_key_size = info.ulMinKeySize;
+
+ return mechinfo;
+}
+
+#if UNIMPLEMENTED
+
+typedef struct InitToken {
+ GP11Arguments base;
+ const guchar *pin;
+ gsize length;
+ const gchar *label;
+} InitToken;
+
+static CK_RV
+perform_init_token (InitToken *args)
+{
+ return (args->base.pkcs11->C_InitToken) (args->base.handle,
+ args->pin, args->length,
+ args->label);
+}
+
+gboolean
+gp11_slot_init_token (GP11Slot *slot, const guchar *pin, gsize length,
+ const gchar *label, GCancellable *cancellable,
+ GError **err)
+{
+ InitToken args = { GP11_ARGUMENTS_INIT, pin, length, label };
+ return _gp11_call_sync (slot, perform_init_token, &args, err);
+}
+
+void
+gp11_slot_init_token_async (GP11Slot *slot, const guchar *pin, gsize length,
+ const gchar *label, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ InitToken* args = _gp11_call_async_prep (slot, perform_init_token,
+ sizeof (*args));
+
+ args->pin = pin;
+ args->length = length;
+ args->label = label;
+
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+gboolean
+gp11_slot_init_token_finish (GP11Slot *slot, GAsyncResult *result, GError **err)
+{
+ return _gp11_call_basic_finish (slot, result, err);
+}
+
+#endif /* UNIMPLEMENTED */
+
+typedef struct OpenSession {
+ GP11Arguments base;
+ guint flags;
+ CK_SESSION_HANDLE session;
+} OpenSession;
+
+static CK_RV
+perform_open_session (OpenSession *args)
+{
+ return (args->base.pkcs11->C_OpenSession) (args->base.handle,
+ args->flags | CKF_SERIAL_SESSION,
+ NULL, NULL, &args->session);
+}
+
+GP11Session*
+gp11_slot_open_session (GP11Slot *slot, guint flags, GError **err)
+{
+ return gp11_slot_open_session_full (slot, flags, NULL, err);
+}
+
+GP11Session*
+gp11_slot_open_session_full (GP11Slot *slot, guint flags, GCancellable *cancellable, GError **err)
+{
+ OpenSession args = { GP11_ARGUMENTS_INIT, flags, 0 };
+
+ if (!_gp11_call_sync (slot, perform_open_session, &args, cancellable, err))
+ return FALSE;
+
+ return gp11_session_from_handle (slot, args.session);
+}
+
+void
+gp11_slot_open_session_async (GP11Slot *slot, guint flags, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ OpenSession *args = _gp11_call_async_prep (slot, perform_open_session,
+ sizeof (*args), NULL);
+
+ args->flags = flags;
+ args->session = 0;
+
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+GP11Session*
+gp11_slot_open_session_finish (GP11Slot *slot, GAsyncResult *result, GError **err)
+{
+ OpenSession *args;
+
+ if (!_gp11_call_basic_finish (slot, result, err))
+ return NULL;
+
+ args = _gp11_call_arguments (result, OpenSession);
+ return gp11_session_from_handle (slot, args->session);
+}
+
+#if UNIMPLEMENTED
+
+static CK_RV
+perform_close_all_sessions (GP11Arguments *args)
+{
+ return (args->pkcs11->C_CloseAllSessions) (args->handle);
+}
+
+gboolean
+gp11_slot_close_all_sessions (GP11Slot *slot, GError **err)
+{
+ return gp11_slot_close_all_sessions_full (slot, NULL, err);
+}
+
+gboolean
+gp11_slot_close_all_sessions_full (GP11Slot *slot, GCancellable *cancellable, GError **err)
+{
+ GP11Arguments args = GP11_ARGUMENTS_INIT;
+ return _gp11_call_sync (slot, perform_close_all_sessions, &args, cancellable, err);
+}
+
+void
+gp11_slot_close_all_sessions_async (GP11Slot *slot, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ GP11Arguments *args = _gp11_call_async_prep (slot, perform_close_all_sessions, 0, NULL);
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+gboolean
+gp11_slot_close_all_sessions_finish (GP11Slot *slot, GAsyncResult *result,
+ GError **err)
+{
+ return _gp11_call_basic_finish (slot, result, err);
+}
+
+#endif