Blame gck/gck-object.c

Packit b00eeb
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
Packit b00eeb
/* gck-object.c - the GObject PKCS#11 wrapper library
Packit b00eeb
Packit b00eeb
   Copyright (C) 2008, Stefan Walter
Packit b00eeb
Packit b00eeb
   The Gnome Keyring Library is free software; you can redistribute it and/or
Packit b00eeb
   modify it under the terms of the GNU Library General Public License as
Packit b00eeb
   published by the Free Software Foundation; either version 2 of the
Packit b00eeb
   License, or (at your option) any later version.
Packit b00eeb
Packit b00eeb
   The Gnome Keyring Library is distributed in the hope that it will be useful,
Packit b00eeb
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit b00eeb
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit b00eeb
   Library General Public License for more details.
Packit b00eeb
Packit b00eeb
   You should have received a copy of the GNU Library General Public
Packit b00eeb
   License along with the Gnome Library; see the file COPYING.LIB.  If not,
Packit b00eeb
   see <http://www.gnu.org/licenses/>.
Packit b00eeb
Packit b00eeb
   Author: Stef Walter <nielsen@memberwebs.com>
Packit b00eeb
*/
Packit b00eeb
Packit b00eeb
#include "config.h"
Packit b00eeb
Packit b00eeb
#include "gck.h"
Packit b00eeb
#include "gck-private.h"
Packit b00eeb
Packit b00eeb
#include <string.h>
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * SECTION:gck-object
Packit b00eeb
 * @title: GckObject
Packit b00eeb
 * @short_description: Represents a PKCS11 object such as a key or certificate.
Packit b00eeb
 *
Packit b00eeb
 * A GckObject holds a handle to a PKCS11 object such as a key or certificate. Token objects
Packit b00eeb
 * are stored on the token persistently. Others are transient and are called session objects.
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * GckObject:
Packit b00eeb
 *
Packit b00eeb
 * Represents a PKCS11 object handle such as a key or certifiacte.
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * GckObjectClass:
Packit b00eeb
 * @parent: derived from this
Packit b00eeb
 *
Packit b00eeb
 * The class for a #GckObject.
Packit b00eeb
 *
Packit b00eeb
 * If the @attribute_types field is set by a derived class, then the a
Packit b00eeb
 * #GckEnumerator which has been setup using gck_enumerator_set_object_type()
Packit b00eeb
 * with this derived type will retrieve these attributes when enumerating. In
Packit b00eeb
 * this case the class must implement an 'attributes' property of boxed type
Packit b00eeb
 * GCK_TYPE_ATTRIBUTES.
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
/*
Packit b00eeb
 * MT safe -- Nothing in GckObjectData changes between
Packit b00eeb
 * init and finalize. All GckObjectPrivate access between init
Packit b00eeb
 * and finalize is locked.
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
enum {
Packit b00eeb
	PROP_0,
Packit b00eeb
	PROP_MODULE,
Packit b00eeb
	PROP_SESSION,
Packit b00eeb
	PROP_HANDLE
Packit b00eeb
};
Packit b00eeb
Packit b00eeb
struct _GckObjectPrivate {
Packit b00eeb
	GckModule *module;
Packit b00eeb
	GckSession *session;
Packit b00eeb
	CK_OBJECT_HANDLE handle;
Packit b00eeb
};
Packit b00eeb
Packit b00eeb
G_DEFINE_TYPE (GckObject, gck_object, G_TYPE_OBJECT);
Packit b00eeb
Packit b00eeb
/* ----------------------------------------------------------------------------
Packit b00eeb
 * OBJECT
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gck_object_init (GckObject *self)
Packit b00eeb
{
Packit b00eeb
	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_OBJECT, GckObjectPrivate);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gck_object_get_property (GObject *obj, guint prop_id, GValue *value,
Packit b00eeb
                          GParamSpec *pspec)
Packit b00eeb
{
Packit b00eeb
	GckObject *self = GCK_OBJECT (obj);
Packit b00eeb
Packit b00eeb
	switch (prop_id) {
Packit b00eeb
	case PROP_MODULE:
Packit b00eeb
		g_value_take_object (value, gck_object_get_module (self));
Packit b00eeb
		break;
Packit b00eeb
	case PROP_SESSION:
Packit b00eeb
		g_value_take_object (value, gck_object_get_session (self));
Packit b00eeb
		break;
Packit b00eeb
	case PROP_HANDLE:
Packit b00eeb
		g_value_set_ulong (value, gck_object_get_handle (self));
Packit b00eeb
		break;
Packit b00eeb
	}
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gck_object_set_property (GObject *obj, guint prop_id, const GValue *value,
Packit b00eeb
                         GParamSpec *pspec)
Packit b00eeb
{
Packit b00eeb
	GckObject *self = GCK_OBJECT (obj);
Packit b00eeb
Packit b00eeb
	/* The sets to data below are only allowed during construction */
Packit b00eeb
Packit b00eeb
	switch (prop_id) {
Packit b00eeb
	case PROP_MODULE:
Packit b00eeb
		g_return_if_fail (!self->pv->module);
Packit b00eeb
		self->pv->module = g_value_get_object (value);
Packit b00eeb
		g_return_if_fail (self->pv->module);
Packit b00eeb
		g_object_ref (self->pv->module);
Packit b00eeb
		break;
Packit b00eeb
	case PROP_SESSION:
Packit b00eeb
		g_return_if_fail (!self->pv->session);
Packit b00eeb
		self->pv->session = g_value_get_object (value);
Packit b00eeb
		g_return_if_fail (self->pv->session);
Packit b00eeb
		g_object_ref (self->pv->session);
Packit b00eeb
		break;
Packit b00eeb
	case PROP_HANDLE:
Packit b00eeb
		g_return_if_fail (!self->pv->handle);
Packit b00eeb
		self->pv->handle = g_value_get_ulong (value);
Packit b00eeb
		break;
Packit b00eeb
	}
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gck_object_finalize (GObject *obj)
Packit b00eeb
{
Packit b00eeb
	GckObject *self = GCK_OBJECT (obj);
Packit b00eeb
Packit b00eeb
	if (self->pv->session)
Packit b00eeb
		g_object_unref (self->pv->session);
Packit b00eeb
	self->pv->session = NULL;
Packit b00eeb
Packit b00eeb
	if (self->pv->module)
Packit b00eeb
		g_object_unref (self->pv->module);
Packit b00eeb
	self->pv->module = NULL;
Packit b00eeb
Packit b00eeb
	self->pv->handle = 0;
Packit b00eeb
Packit b00eeb
	G_OBJECT_CLASS (gck_object_parent_class)->finalize (obj);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
gck_object_class_init (GckObjectClass *klass)
Packit b00eeb
{
Packit b00eeb
	GObjectClass *gobject_class = (GObjectClass*)klass;
Packit b00eeb
	gck_object_parent_class = g_type_class_peek_parent (klass);
Packit b00eeb
Packit b00eeb
	gobject_class->get_property = gck_object_get_property;
Packit b00eeb
	gobject_class->set_property = gck_object_set_property;
Packit b00eeb
	gobject_class->finalize = gck_object_finalize;
Packit b00eeb
Packit b00eeb
	/**
Packit b00eeb
	 * GckObject:module:
Packit b00eeb
	 *
Packit b00eeb
	 * The GckModule that this object belongs to.
Packit b00eeb
	 */
Packit b00eeb
	g_object_class_install_property (gobject_class, PROP_MODULE,
Packit b00eeb
		g_param_spec_object ("module", "Module", "PKCS11 Module",
Packit b00eeb
		                     GCK_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
Packit b00eeb
Packit b00eeb
	/**
Packit b00eeb
	 * GckObject:handle:
Packit b00eeb
	 *
Packit b00eeb
	 * The raw PKCS11 handle for this object.
Packit b00eeb
	 */
Packit b00eeb
	g_object_class_install_property (gobject_class, PROP_HANDLE,
Packit b00eeb
		g_param_spec_ulong ("handle", "Object Handle", "PKCS11 Object Handle",
Packit b00eeb
		                   0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
Packit b00eeb
Packit b00eeb
	/**
Packit b00eeb
	 * GckObject:session:
Packit b00eeb
	 *
Packit b00eeb
	 * The PKCS11 session to make calls on when this object needs to
Packit b00eeb
	 * perform operations on itself.
Packit b00eeb
	 *
Packit b00eeb
	 * If this is NULL then a new session is opened for each operation,
Packit b00eeb
	 * such as gck_object_get(), gck_object_set() or gck_object_destroy().
Packit b00eeb
	 */
Packit b00eeb
	g_object_class_install_property (gobject_class, PROP_SESSION,
Packit b00eeb
		g_param_spec_object ("session", "session", "PKCS11 Session to make calls on",
Packit b00eeb
		                     GCK_TYPE_SESSION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
Packit b00eeb
Packit b00eeb
	g_type_class_add_private (klass, sizeof (GckObjectPrivate));
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/* ----------------------------------------------------------------------------
Packit b00eeb
 * PUBLIC
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_from_handle:
Packit b00eeb
 * @session: The session through which this object is accessed or created.
Packit b00eeb
 * @object_handle: The raw CK_OBJECT_HANDLE of the object.
Packit b00eeb
 *
Packit b00eeb
 * Initialize a GckObject from a raw PKCS\#11 handle. Normally you would use
Packit b00eeb
 * gck_session_create_object() or gck_session_find_objects() to access objects.
Packit b00eeb
 *
Packit b00eeb
 * Return value: (transfer full): The new GckObject. You should use
Packit b00eeb
 *               g_object_unref() when done with this object.
Packit b00eeb
 **/
Packit b00eeb
GckObject *
Packit b00eeb
gck_object_from_handle (GckSession *session,
Packit b00eeb
                        gulong object_handle)
Packit b00eeb
{
Packit b00eeb
	GckModule *module = NULL;
Packit b00eeb
	GckObject *object;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_SESSION (session), NULL);
Packit b00eeb
Packit b00eeb
	module = gck_session_get_module (session);
Packit b00eeb
	object = g_object_new (GCK_TYPE_OBJECT,
Packit b00eeb
	                       "module", module,
Packit b00eeb
	                       "handle", object_handle,
Packit b00eeb
	                       "session", session,
Packit b00eeb
	                       NULL);
Packit b00eeb
	g_object_unref (module);
Packit b00eeb
Packit b00eeb
	return object;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_objects_from_handle_array:
Packit b00eeb
 * @session: The session for these objects
Packit b00eeb
 * @object_handles: (array length=n_object_handles): The raw object handles.
Packit b00eeb
 * @n_object_handles: The number of raw object handles.
Packit b00eeb
 *
Packit b00eeb
 * Initialize a list of GckObject from raw PKCS\#11 handles. The handles argument must contain
Packit b00eeb
 * contiguous CK_OBJECT_HANDLE handles in an array.
Packit b00eeb
 *
Packit b00eeb
 * Returns: (transfer full) (element-type Gck.Object): The list of #GckObject
Packit b00eeb
 *          objects. You should use gck_list_unref_free() when done with this
Packit b00eeb
 *          list.
Packit b00eeb
 **/
Packit b00eeb
GList *
Packit b00eeb
gck_objects_from_handle_array (GckSession *session,
Packit b00eeb
                               gulong *object_handles,
Packit b00eeb
                               gulong n_object_handles)
Packit b00eeb
{
Packit b00eeb
	GList *results = NULL;
Packit b00eeb
	CK_ULONG i;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_SESSION (session), NULL);
Packit b00eeb
	g_return_val_if_fail (n_object_handles == 0 || object_handles != NULL, NULL);
Packit b00eeb
Packit b00eeb
	for (i = 0; i < n_object_handles; ++i)
Packit b00eeb
		results = g_list_prepend (results, gck_object_from_handle (session, object_handles[i]));
Packit b00eeb
	return g_list_reverse (results);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_equal:
Packit b00eeb
 * @object1: (type Gck.Object): a pointer to the first #GckObject
Packit b00eeb
 * @object2: (type Gck.Object): a pointer to the second #GckObject
Packit b00eeb
 *
Packit b00eeb
 * Checks equality of two objects. Two GckObject objects can point to the same
Packit b00eeb
 * underlying PKCS\#11 object.
Packit b00eeb
 *
Packit b00eeb
 * Return value: TRUE if object1 and object2 are equal. FALSE if either is not a GckObject.
Packit b00eeb
 **/
Packit b00eeb
gboolean
Packit b00eeb
gck_object_equal (gconstpointer object1, gconstpointer object2)
Packit b00eeb
{
Packit b00eeb
	GckObject *obj1, *obj2;
Packit b00eeb
	GckSlot *slot1, *slot2;
Packit b00eeb
	gboolean ret;
Packit b00eeb
Packit b00eeb
	if (object1 == object2)
Packit b00eeb
		return TRUE;
Packit b00eeb
	if (!GCK_IS_OBJECT (object1) || !GCK_IS_OBJECT (object2))
Packit b00eeb
		return FALSE;
Packit b00eeb
Packit b00eeb
	obj1 = GCK_OBJECT (object1);
Packit b00eeb
	obj2 = GCK_OBJECT (object2);
Packit b00eeb
Packit b00eeb
	slot1 = gck_session_get_slot (obj1->pv->session);
Packit b00eeb
	slot2 = gck_session_get_slot (obj2->pv->session);
Packit b00eeb
Packit b00eeb
	ret = obj1->pv->handle == obj2->pv->handle &&
Packit b00eeb
	      gck_slot_equal (slot1, slot2);
Packit b00eeb
Packit b00eeb
	g_object_unref (slot1);
Packit b00eeb
	g_object_unref (slot2);
Packit b00eeb
Packit b00eeb
	return ret;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_hash:
Packit b00eeb
 * @object: (type Gck.Object): a pointer to a #GckObject
Packit b00eeb
 *
Packit b00eeb
 * Create a hash value for the GckObject.
Packit b00eeb
 *
Packit b00eeb
 * This function is intended for easily hashing a GckObject to add to
Packit b00eeb
 * a GHashTable or similar data structure.
Packit b00eeb
 *
Packit b00eeb
 * Return value: An integer that can be used as a hash value, or 0 if invalid.
Packit b00eeb
 **/
Packit b00eeb
guint
Packit b00eeb
gck_object_hash (gconstpointer object)
Packit b00eeb
{
Packit b00eeb
	GckObject *self;
Packit b00eeb
	GckSlot *slot;
Packit b00eeb
	guint hash;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (object), 0);
Packit b00eeb
Packit b00eeb
	self = GCK_OBJECT (object);
Packit b00eeb
	slot = gck_session_get_slot (self->pv->session);
Packit b00eeb
Packit b00eeb
	hash = _gck_ulong_hash (&self->pv->handle) ^
Packit b00eeb
	       gck_slot_hash (slot);
Packit b00eeb
Packit b00eeb
	g_object_unref (slot);
Packit b00eeb
Packit b00eeb
	return hash;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_handle:
Packit b00eeb
 * @self: The object.
Packit b00eeb
 *
Packit b00eeb
 * Get the raw PKCS\#11 handle of a GckObject.
Packit b00eeb
 *
Packit b00eeb
 * Return value: the raw CK_OBJECT_HANDLE object handle
Packit b00eeb
 **/
Packit b00eeb
gulong
Packit b00eeb
gck_object_get_handle (GckObject *self)
Packit b00eeb
{
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), (CK_OBJECT_HANDLE)-1);
Packit b00eeb
	return self->pv->handle;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_module:
Packit b00eeb
 * @self: The object.
Packit b00eeb
 *
Packit b00eeb
 * Get the PKCS\#11 module to which this object belongs.
Packit b00eeb
 *
Packit b00eeb
 * Returns: (transfer full): the module, which should be unreffed after use
Packit b00eeb
 **/
Packit b00eeb
GckModule *
Packit b00eeb
gck_object_get_module (GckObject *self)
Packit b00eeb
{
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
Packit b00eeb
	g_return_val_if_fail (GCK_IS_MODULE (self->pv->module), NULL);
Packit b00eeb
	return g_object_ref (self->pv->module);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_session:
Packit b00eeb
 * @self: The object
Packit b00eeb
 *
Packit b00eeb
 * Get the PKCS\#11 session assigned to make calls on when operating
Packit b00eeb
 * on this object.
Packit b00eeb
 *
Packit b00eeb
 * This will only return a session if it was set explitly on this
Packit b00eeb
 * object. By default an object will open and close sessions
Packit b00eeb
 * appropriate for its calls.
Packit b00eeb
 *
Packit b00eeb
 * Returns: (transfer full): the assigned session, which must be unreffed after use
Packit b00eeb
 **/
Packit b00eeb
GckSession *
Packit b00eeb
gck_object_get_session (GckObject *self)
Packit b00eeb
{
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
Packit b00eeb
	g_return_val_if_fail (GCK_IS_SESSION (self->pv->session), NULL);
Packit b00eeb
	return g_object_ref (self->pv->session);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/* --------------------------------------------------------------------------------------
Packit b00eeb
 * DESTROY
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
typedef struct _Destroy {
Packit b00eeb
	GckArguments base;
Packit b00eeb
	CK_OBJECT_HANDLE object;
Packit b00eeb
} Destroy;
Packit b00eeb
Packit b00eeb
static CK_RV
Packit b00eeb
perform_destroy (Destroy *args)
Packit b00eeb
{
Packit b00eeb
	g_assert (args);
Packit b00eeb
	return (args->base.pkcs11->C_DestroyObject) (args->base.handle, args->object);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_destroy:
Packit b00eeb
 * @self: The object to destroy.
Packit b00eeb
 * @cancellable: Optional cancellable object, or NULL to ignore.
Packit b00eeb
 * @error: A location to return an error.
Packit b00eeb
 *
Packit b00eeb
 * Destroy a PKCS\#11 object, deleting it from storage or the session.
Packit b00eeb
 * This call may block for an indefinite period.
Packit b00eeb
 *
Packit b00eeb
 * Return value: Whether the call was successful or not.
Packit b00eeb
 **/
Packit b00eeb
gboolean
Packit b00eeb
gck_object_destroy (GckObject *self, GCancellable *cancellable, GError **error)
Packit b00eeb
{
Packit b00eeb
	Destroy args = { GCK_ARGUMENTS_INIT, 0 };
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
Packit b00eeb
	g_return_val_if_fail (GCK_IS_SESSION (self->pv->session), FALSE);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, FALSE);
Packit b00eeb
Packit b00eeb
	args.object = self->pv->handle;
Packit b00eeb
	return _gck_call_sync (self->pv->session, perform_destroy, NULL, &args, cancellable, error);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_destroy_async:
Packit b00eeb
 * @self: The object to destroy.
Packit b00eeb
 * @cancellable: Optional cancellable object, or NULL to ignore.
Packit b00eeb
 * @callback: Callback which is called when operation completes.
Packit b00eeb
 * @user_data: Data to pass to the callback.
Packit b00eeb
 *
Packit b00eeb
 * Destroy a PKCS\#11 object, deleting it from storage or the session.
Packit b00eeb
 * This call will return immediately and complete asynchronously.
Packit b00eeb
 **/
Packit b00eeb
void
Packit b00eeb
gck_object_destroy_async (GckObject *self, GCancellable *cancellable,
Packit b00eeb
                           GAsyncReadyCallback callback, gpointer user_data)
Packit b00eeb
{
Packit b00eeb
	Destroy* args;
Packit b00eeb
Packit b00eeb
	g_return_if_fail (GCK_IS_OBJECT (self));
Packit b00eeb
	g_return_if_fail (GCK_IS_SESSION (self->pv->session));
Packit b00eeb
Packit b00eeb
	args = _gck_call_async_prep (self->pv->session, self, perform_destroy, NULL, sizeof (*args), NULL);
Packit b00eeb
	args->object = self->pv->handle;
Packit b00eeb
Packit b00eeb
	_gck_call_async_ready_go (args, cancellable, callback, user_data);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_destroy_finish:
Packit b00eeb
 * @self: The object being destroyed.
Packit b00eeb
 * @result: The result of the destory operation passed to the callback.
Packit b00eeb
 * @error: A location to store an error.
Packit b00eeb
 *
Packit b00eeb
 * Get the status of the operation to destroy a PKCS\#11 object, begun with
Packit b00eeb
 * gck_object_destroy_async().
Packit b00eeb
 *
Packit b00eeb
 * Return value: Whether the object was destroyed successfully or not.
Packit b00eeb
 */
Packit b00eeb
gboolean
Packit b00eeb
gck_object_destroy_finish (GckObject *self, GAsyncResult *result, GError **error)
Packit b00eeb
{
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
Packit b00eeb
	g_return_val_if_fail (GCK_IS_CALL (result), FALSE);
Packit b00eeb
	return _gck_call_basic_finish (result, error);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/* --------------------------------------------------------------------------------------
Packit b00eeb
 * SET ATTRIBUTES
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
typedef struct _SetAttributes {
Packit b00eeb
	GckArguments base;
Packit b00eeb
	GckAttributes *attrs;
Packit b00eeb
	CK_OBJECT_HANDLE object;
Packit b00eeb
} SetAttributes;
Packit b00eeb
Packit b00eeb
static CK_RV
Packit b00eeb
perform_set_attributes (SetAttributes *args)
Packit b00eeb
{
Packit b00eeb
	CK_ATTRIBUTE_PTR attrs;
Packit b00eeb
	CK_ULONG n_attrs;
Packit b00eeb
Packit b00eeb
	g_assert (args);
Packit b00eeb
	attrs = _gck_attributes_commit_out (args->attrs, &n_attrs);
Packit b00eeb
Packit b00eeb
	return (args->base.pkcs11->C_SetAttributeValue) (args->base.handle, args->object,
Packit b00eeb
	                                                 attrs, n_attrs);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
free_set_attributes (SetAttributes *args)
Packit b00eeb
{
Packit b00eeb
	g_assert (args);
Packit b00eeb
	gck_attributes_unref (args->attrs);
Packit b00eeb
	g_free (args);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_set:
Packit b00eeb
 * @self: The object to set attributes on.
Packit b00eeb
 * @attrs: The attributes to set on the object.
Packit b00eeb
 * @cancellable: Optional cancellable object, or NULL to ignore.
Packit b00eeb
 * @error: A location to return an error.
Packit b00eeb
 *
Packit b00eeb
 * Set PKCS\#11 attributes on an object. This call may block for an indefinite period.
Packit b00eeb
 *
Packit b00eeb
 * If the @attrs #GckAttributes is floating, it is consumed.
Packit b00eeb
 *
Packit b00eeb
 * Return value: Whether the call was successful or not.
Packit b00eeb
 **/
Packit b00eeb
gboolean
Packit b00eeb
gck_object_set (GckObject *self, GckAttributes *attrs,
Packit b00eeb
                GCancellable *cancellable, GError **error)
Packit b00eeb
{
Packit b00eeb
	SetAttributes args;
Packit b00eeb
	gboolean ret = FALSE;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
Packit b00eeb
	g_return_val_if_fail (attrs != NULL, FALSE);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, FALSE);
Packit b00eeb
Packit b00eeb
	memset (&args, 0, sizeof (args));
Packit b00eeb
	args.attrs = attrs;
Packit b00eeb
	args.object = self->pv->handle;
Packit b00eeb
Packit b00eeb
	gck_attributes_ref_sink (attrs);
Packit b00eeb
Packit b00eeb
	ret = _gck_call_sync (self->pv->session, perform_set_attributes, NULL, &args, cancellable, error);
Packit b00eeb
Packit b00eeb
	gck_attributes_unref (attrs);
Packit b00eeb
Packit b00eeb
	return ret;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_set_async:
Packit b00eeb
 * @self: The object to set attributes on.
Packit b00eeb
 * @attrs: The attributes to set on the object.
Packit b00eeb
 * @cancellable: Optional cancellable object, or NULL to ignore.
Packit b00eeb
 * @callback: Callback which is called when operation completes.
Packit b00eeb
 * @user_data: Data to pass to the callback.
Packit b00eeb
 *
Packit b00eeb
 * Set PKCS\#11 attributes on an object. This call will return
Packit b00eeb
 * immediately and completes asynchronously.
Packit b00eeb
 *
Packit b00eeb
 * If the @attrs #GckAttributes is floating, it is consumed.
Packit b00eeb
 **/
Packit b00eeb
void
Packit b00eeb
gck_object_set_async (GckObject *self, GckAttributes *attrs, GCancellable *cancellable,
Packit b00eeb
                       GAsyncReadyCallback callback, gpointer user_data)
Packit b00eeb
{
Packit b00eeb
	SetAttributes *args;
Packit b00eeb
Packit b00eeb
	g_return_if_fail (GCK_IS_OBJECT (self));
Packit b00eeb
	g_return_if_fail (attrs != NULL);
Packit b00eeb
Packit b00eeb
	args = _gck_call_async_prep (self->pv->session, self, perform_set_attributes,
Packit b00eeb
	                             NULL, sizeof (*args), free_set_attributes);
Packit b00eeb
Packit b00eeb
	args->attrs = gck_attributes_ref_sink (attrs);
Packit b00eeb
	args->object = self->pv->handle;
Packit b00eeb
Packit b00eeb
	_gck_call_async_ready_go (args, cancellable, callback, user_data);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_set_finish:
Packit b00eeb
 * @self: The object to set attributes on.
Packit b00eeb
 * @result: The result of the destory operation passed to the callback.
Packit b00eeb
 * @error: A location to store an error.
Packit b00eeb
 *
Packit b00eeb
 * Get the status of the operation to set attributes on a PKCS\#11 object,
Packit b00eeb
 * begun with gck_object_set_async().
Packit b00eeb
 *
Packit b00eeb
 * Return value: Whether the attributes were successfully set on the object or not.
Packit b00eeb
 */
Packit b00eeb
gboolean
Packit b00eeb
gck_object_set_finish (GckObject *self, GAsyncResult *result, GError **error)
Packit b00eeb
{
Packit b00eeb
	SetAttributes *args;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
Packit b00eeb
	g_return_val_if_fail (GCK_IS_CALL (result), FALSE);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, FALSE);
Packit b00eeb
Packit b00eeb
	/* Unlock the attributes we were using */
Packit b00eeb
	args = _gck_call_arguments (result, SetAttributes);
Packit b00eeb
	g_assert (args->attrs);
Packit b00eeb
Packit b00eeb
	return _gck_call_basic_finish (result, error);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/* ------------------------------------------------------------------------------------
Packit b00eeb
 * GET ATTRIBUTES
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
typedef struct _GetAttributes {
Packit b00eeb
	GckArguments base;
Packit b00eeb
	CK_OBJECT_HANDLE object;
Packit b00eeb
	GckBuilder builder;
Packit b00eeb
} GetAttributes;
Packit b00eeb
Packit b00eeb
static CK_RV
Packit b00eeb
perform_get_attributes (GetAttributes *args)
Packit b00eeb
{
Packit b00eeb
	CK_ATTRIBUTE_PTR attrs;
Packit b00eeb
	CK_ULONG n_attrs;
Packit b00eeb
	CK_RV rv;
Packit b00eeb
Packit b00eeb
	g_assert (args != NULL);
Packit b00eeb
Packit b00eeb
	/* Prepare all the attributes */
Packit b00eeb
	attrs = _gck_builder_prepare_in (&args->builder, &n_attrs);
Packit b00eeb
Packit b00eeb
	/* Get the size of each value */
Packit b00eeb
	rv = (args->base.pkcs11->C_GetAttributeValue) (args->base.handle, args->object,
Packit b00eeb
	                                               attrs, n_attrs);
Packit b00eeb
	if (!GCK_IS_GET_ATTRIBUTE_RV_OK (rv))
Packit b00eeb
		return rv;
Packit b00eeb
Packit b00eeb
	/* Allocate memory for each value */
Packit b00eeb
	attrs = _gck_builder_commit_in (&args->builder, &n_attrs);
Packit b00eeb
Packit b00eeb
	/* Now get the actual values */
Packit b00eeb
	rv = (args->base.pkcs11->C_GetAttributeValue) (args->base.handle, args->object,
Packit b00eeb
	                                               attrs, n_attrs);
Packit b00eeb
Packit b00eeb
	if (GCK_IS_GET_ATTRIBUTE_RV_OK (rv))
Packit b00eeb
		rv = CKR_OK;
Packit b00eeb
Packit b00eeb
	return rv;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
free_get_attributes (GetAttributes *args)
Packit b00eeb
{
Packit b00eeb
	g_assert (args != NULL);
Packit b00eeb
	gck_builder_clear (&args->builder);
Packit b00eeb
	g_free (args);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get:
Packit b00eeb
 * @self: The object to get attributes from.
Packit b00eeb
 * @cancellable: A #GCancellable or %NULL
Packit b00eeb
 * @error: A location to store an error.
Packit b00eeb
 * @...: The attribute types to get.
Packit b00eeb
 *
Packit b00eeb
 * Get the specified attributes from the object. This call may
Packit b00eeb
 * block for an indefinite period.
Packit b00eeb
 *
Packit b00eeb
 * Returns: (transfer full): the resulting PKCS\#11 attributes, or %NULL if an
Packit b00eeb
 *          error occurred; the result must be unreffed when you're finished
Packit b00eeb
 *          with it
Packit b00eeb
 **/
Packit b00eeb
GckAttributes *
Packit b00eeb
gck_object_get (GckObject *self, GCancellable *cancellable, GError **error, ...)
Packit b00eeb
{
Packit b00eeb
	GckAttributes *attrs;
Packit b00eeb
	GArray *array;
Packit b00eeb
	va_list va;
Packit b00eeb
	gulong type;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, NULL);
Packit b00eeb
Packit b00eeb
	array = g_array_new (FALSE, TRUE, sizeof (gulong));
Packit b00eeb
	va_start (va, error);
Packit b00eeb
	for (;;) {
Packit b00eeb
		type = va_arg (va, gulong);
Packit b00eeb
		if (type == GCK_INVALID)
Packit b00eeb
			break;
Packit b00eeb
		g_array_append_val (array, type);
Packit b00eeb
	}
Packit b00eeb
	va_end (va);
Packit b00eeb
Packit b00eeb
	attrs = gck_object_get_full (self, (gulong*)array->data, array->len, cancellable, error);
Packit b00eeb
	g_array_free (array, TRUE);
Packit b00eeb
Packit b00eeb
	return attrs;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_full:
Packit b00eeb
 * @self: The object to get attributes from.
Packit b00eeb
 * @attr_types: (array length=n_attr_types): the types of the attributes to get
Packit b00eeb
 * @n_attr_types: the number of attr_types
Packit b00eeb
 * @cancellable: optional cancellation object, or %NULL
Packit b00eeb
 * @error: A location to store an error.
Packit b00eeb
 *
Packit b00eeb
 * Get the specified attributes from the object. This call may
Packit b00eeb
 * block for an indefinite period.
Packit b00eeb
 *
Packit b00eeb
 * No extra references are added to the returned attributes pointer.
Packit b00eeb
 * During this call you may not access the attributes in any way.
Packit b00eeb
 *
Packit b00eeb
 * Returns: (transfer full): a pointer to the filled in attributes if successful,
Packit b00eeb
 *          or %NULL if not
Packit b00eeb
 **/
Packit b00eeb
GckAttributes *
Packit b00eeb
gck_object_get_full (GckObject *self,
Packit b00eeb
                     const gulong *attr_types,
Packit b00eeb
                     guint n_attr_types,
Packit b00eeb
                     GCancellable *cancellable,
Packit b00eeb
                     GError **error)
Packit b00eeb
{
Packit b00eeb
	GetAttributes args;
Packit b00eeb
	gboolean ret;
Packit b00eeb
	guint i;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, NULL);
Packit b00eeb
Packit b00eeb
	memset (&args, 0, sizeof (args));
Packit b00eeb
Packit b00eeb
	gck_builder_init (&args.builder);
Packit b00eeb
	for (i = 0; i < n_attr_types; ++i)
Packit b00eeb
		gck_builder_add_empty (&args.builder, attr_types[i]);
Packit b00eeb
Packit b00eeb
	args.object = self->pv->handle;
Packit b00eeb
Packit b00eeb
	ret = _gck_call_sync (self->pv->session, perform_get_attributes, NULL, &args, cancellable, error);
Packit b00eeb
Packit b00eeb
	if (ret) {
Packit b00eeb
		return gck_attributes_ref_sink (gck_builder_end (&args.builder));
Packit b00eeb
	} else {
Packit b00eeb
		gck_builder_clear (&args.builder);
Packit b00eeb
		return NULL;
Packit b00eeb
	}
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_async:
Packit b00eeb
 * @self: The object to get attributes from.
Packit b00eeb
 * @attr_types: (array length=n_attr_types): the types of the attributes to get
Packit b00eeb
 * @n_attr_types: the number of attr_types
Packit b00eeb
 * @cancellable: optional cancellation object, or %NULL
Packit b00eeb
 * @callback: A callback which is called when the operation completes.
Packit b00eeb
 * @user_data: Data to be passed to the callback.
Packit b00eeb
 *
Packit b00eeb
 * Get the specified attributes from the object. The attributes will be cleared
Packit b00eeb
 * of their current values, and new attributes will be stored. The attributes
Packit b00eeb
 * should not be accessed in any way except for referencing and unreferencing
Packit b00eeb
 * them until gck_object_get_finish() is called.
Packit b00eeb
 *
Packit b00eeb
 * This call returns immediately and completes asynchronously.
Packit b00eeb
 **/
Packit b00eeb
void
Packit b00eeb
gck_object_get_async (GckObject *self,
Packit b00eeb
                      const gulong *attr_types,
Packit b00eeb
                      guint n_attr_types,
Packit b00eeb
                      GCancellable *cancellable,
Packit b00eeb
                      GAsyncReadyCallback callback,
Packit b00eeb
                      gpointer user_data)
Packit b00eeb
{
Packit b00eeb
	GetAttributes *args;
Packit b00eeb
	guint i;
Packit b00eeb
Packit b00eeb
	g_return_if_fail (GCK_IS_OBJECT (self));
Packit b00eeb
Packit b00eeb
	args = _gck_call_async_prep (self->pv->session, self, perform_get_attributes,
Packit b00eeb
	                             NULL, sizeof (*args), free_get_attributes);
Packit b00eeb
Packit b00eeb
	gck_builder_init (&args->builder);
Packit b00eeb
	for (i = 0; i < n_attr_types; ++i)
Packit b00eeb
		gck_builder_add_empty (&args->builder, attr_types[i]);
Packit b00eeb
Packit b00eeb
	args->object = self->pv->handle;
Packit b00eeb
Packit b00eeb
	_gck_call_async_ready_go (args, cancellable, callback, user_data);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_finish:
Packit b00eeb
 * @self: The object to get attributes from.
Packit b00eeb
 * @result: The result passed to the callback.
Packit b00eeb
 * @error: A location to store an error.
Packit b00eeb
 *
Packit b00eeb
 * Get the result of a get operation and return specified attributes from
Packit b00eeb
 * the object.
Packit b00eeb
 *
Packit b00eeb
 * No extra references are added to the returned attributes pointer.
Packit b00eeb
 *
Packit b00eeb
 * Return value: The filled in attributes structure if successful or
Packit b00eeb
 * NULL if not successful.
Packit b00eeb
 **/
Packit b00eeb
GckAttributes*
Packit b00eeb
gck_object_get_finish (GckObject *self, GAsyncResult *result, GError **error)
Packit b00eeb
{
Packit b00eeb
	GetAttributes *args;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
Packit b00eeb
	g_return_val_if_fail (GCK_IS_CALL (result), NULL);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, NULL);
Packit b00eeb
Packit b00eeb
	args = _gck_call_arguments (result, GetAttributes);
Packit b00eeb
Packit b00eeb
	if (!_gck_call_basic_finish (result, error))
Packit b00eeb
		return NULL;
Packit b00eeb
Packit b00eeb
	return gck_attributes_ref_sink (gck_builder_end (&args->builder));
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/* ---------------------------------------------------------------------------------
Packit b00eeb
 * GET ATTRIBUTE DATA
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
typedef struct _GetAttributeData {
Packit b00eeb
	GckArguments base;
Packit b00eeb
	CK_OBJECT_HANDLE object;
Packit b00eeb
	CK_ATTRIBUTE_TYPE type;
Packit b00eeb
	GckAllocator allocator;
Packit b00eeb
	guchar *result;
Packit b00eeb
	gsize n_result;
Packit b00eeb
} GetAttributeData;
Packit b00eeb
Packit b00eeb
static CK_RV
Packit b00eeb
perform_get_attribute_data (GetAttributeData *args)
Packit b00eeb
{
Packit b00eeb
	CK_ATTRIBUTE attr;
Packit b00eeb
	CK_RV rv;
Packit b00eeb
Packit b00eeb
	g_assert (args);
Packit b00eeb
	g_assert (args->allocator);
Packit b00eeb
Packit b00eeb
	attr.type = args->type;
Packit b00eeb
	attr.ulValueLen = 0;
Packit b00eeb
	attr.pValue = 0;
Packit b00eeb
Packit b00eeb
	/* Get the size of the value */
Packit b00eeb
	rv = (args->base.pkcs11->C_GetAttributeValue) (args->base.handle, args->object,
Packit b00eeb
	                                               &attr, 1);
Packit b00eeb
	if (rv != CKR_OK)
Packit b00eeb
		return rv;
Packit b00eeb
Packit b00eeb
	/* Allocate memory for the value */
Packit b00eeb
	args->result = (args->allocator) (NULL, attr.ulValueLen + 1);
Packit b00eeb
	g_assert (args->result);
Packit b00eeb
	attr.pValue = args->result;
Packit b00eeb
Packit b00eeb
	/* Now get the actual value */
Packit b00eeb
	rv = (args->base.pkcs11->C_GetAttributeValue) (args->base.handle, args->object,
Packit b00eeb
	                                               &attr, 1);
Packit b00eeb
Packit b00eeb
	if (rv == CKR_OK) {
Packit b00eeb
		args->n_result = attr.ulValueLen;
Packit b00eeb
		args->result[args->n_result] = 0;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	return rv;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
free_get_attribute_data (GetAttributeData *args)
Packit b00eeb
{
Packit b00eeb
	g_assert (args);
Packit b00eeb
	g_free (args->result);
Packit b00eeb
	g_free (args);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_data:
Packit b00eeb
 * @self: The object to get attribute data from.
Packit b00eeb
 * @attr_type: The attribute to get data for.
Packit b00eeb
 * @cancellable: A #GCancellable or %NULL
Packit b00eeb
 * @n_data: The length of the resulting data.
Packit b00eeb
 * @error: A location to store an error.
Packit b00eeb
 *
Packit b00eeb
 * Get the data for the specified attribute from the object. For convenience
Packit b00eeb
 * the returned data has a null terminator.
Packit b00eeb
 *
Packit b00eeb
 * This call may block for an indefinite period.
Packit b00eeb
 *
Packit b00eeb
 * Returns: (transfer full) (array length=n_data): the resulting PKCS\#11
Packit b00eeb
 *          attribute data, or %NULL if an error occurred
Packit b00eeb
 **/
Packit b00eeb
guchar *
Packit b00eeb
gck_object_get_data (GckObject *self,
Packit b00eeb
                     gulong attr_type,
Packit b00eeb
                     GCancellable *cancellable,
Packit b00eeb
                     gsize *n_data,
Packit b00eeb
                     GError **error)
Packit b00eeb
{
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
Packit b00eeb
	g_return_val_if_fail (n_data, NULL);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, NULL);
Packit b00eeb
Packit b00eeb
	return gck_object_get_data_full (self, attr_type, g_realloc, cancellable, n_data, error);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_data_full: (skip)
Packit b00eeb
 * @self: The object to get attribute data from.
Packit b00eeb
 * @attr_type: The attribute to get data for.
Packit b00eeb
 * @allocator: An allocator with which to allocate memory for the data, or NULL for default.
Packit b00eeb
 * @cancellable: Optional cancellation object, or NULL.
Packit b00eeb
 * @n_data: The length of the resulting data.
Packit b00eeb
 * @error: A location to store an error.
Packit b00eeb
 *
Packit b00eeb
 * Get the data for the specified attribute from the object. For convenience
Packit b00eeb
 * the returned data has an extra null terminator, not included in the returned length.
Packit b00eeb
 *
Packit b00eeb
 * This call may block for an indefinite period.
Packit b00eeb
 *
Packit b00eeb
 * Returns: (transfer full) (array length=n_data): The resulting PKCS\#11
Packit b00eeb
 *          attribute data, or %NULL if an error occurred.
Packit b00eeb
 **/
Packit b00eeb
guchar *
Packit b00eeb
gck_object_get_data_full (GckObject *self, gulong attr_type, GckAllocator allocator,
Packit b00eeb
                           GCancellable *cancellable, gsize *n_data, GError **error)
Packit b00eeb
{
Packit b00eeb
	GetAttributeData args;
Packit b00eeb
	gboolean ret;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
Packit b00eeb
	g_return_val_if_fail (n_data, NULL);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, NULL);
Packit b00eeb
Packit b00eeb
	if (!allocator)
Packit b00eeb
		allocator = g_realloc;
Packit b00eeb
Packit b00eeb
	memset (&args, 0, sizeof (args));
Packit b00eeb
	args.allocator = allocator;
Packit b00eeb
	args.object = self->pv->handle;
Packit b00eeb
	args.type = attr_type;
Packit b00eeb
Packit b00eeb
	ret = _gck_call_sync (self->pv->session, perform_get_attribute_data, NULL, &args, cancellable, error);
Packit b00eeb
Packit b00eeb
	/* Free any value if failed */
Packit b00eeb
	if (!ret) {
Packit b00eeb
		if (args.result)
Packit b00eeb
			(allocator) (args.result, 0);
Packit b00eeb
		return NULL;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	*n_data = args.n_result;
Packit b00eeb
	return args.result;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_data_async:
Packit b00eeb
 * @self: The object to get attribute data from.
Packit b00eeb
 * @attr_type: The attribute to get data for.
Packit b00eeb
 * @allocator: (skip): An allocator with which to allocate memory for the data, or NULL for default.
Packit b00eeb
 * @cancellable: Optional cancellation object, or NULL.
Packit b00eeb
 * @callback: Called when the operation completes.
Packit b00eeb
 * @user_data: Data to be passed to the callback.
Packit b00eeb
 *
Packit b00eeb
 * Get the data for the specified attribute from the object.
Packit b00eeb
 *
Packit b00eeb
 * This call will return immediately and complete asynchronously.
Packit b00eeb
 **/
Packit b00eeb
void
Packit b00eeb
gck_object_get_data_async (GckObject *self, gulong attr_type, GckAllocator allocator,
Packit b00eeb
                            GCancellable *cancellable, GAsyncReadyCallback callback,
Packit b00eeb
                            gpointer user_data)
Packit b00eeb
{
Packit b00eeb
	GetAttributeData *args;
Packit b00eeb
Packit b00eeb
	g_return_if_fail (GCK_IS_OBJECT (self));
Packit b00eeb
Packit b00eeb
	if (!allocator)
Packit b00eeb
		allocator = g_realloc;
Packit b00eeb
Packit b00eeb
	args = _gck_call_async_prep (self->pv->session, self, perform_get_attribute_data,
Packit b00eeb
	                             NULL, sizeof (*args), free_get_attribute_data);
Packit b00eeb
Packit b00eeb
	args->allocator = allocator;
Packit b00eeb
	args->object = self->pv->handle;
Packit b00eeb
	args->type = attr_type;
Packit b00eeb
Packit b00eeb
	_gck_call_async_ready_go (args, cancellable, callback, user_data);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_data_finish:
Packit b00eeb
 * @self: The object to get an attribute from.
Packit b00eeb
 * @result: The result passed to the callback.
Packit b00eeb
 * @n_data: The length of the resulting data.
Packit b00eeb
 * @error: A location to store an error.
Packit b00eeb
 *
Packit b00eeb
 * Get the result of an operation to get attribute data from
Packit b00eeb
 * an object. For convenience the returned data has an extra null terminator,
Packit b00eeb
 * not included in the returned length.
Packit b00eeb
 *
Packit b00eeb
 * Returns: (transfer full) (array length=n_data): The PKCS\#11 attribute data
Packit b00eeb
 *          or %NULL if an error occurred.
Packit b00eeb
 **/
Packit b00eeb
guchar *
Packit b00eeb
gck_object_get_data_finish (GckObject *self,
Packit b00eeb
                            GAsyncResult *result,
Packit b00eeb
                            gsize *n_data,
Packit b00eeb
                            GError **error)
Packit b00eeb
{
Packit b00eeb
	GetAttributeData *args;
Packit b00eeb
	guchar *data;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
Packit b00eeb
	g_return_val_if_fail (GCK_IS_CALL (result), NULL);
Packit b00eeb
	g_return_val_if_fail (n_data, NULL);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, NULL);
Packit b00eeb
Packit b00eeb
	if (!_gck_call_basic_finish (result, error))
Packit b00eeb
		return NULL;
Packit b00eeb
Packit b00eeb
	args = _gck_call_arguments (result, GetAttributeData);
Packit b00eeb
Packit b00eeb
	*n_data = args->n_result;
Packit b00eeb
	data = args->result;
Packit b00eeb
	args->result = NULL;
Packit b00eeb
Packit b00eeb
	return data;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/* ---------------------------------------------------------------------------------------
Packit b00eeb
 * SET TEMPLATE
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
typedef struct _set_template_args {
Packit b00eeb
	GckArguments base;
Packit b00eeb
	CK_OBJECT_HANDLE object;
Packit b00eeb
	CK_ATTRIBUTE_TYPE type;
Packit b00eeb
	GckAttributes *attrs;
Packit b00eeb
} set_template_args;
Packit b00eeb
Packit b00eeb
static CK_RV
Packit b00eeb
perform_set_template (set_template_args *args)
Packit b00eeb
{
Packit b00eeb
	CK_ATTRIBUTE attr;
Packit b00eeb
	CK_ULONG n_attrs;
Packit b00eeb
Packit b00eeb
	g_assert (args);
Packit b00eeb
Packit b00eeb
	attr.type = args->type;
Packit b00eeb
	attr.pValue = _gck_attributes_commit_out (args->attrs, &n_attrs);
Packit b00eeb
	attr.ulValueLen = n_attrs * sizeof (CK_ATTRIBUTE);
Packit b00eeb
Packit b00eeb
	return (args->base.pkcs11->C_SetAttributeValue) (args->base.handle, args->object, &attr, 1);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
free_set_template (set_template_args *args)
Packit b00eeb
{
Packit b00eeb
	g_assert (args);
Packit b00eeb
	gck_attributes_unref (args->attrs);
Packit b00eeb
	g_free (args);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_set_template:
Packit b00eeb
 * @self: The object to set an attribute template on.
Packit b00eeb
 * @attr_type: The attribute template type.
Packit b00eeb
 * @attrs: The attribute template.
Packit b00eeb
 * @cancellable: Optional cancellation object, or NULL.
Packit b00eeb
 * @error: A location to store an error.
Packit b00eeb
 *
Packit b00eeb
 * Set an attribute template on the object. The attr_type must be for
Packit b00eeb
 * an attribute which contains a template.
Packit b00eeb
 *
Packit b00eeb
 * If the @attrs #GckAttributes is floating, it is consumed.
Packit b00eeb
 *
Packit b00eeb
 * This call may block for an indefinite period.
Packit b00eeb
 *
Packit b00eeb
 * Return value: TRUE if the operation succeeded.
Packit b00eeb
 **/
Packit b00eeb
gboolean
Packit b00eeb
gck_object_set_template (GckObject *self, gulong attr_type, GckAttributes *attrs,
Packit b00eeb
                         GCancellable *cancellable, GError **error)
Packit b00eeb
{
Packit b00eeb
	set_template_args args;
Packit b00eeb
	gboolean ret = FALSE;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
Packit b00eeb
	g_return_val_if_fail (attrs, FALSE);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, FALSE);
Packit b00eeb
Packit b00eeb
	memset (&args, 0, sizeof (args));
Packit b00eeb
	args.attrs = attrs;
Packit b00eeb
	args.type = attr_type;
Packit b00eeb
	args.object = self->pv->handle;
Packit b00eeb
Packit b00eeb
	gck_attributes_ref_sink (attrs);
Packit b00eeb
Packit b00eeb
	ret = _gck_call_sync (self->pv->session, perform_set_template, NULL, &args, cancellable, error);
Packit b00eeb
Packit b00eeb
	gck_attributes_unref (attrs);
Packit b00eeb
Packit b00eeb
	return ret;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_set_template_async:
Packit b00eeb
 * @self: The object to set an attribute template on.
Packit b00eeb
 * @attr_type: The attribute template type.
Packit b00eeb
 * @attrs: The attribute template.
Packit b00eeb
 * @cancellable: Optional cancellation object, or NULL.
Packit b00eeb
 * @callback: Called when the operation completes.
Packit b00eeb
 * @user_data: Data to be passed to the callback.
Packit b00eeb
 *
Packit b00eeb
 * Set an attribute template on the object. The attr_type must be for
Packit b00eeb
 * an attribute which contains a template.
Packit b00eeb
 *
Packit b00eeb
 * If the @attrs #GckAttributes is floating, it is consumed.
Packit b00eeb
 *
Packit b00eeb
 * This call will return immediately and complete asynchronously.
Packit b00eeb
 **/
Packit b00eeb
void
Packit b00eeb
gck_object_set_template_async (GckObject *self, gulong attr_type, GckAttributes *attrs,
Packit b00eeb
                                GCancellable *cancellable, GAsyncReadyCallback callback,
Packit b00eeb
                                gpointer user_data)
Packit b00eeb
{
Packit b00eeb
	set_template_args *args;
Packit b00eeb
Packit b00eeb
	g_return_if_fail (GCK_IS_OBJECT (self));
Packit b00eeb
	g_return_if_fail (attrs);
Packit b00eeb
Packit b00eeb
	args = _gck_call_async_prep (self->pv->session, self, perform_set_template,
Packit b00eeb
	                             NULL, sizeof (*args), free_set_template);
Packit b00eeb
Packit b00eeb
	args->attrs = gck_attributes_ref_sink (attrs);
Packit b00eeb
	args->type = attr_type;
Packit b00eeb
	args->object = self->pv->handle;
Packit b00eeb
Packit b00eeb
	_gck_call_async_ready_go (args, cancellable, callback, user_data);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_set_template_finish:
Packit b00eeb
 * @self: The object to set an attribute template on.
Packit b00eeb
 * @result: The result passed to the callback.
Packit b00eeb
 * @error: A location to store an error.
Packit b00eeb
 *
Packit b00eeb
 * Get the result of an operation to set attribute template on
Packit b00eeb
 * an object.
Packit b00eeb
 *
Packit b00eeb
 * Return value: TRUE if the operation succeeded.
Packit b00eeb
 **/
Packit b00eeb
gboolean
Packit b00eeb
gck_object_set_template_finish (GckObject *self, GAsyncResult *result, GError **error)
Packit b00eeb
{
Packit b00eeb
	set_template_args *args;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
Packit b00eeb
	g_return_val_if_fail (GCK_IS_CALL (result), FALSE);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, FALSE);
Packit b00eeb
Packit b00eeb
	/* Unlock the attributes we were using */
Packit b00eeb
	args = _gck_call_arguments (result, set_template_args);
Packit b00eeb
	g_assert (args->attrs);
Packit b00eeb
Packit b00eeb
	return _gck_call_basic_finish (result, error);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/* ---------------------------------------------------------------------------------------
Packit b00eeb
 * GET TEMPLATE
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
typedef struct _get_template_args {
Packit b00eeb
	GckArguments base;
Packit b00eeb
	CK_OBJECT_HANDLE object;
Packit b00eeb
	CK_ATTRIBUTE_TYPE type;
Packit b00eeb
	GckBuilder builder;
Packit b00eeb
} get_template_args;
Packit b00eeb
Packit b00eeb
static CK_RV
Packit b00eeb
perform_get_template (get_template_args *args)
Packit b00eeb
{
Packit b00eeb
	CK_ATTRIBUTE attr;
Packit b00eeb
	CK_ULONG n_attrs, i;
Packit b00eeb
	CK_RV rv;
Packit b00eeb
Packit b00eeb
	g_assert (args);
Packit b00eeb
Packit b00eeb
	gck_builder_init (&args->builder);
Packit b00eeb
	attr.type = args->type;
Packit b00eeb
	attr.ulValueLen = 0;
Packit b00eeb
	attr.pValue = 0;
Packit b00eeb
Packit b00eeb
	/* Get the length of the entire template */
Packit b00eeb
	rv = (args->base.pkcs11->C_GetAttributeValue) (args->base.handle, args->object, &attr, 1);
Packit b00eeb
	if (rv != CKR_OK)
Packit b00eeb
		return rv;
Packit b00eeb
Packit b00eeb
	/* Number of attributes, rounded down */
Packit b00eeb
	n_attrs = (attr.ulValueLen / sizeof (CK_ATTRIBUTE));
Packit b00eeb
	for (i = 0; i < n_attrs; ++i)
Packit b00eeb
		gck_builder_add_empty (&args->builder, 0);
Packit b00eeb
Packit b00eeb
	/* Prepare all the attributes */
Packit b00eeb
	attr.pValue = _gck_builder_prepare_in (&args->builder, &n_attrs);
Packit b00eeb
Packit b00eeb
	/* Get the size of each value */
Packit b00eeb
	rv = (args->base.pkcs11->C_GetAttributeValue) (args->base.handle, args->object, &attr, 1);
Packit b00eeb
	if (rv != CKR_OK)
Packit b00eeb
		return rv;
Packit b00eeb
Packit b00eeb
	/* Allocate memory for each value */
Packit b00eeb
	attr.pValue = _gck_builder_commit_in (&args->builder, &n_attrs);
Packit b00eeb
Packit b00eeb
	/* Now get the actual values */
Packit b00eeb
	return (args->base.pkcs11->C_GetAttributeValue) (args->base.handle, args->object, &attr, 1);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
free_get_template (get_template_args *args)
Packit b00eeb
{
Packit b00eeb
	g_assert (args != NULL);
Packit b00eeb
	gck_builder_clear (&args->builder);
Packit b00eeb
	g_free (args);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_template:
Packit b00eeb
 * @self: The object to get an attribute template from.
Packit b00eeb
 * @attr_type: The template attribute type.
Packit b00eeb
 * @cancellable: Optional cancellation object, or NULL.
Packit b00eeb
 * @error: A location to store an error.
Packit b00eeb
 *
Packit b00eeb
 * Get an attribute template from the object. The attr_type must be for
Packit b00eeb
 * an attribute which returns a template.
Packit b00eeb
 *
Packit b00eeb
 * This call may block for an indefinite period.
Packit b00eeb
 *
Packit b00eeb
 * Returns: (transfer full): the resulting PKCS\#11 attribute template, or %NULL
Packit b00eeb
 *          if an error occurred
Packit b00eeb
 **/
Packit b00eeb
GckAttributes *
Packit b00eeb
gck_object_get_template (GckObject *self, gulong attr_type,
Packit b00eeb
                         GCancellable *cancellable, GError **error)
Packit b00eeb
{
Packit b00eeb
	get_template_args args;
Packit b00eeb
	gboolean ret;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, NULL);
Packit b00eeb
Packit b00eeb
	memset (&args, 0, sizeof (args));
Packit b00eeb
	args.object = self->pv->handle;
Packit b00eeb
	args.type = attr_type;
Packit b00eeb
Packit b00eeb
	ret = _gck_call_sync (self->pv->session, perform_get_template, NULL, &args, cancellable, error);
Packit b00eeb
Packit b00eeb
	/* Free any value if failed */
Packit b00eeb
	if (!ret) {
Packit b00eeb
		gck_builder_clear (&args.builder);
Packit b00eeb
		return NULL;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	return gck_attributes_ref_sink (gck_builder_end (&args.builder));
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_template_async:
Packit b00eeb
 * @self: The object to get an attribute template from.
Packit b00eeb
 * @attr_type: The template attribute type.
Packit b00eeb
 * @cancellable: Optional cancellation object, or NULL.
Packit b00eeb
 * @callback: Called when the operation completes.
Packit b00eeb
 * @user_data: Data to be passed to the callback.
Packit b00eeb
 *
Packit b00eeb
 * Get an attribute template from the object. The attr_type must be for
Packit b00eeb
 * an attribute which returns a template.
Packit b00eeb
 *
Packit b00eeb
 * This call will return immediately and complete asynchronously.
Packit b00eeb
 **/
Packit b00eeb
void
Packit b00eeb
gck_object_get_template_async (GckObject *self, gulong attr_type,
Packit b00eeb
                                GCancellable *cancellable, GAsyncReadyCallback callback,
Packit b00eeb
                                gpointer user_data)
Packit b00eeb
{
Packit b00eeb
	get_template_args *args;
Packit b00eeb
Packit b00eeb
	g_return_if_fail (GCK_IS_OBJECT (self));
Packit b00eeb
Packit b00eeb
	args = _gck_call_async_prep (self->pv->session, self, perform_get_template,
Packit b00eeb
	                             NULL, sizeof (*args), free_get_template);
Packit b00eeb
Packit b00eeb
	args->object = self->pv->handle;
Packit b00eeb
	args->type = attr_type;
Packit b00eeb
Packit b00eeb
	_gck_call_async_ready_go (args, cancellable, callback, user_data);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
/**
Packit b00eeb
 * gck_object_get_template_finish:
Packit b00eeb
 * @self: The object to get an attribute from.
Packit b00eeb
 * @result: The result passed to the callback.
Packit b00eeb
 * @error: A location to store an error.
Packit b00eeb
 *
Packit b00eeb
 * Get the result of an operation to get attribute template from
Packit b00eeb
 * an object.
Packit b00eeb
 *
Packit b00eeb
 * Returns: (transfer full): the resulting PKCS\#11 attribute template, or %NULL
Packit b00eeb
 *          if an error occurred
Packit b00eeb
 **/
Packit b00eeb
GckAttributes *
Packit b00eeb
gck_object_get_template_finish (GckObject *self, GAsyncResult *result,
Packit b00eeb
                                GError **error)
Packit b00eeb
{
Packit b00eeb
	get_template_args *args;
Packit b00eeb
Packit b00eeb
	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
Packit b00eeb
	g_return_val_if_fail (GCK_IS_CALL (result), NULL);
Packit b00eeb
	g_return_val_if_fail (!error || !*error, NULL);
Packit b00eeb
Packit b00eeb
	if (!_gck_call_basic_finish (result, error))
Packit b00eeb
		return NULL;
Packit b00eeb
Packit b00eeb
	args = _gck_call_arguments (result, get_template_args);
Packit b00eeb
	return gck_attributes_ref_sink (gck_builder_end (&args->builder));
Packit b00eeb
}