summaryrefslogtreecommitdiff
path: root/gck/gck-session.c
diff options
context:
space:
mode:
Diffstat (limited to 'gck/gck-session.c')
-rw-r--r--gck/gck-session.c2980
1 files changed, 0 insertions, 2980 deletions
diff --git a/gck/gck-session.c b/gck/gck-session.c
deleted file mode 100644
index c984eb6f..00000000
--- a/gck/gck-session.c
+++ /dev/null
@@ -1,2980 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* gck-session.h - the GObject PKCS#11 wrapper library
-
- Copyright (C) 2008, Stefan 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,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Stef Walter <nielsen@memberwebs.com>
-*/
-
-#include "config.h"
-
-#include "gck.h"
-#define DEBUG_FLAG GCK_DEBUG_SESSION
-#include "gck-debug.h"
-#include "gck-marshal.h"
-#include "gck-private.h"
-
-#include <string.h>
-
-#include <glib/gi18n.h>
-
-/**
- * SECTION:gck-session
- * @title: GckSession
- * @short_description: Represents an open PKCS11 session.
- *
- * Before performing any PKCS11 operations, a session must be opened. This is
- * analogous to an open database handle, or a file handle.
- */
-
-/**
- * GckSession:
- * @parent: derived from this.
- *
- * Represents an open PKCS11 session.
- */
-
-/**
- * GckSessionOptions:
- * @GCK_SESSION_READ_ONLY: Open session as read only
- * @GCK_SESSION_READ_WRITE: Open sessions as read/write
- * @GCK_SESSION_LOGIN_USER: Login as user on new sessions
- * @GCK_SESSION_AUTHENTICATE: Authenticate as necessary
- *
- * Options for creating sessions.
- */
-
-/**
- * GckMechanism:
- * @type: The mechanism type
- * @parameter: Mechanism specific data.
- * @n_parameter: Length of mechanism specific data.
- *
- * Represents a mechanism used with crypto operations.
- */
-
-enum {
- DISCARD_HANDLE,
- LAST_SIGNAL
-};
-
-enum {
- PROP_0,
- PROP_MODULE,
- PROP_HANDLE,
- PROP_INTERACTION,
- PROP_SLOT,
- PROP_OPTIONS,
-};
-
-struct _GckSessionPrivate {
- GckSlot *slot;
- GckModule *module;
- CK_SESSION_HANDLE handle;
- GTlsInteraction *interaction;
- GckSessionOptions options;
-
- /* Modified atomically */
- gint discarded;
-};
-
-G_DEFINE_TYPE (GckSession, gck_session, G_TYPE_OBJECT);
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-/* ----------------------------------------------------------------------------
- * OBJECT
- */
-
-static gboolean
-gck_session_real_discard_handle (GckSession *self, CK_OBJECT_HANDLE handle)
-{
- CK_FUNCTION_LIST_PTR funcs;
- CK_RV rv;
-
- /* The default functionality, close the handle */
-
- g_return_val_if_fail (self->pv->module, FALSE);
- g_object_ref (self->pv->module);
-
- funcs = gck_module_get_functions (self->pv->module);
- g_return_val_if_fail (funcs, FALSE);
-
- rv = (funcs->C_CloseSession) (handle);
- if (rv != CKR_OK) {
- g_warning ("couldn't close session properly: %s",
- gck_message_from_rv (rv));
- }
-
- g_object_unref (self->pv->module);
- return TRUE;
-}
-
-static void
-gck_session_init (GckSession *self)
-{
- self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_SESSION, GckSessionPrivate);
-}
-
-static void
-gck_session_get_property (GObject *obj, guint prop_id, GValue *value,
- GParamSpec *pspec)
-{
- GckSession *self = GCK_SESSION (obj);
-
- switch (prop_id) {
- case PROP_MODULE:
- g_value_take_object (value, gck_session_get_module (self));
- break;
- case PROP_HANDLE:
- g_value_set_ulong (value, gck_session_get_handle (self));
- break;
- case PROP_SLOT:
- g_value_take_object (value, gck_session_get_slot (self));
- break;
- case PROP_OPTIONS:
- g_value_set_uint (value, gck_session_get_options (self));
- break;
- case PROP_INTERACTION:
- g_value_take_object (value, self->pv->interaction);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
- break;
- }
-}
-
-static void
-gck_session_set_property (GObject *obj, guint prop_id, const GValue *value,
- GParamSpec *pspec)
-{
- GckSession *self = GCK_SESSION (obj);
-
- /* Only valid calls are from constructor */
-
- switch (prop_id) {
- case PROP_MODULE:
- g_return_if_fail (!self->pv->module);
- self->pv->module = g_value_dup_object (value);
- g_return_if_fail (self->pv->module);
- break;
- case PROP_HANDLE:
- g_return_if_fail (!self->pv->handle);
- self->pv->handle = g_value_get_ulong (value);
- break;
- case PROP_INTERACTION:
- g_return_if_fail (self->pv->interaction == NULL);
- self->pv->interaction = g_value_dup_object (value);
- break;
- case PROP_SLOT:
- g_return_if_fail (!self->pv->slot);
- self->pv->slot = g_value_dup_object (value);
- g_return_if_fail (self->pv->slot);
- break;
- case PROP_OPTIONS:
- g_return_if_fail (!self->pv->options);
- self->pv->options = g_value_get_flags (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
- break;
- }
-}
-
-static void
-gck_session_dispose (GObject *obj)
-{
- GckSession *self = GCK_SESSION (obj);
- gboolean handled;
-
- g_return_if_fail (GCK_IS_SESSION (self));
-
- if (g_atomic_int_compare_and_exchange (&self->pv->discarded, 0, 1)) {
-
- /*
- * Let the world know that we're discarding the session
- * handle. This allows any necessary session reuse to work.
- */
-
- g_signal_emit_by_name (self, "discard-handle", self->pv->handle, &handled);
- g_return_if_fail (handled);
- }
-
- G_OBJECT_CLASS (gck_session_parent_class)->dispose (obj);
-}
-
-static void
-gck_session_finalize (GObject *obj)
-{
- GckSession *self = GCK_SESSION (obj);
-
- g_assert (g_atomic_int_get (&self->pv->discarded) != 0);
-
- g_clear_object (&self->pv->interaction);
- g_clear_object (&self->pv->slot);
- g_clear_object (&self->pv->module);
-
- G_OBJECT_CLASS (gck_session_parent_class)->finalize (obj);
-}
-
-static void
-gck_session_class_init (GckSessionClass *klass)
-{
- GObjectClass *gobject_class = (GObjectClass*)klass;
- gck_session_parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->get_property = gck_session_get_property;
- gobject_class->set_property = gck_session_set_property;
- gobject_class->dispose = gck_session_dispose;
- gobject_class->finalize = gck_session_finalize;
-
- klass->discard_handle = gck_session_real_discard_handle;
-
- /**
- * GckSession:module:
- *
- * The GckModule that this session is opened on.
- */
- g_object_class_install_property (gobject_class, PROP_MODULE,
- g_param_spec_object ("module", "Module", "PKCS11 Module",
- GCK_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GckSession:handle:
- *
- * The raw CK_SESSION_HANDLE handle of this session.
- */
- g_object_class_install_property (gobject_class, PROP_HANDLE,
- g_param_spec_ulong ("handle", "Session Handle", "PKCS11 Session Handle",
- 0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GckSession:slot:
- *
- * The GckSlot this session is opened on.
- */
- g_object_class_install_property (gobject_class, PROP_SLOT,
- g_param_spec_object ("slot", "Slot that this session uses", "PKCS11 Slot",
- GCK_TYPE_SLOT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GckSession:options:
- *
- * The options this session was opened with.
- */
- g_object_class_install_property (gobject_class, PROP_OPTIONS,
- g_param_spec_flags ("options", "Session Options", "Session Options",
- GCK_TYPE_SESSION_OPTIONS, GCK_SESSION_READ_ONLY,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GckSession:interaction:
- *
- * Interaction object used to ask the user for pins when opening
- * sessions. Used if the session_options of the enumerator have
- * %GCK_SESSION_LOGIN_USER
- */
- g_object_class_install_property (gobject_class, PROP_INTERACTION,
- g_param_spec_object ("interaction", "Interaction", "Interaction asking for pins",
- G_TYPE_TLS_INTERACTION, G_PARAM_READWRITE));
-
- /**
- * GckSession::discard-handle:
- * @session: The session.
- * @handle: The handle being discarded.
- *
- * When a GckSession is being disposed of it emits this signal to allow
- * a session pool to pick up the handle and keep it around.
- *
- * If no signal handler claims the handle, then it is closed. This is used by
- * gck_module_set_pool_sessions() to implement the module session pool.
- *
- * Returns: Whether or not this handle was claimed.
- */
- signals[DISCARD_HANDLE] = g_signal_new ("discard-handle", GCK_TYPE_SESSION,
- G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GckSessionClass, discard_handle),
- g_signal_accumulator_true_handled, NULL,
- _gck_marshal_BOOLEAN__ULONG, G_TYPE_BOOLEAN, 1, G_TYPE_ULONG);
-
- g_type_class_add_private (klass, sizeof (GckSessionPrivate));
-}
-
-/* ----------------------------------------------------------------------------
- * PUBLIC
- */
-
-/**
- * GckSessionInfo:
- * @slot_id: The handle of the PKCS11 slot that this session is opened on.
- * @state: The user login state of the session.
- * @flags: Various PKCS11 flags.
- * @device_error: The last device error that occurred from an operation on this session.
- *
- * Information about the session. This is analogous to a CK_SESSION_INFO structure.
- *
- * When done with this structure, release it using gck_session_info_free().
- */
-
-GType
-gck_session_info_get_type (void)
-{
- static volatile gsize initialized = 0;
- static GType type = 0;
- if (g_once_init_enter (&initialized)) {
- type = g_boxed_type_register_static ("GckSessionInfo",
- (GBoxedCopyFunc)gck_session_info_copy,
- (GBoxedFreeFunc)gck_session_info_free);
- g_once_init_leave (&initialized, 1);
- }
- return type;
-}
-
-/**
- * gck_session_info_copy:
- * @session_info: a session info structure
- *
- * Make a new copy of a session info structure.
- *
- * Returns: (transfer full): a new copy of the session info
- */
-GckSessionInfo *
-gck_session_info_copy (GckSessionInfo *session_info)
-{
- return g_memdup (session_info, sizeof (GckSessionInfo));
-}
-
-/**
- * gck_session_info_free:
- * @session_info: Session info to free.
- *
- * Free the GckSessionInfo structure and all associated memory.
- **/
-void
-gck_session_info_free (GckSessionInfo *session_info)
-{
- if (!session_info)
- return;
- g_free (session_info);
-}
-
-/**
- * gck_session_from_handle:
- * @slot: The slot which the session belongs to.
- * @session_handle: the raw PKCS\#11 handle of the session
- * @options: Session options. Those which are used during opening a session have no effect.
- *
- * Initialize a GckSession object from a raw PKCS\#11 session handle.
- * Usually one would use the gck_slot_open_session() function to
- * create a session.
- *
- * Returns: (transfer full): the new GckSession object
- **/
-GckSession *
-gck_session_from_handle (GckSlot *slot,
- gulong session_handle,
- GckSessionOptions options)
-{
- GTlsInteraction *interaction;
- GckModule *module;
- GckSession *session;
-
- g_return_val_if_fail (GCK_IS_SLOT (slot), NULL);
-
- module = gck_slot_get_module (slot);
- interaction = gck_slot_get_interaction (slot);
-
- session = g_object_new (GCK_TYPE_SESSION,
- "module", module,
- "interaction", interaction,
- "handle", session_handle,
- "slot", slot,
- "options", options,
- NULL);
-
- g_object_unref (module);
- g_clear_object (&interaction);
-
- return session;
-}
-
-/**
- * gck_session_get_handle:
- * @self: The session object.
- *
- * Get the raw PKCS\#11 session handle from a GckSession object.
- *
- * Return value: The raw session handle.
- **/
-gulong
-gck_session_get_handle (GckSession *self)
-{
- g_return_val_if_fail (GCK_IS_SESSION (self), (CK_SESSION_HANDLE)-1);
- return self->pv->handle;
-}
-
-/**
- * gck_session_get_module:
- * @self: The session object.
- *
- * Get the PKCS\#11 module to which this session belongs.
- *
- * Returns: (transfer full): the module, which should be unreffed after use
- **/
-GckModule *
-gck_session_get_module (GckSession *self)
-{
- g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
- g_return_val_if_fail (GCK_IS_MODULE (self->pv->module), NULL);
- return g_object_ref (self->pv->module);
-}
-
-/**
- * gck_session_get_slot:
- * @self: The session object.
- *
- * Get the PKCS\#11 slot to which this session belongs.
- *
- * Return value: (transfer full): The slot, which should be unreffed after use.
- **/
-GckSlot *
-gck_session_get_slot (GckSession *self)
-{
- g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
- g_return_val_if_fail (GCK_IS_SLOT (self->pv->slot), NULL);
- return g_object_ref (self->pv->slot);
-}
-
-/**
- * gck_session_get_info:
- * @self: The session object.
- *
- * Get information about the session.
- *
- * Returns: (transfer full): the session info. Use the gck_session_info_free()
- * to release when done
- **/
-GckSessionInfo*
-gck_session_get_info (GckSession *self)
-{
- GckSessionInfo *sessioninfo;
- CK_FUNCTION_LIST_PTR funcs;
- CK_SESSION_INFO info;
- CK_RV rv;
-
- g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
- g_return_val_if_fail (GCK_IS_MODULE (self->pv->module), NULL);
-
- g_object_ref (self->pv->module);
-
- funcs = gck_module_get_functions (self->pv->module);
- g_return_val_if_fail (funcs, NULL);
-
- memset (&info, 0, sizeof (info));
- rv = (funcs->C_GetSessionInfo) (self->pv->handle, &info);
-
- g_object_unref (self->pv->module);
-
- if (rv != CKR_OK) {
- g_warning ("couldn't get session info: %s", gck_message_from_rv (rv));
- return NULL;
- }
-
- sessioninfo = g_new0 (GckSessionInfo, 1);
- sessioninfo->flags = info.flags;
- sessioninfo->slot_id = info.slotID;
- sessioninfo->state = info.state;
- sessioninfo->device_error = info.ulDeviceError;
-
- return sessioninfo;
-}
-
-/**
- * gck_session_get_state:
- * @self: the session
- *
- * Get the session state. The state is the various PKCS\#11 CKS_XXX flags.
- *
- * Returns: the session state
- */
-gulong
-gck_session_get_state (GckSession *self)
-{
- CK_FUNCTION_LIST_PTR funcs;
- CK_SESSION_INFO info;
- CK_RV rv;
-
- g_return_val_if_fail (GCK_IS_SESSION (self), 0);
- g_return_val_if_fail (GCK_IS_MODULE (self->pv->module), 0);
-
- g_object_ref (self->pv->module);
-
- funcs = gck_module_get_functions (self->pv->module);
- g_return_val_if_fail (funcs, 0);
-
- memset (&info, 0, sizeof (info));
- rv = (funcs->C_GetSessionInfo) (self->pv->handle, &info);
-
- g_object_unref (self->pv->module);
-
- if (rv != CKR_OK) {
- g_warning ("couldn't get session info: %s", gck_message_from_rv (rv));
- return 0;
- }
-
- return info.state;
-}
-
-/**
- * gck_session_get_options:
- * @self: The session to get options from.
- *
- * Get the options this session was opened with.
- *
- * Return value: The session options.
- **/
-GckSessionOptions
-gck_session_get_options (GckSession *self)
-{
- g_return_val_if_fail (GCK_IS_SESSION (self), 0);
- return self->pv->options;
-}
-
-/**
- * gck_session_get_interaction:
- * @self: the session
- *
- * Get the interaction object set on this session, which is used to prompt
- * for pins and the like.
- *
- * Returns: (transfer full) (allow-none): the interaction object, or %NULL
- */
-GTlsInteraction *
-gck_session_get_interaction (GckSession *self)
-{
- g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
-
- if (self->pv->interaction)
- return g_object_ref (self->pv->interaction);
-
- return NULL;
-}
-
-/* ---------------------------------------------------------------------------------------------
- * INIT PIN
- */
-
-typedef struct _InitPin {
- GckArguments base;
- guchar *pin;
- gsize n_pin;
-} InitPin;
-
-
-static void
-free_init_pin (InitPin *args)
-{
- g_free (args->pin);
- g_free (args);
-}
-
-static CK_RV
-perform_init_pin (InitPin *args)
-{
- return (args->base.pkcs11->C_InitPIN) (args->base.handle, (CK_BYTE_PTR)args->pin,
- args->n_pin);
-}
-
-/**
- * gck_session_init_pin:
- * @self: Initialize PIN for this session's slot.
- * @pin: The user's PIN, or NULL for protected authentication path.
- * @n_pin: The length of the PIN.
- * @cancellable: Optional cancellation object, or NULL.
- * @error: A location to return an error.
- *
- * Initialize the user's pin on this slot that this session is opened on.
- * According to the PKCS\#11 standards, the session must be logged in with
- * the CKU_SO user type.
- *
- * This call may block for an indefinite period.
- *
- * Return value: Whether successful or not.
- **/
-gboolean
-gck_session_init_pin (GckSession *self, const guchar *pin, gsize n_pin,
- GCancellable *cancellable, GError **error)
-{
- InitPin args = { GCK_ARGUMENTS_INIT, (guchar*)pin, n_pin };
- return _gck_call_sync (self, perform_init_pin, NULL, &args, cancellable, error);
-
-}
-
-/**
- * gck_session_init_pin_async:
- * @self: Initialize PIN for this session's slot.
- * @pin: (allow-none) (array length=n_pin): The user's PIN, or NULL for protected authentication path.
- * @n_pin: The length of the PIN.
- * @cancellable: Optional cancellation object, or NULL.
- * @callback: Called when the operation completes.
- * @user_data: Data to pass to the callback.
- *
- * Initialize the user's pin on this slot that this session is opened on.
- * According to the PKCS\#11 standards, the session must be logged in with
- * the CKU_SO user type.
- *
- * This call will return immediately and completes asynchronously.
- **/
-void
-gck_session_init_pin_async (GckSession *self, const guchar *pin, gsize n_pin,
- GCancellable *cancellable, GAsyncReadyCallback callback,
- gpointer user_data)
-{
- InitPin* args = _gck_call_async_prep (self, self, perform_init_pin, NULL, sizeof (*args), free_init_pin);
-
- args->pin = pin && n_pin ? g_memdup (pin, n_pin) : NULL;
- args->n_pin = n_pin;
-
- _gck_call_async_ready_go (args, cancellable, callback, user_data);
-}
-
-/**
- * gck_session_init_pin_finish:
- * @self: The session.
- * @result: The result passed to the callback.
- * @error: A location to return an error.
- *
- * Get the result of initializing a user's PIN.
- *
- * Return value: Whether the operation was successful or not.
- **/
-gboolean
-gck_session_init_pin_finish (GckSession *self, GAsyncResult *result, GError **error)
-{
- return _gck_call_basic_finish (result, error);
-}
-
-
-/* ---------------------------------------------------------------------------------------------
- * SET PIN
- */
-
-typedef struct _SetPin {
- GckArguments base;
- guchar *old_pin;
- gsize n_old_pin;
- guchar *new_pin;
- gsize n_new_pin;
-} SetPin;
-
-static void
-free_set_pin (SetPin *args)
-{
- g_free (args->old_pin);
- g_free (args->new_pin);
- g_free (args);
-}
-
-static CK_RV
-perform_set_pin (SetPin *args)
-{
- return (args->base.pkcs11->C_SetPIN) (args->base.handle, (CK_BYTE_PTR)args->old_pin,
- args->n_old_pin, args->new_pin, args->n_new_pin);
-}
-
-/**
- * gck_session_set_pin:
- * @self: Change the PIN for this session's slot.
- * @old_pin: (allow-none) (array length=n_old_pin): the user's old PIN, or %NULL
- * for protected authentication path.
- * @n_old_pin: The length of the PIN.
- * @new_pin: (allow-none) (array length=n_new_pin): the user's new PIN, or %NULL
- * for protected authentication path
- * @n_new_pin: The length of the PIN.
- * @cancellable: Optional cancellation object, or NULL.
- * @error: A location to return an error.
- *
- * Change the user's pin on this slot that this session is opened on.
- *
- * This call may block for an indefinite period.
- *
- * Return value: Whether successful or not.
- **/
-gboolean
-gck_session_set_pin (GckSession *self, const guchar *old_pin, gsize n_old_pin,
- const guchar *new_pin, gsize n_new_pin, GCancellable *cancellable,
- GError **error)
-{
- SetPin args = { GCK_ARGUMENTS_INIT, (guchar*)old_pin, n_old_pin, (guchar*)new_pin, n_new_pin };
- return _gck_call_sync (self, perform_set_pin, NULL, &args, cancellable, error);
-}
-
-/**
- * gck_session_set_pin_async:
- * @self: Change the PIN for this session's slot.
- * @old_pin: The user's old PIN, or NULL for protected authentication path.
- * @n_old_pin: The length of the PIN.
- * @new_pin: The user's new PIN, or NULL for protected authentication path.
- * @n_new_pin: The length of the PIN.
- * @cancellable: Optional cancellation object, or NULL.
- * @callback: Called when the operation completes.
- * @user_data: Data to pass to the callback.
- *
- * Change the user's pin on this slot that this session is opened on.
- *
- * This call will return immediately and completes asynchronously.
- **/
-void
-gck_session_set_pin_async (GckSession *self, const guchar *old_pin, gsize n_old_pin,
- const guchar *new_pin, gsize n_new_pin, GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer user_data)
-{
- SetPin* args = _gck_call_async_prep (self, self, perform_set_pin, NULL, sizeof (*args), free_set_pin);
-
- args->old_pin = old_pin && n_old_pin ? g_memdup (old_pin, n_old_pin) : NULL;
- args->n_old_pin = n_old_pin;
- args->new_pin = new_pin && n_new_pin ? g_memdup (new_pin, n_new_pin) : NULL;
- args->n_new_pin = n_new_pin;
-
- _gck_call_async_ready_go (args, cancellable, callback, user_data);
-}
-
-/**
- * gck_session_set_pin_finish:
- * @self: The session.
- * @result: The result passed to the callback.
- * @error: A location to return an error.
- *
- * Get the result of changing a user's PIN.
- *
- * Return value: Whether the operation was successful or not.
- **/
-gboolean
-gck_session_set_pin_finish (GckSession *self, GAsyncResult *result, GError **error)
-{
- return _gck_call_basic_finish (result, error);
-}
-
-
-/* ---------------------------------------------------------------------------------------------
- * LOGIN
- */
-
-typedef struct _Login {
- GckArguments base;
- gulong user_type;
- guchar *pin;
- gsize n_pin;
-} Login;
-
-static void
-free_login (Login *args)
-{
- g_free (args->pin);
- g_free (args);
-}
-
-static CK_RV
-perform_login (Login *args)
-{
- return (args->base.pkcs11->C_Login) (args->base.handle, args->user_type,
- (CK_BYTE_PTR)args->pin, args->n_pin);
-}
-
-/**
- * gck_session_login:
- * @self: Log in to this session.
- * @user_type: The type of login user.
- * @pin: (allow-none) (array length=n_pin): the user's PIN, or %NULL for
- * protected authentication path
- * @n_pin: The length of the PIN.
- * @cancellable: Optional cancellation object, or NULL.
- * @error: A location to return an error.
- *
- * Login the user on the session. This call may block for
- * an indefinite period.
- *
- * Return value: Whether successful or not.
- **/
-gboolean
-gck_session_login (GckSession *self, gulong user_type, const guchar *pin,
- gsize n_pin, GCancellable *cancellable, GError **error)
-{
- Login args = { GCK_ARGUMENTS_INIT, user_type, (guchar*)pin, n_pin };
- return _gck_call_sync (self, perform_login, NULL, &args, cancellable, error);
-
-}
-
-/**
- * gck_session_login_async:
- * @self: Log in to this session.
- * @user_type: The type of login user.
- * @pin: (allow-none) (array length=n_pin): the user's PIN, or %NULL for
- * protected authentication path
- * @n_pin: The length of the PIN.
- * @cancellable: Optional cancellation object, or NULL.
- * @callback: Called when the operation completes.
- * @user_data: Data to pass to the callback.
- *
- * Login the user on the session. This call will return
- * immediately and completes asynchronously.
- **/
-void
-gck_session_login_async (GckSession *self, gulong user_type, const guchar *pin,
- gsize n_pin, GCancellable *cancellable, GAsyncReadyCallback callback,
- gpointer user_data)
-{
- Login* args = _gck_call_async_prep (self, self, perform_login, NULL, sizeof (*args), free_login);
-
- args->user_type = user_type;
- args->pin = pin && n_pin ? g_memdup (pin, n_pin) : NULL;
- args->n_pin = n_pin;
-
- _gck_call_async_ready_go (args, cancellable, callback, user_data);
-
-}
-
-/**
- * gck_session_login_finish:
- * @self: The session logged into.
- * @result: The result passed to the callback.
- * @error: A location to return an error.
- *
- * Get the result of a login operation.
- *
- * Return value: Whether the operation was successful or not.
- **/
-gboolean
-gck_session_login_finish (GckSession *self, GAsyncResult *result, GError **error)
-{
- return _gck_call_basic_finish (result, error);
-}
-
-
-
-
-/* LOGOUT */
-
-static CK_RV
-perform_logout (GckArguments *args)
-{
- return (args->pkcs11->C_Logout) (args->handle);
-}
-
-/**
- * gck_session_logout:
- * @self: Logout of this session.
- * @cancellable: Optional cancellation object, or NULL.
- * @error: A location to return an error.
- *
- * Log out of the session. This call may block for an indefinite period.
- *
- * Return value: Whether the logout was successful or not.
- **/
-gboolean
-gck_session_logout (GckSession *self, GCancellable *cancellable, GError **error)
-{
- GckArguments args = GCK_ARGUMENTS_INIT;
- return _gck_call_sync (self, perform_logout, NULL, &args, cancellable, error);
-}
-
-/**
- * gck_session_logout_async:
- * @self: Logout of this session.
- * @cancellable: Optional cancellation object, or NULL.
- * @callback: Called when the operation completes.
- * @user_data: Data to pass to the callback.
- *
- * Log out of the session. This call returns immediately and completes
- * asynchronously.
- **/
-void
-gck_session_logout_async (GckSession *self, GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer user_data)
-{
- GckArguments *args = _gck_call_async_prep (self, self, perform_logout, NULL, 0, NULL);
- _gck_call_async_ready_go (args, cancellable, callback, user_data);
-}
-
-/**
- * gck_session_logout_finish:
- * @self: Logout of this session.
- * @result: The result passed to the callback.
- * @error: A location to return an error.
- *
- * Get the result of logging out of a session.
- *
- * Return value: Whether the logout was successful or not.
- **/
-gboolean
-gck_session_logout_finish (GckSession *self, GAsyncResult *result, GError **error)
-{
- return _gck_call_basic_finish (result, error);
-}
-
-
-
-
-/* CREATE OBJECT */
-
-typedef struct _CreateObject {
- GckArguments base;
- GckAttributes *attrs;
- CK_OBJECT_HANDLE object;
-} CreateObject;
-
-static void
-free_create_object (CreateObject *args)
-{
- gck_attributes_unref (args->attrs);
- g_free (args);
-}
-
-static CK_RV
-perform_create_object (CreateObject *args)
-{
- CK_ATTRIBUTE_PTR attrs;
- CK_ULONG n_attrs;
- CK_RV rv;
-
- attrs = _gck_attributes_commit_out (args->attrs, &n_attrs);
-
- rv = (args->base.pkcs11->C_CreateObject) (args->base.handle,
- attrs, n_attrs,
- &args->object);
-
- if (_gck_debugging) {
- gchar *string = _gck_attributes_format (args->attrs);
- if (rv == CKR_OK)
- _gck_debug ("created object: %s", string);
- else
- _gck_debug ("failed %s to create object: %s",
- _gck_stringize_rv (rv), string);
- g_free (string);
- }
-
- return rv;
-}
-
-/**
- * gck_session_create_object:
- * @self: The session to create the object on.
- * @attrs: The attributes to create the object with.
- * @cancellable: Optional cancellation object, or NULL.
- * @error: A location to return an error, or NULL.
- *
- * Create a new PKCS\#11 object. This call may block for an
- * indefinite period.
- *
- * Returns: (transfer full): the newly created object or %NULL if an error occurred
- **/
-GckObject *
-gck_session_create_object (GckSession *self, GckAttributes *attrs,
- GCancellable *cancellable, GError **error)
-{
- CreateObject args = { GCK_ARGUMENTS_INIT, attrs, 0 };
- gboolean ret;
-
- g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
- g_return_val_if_fail (attrs != NULL, NULL);
-
- _gck_attributes_lock (attrs);
- ret = _gck_call_sync (self, perform_create_object, NULL, &args, cancellable, error);
- _gck_attributes_unlock (attrs);
-
- if (!ret)
- return NULL;
-
- return gck_object_from_handle (self, args.object);
-}
-
-/**
- * gck_session_create_object_async:
- * @self: The session to create the object on.
- * @attrs: The attributes to create the object with.
- * @cancellable: Optional cancellation object or NULL.
- * @callback: Called when the operation completes.
- * @user_data: Data to pass to the callback.
- *
- * Create a new PKCS\#11 object. This call will return immediately
- * and complete asynchronously.
- **/
-void
-gck_session_create_object_async (GckSession *self, GckAttributes *attrs,
- GCancellable *cancellable, GAsyncReadyCallback callback,
- gpointer user_data)
-{
- CreateObject *args = _gck_call_async_prep (self, self, perform_create_object,
- NULL, sizeof (*args), free_create_object);
-
- g_return_if_fail (attrs);
-
- args->attrs = gck_attributes_ref (attrs);
- _gck_attributes_lock (attrs);
-
- _gck_call_async_ready_go (args, cancellable, callback, user_data);
-}
-
-/**
- * gck_session_create_object_finish:
- * @self: The session to create the object on.
- * @result: The result passed to the callback.
- * @error: A location to return an error, or NULL.
- *
- * Get the result of creating a new PKCS\#11 object.
- *
- * Return value: (transfer full): the newly created object or NULL if an error occurred
- **/
-GckObject *
-gck_session_create_object_finish (GckSession *self, GAsyncResult *result, GError **error)
-{
- CreateObject *args;
-
- args = _gck_call_arguments (result, CreateObject);
- _gck_attributes_unlock (args->attrs);
-
- if (!_gck_call_basic_finish (result, error))
- return NULL;
- return gck_object_from_handle (self, args->object);
-}
-
-
-
-/* FIND OBJECTS */
-
-typedef struct _FindObjects {
- GckArguments base;
- GckAttributes *attrs;
- CK_OBJECT_HANDLE_PTR objects;
- CK_ULONG n_objects;
-} FindObjects;
-
-static void
-free_find_objects (FindObjects *args)
-{
- gck_attributes_unref (args->attrs);
- g_free (args->objects);
-}
-
-static CK_RV
-perform_find_objects (FindObjects *args)
-{
- CK_OBJECT_HANDLE_PTR batch;
- CK_ULONG n_batch, n_found;
- CK_ATTRIBUTE_PTR attrs;
- CK_ULONG n_attrs;
- GArray *array;
- CK_RV rv;
-
- if (_gck_debugging) {
- gchar *string = _gck_attributes_format (args->attrs);
- _gck_debug ("matching: %s", string);
- g_free (string);
- }
-
- attrs = _gck_attributes_commit_out (args->attrs, &n_attrs);
-
- rv = (args->base.pkcs11->C_FindObjectsInit) (args->base.handle,
- attrs, n_attrs);
- if (rv != CKR_OK)
- return rv;
-
- batch = NULL;
- n_found = n_batch = 4;
- array = g_array_new (0, 1, sizeof (CK_OBJECT_HANDLE));
-
- do {
- /*
- * Reallocate and double in size:
- * - First time.
- * - Each time we found as many as batch
- */
-
- if (n_found == n_batch) {
- n_batch *= 2;
- batch = g_realloc (batch, sizeof (CK_OBJECT_HANDLE) * n_batch);
- }
-
- rv = (args->base.pkcs11->C_FindObjects) (args->base.handle,
- batch, n_batch, &n_found);
- if (rv != CKR_OK)
- break;
-
- g_array_append_vals (array, batch, n_found);
-
- } while (n_found > 0);
-
- g_free (batch);
-
- if (rv == CKR_OK) {
- args->n_objects = array->len;
- args->objects = (CK_OBJECT_HANDLE_PTR)g_array_free (array, FALSE);
- rv = (args->base.pkcs11->C_FindObjectsFinal) (args->base.handle);
- } else {
- args->objects = NULL;
- args->n_objects = 0;
- g_array_free (array, TRUE);
- }
-
- return rv;
-}
-
-static GList*
-objlist_from_handles (GckSession *self, CK_OBJECT_HANDLE_PTR objects,
- CK_ULONG n_objects)
-{
- GList *results = NULL;
-
- while (n_objects > 0) {
- results = g_list_prepend (results,
- gck_object_from_handle (self, objects[--n_objects]));
- }
-
- return g_list_reverse (results);
-}
-
-/**
- * gck_session_find_objects:
- * @self: The session to find objects on.
- * @attrs: The attributes to match.
- * @cancellable: Optional cancellation object or NULL.
- * @error: A location to return an error or NULL.
- *
- * Find the objects matching the passed attributes. This call may
- * block for an indefinite period.
- *
- * Returns: (transfer full) (element-type Gck.Object): a list of the matching
- * objects, which may be empty
- **/
-GList *
-gck_session_find_objects (GckSession *self, GckAttributes *attrs,
- GCancellable *cancellable, GError **error)
-{
- FindObjects args = { GCK_ARGUMENTS_INIT, attrs, NULL, 0 };
- GList *results = NULL;
-
- g_return_val_if_fail (attrs, NULL);
- _gck_attributes_lock (attrs);
-
- if (_gck_call_sync (self, perform_find_objects, NULL, &args, cancellable, error))
- results = objlist_from_handles (self, args.objects, args.n_objects);
-
- g_free (args.objects);
- _gck_attributes_unlock (attrs);
- return results;
-}
-
-/**
- * gck_session_find_objects_async:
- * @self: The session to find objects on.
- * @attrs: The attributes to match.
- * @cancellable: Optional cancellation object or NULL.
- * @callback: Called when the operation completes.
- * @user_data: Data to pass to the callback.
- *
- * Find the objects matching the passed attributes. This call will
- * return immediately and complete asynchronously.
- **/
-void
-gck_session_find_objects_async (GckSession *self, GckAttributes *attrs,
- GCancellable *cancellable, GAsyncReadyCallback callback,
- gpointer user_data)
-{
- FindObjects *args = _gck_call_async_prep (self, self, perform_find_objects,
- NULL, sizeof (*args), free_find_objects);
- args->attrs = gck_attributes_ref (attrs);
- _gck_attributes_lock (attrs);
- _gck_call_async_ready_go (args, cancellable, callback, user_data);
-}
-
-/**
- * gck_session_find_objects_finish:
- * @self: The session to find objects on.
- * @result: The attributes to match.
- * @error: A location to return an error.
- *
- * Get the result of a find operation.
- *
- * Returns: (transfer full) (element-type Gck.Object): a list of the matching
- * objects, which may be empty
- **/
-GList *
-gck_session_find_objects_finish (GckSession *self, GAsyncResult *result, GError **error)
-{
- FindObjects *args;
-
- args = _gck_call_arguments (result, FindObjects);
- _gck_attributes_unlock (args->attrs);
-
- if (!_gck_call_basic_finish (result, error))
- return NULL;
- return objlist_from_handles (self, args->objects, args->n_objects);
-}
-
-/* -----------------------------------------------------------------------------
- * KEY PAIR GENERATION
- */
-
-typedef struct _GenerateKeyPair {
- GckArguments base;
- GckMechanism mechanism;
- GckAttributes *public_attrs;
- GckAttributes *private_attrs;
- CK_OBJECT_HANDLE public_key;
- CK_OBJECT_HANDLE private_key;
-} GenerateKeyPair;
-
-static void
-free_generate_key_pair (GenerateKeyPair *args)
-{
- gck_attributes_unref (args->public_attrs);
- gck_attributes_unref (args->private_attrs);
- g_free (args);
-}
-
-static CK_RV
-perform_generate_key_pair (GenerateKeyPair *args)
-{
- CK_ATTRIBUTE_PTR pub_attrs, priv_attrs;
- CK_ULONG n_pub_attrs, n_priv_attrs;
-
- g_assert (sizeof (CK_MECHANISM) == sizeof (GckMechanism));
-
- pub_attrs = _gck_attributes_commit_out (args->public_attrs, &n_pub_attrs);
- priv_attrs = _gck_attributes_commit_out (args->private_attrs, &n_priv_attrs);
-
- return (args->base.pkcs11->C_GenerateKeyPair) (args->base.handle,
- (CK_MECHANISM_PTR)&(args->mechanism),
- pub_attrs, n_pub_attrs,
- priv_attrs, n_priv_attrs,
- &args->public_key,
- &args->private_key);
-}
-
-/**
- * gck_session_generate_key_pair:
- * @self: The session to use.
- * @mech_type: The mechanism type to use for key generation.
- * @public_attrs: Additional attributes for the generated public key.
- * @private_attrs: Additional attributes for the generated private key.
- * @public_key: A location to return the resulting public key.
- * @private_key: A location to return the resulting private key.
- * @cancellable: Optional cancellation object, or NULL.
- * @error: A location to return an error, or NULL.
- *
- * Generate a new key pair of public and private keys. This call may block for an
- * indefinite period.
- *
- * Return value: TRUE if the operation succeeded.
- **/
-gboolean
-gck_session_generate_key_pair (GckSession *self, gulong mech_type,
- GckAttributes *public_attrs, GckAttributes *private_attrs,
- GckObject **public_key, GckObject **private_key,
- GCancellable *cancellable, GError **error)
-{
- GckMechanism mech = { mech_type, NULL, 0 };
- return gck_session_generate_key_pair_full (self, &mech, public_attrs, private_attrs, public_key, private_key, cancellable, error);
-}
-
-/**
- * gck_session_generate_key_pair_full:
- * @self: The session to use.
- * @mechanism: The mechanism to use for key generation.
- * @public_attrs: Additional attributes for the generated public key.
- * @private_attrs: Additional attributes for the generated private key.
- * @public_key: A location to return the resulting public key.
- * @private_key: A location to return the resulting private key.
- * @cancellable: Optional cancellation object, or NULL.
- * @error: A location to return an error, or NULL.
- *
- * Generate a new key pair of public and private keys. This call may block for an
- * indefinite period.
- *
- * Return value: TRUE if the operation succeeded.
- **/
-gboolean
-gck_session_generate_key_pair_full (GckSession *self, GckMechanism *mechanism,
- GckAttributes *public_attrs, GckAttributes *private_attrs,
- GckObject **public_key, GckObject **private_key,
- GCancellable *cancellable, GError **error)
-{
- GenerateKeyPair args = { GCK_ARGUMENTS_INIT, GCK_MECHANISM_EMPTY, public_attrs, private_attrs, 0, 0 };
- gboolean ret;
-
- g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
- g_return_val_if_fail (mechanism, FALSE);
- g_return_val_if_fail (public_attrs, FALSE);
- g_return_val_if_fail (private_attrs, FALSE);
- g_return_val_if_fail (public_key, FALSE);
- g_return_val_if_fail (private_key, FALSE);
-
- /* Shallow copy of the mechanism structure */
- memcpy (&args.mechanism, mechanism, sizeof (args.mechanism));
-
- _gck_attributes_lock (public_attrs);
- if (public_attrs != private_attrs)
- _gck_attributes_lock (private_attrs);
- ret = _gck_call_sync (self, perform_generate_key_pair, NULL, &args, cancellable, error);
- if (public_attrs != private_attrs)
- _gck_attributes_unlock (private_attrs);
- _gck_attributes_unlock (public_attrs);
-
- if (!ret)
- return FALSE;
-
- *public_key = gck_object_from_handle (self, args.public_key);
- *private_key = gck_object_from_handle (self, args.private_key);
- return TRUE;
-}
-
-/**
- * gck_session_generate_key_pair_async:
- * @self: The session to use.
- * @mechanism: The mechanism to use for key generation.
- * @public_attrs: Additional attributes for the generated public key.
- * @private_attrs: Additional attributes for the generated private key.
- * @cancellable: Optional cancellation object or NULL.
- * @callback: Called when the operation completes.
- * @user_data: Data to pass to the callback.
- *
- * Generate a new key pair of public and private keys. This call will
- * return immediately and complete asynchronously.
- **/
-void
-gck_session_generate_key_pair_async (GckSession *self, GckMechanism *mechanism,
- GckAttributes *public_attrs, GckAttributes *private_attrs,
- GCancellable *cancellable, GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GenerateKeyPair *args = _gck_call_async_prep (self, self, perform_generate_key_pair,
- NULL, sizeof (*args), free_generate_key_pair);
-
- g_return_if_fail (GCK_IS_SESSION (self));
- g_return_if_fail (mechanism);
- g_return_if_fail (public_attrs);
- g_return_if_fail (private_attrs);
-
- /* Shallow copy of the mechanism structure */
- memcpy (&args->mechanism, mechanism, sizeof (args->mechanism));
-
- args->public_attrs = gck_attributes_ref (public_attrs);
- _gck_attributes_lock (public_attrs);
- args->private_attrs = gck_attributes_ref (private_attrs);
- if (public_attrs != private_attrs)
- _gck_attributes_lock (private_attrs);
-
- _gck_call_async_ready_go (args, cancellable, callback, user_data);
-}
-
-/**
- * gck_session_generate_key_pair_finish:
- * @self: The session to use.
- * @result: The async result passed to the callback.
- * @public_key: A location to return the resulting public key.
- * @private_key: A location to return the resulting private key.
- * @error: A location to return an error.
- *
- * Get the result of a generate key pair operation.
- *
- * Return value: TRUE if the operation succeeded.
- **/
-gboolean
-gck_session_generate_key_pair_finish (GckSession *self, GAsyncResult *result,
- GckObject **public_key, GckObject **private_key,
- GError **error)
-{
- GenerateKeyPair *args;
-
- g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
- g_return_val_if_fail (public_key, FALSE);
- g_return_val_if_fail (private_key, FALSE);
-
- args = _gck_call_arguments (result, GenerateKeyPair);
- _gck_attributes_unlock (args->public_attrs);
- if (args->public_attrs != args->private_attrs)
- _gck_attributes_unlock (args->private_attrs);
-
- if (!_gck_call_basic_finish (result, error))
- return FALSE;
-
- *public_key = gck_object_from_handle (self, args->public_key);
- *private_key = gck_object_from_handle (self, args->private_key);
- return TRUE;
-}
-
-/* -----------------------------------------------------------------------------
- * KEY WRAPPING
- */
-
-typedef struct _WrapKey {
- GckArguments base;
- GckMechanism mechanism;
- CK_OBJECT_HANDLE wrapper;
- CK_OBJECT_HANDLE wrapped;
- gpointer result;
- gulong n_result;
-} WrapKey;
-
-static void
-free_wrap_key (WrapKey *args)
-{
- g_free (args->result);
- g_free (args);
-}
-
-static CK_RV
-perform_wrap_key (WrapKey *args)
-{
- CK_RV rv;
-
- g_assert (sizeof (CK_MECHANISM) == sizeof (GckMechanism));
-
- /* Get the length of the result */
- rv = (args->base.pkcs11->C_WrapKey) (args->base.handle,
- (CK_MECHANISM_PTR)&(args->mechanism),
- args->wrapper, args->wrapped,
- NULL, &args->n_result);
- if (rv != CKR_OK)
- return rv;
-
- /* And try again with a real buffer */
- args->result = g_malloc0 (args->n_result);
- return (args->base.pkcs11->C_WrapKey) (args->base.handle,
- (CK_MECHANISM_PTR)&(args->mechanism),
- args->wrapper, args->wrapped,
- args->result, &args->n_result);
-}
-
-/**
- * gck_session_wrap_key:
- * @self: The session to use.
- * @wrapper: The key to use for wrapping.
- * @mech_type: The mechanism type to use for wrapping.
- * @wrapped: The key to wrap.
- * @n_result: A location in which to return the length of the wrapped data.
- * @cancellable: A #GCancellable or %NULL
- * @error: A location to return an error, or NULL.
- *
- * Wrap a key into a byte stream. This call may block for an
- * indefinite period.
- *
- * Returns: (transfer full) (array length=n_result): the wrapped data or %NULL
- * if the operation failed
- **/
-guchar *
-gck_session_wrap_key (GckSession *self, GckObject *key, gulong mech_type,
- GckObject *wrapped, gsize *n_result, GCancellable *cancellable, GError **error)
-{
- GckMechanism mech = { mech_type, NULL, 0 };
- return gck_session_wrap_key_full (self, key, &mech, wrapped, n_result, cancellable, error);
-}
-
-/**
- * gck_session_wrap_key_full:
- * @self: The session to use.
- * @wrapper: The key to use for wrapping.
- * @mechanism: The mechanism to use for wrapping.
- * @wrapped: The key to wrap.
- * @n_result: A location in which to return the length of the wrapped data.
- * @cancellable: Optional cancellation object, or NULL.
- * @error: A location to return an error, or NULL.
- *
- * Wrap a key into a byte stream. This call may block for an
- * indefinite period.
- *
- * Returns: (transfer full) (array length=n_result): the wrapped data or %NULL
- * if the operation failed
- **/
-guchar *
-gck_session_wrap_key_full (GckSession *self, GckObject *wrapper, GckMechanism *mechanism,
- GckObject *wrapped, gsize *n_result, GCancellable *cancellable,
- GError **error)
-{
- WrapKey args = { GCK_ARGUMENTS_INIT, GCK_MECHANISM_EMPTY, 0, 0, NULL, 0 };
- gboolean ret;
-
- g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
- g_return_val_if_fail (mechanism, FALSE);
- g_return_val_if_fail (GCK_IS_OBJECT (wrapped), FALSE);
- g_return_val_if_fail (GCK_IS_OBJECT (wrapper), FALSE);
- g_return_val_if_fail (n_result, FALSE);
-
- /* Shallow copy of the mechanism structure */
- memcpy (&args.mechanism, mechanism, sizeof (args.mechanism));
-
- g_object_get (wrapper, "handle", &args.wrapper, NULL);
- g_return_val_if_fail (args.wrapper != 0, NULL);
- g_object_get (wrapped, "handle", &args.wrapped, NULL);
- g_return_val_if_fail (args.wrapped != 0, NULL);
-
- ret = _gck_call_sync (self, perform_wrap_key, NULL, &args, cancellable, error);
-
- if (!ret)
- return FALSE;
-
- *n_result = args.n_result;
- return args.result;
-}
-
-/**
- * gck_session_wrap_key_async:
- * @self: The session to use.
- * @wrapper: The key to use for wrapping.
- * @mechanism: The mechanism to use for wrapping.
- * @wrapped: The key to wrap.
- * @cancellable: Optional cancellation object or NULL.
- * @callback: Called when the operation completes.
- * @user_data: Data to pass to the callback.
- *
- * Wrap a key into a byte stream. This call will
- * return immediately and complete asynchronously.
- **/
-void
-gck_session_wrap_key_async (GckSession *self, GckObject *key, GckMechanism *mechanism,
- GckObject *wrapped, GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer user_data)
-{
- WrapKey *args = _gck_call_async_prep (self, self, perform_wrap_key,
- NULL, sizeof (*args), free_wrap_key);
-
- g_return_if_fail (GCK_IS_SESSION (self));
- g_return_if_fail (mechanism);
- g_return_if_fail (GCK_IS_OBJECT (wrapped));
- g_return_if_fail (GCK_IS_OBJECT (key));
-
- /* Shallow copy of the mechanism structure */
- memcpy (&args->mechanism, mechanism, sizeof (args->mechanism));
-
- g_object_get (key, "handle", &args->wrapper, NULL);
- g_return_if_fail (args->wrapper != 0);
- g_object_get (wrapped, "handle", &args->wrapped, NULL);
- g_return_if_fail (args->wrapped != 0);
-
- _gck_call_async_ready_go (args, cancellable, callback, user_data);
-}
-
-/**
- * gck_session_wrap_key_finish:
- * @self: The session to use.
- * @result: The async result passed to the callback.
- * @n_result: A location in which to return the length of the wrapped data.
- * @error: A location to return an error.
- *
- * Get the result of a wrap key operation.
- *
- * Returns: (transfer full) (array length=n_result): the wrapped data or %NULL
- * if the operation failed
- **/
-guchar *
-gck_session_wrap_key_finish (GckSession *self, GAsyncResult *result,
- gsize *n_result, GError **error)
-{
- WrapKey *args;
- gpointer ret;
-
- g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
- g_return_val_if_fail (n_result, NULL);
-
- args = _gck_call_arguments (result, WrapKey);
-
- if (!_gck_call_basic_finish (result, error))
- return NULL;
-
- *n_result = args->n_result;
- args->n_result = 0;
- ret = args->result;
- args->result = NULL;
-
- return ret;
-}
-
-/* -----------------------------------------------------------------------------
- * KEY UNWRAPPING
- */
-
-typedef struct _UnwrapKey {
- GckArguments base;
- GckMechanism mechanism;
- GckAttributes *attrs;
- CK_OBJECT_HANDLE wrapper;
- gconstpointer input;
- gulong n_input;
- CK_OBJECT_HANDLE unwrapped;
-} UnwrapKey;
-
-static void
-free_unwrap_key (UnwrapKey *args)
-{
- gck_attributes_unref (args->attrs);
- g_free (args);
-}
-
-static CK_RV
-perform_unwrap_key (UnwrapKey *args)
-{
- CK_ATTRIBUTE_PTR attrs;
- CK_ULONG n_attrs;
-
- g_assert (sizeof (CK_MECHANISM) == sizeof (GckMechanism));
-
- attrs = _gck_attributes_commit_out (args->attrs, &n_attrs);
-
- return (args->base.pkcs11->C_UnwrapKey) (args->base.handle,
- (CK_MECHANISM_PTR)&(args->mechanism),
- args->wrapper, (CK_BYTE_PTR)args->input,
- args->n_input, attrs, n_attrs,
- &args->unwrapped);
-}
-
-/**
- * gck_session_unwrap_key:
- * @self: The session to use.
- * @wrapper: The key to use for unwrapping.
- * @mech_type: The mechanism to use for unwrapping.
- * @input: (array length=n_input): the wrapped data as a byte stream
- * @n_input: The length of the wrapped data.
- * @attrs: Additional attributes for the unwrapped key.
- * @cancellable: Optional cancellation object, or NULL.
- * @error: A location to return an error, or NULL.
- *
- * Unwrap a key from a byte stream. This call may block for an
- * indefinite period.
- *
- * Returns: (transfer full): the new unwrapped key or NULL if the
- * operation failed
- **/
-GckObject *
-gck_session_unwrap_key (GckSession *self,
- GckObject *wrapper,
- gulong mech_type,
- const guchar *input,
- gsize n_input,
- GckAttributes *attrs,
- GCancellable *cancellable,
- GError **error)
-{
- GckMechanism mech = { mech_type, NULL, 0 };
- return gck_session_unwrap_key_full (self, wrapper, &mech, input, n_input, attrs, cancellable, error);
-}
-
-/**
- * gck_session_unwrap_key_full:
- * @self: The session to use.
- * @wrapper: The key to use for unwrapping.
- * @mechanism: The mechanism to use for unwrapping.
- * @input: (array length=n_input): the wrapped data as a byte stream
- * @n_input: The length of the wrapped data.
- * @attrs: Additional attributes for the unwrapped key.
- * @cancellable: Optional cancellation object, or NULL.
- * @error: A location to return an error, or NULL.
- *
- * Unwrap a key from a byte stream. This call may block for an
- * indefinite period.
- *
- * Returns: (transfer full): the new unwrapped key or NULL if the operation
- * failed
- **/
-GckObject *
-gck_session_unwrap_key_full (GckSession *self,
- GckObject *wrapper,
- GckMechanism *mechanism,
- const guchar *input,
- gsize n_input,
- GckAttributes *attrs,
- GCancellable *cancellable,
- GError **error)
-{
- UnwrapKey args = { GCK_ARGUMENTS_INIT, GCK_MECHANISM_EMPTY, attrs, 0, input, n_input, 0 };
- gboolean ret;
-
- g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
- g_return_val_if_fail (GCK_IS_OBJECT (wrapper), FALSE);
- g_return_val_if_fail (mechanism, FALSE);
- g_return_val_if_fail (attrs, FALSE);
-
- /* Shallow copy of the mechanism structure */
- memcpy (&args.mechanism, mechanism, sizeof (args.mechanism));
-
- g_object_get (wrapper, "handle", &args.wrapper, NULL);
- g_return_val_if_fail (args.wrapper != 0, NULL);
-
- _gck_attributes_lock (attrs);
- ret = _gck_call_sync (self, perform_unwrap_key, NULL, &args, cancellable, error);
- _gck_attributes_unlock (attrs);
-
- if (!ret)
- return NULL;
-
- return gck_object_from_handle (self, args.unwrapped);
-}
-
-/**
- * gck_session_unwrap_key_async:
- * @self: The session to use.
- * @wrapper: The key to use for unwrapping.
- * @mechanism: The mechanism to use for unwrapping.
- * @input: (array length=n_input): the wrapped data as a byte stream
- * @n_input: The length of the wrapped data.
- * @attrs: Additional attributes for the unwrapped key.
- * @cancellable: Optional cancellation object or NULL.
- * @callback: Called when the operation completes.
- * @user_data: Data to pass to the callback.
- *
- * Unwrap a key from a byte stream. This call will
- * return immediately and complete asynchronously.
- **/
-void
-gck_session_unwrap_key_async (GckSession *self,
- GckObject *wrapper,
- GckMechanism *mechanism,
- const guchar *input,
- gsize n_input,
- GckAttributes *attrs,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- UnwrapKey *args = _gck_call_async_prep (self, self, perform_unwrap_key,
- NULL, sizeof (*args), free_unwrap_key);
-
- g_return_if_fail (GCK_IS_SESSION (self));
- g_return_if_fail (GCK_IS_OBJECT (wrapper));
- g_return_if_fail (attrs);
-
- g_object_get (wrapper, "handle", &args->wrapper, NULL);
- g_return_if_fail (args->wrapper != 0);
-
- /* Shallow copy of the mechanism structure */
- memcpy (&args->mechanism, mechanism, sizeof (args->mechanism));
-
- args->attrs = gck_attributes_ref (attrs);
- args->input = input;
- args->n_input = n_input;
- _gck_attributes_lock (attrs);
-
- _gck_call_async_ready_go (args, cancellable, callback, user_data);
-}
-
-/**
- * gck_session_unwrap_key_finish:
- * @self: The session to use.
- * @result: The async result passed to the callback.
- * @error: A location to return an error.
- *
- * Get the result of a unwrap key operation.
- *
- * Returns: (transfer full): the new unwrapped key or %NULL if the operation
- * failed.
- **/
-GckObject *
-gck_session_unwrap_key_finish (GckSession *self, GAsyncResult *result, GError **error)
-{
- UnwrapKey *args;
-
- g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
-
- args = _gck_call_arguments (result, UnwrapKey);
- _gck_attributes_unlock (args->attrs);
-
- if (!_gck_call_basic_finish (result, error))
- return NULL;
- return gck_object_from_handle (self, args->unwrapped);
-}
-
-/* -----------------------------------------------------------------------------
- * KEY DERIVATION
- */
-
-typedef struct _DeriveKey {
- GckArguments base;
- GckMechanism mechanism;
- GckAttributes *attrs;
- CK_OBJECT_HANDLE key;
- CK_OBJECT_HANDLE derived;
-} DeriveKey;
-
-static void
-free_derive_key (DeriveKey *args)
-{
- gck_attributes_unref (args->attrs);
- g_free (args);
-}
-
-static CK_RV
-perform_derive_key (DeriveKey *args)
-{
- CK_ATTRIBUTE_PTR attrs;
- CK_ULONG n_attrs;
-
- g_assert (sizeof (CK_MECHANISM) == sizeof (GckMechanism));
-
- attrs = _gck_attributes_commit_out (args->attrs, &n_attrs);
-
- return (args->base.pkcs11->C_DeriveKey) (args->base.handle,
- (CK_MECHANISM_PTR)&(args->mechanism),
- args->key, attrs, n_attrs,
- &args->derived);
-}
-
-/**
- * gck_session_derive_key:
- * @self: The session to use.
- * @base: The key to derive from.
- * @mech_type: The mechanism to use for derivation.
- * @attrs: Additional attributes for the derived key.
- * @cancellable: Optional cancellation object, or NULL.
- * @error: A location to return an error, or NULL.
- *
- * Derive a key from another key. This call may block for an
- * indefinite period.
- *
- * Returns: (transfer full): the new derived key or NULL if the operation
- * failed
- **/
-GckObject *
-gck_session_derive_key (GckSession *self, GckObject *base, gulong mech_type,
- GckAttributes *attrs, GCancellable *cancellable, GError **error)
-{
- GckMechanism mech = { mech_type, NULL, 0 };
- return gck_session_derive_key_full (self, base, &mech, attrs, cancellable, error);
-}
-
-/**
- * gck_session_derive_key_full:
- * @self: The session to use.
- * @base: The key to derive from.
- * @mechanism: The mechanism to use for derivation.
- * @attrs: Additional attributes for the derived key.
- * @cancellable: Optional cancellation object, or NULL.
- * @error: A location to return an error, or NULL.
- *
- * Derive a key from another key. This call may block for an
- * indefinite period.
- *
- * Returns: (transfer full): the new derived key or NULL if the operation
- * failed
- **/
-GckObject*
-gck_session_derive_key_full (GckSession *self, GckObject *base, GckMechanism *mechanism,
- GckAttributes *attrs, GCancellable *cancellable, GError **error)
-{
- DeriveKey args = { GCK_ARGUMENTS_INIT, GCK_MECHANISM_EMPTY, attrs, 0, 0 };
- gboolean ret;
-
- g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
- g_return_val_if_fail (GCK_IS_OBJECT (base), FALSE);
- g_return_val_if_fail (mechanism, FALSE);
- g_return_val_if_fail (attrs, FALSE);
-
- /* Shallow copy of the mechanism structure */
- memcpy (&args.mechanism, mechanism, sizeof (args.mechanism));
-
- g_object_get (base, "handle", &args.key, NULL);
- g_return_val_if_fail (args.key != 0, NULL);
-
- _gck_attributes_lock (attrs);
- ret = _gck_call_sync (self, perform_derive_key, NULL, &args, cancellable, error);
- _gck_attributes_unlock (attrs);
-
- if (!ret)
- return NULL;
-
- return gck_object_from_handle (self, args.derived);
-}
-
-/**
- * gck_session_derive_key_async:
- * @self: The session to use.
- * @base: The key to derive from.
- * @mechanism: The mechanism to use for derivation.
- * @attrs: Additional attributes for the derived key.
- * @cancellable: Optional cancellation object or NULL.
- * @callback: Called when the operation completes.
- * @user_data: Data to pass to the callback.
- *
- * Derive a key from another key. This call will
- * return immediately and complete asynchronously.
- **/
-void
-gck_session_derive_key_async (GckSession *self, GckObject *base, GckMechanism *mechanism,
- GckAttributes *attrs, GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer user_data)
-{
- DeriveKey *args = _gck_call_async_prep (self, self, perform_derive_key,
- NULL, sizeof (*args), free_derive_key);
-
- g_return_if_fail (GCK_IS_SESSION (self));
- g_return_if_fail (GCK_IS_OBJECT (base));
- g_return_if_fail (attrs);
-
- g_object_get (base, "handle", &args->key, NULL);
- g_return_if_fail (args->key != 0);
-
- /* Shallow copy of the mechanism structure */
- memcpy (&args->mechanism, mechanism, sizeof (args->mechanism));
-
- args->attrs = gck_attributes_ref (attrs);
- _gck_attributes_lock (attrs);
-
- _gck_call_async_ready_go (args, cancellable, callback, user_data);
-}
-
-/**
- * gck_session_derive_key_finish:
- * @self: The session to use.
- * @result: The async result passed to the callback.
- * @error: A location to return an error.
- *
- * Get the result of a derive key operation.
- *
- * Returns: (transfer full): the new derived key or %NULL if the operation
- * failed
- **/
-GckObject *
-gck_session_derive_key_finish (GckSession *self, GAsyncResult *result, GError **error)
-{
- DeriveKey *args;
-
- g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
-
- args = _gck_call_arguments (result, DeriveKey);
- _gck_attributes_unlock (args->attrs);
-
- if (!_gck_call_basic_finish (result, error))
- return NULL;
-
- return gck_object_from_handle (self, args->derived);
-}
-
-/* --------------------------------------------------------------------------------------------------
- * COMMON CRYPTO ROUTINES
- */
-
-typedef struct _Crypt {
- GckArguments base;
-
- /* Functions to call */
- CK_C_EncryptInit init_func;
- CK_C_Encrypt complete_func;
-
- /* Interaction */
- GckObject *key_object;
- GTlsInteraction *interaction;
-
- /* Input */
- CK_OBJECT_HANDLE key;
- GckMechanism mechanism;
- guchar *input;
- CK_ULONG n_input;
-
- /* Output */
- guchar *result;
- CK_ULONG n_result;
-
-} Crypt;
-
-static CK_RV
-perform_crypt (Crypt *args)
-{
- GTlsInteraction *interaction;
- CK_RV rv;
-
- g_assert (args);
- g_assert (args->init_func);
- g_assert (args->complete_func);
- g_assert (!args->result);
- g_assert (!args->n_result);
-
- /* Initialize the crypt operation */
- rv = (args->init_func) (args->base.handle, (CK_MECHANISM_PTR)&(args->mechanism), args->key);
- if (rv != CKR_OK)
- return rv;
-
- /* Compatibility, hook into GckModule signals if no interaction set */
- if (args->interaction)
- interaction = g_object_ref (args->interaction);
- else
- interaction = _gck_interaction_new (args->key_object);
-
- rv = _gck_session_authenticate_key (args->base.pkcs11, args->base.handle,
- args->key_object, interaction, NULL);
-
- g_object_unref (interaction);
-
- if (rv != CKR_OK)
- return rv;
-
- /* Get the length of the result */
- rv = (args->complete_func) (args->base.handle, args->input, args->n_input, NULL, &args->n_result);
- if (rv != CKR_OK)
- return rv;
-
- /* And try again with a real buffer */
- args->result = g_malloc0 (args->n_result);
- return (args->complete_func) (args->base.handle, args->input, args->n_input, args->result, &args->n_result);
-}
-
-static void
-free_crypt (Crypt *args)
-{
- g_clear_object (&args->interaction);
- g_clear_object (&args->key_object);
-
- g_free (args->input);
- g_free (args->result);
- g_free (args);
-}
-
-static guchar*
-crypt_sync (GckSession *self, GckObject *key, GckMechanism *mechanism, const guchar *input,
- gsize n_input, gsize *n_result, GCancellable *cancellable, GError **error,
- CK_C_EncryptInit init_func, CK_C_Encrypt complete_func)
-{
- Crypt args;
-
- g_return_val_if_fail (GCK_IS_OBJECT (key), NULL);
- g_return_val_if_fail (mechanism, NULL);
- g_return_val_if_fail (init_func, NULL);
- g_return_val_if_fail (complete_func, NULL);
-
- memset (&args, 0, sizeof (args));
- g_object_get (key, "handle", &args.key, NULL);
- g_return_val_if_fail (args.key != 0, NULL);
-
- /* Shallow copy of the mechanism structure */
- memcpy (&args.mechanism, mechanism, sizeof (args.mechanism));
-
- /* No need to copy in this case */
- args.input = (guchar*)input;
- args.n_input = n_input;
-
- args.init_func = init_func;
- args.complete_func = complete_func;
-
- args.key_object = key;
- args.interaction = self->pv->interaction;
-
- if (!_gck_call_sync (self, perform_crypt, NULL, &args, cancellable, error)) {
- g_free (args.result);
- return NULL;
- }
-
- *n_result = args.n_result;
- return args.result;
-}
-
-static void
-crypt_async (GckSession *self, GckObject *key, GckMechanism *mechanism, const guchar *input,
- gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data,
- CK_C_EncryptInit init_func, CK_C_Encrypt complete_func)
-{
- Crypt *args = _gck_call_async_prep (self, self, perform_crypt, NULL, sizeof (*args), free_crypt);
-
- g_return_if_fail (GCK_IS_OBJECT (key));
- g_return_if_fail (mechanism);
- g_return_if_fail (init_func);
- g_return_if_fail (complete_func);
-
- g_object_get (key, "handle", &args->key, NULL);
- g_return_if_fail (args->key != 0);
-
- /* Shallow copy of the mechanism structure */
- memcpy (&args->mechanism, mechanism, sizeof (args->mechanism));
-
- args->input = input && n_input ? g_memdup (input, n_input) : NULL;
- args->n_input = n_input;
-
- args->init_func = init_func;
- args->complete_func = complete_func;
-
- args->key_object = g_object_ref (key);
- args->interaction = gck_session_get_interaction (self);
-
- _gck_call_async_ready_go (args, cancellable, callback, user_data);
-}
-
-static guchar*
-crypt_finish (GckSession *self, GAsyncResult *result, gsize *n_result, GError **error)
-{
- Crypt *args;
- guchar *res;
-
- if (!_gck_call_basic_finish (result, error))
- return NULL;
- args = _gck_call_arguments (result, Crypt);
-
- /* Steal the values from the results */
- res = args->result;
- args->result = NULL;
- *n_result = args->n_result;
- args->n_result = 0;
-
- return res;
-}
-
-/* --------------------------------------------------------------------------------------------------
- * ENCRYPT
- */
-
-/**
- * gck_session_encrypt:
- * @self: The session.
- * @key: The key to encrypt with.
- * @mech_type: The mechanism type to use for encryption.
- * @input: The data to encrypt.
- * @n_input: The length of the data to encrypt.
- * @n_result: A location to store the length of the result data.
- * @cancellable: Optional cancellation object, or %NULL
- * @error: A location to place error information.
- *
- * Encrypt data in a mechanism specific manner. This call may
- * block for an indefinite period.
- *
- * Returns: (transfer full) (array length=n_result): the data that was encrypted,
- * or %NULL if an error occured.
- */
-guchar *
-gck_session_encrypt (GckSession *self, GckObject *key, gulong mech_type, const guchar *input,
- gsize n_input, gsize *n_result, GCancellable *cancellable, GError **error)
-{
- GckMechanism mechanism = { mech_type, NULL, 0 };
- return gck_session_encrypt_full (self, key, &mechanism, input, n_input, n_result, cancellable, error);
-}
-
-/**
- * gck_session_encrypt_full:
- * @self: The session.
- * @key: The key to encrypt with.
- * @mechanism: The mechanism type and parameters to use for encryption.
- * @input: The data to encrypt.
- * @n_input: The length of the data to encrypt.
- * @n_result: A location to store the length of the result data.
- * @cancellable: A GCancellable which can be used to cancel the operation.
- * @error: A location to place error information.
- *
- * Encrypt data in a mechanism specific manner. This call may
- * block for an indefinite period.
- *
- * Returns: (transfer full) (array length=n_result): the data that was encrypted,
- * or %NULL if an error occured
- */
-guchar *
-gck_session_encrypt_full (GckSession *self, GckObject *key, GckMechanism *mechanism,
- const guchar *input, gsize n_input, gsize *n_result,
- GCancellable *cancellable, GError **error)
-{
- GckModule *module = NULL;
- CK_FUNCTION_LIST_PTR funcs;
- guchar *ret;
-
- g_object_get (self, "module", &module, NULL);
- g_return_val_if_fail (module != NULL, NULL);
-
- funcs = gck_module_get_functions (module);
- g_return_val_if_fail (module != NULL, NULL);
-
- ret = crypt_sync (self, key, mechanism, input, n_input, n_result, cancellable, error,
- funcs->C_EncryptInit, funcs->C_Encrypt);
-
- g_object_unref (module);
- return ret;
-}
-
-/**
- * gck_session_encrypt_async:
- * @self: The session.
- * @key: The key to encrypt with.
- * @mechanism: The mechanism type and parameters to use for encryption.
- * @input: The data to encrypt.
- * @n_input: The length of the data to encrypt.
- * @cancellable: A GCancellable which can be used to cancel the operation.
- * @callback: Called when the operation completes.
- * @user_data: A pointer to pass to the callback.
- *
- * Encrypt data in a mechanism specific manner. This call will
- * return immediately and complete asynchronously.
- **/
-void
-gck_session_encrypt_async (GckSession *self, GckObject *key, GckMechanism *mechanism,
- const guchar *input, gsize n_input, GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer user_data)
-{
- GckModule *module = NULL;
- CK_FUNCTION_LIST_PTR funcs;
-
- g_object_get (self, "module", &module, NULL);
- g_return_if_fail (module != NULL);
-
- funcs = gck_module_get_functions (module);
- g_return_if_fail (module != NULL);
-
- crypt_async (self, key, mechanism, input, n_input, cancellable, callback, user_data,
- funcs->C_EncryptInit, funcs->C_Encrypt);
-
- g_object_unref (module);
-}
-
-/**
- * gck_session_encrypt_finish:
- * @self: The session.
- * @result: The result object passed to the callback.
- * @n_result: A location to store the length of the result data.
- * @error: A location to place error information.
- *
- * Get the result of an encryption operation.
- *
- * Returns: (transfer full) (array length=n_result): the data that was encrypted,
- * or %NULL if an error occurred.
- */
-guchar*
-gck_session_encrypt_finish (GckSession *self, GAsyncResult *result, gsize *n_result,
- GError **error)
-{
- return crypt_finish (self, result, n_result, error);
-}
-
-/* --------------------------------------------------------------------------------------------------
- * DECRYPT
- */
-
-/**
- * gck_session_decrypt:
- * @self: The session.
- * @key: The key to decrypt with.
- * @mech_type: The mechanism type to use for decryption.
- * @input: The data to decrypt.
- * @n_input: The length of the data to decrypt.
- * @n_result: A location to store the length of the result data.
- * @cancellable: Optional cancellation object, or %NULL
- * @error: A location to place an error.
- *
- * Decrypt data in a mechanism specific manner. This call may
- * block for an indefinite period.
- *
- * Returns: (transfer full) (array length=n_result): the data that was decrypted,
- * or NULL if an error occured
- */
-guchar *
-gck_session_decrypt (GckSession *self, GckObject *key, gulong mech_type, const guchar *input,
- gsize n_input, gsize *n_result, GCancellable *cancellable, GError **error)
-{
- GckMechanism mechanism = { mech_type, NULL, 0 };
- return gck_session_decrypt_full (self, key, &mechanism, input, n_input, n_result, cancellable, error);
-}
-
-/**
- * gck_session_decrypt_full:
- * @self: The session.
- * @key: The key to decrypt with.
- * @mechanism: The mechanism type and parameters to use for decryption.
- * @input: The data to decrypt.
- * @n_input: The length of the data to decrypt.
- * @n_result: A location to store the length of the result data.
- * @cancellable: A GCancellable which can be used to cancel the operation.
- * @error: A location to place error information.
- *
- * Decrypt data in a mechanism specific manner. This call may
- * block for an indefinite period.
- *
- * Returns: (transfer full) (array length=n_result): the data that was decrypted,
- * or %NULL if an error occured
- */
-guchar *
-gck_session_decrypt_full (GckSession *self, GckObject *key, GckMechanism *mechanism,
- const guchar *input, gsize n_input, gsize *n_result,
- GCancellable *cancellable, GError **error)
-{
- GckModule *module = NULL;
- CK_FUNCTION_LIST_PTR funcs;
- guchar *ret;
-
- g_object_get (self, "module", &module, NULL);
- g_return_val_if_fail (module != NULL, NULL);
-
- funcs = gck_module_get_functions (module);
- g_return_val_if_fail (module != NULL, NULL);
-
- ret = crypt_sync (self, key, mechanism, input, n_input, n_result, cancellable, error,
- funcs->C_DecryptInit, funcs->C_Decrypt);
- g_object_unref (module);
- return ret;
-}
-
-/**
- * gck_session_decrypt_async:
- * @self: The session.
- * @key: The key to decrypt with.
- * @mechanism: The mechanism type and parameters to use for decryption.
- * @input: The data to decrypt.
- * @n_input: The length of the data to decrypt.
- * @cancellable: A GCancellable which can be used to cancel the operation.
- * @callback: Called when the operation completes.
- * @user_data: A pointer to pass to the callback.
- *
- * Decrypt data in a mechanism specific manner. This call will
- * return immediately and complete asynchronously.
- */
-void
-gck_session_decrypt_async (GckSession *self, GckObject *key, GckMechanism *mechanism,
- const guchar *input, gsize n_input, GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer user_data)
-{
- GckModule *module = NULL;
- CK_FUNCTION_LIST_PTR funcs;
-
- g_object_get (self, "module", &module, NULL);
- g_return_if_fail (module != NULL);
-
- funcs = gck_module_get_functions (module);
- g_return_if_fail (module != NULL);
-
- crypt_async (self, key, mechanism, input, n_input, cancellable, callback, user_data,
- funcs->C_DecryptInit, funcs->C_Decrypt);
- g_object_unref (module);
-}
-
-/**
- * gck_session_decrypt_finish:
- * @self: The session.
- * @result: The result object passed to the callback.
- * @n_result: A location to store the length of the result data.
- * @error: A location to place error information.
- *
- * Get the result of an decryption operation.
- *
- * Returns: (transfer full) (array length=n_result): the data that was decrypted,
- * or NULL if an error occurred
- */
-guchar*
-gck_session_decrypt_finish (GckSession *self, GAsyncResult *result,
- gsize *n_result, GError **error)
-{
- return crypt_finish (self, result, n_result, error);
-}
-
-/* --------------------------------------------------------------------------------------------------
- * SIGN
- */
-
-/**
- * gck_session_sign:
- * @self: The session.
- * @key: The key to sign with.
- * @mech_type: The mechanism type to use for signing.
- * @input: The data to sign.
- * @n_input: The length of the data to sign.
- * @n_result: A location to store the length of the result data.
- * @cancellable: Optional cancellation object, or %NULL
- * @error: A location to place an error.
- *
- * Sign data in a mechanism specific manner. This call may
- * block for an indefinite period.
- *
- * Returns: (transfer full) (array length=n_result): the data that was signed,
- * or %NULL if an error occured
- */
-guchar *
-gck_session_sign (GckSession *self, GckObject *key, gulong mech_type, const guchar *input,
- gsize n_input, gsize *n_result, GCancellable *cancellable, GError **error)
-{
- GckMechanism mechanism = { mech_type, NULL, 0 };
- return gck_session_sign_full (self, key, &mechanism, input, n_input, n_result, NULL, error);
-}
-
-/**
- * gck_session_sign_full:
- * @self: The session.
- * @key: The key to sign with.
- * @mechanism: The mechanism type and parameters to use for signing.
- * @input: The data to sign.
- * @n_input: The length of the data to sign.
- * @n_result: A location to store the length of the result data.
- * @cancellable: A GCancellable which can be used to cancel the operation.
- * @error: A location to place error information.
- *
- * Sign data in a mechanism specific manner. This call may
- * block for an indefinite period.
- *
- * Returns: The data that was signed, or NULL if an error occured.
- */
-guchar*
-gck_session_sign_full (GckSession *self, GckObject *key, GckMechanism *mechanism,
- const guchar *input, gsize n_input, gsize *n_result,
- GCancellable *cancellable, GError **error)
-{
- GckModule *module = NULL;
- CK_FUNCTION_LIST_PTR funcs;
- guchar *ret;
-
- g_object_get (self, "module", &module, NULL);
- g_return_val_if_fail (module != NULL, NULL);
-
- funcs = gck_module_get_functions (module);
- g_return_val_if_fail (module != NULL, NULL);
-
- ret = crypt_sync (self, key, mechanism, input, n_input, n_result, cancellable, error,
- funcs->C_SignInit, funcs->C_Sign);
- g_object_unref (module);
- return ret;
-}
-
-/**
- * gck_session_sign_async:
- * @self: The session.
- * @key: The key to sign with.
- * @mechanism: The mechanism type and parameters to use for signing.
- * @input: The data to sign.
- * @n_input: The length of the data to sign.
- * @cancellable: A GCancellable which can be used to cancel the operation.
- * @callback: Called when the operation completes.
- * @user_data: A pointer to pass to the callback.
- *
- * Sign data in a mechanism specific manner. This call will
- * return immediately and complete asynchronously.
- */
-void
-gck_session_sign_async (GckSession *self, GckObject *key, GckMechanism *mechanism,
- const guchar *input, gsize n_input, GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer user_data)
-{
- GckModule *module = NULL;
- CK_FUNCTION_LIST_PTR funcs;
-
- g_object_get (self, "module", &module, NULL);
- g_return_if_fail (module != NULL);
-
- funcs = gck_module_get_functions (module);
- g_return_if_fail (module != NULL);
-
- crypt_async (self, key, mechanism, input, n_input, cancellable, callback, user_data,
- funcs->C_SignInit, funcs->C_Sign);
- g_object_unref (module);
-}
-
-/**
- * gck_session_sign_finish:
- * @self: The session.
- * @result: The result object passed to the callback.
- * @n_result: A location to store the length of the result data.
- * @error: A location to place error information.
- *
- * Get the result of an signing operation.
- *
- * Returns: (transfer full) (array length=n_result): the data that was signed,
- * or %NULL if an error occurred
- */
-guchar *
-gck_session_sign_finish (GckSession *self, GAsyncResult *result,
- gsize *n_result, GError **error)
-{
- return crypt_finish (self, result, n_result, error);
-}
-
-/* --------------------------------------------------------------------------------------------------
- * VERIFY
- */
-
-typedef struct _Verify {
- GckArguments base;
-
- /* Interaction */
- GckObject *key_object;
- GTlsInteraction *interaction;
-
- /* Input */
- CK_OBJECT_HANDLE key;
- GckMechanism mechanism;
- guchar *input;
- CK_ULONG n_input;
- guchar *signature;
- CK_ULONG n_signature;
-
-} Verify;
-
-static CK_RV
-perform_verify (Verify *args)
-{
- GTlsInteraction *interaction;
- CK_RV rv;
-
- /* Initialize the crypt operation */
- rv = (args->base.pkcs11->C_VerifyInit) (args->base.handle, (CK_MECHANISM_PTR)&(args->mechanism), args->key);
- if (rv != CKR_OK)
- return rv;
-
- /* Compatibility, hook into GckModule signals if no interaction set */
- if (args->interaction)
- interaction = g_object_ref (args->interaction);
- else
- interaction = _gck_interaction_new (args->key_object);
-
-
- rv = _gck_session_authenticate_key (args->base.pkcs11, args->base.handle,
- args->key_object, interaction, NULL);
-
- g_object_unref (interaction);
-
- if (rv != CKR_OK)
- return rv;
-
- /* Do the actual verify */
- return (args->base.pkcs11->C_Verify) (args->base.handle, args->input, args->n_input,
- args->signature, args->n_signature);
-}
-
-static void
-free_verify (Verify *args)
-{
- g_clear_object (&args->interaction);
- g_clear_object (&args->key_object);
-
- g_free (args->input);
- g_free (args->signature);
- g_free (args);
-}
-
-/**
- * gck_session_verify:
- * @self: The session.
- * @key: The key to verify with.
- * @mech_type: The mechanism type to use for verifying.
- * @input: The data to verify.
- * @n_input: The length of the data to verify.
- * @signature: The signature.
- * @n_signature: The length of the signature.
- * @cancellable: Optional cancellation object, or %NULL
- * @error: A location to place an error.
- *
- * Verify data in a mechanism specific manner. This call may
- * block for an indefinite period.
- *
- * Returns: TRUE if the data verified correctly, otherwise a failure or error occurred.
- */
-gboolean
-gck_session_verify (GckSession *self, GckObject *key, gulong mech_type, const guchar *input,
- gsize n_input, const guchar *signature, gsize n_signature, GCancellable *cancellable, GError **error)
-{
- GckMechanism mechanism = { mech_type, NULL, 0 };
- return gck_session_verify_full (self, key, &mechanism, input, n_input,
- signature, n_signature, NULL, error);
-}
-
-/**
- * gck_session_verify_full:
- * @self: The session.
- * @key: The key to verify with.
- * @mechanism: The mechanism type and parameters to use for signing.
- * @input: The data to verify.
- * @n_input: The length of the data to verify.
- * @signature: The signature.
- * @n_signature: The length of the signature.
- * @cancellable: A GCancellable which can be used to cancel the operation.
- * @error: A location to place an error.
- *
- * Verify data in a mechanism specific manner. This call may
- * block for an indefinite period.
- *
- * Returns: TRUE if the data verified correctly, otherwise a failure or error occurred.
- */
-gboolean
-gck_session_verify_full (GckSession *self, GckObject *key, GckMechanism *mechanism,
- const guchar *input, gsize n_input, const guchar *signature,
- gsize n_signature, GCancellable *cancellable, GError **error)
-{
- Verify args;
-
- g_return_val_if_fail (GCK_IS_OBJECT (key), FALSE);
- g_return_val_if_fail (mechanism, FALSE);
-
- memset (&args, 0, sizeof (args));
- g_object_get (key, "handle", &args.key, NULL);
- g_return_val_if_fail (args.key != 0, FALSE);
-
- /* Shallow copy of the mechanism structure */
- memcpy (&args.mechanism, mechanism, sizeof (args.mechanism));
-
- /* No need to copy in this case */
- args.input = (guchar*)input;
- args.n_input = n_input;
- args.signature = (guchar*)signature;
- args.n_signature = n_signature;
-
- args.key_object = key;
- args.interaction = self->pv->interaction;
-
- return _gck_call_sync (self, perform_verify, NULL, &args, cancellable, error);
-}
-
-/**
- * gck_session_verify_async:
- * @self: The session.
- * @key: The key to verify with.
- * @mechanism: The mechanism type and parameters to use for signing.
- * @input: The data to verify.
- * @n_input: The length of the data to verify.
- * @signature: The signature.
- * @n_signature: The length of the signature.
- * @cancellable: A GCancellable which can be used to cancel the operation.
- * @callback: Called when the operation completes.
- * @user_data: A pointer to pass to the callback.
- *
- * Verify data in a mechanism specific manner. This call returns
- * immediately and completes asynchronously.
- */
-void
-gck_session_verify_async (GckSession *self, GckObject *key, GckMechanism *mechanism,
- const guchar *input, gsize n_input, const guchar *signature,
- gsize n_signature, GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer user_data)
-{
- Verify *args = _gck_call_async_prep (self, self, perform_verify, NULL, sizeof (*args), free_verify);
-
- g_return_if_fail (GCK_IS_OBJECT (key));
- g_return_if_fail (mechanism);
-
- g_object_get (key, "handle", &args->key, NULL);
- g_return_if_fail (args->key != 0);
-
- /* Shallow copy of the mechanism structure */
- memcpy (&args->mechanism, mechanism, sizeof (args->mechanism));
-
- args->input = input && n_input ? g_memdup (input, n_input) : NULL;
- args->n_input = n_input;
- args->signature = signature && n_signature ? g_memdup (signature, n_signature) : NULL;
- args->n_signature = n_signature;
-
- args->key_object = g_object_ref (key);
- args->interaction = gck_session_get_interaction (self);
-
- _gck_call_async_ready_go (args, cancellable, callback, user_data);
-}
-
-/**
- * gck_session_verify_finish:
- * @self: The session.
- * @result: The result object passed to the callback.
- * @error: A location to place error information.
- *
- * Get the result of an verify operation.
- *
- * Returns: TRUE if the data verified correctly, otherwise a failure or error occurred.
- */
-gboolean
-gck_session_verify_finish (GckSession *self, GAsyncResult *result, GError **error)
-{
- return _gck_call_basic_finish (result, error);
-}
-
-static void
-update_password_for_token (GTlsPassword *password,
- CK_TOKEN_INFO *token_info,
- gboolean request_retry)
-{
- GTlsPasswordFlags flags;
- gchar *label;
-
- label = gck_string_from_chars (token_info->label, sizeof (token_info->label));
- g_tls_password_set_description (password, label);
- g_free (label);
-
- flags = 0;
- if (request_retry)
- flags |= G_TLS_PASSWORD_RETRY;
- if (token_info && token_info->flags & CKF_USER_PIN_COUNT_LOW)
- flags |= G_TLS_PASSWORD_MANY_TRIES;
- if (token_info && token_info->flags & CKF_USER_PIN_FINAL_TRY)
- flags |= G_TLS_PASSWORD_FINAL_TRY;
- g_tls_password_set_flags (password, flags);
-}
-
-CK_RV
-_gck_session_authenticate_token (CK_FUNCTION_LIST_PTR funcs,
- CK_SESSION_HANDLE session,
- GckSlot *token,
- GTlsInteraction *interaction,
- GCancellable *cancellable)
-{
- CK_SESSION_INFO session_info;
- GTlsPassword *password = NULL;
- CK_TOKEN_INFO token_info;
- GTlsInteractionResult res;
- gboolean request_retry;
- CK_SLOT_ID slot_id;
- CK_BYTE_PTR pin;
- CK_ULONG n_pin;
- CK_RV rv = CKR_OK;
- GError *error = NULL;
-
- g_assert (funcs != NULL);
- g_assert (GCK_IS_SLOT (token));
-
- slot_id = gck_slot_get_handle (token);
- request_retry = FALSE;
-
- do {
- if (g_cancellable_is_cancelled (cancellable)) {
- rv = CKR_FUNCTION_CANCELED;
- break;
- }
-
- rv = (funcs->C_GetTokenInfo) (slot_id, &token_info);
- if (rv != CKR_OK) {
- g_warning ("couldn't get token info when logging in: %s",
- gck_message_from_rv (rv));
- break;
- }
-
- /* No login necessary? */
- if ((token_info.flags & CKF_LOGIN_REQUIRED) == 0) {
- _gck_debug ("no login required for token, skipping login");
- rv = CKR_OK;
- break;
- }
-
- /* Next check if session is logged in? */
- rv = (funcs->C_GetSessionInfo) (session, &session_info);
- if (rv != CKR_OK) {
- g_warning ("couldn't get session info when logging in: %s",
- gck_message_from_rv (rv));
- break;
- }
-
- /* Already logged in? */
- if (session_info.state == CKS_RW_USER_FUNCTIONS ||
- session_info.state == CKS_RO_USER_FUNCTIONS ||
- session_info.state == CKS_RW_SO_FUNCTIONS) {
- _gck_debug ("already logged in, skipping login");
- rv = CKR_OK;
- break;
- }
-
- if (token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
- _gck_debug ("trying to log into session: protected authentication path, no password");
-
- /* No password passed for PAP */
- pin = NULL;
- n_pin = 0;
-
-
- /* Not protected auth path */
- } else {
- _gck_debug ("trying to log into session: want password %s",
- request_retry ? "login was incorrect" : "");
-
- if (password == NULL)
- password = g_object_new (GCK_TYPE_PASSWORD, "token", token, NULL);
-
- update_password_for_token (password, &token_info, request_retry);
-
- if (interaction == NULL)
- res = G_TLS_INTERACTION_UNHANDLED;
-
- else
- res = g_tls_interaction_invoke_ask_password (interaction,
- G_TLS_PASSWORD (password),
- NULL, &error);
-
- if (res == G_TLS_INTERACTION_FAILED) {
- g_message ("interaction couldn't ask password: %s", error->message);
- rv = _gck_rv_from_error (error, CKR_USER_NOT_LOGGED_IN);
- g_clear_error (&error);
- break;
-
- } else if (res == G_TLS_INTERACTION_UNHANDLED) {
- g_message ("couldn't authenticate: no interaction handler");
- rv = CKR_USER_NOT_LOGGED_IN;
- break;
- }
-
- pin = (CK_BYTE_PTR)g_tls_password_get_value (password, &n_pin);
- }
-
- /* Try to log in */
- rv = (funcs->C_Login) (session, CKU_USER, (CK_BYTE_PTR)pin, n_pin);
-
- /* Only one C_Login call if protected auth path */
- if (token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
- break;
-
- request_retry = TRUE;
- } while (rv == CKR_PIN_INCORRECT);
-
- g_clear_object (&password);
-
- return rv;
-}
-
-static void
-update_password_for_key (GTlsPassword *password,
- CK_TOKEN_INFO *token_info,
- gboolean request_retry)
-{
- GTlsPasswordFlags flags;
-
- flags = 0;
- if (request_retry)
- flags |= G_TLS_PASSWORD_RETRY;
- if (token_info && token_info->flags & CKF_USER_PIN_COUNT_LOW)
- flags |= G_TLS_PASSWORD_MANY_TRIES;
- if (token_info && token_info->flags & CKF_USER_PIN_FINAL_TRY)
- flags |= G_TLS_PASSWORD_FINAL_TRY;
- g_tls_password_set_flags (password, flags);
-}
-
-CK_RV
-_gck_session_authenticate_key (CK_FUNCTION_LIST_PTR funcs,
- CK_SESSION_HANDLE session,
- GckObject *key,
- GTlsInteraction *interaction,
- GCancellable *cancellable)
-{
- CK_ATTRIBUTE attrs[2];
- CK_SESSION_INFO session_info;
- CK_TOKEN_INFO token_info;
- GTlsPassword *password = NULL;
- CK_OBJECT_HANDLE handle;
- GTlsInteractionResult res;
- gboolean request_retry;
- GError *error = NULL;
- CK_BYTE_PTR pin;
- gsize pin_len;
- CK_BBOOL bvalue;
- gboolean got_label;
- CK_RV rv;
-
- g_assert (funcs != NULL);
-
- handle = gck_object_get_handle (key);
-
- attrs[0].type = CKA_LABEL;
- attrs[0].pValue = NULL;
- attrs[0].ulValueLen = 0;
- attrs[1].type = CKA_ALWAYS_AUTHENTICATE;
- attrs[1].pValue = &bvalue;
- attrs[1].ulValueLen = sizeof (bvalue);
-
- rv = (funcs->C_GetAttributeValue) (session, handle, attrs, 2);
- if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
- bvalue = CK_FALSE;
-
- } else if (rv != CKR_OK) {
- g_message ("couldn't check whether key requires authentication, assuming it doesn't: %s",
- gck_message_from_rv (rv));
- return CKR_OK;
- }
-
- /* No authentication needed, on this object */
- if (bvalue != CK_TRUE) {
- _gck_debug ("key does not require authentication");
- return CKR_OK;
- }
-
- got_label = FALSE;
- request_retry = FALSE;
-
- do {
- if (g_cancellable_is_cancelled (cancellable)) {
- rv = CKR_FUNCTION_CANCELED;
- break;
- }
-
- rv = (funcs->C_GetSessionInfo) (session, &session_info);
- if (rv != CKR_OK) {
- g_warning ("couldn't get session info when authenticating key: %s",
- gck_message_from_rv (rv));
- return rv;
- }
-
- rv = (funcs->C_GetTokenInfo) (session_info.slotID, &token_info);
- if (rv != CKR_OK) {
- g_warning ("couldn't get token info when authenticating key: %s",
- gck_message_from_rv (rv));
- return rv;
- }
-
- /* Protected authentication path, just use NULL passwords */
- if (token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
-
- password = NULL;
- pin = NULL;
- pin_len = 0;
-
- /* Need to prompt for a password */
- } else {
- _gck_debug ("trying to log into session: want password %s",
- request_retry ? "login was incorrect" : "");
-
- if (password == NULL)
- password = g_object_new (GCK_TYPE_PASSWORD, "key", key, NULL);
-
- /* Set the password */
- update_password_for_key (password, &token_info, request_retry);
-
- /* Set the label properly */
- if (!got_label) {
- if (attrs[0].ulValueLen && attrs[0].ulValueLen != GCK_INVALID) {
- attrs[0].pValue = g_malloc0 (attrs[0].ulValueLen + 1);
- rv = (funcs->C_GetAttributeValue) (session, handle, attrs, 1);
- if (rv == CKR_OK) {
- ((gchar *)attrs[0].pValue)[attrs[0].ulValueLen] = 0;
- g_tls_password_set_description (password, attrs[0].pValue);
- }
- g_free (attrs[0].pValue);
- attrs[0].pValue = NULL;
- }
-
- got_label = TRUE;
- }
-
- if (interaction == NULL)
- res = G_TLS_INTERACTION_UNHANDLED;
-
- else
- res = g_tls_interaction_invoke_ask_password (interaction,
- G_TLS_PASSWORD (password),
- NULL, &error);
-
- if (res == G_TLS_INTERACTION_FAILED) {
- g_message ("interaction couldn't ask password: %s", error->message);
- rv = _gck_rv_from_error (error, CKR_USER_NOT_LOGGED_IN);
- g_clear_error (&error);
- break;
-
- } else if (res == G_TLS_INTERACTION_UNHANDLED) {
- g_message ("couldn't authenticate: no interaction handler");
- rv = CKR_USER_NOT_LOGGED_IN;
- break;
- }
-
- pin = (CK_BYTE_PTR)g_tls_password_get_value (G_TLS_PASSWORD (password), &pin_len);
- }
-
- /* Try to log in */
- rv = (funcs->C_Login) (session, CKU_CONTEXT_SPECIFIC, pin, pin_len);
-
- /* Only one C_Login call if protected auth path */
- if (token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
- break;
-
- request_retry = TRUE;
- } while (rv == CKR_PIN_INCORRECT);
-
- g_clear_object (&password);
-
- return rv;
-}