public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/gnome:master commit in: gnome-base/gnome-keyring/, gnome-base/gnome-keyring/files/
@ 2011-03-09 11:34 Nirbheek Chauhan
  0 siblings, 0 replies; 2+ messages in thread
From: Nirbheek Chauhan @ 2011-03-09 11:34 UTC (permalink / raw
  To: gentoo-commits

commit:     75ec0b9f144846a5c361f6bf029775e73cd55091
Author:     Nirbheek Chauhan <nirbheek <AT> gentoo <DOT> org>
AuthorDate: Tue Mar  8 13:26:22 2011 +0000
Commit:     Nirbheek Chauhan <nirbheek <AT> gentoo <DOT> org>
CommitDate: Wed Mar  9 11:21:11 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/gnome.git;a=commit;h=75ec0b9f

gnome-base/gnome-keyring: 2.91.4 → 2.91.91

* Update both gtk3 and gtk2 versions
* Add patches from upstream to make ssh-agent work properly

---
 .../files/gnome-keyring-trunk-1.patch              |  169 +++
 .../files/gnome-keyring-trunk-2.patch              |   80 +
 .../files/gnome-keyring-trunk-3.patch              |  892 ++++++++++++
 .../files/gnome-keyring-trunk-4.patch              |   21 +
 .../files/gnome-keyring-trunk-5.patch              | 1538 ++++++++++++++++++++
 .../files/gnome-keyring-trunk-6.patch              |   42 +
 ...00.ebuild => gnome-keyring-2.91.91-r300.ebuild} |   16 +-
 ...-2.91.4.ebuild => gnome-keyring-2.91.91.ebuild} |   11 +-
 gnome-base/gnome-keyring/gnome-keyring-9999.ebuild |    1 -
 9 files changed, 2761 insertions(+), 9 deletions(-)

diff --git a/gnome-base/gnome-keyring/files/gnome-keyring-trunk-1.patch b/gnome-base/gnome-keyring/files/gnome-keyring-trunk-1.patch
new file mode 100644
index 0000000..518cf29
--- /dev/null
+++ b/gnome-base/gnome-keyring/files/gnome-keyring-trunk-1.patch
@@ -0,0 +1,169 @@
+From a78de9fffce4ef2ac669e389b2283e0efbb6feb2 Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw@collabora.co.uk>
+Date: Tue, 08 Mar 2011 17:10:19 +0000
+Subject: [egg] Complete implementation of openssl sytle PEM writing
+
+The openssl PEM parser is particularly fragile, so write some
+stringent tests to check.
+---
+diff --git a/egg/egg-openssl.c b/egg/egg-openssl.c
+index ef715dd..2e83e63 100644
+--- a/egg/egg-openssl.c
++++ b/egg/egg-openssl.c
+@@ -284,13 +284,11 @@ egg_openssl_pem_parse (const guchar *data, gsize n_data,
+ 	return nfound;
+ }
+ 
+-#ifdef UNTESTED_CODE
+-
+ static void 
+ append_each_header (gpointer key, gpointer value, gpointer user_data)
+ {
+ 	GString *string = (GString*)user_data;
+-	
++
+ 	g_string_append (string, (gchar*)key);
+ 	g_string_append (string, ": ");
+ 	g_string_append (string, (gchar*)value);
+@@ -303,14 +301,15 @@ egg_openssl_pem_write (const guchar *data, gsize n_data, GQuark type,
+ {
+ 	GString *string;
+ 	gint state, save;
+-	gsize length, n_prefix;
+-	
++	gsize i, length;
++	gsize n_prefix, estimate;
++
+ 	g_return_val_if_fail (data || !n_data, NULL);
+ 	g_return_val_if_fail (type, NULL);
+ 	g_return_val_if_fail (n_result, NULL);
+ 
+ 	string = g_string_sized_new (4096);
+-	
++
+ 	/* The prefix */
+ 	g_string_append_len (string, PEM_PREF_BEGIN, PEM_PREF_BEGIN_L);
+ 	g_string_append (string, g_quark_to_string (type));
+@@ -324,29 +323,42 @@ egg_openssl_pem_write (const guchar *data, gsize n_data, GQuark type,
+ 	}
+ 
+ 	/* Resize string to fit the base64 data. Algorithm from Glib reference */
+-	length = n_data * 4 / 3 + n_data * 4 / (3 * 72) + 7;
++	estimate = n_data * 4 / 3 + n_data * 4 / (3 * 65) + 7;
+ 	n_prefix = string->len;
+-	g_string_set_size (string, n_prefix + length);
+-	
+-	/* The actual base64 data */
++	g_string_set_size (string, n_prefix + estimate);
++
++	/* The actual base64 data, without line breaks */
+ 	state = save = 0;
+-	length = g_base64_encode_step (data, n_data, TRUE, 
+-	                               string->str + string->len, &state, &save);
++	length = g_base64_encode_step (data, n_data, FALSE,
++	                               string->str + n_prefix, &state, &save);
++	length += g_base64_encode_close (TRUE, string->str + n_prefix + length,
++	                                 &state, &save);
++
++	g_assert (length <= estimate);
+ 	g_string_set_size (string, n_prefix + length);
+-	
++
++	/*
++	 * OpenSSL is absolutely certain that it wants its PEM base64
++	 * lines to be 64 characters in length. So go through and break
++	 * those lines up.
++	 */
++
++	for (i = 64; i < length; i += 64) {
++		g_string_insert_c (string, n_prefix + i, '\n');
++		++length;
++		++i;
++	}
++
+ 	/* The suffix */
+-	g_string_append_c (string, '\n');
+ 	g_string_append_len (string, PEM_PREF_END, PEM_PREF_END_L);
+ 	g_string_append (string, g_quark_to_string (type));
+ 	g_string_append_len (string, PEM_SUFF, PEM_SUFF_L);
+ 	g_string_append_c (string, '\n');
+-	
++
+ 	*n_result = string->len;
+ 	return (guchar*)g_string_free (string, FALSE);
+ }
+ 
+-#endif /* UNTESTED_CODE */
+-
+ /* ----------------------------------------------------------------------------
+  * DEFINITIONS
+  */
+diff --git a/egg/tests/test-openssl.c b/egg/tests/test-openssl.c
+index bf8134a..18f9fd9 100644
+--- a/egg/tests/test-openssl.c
++++ b/egg/tests/test-openssl.c
+@@ -33,12 +33,14 @@
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
++#include <unistd.h>
+ 
+ EGG_SECURE_GLIB_DEFINITIONS ();
+ 
+ typedef struct {
+ 	guchar *input;
+ 	gsize n_input;
++	GQuark reftype;
+ 	guchar *refenc;
+ 	guchar *refdata;
+ 	gsize n_refenc;
+@@ -76,6 +78,9 @@ parse_reference (GQuark type, const guchar *data, gsize n_data,
+ 	gboolean res;
+ 	const gchar *dekinfo;
+ 
++	g_assert (type);
++	test->reftype = type;
++
+ 	g_assert ("no data in PEM callback" && data != NULL);
+ 	g_assert ("no data in PEM callback" && n_data > 0);
+ 	test->refenc = g_memdup (data, n_data);
+@@ -129,6 +134,29 @@ test_write_reference (Test *test, gconstpointer unused)
+ 	g_assert ("data doesn't match input" && memcmp (encrypted, test->refenc, n_encrypted) == 0);
+ }
+ 
++static void
++test_write_exactly_same (Test *test, gconstpointer unused)
++{
++	guchar *result;
++	gsize n_result;
++	guint num;
++
++	num = egg_openssl_pem_parse (test->input, test->n_input, parse_reference, test);
++	g_assert ("couldn't PEM block in reference data" && num == 1);
++
++	result = egg_openssl_pem_write (test->refenc, test->n_refenc, test->reftype,
++	                                test->refheaders, &n_result);
++
++	/*
++	 * Yes sirrr. Openssl's parser is so fragile, that we have to make it
++	 * character for character identical. This includes line breaks, whitespace
++	 * and line endings.
++	 */
++
++	egg_assert_cmpmem (test->input, test->n_input, ==, result, n_result);
++	g_free (result);
++}
++
+ /* 29 bytes (prime number, so block length has bad chance of matching */
+ static const guchar *TEST_DATA = (guchar*)"ABCDEFGHIJKLMNOPQRSTUVWXYZ123";
+ const gsize TEST_DATA_L = 29;
+@@ -175,6 +203,7 @@ main (int argc, char **argv)
+ 
+ 	g_test_add ("/openssl/parse_reference", Test, NULL, setup, test_parse_reference, teardown);
+ 	g_test_add ("/openssl/write_reference", Test, NULL, setup, test_write_reference, teardown);
++	g_test_add ("/openssl/write_exactly_same", Test, NULL, setup, test_write_exactly_same, teardown);
+ 	g_test_add ("/openssl/openssl_roundtrip", Test, NULL, setup, test_openssl_roundtrip, teardown);
+ 
+ 	return g_test_run ();
+--
+cgit v0.8.3.4

diff --git a/gnome-base/gnome-keyring/files/gnome-keyring-trunk-2.patch b/gnome-base/gnome-keyring/files/gnome-keyring-trunk-2.patch
new file mode 100644
index 0000000..ebbad47
--- /dev/null
+++ b/gnome-base/gnome-keyring/files/gnome-keyring-trunk-2.patch
@@ -0,0 +1,80 @@
+From e4df658ea0751ce78598b8783664899b0ad54a52 Mon Sep 17 00:00:00 2001
+From: Matthias Clasen <mclasen@redhat.com>
+Date: Sat, 26 Feb 2011 05:38:48 +0000
+Subject: Add a desktop file for gnome-keyring-prompt
+
+This is necessary for gnome-shell to pick up a meaningful
+name and icon to display in the application menu while the
+dialog is shown.
+https://bugzilla.gnome.org/show_bug.cgi?id=643229
+---
+diff --git a/configure.in b/configure.in
+index 3249666..8e03c7d 100644
+--- a/configure.in
++++ b/configure.in
+@@ -730,6 +730,7 @@ schema/Makefile
+ testing/Makefile
+ tool/Makefile
+ ui/Makefile
++ui/gnome-keyring-prompt.desktop.in
+ ui/tests/Makefile
+ ])
+ 
+diff --git a/po/POTFILES.in b/po/POTFILES.in
+index a21a4f9..7485677 100644
+--- a/po/POTFILES.in
++++ b/po/POTFILES.in
+@@ -30,4 +30,5 @@ pkcs11/wrap-layer/gkm-wrap-login.c
+ pkcs11/wrap-layer/gkm-wrap-prompt.c
+ tool/gkr-tool.c
+ ui/gku-prompt-tool.c
++ui/gnome-keyring-prompt.desktop.in.in
+ [type: gettext/glade]ui/gku-prompt.ui
+diff --git a/po/POTFILES.skip b/po/POTFILES.skip
+index 4230965..4a6ef38 100644
+--- a/po/POTFILES.skip
++++ b/po/POTFILES.skip
+@@ -6,3 +6,4 @@ daemon/org.freedesktop.secrets.service.in
+ daemon/org.gnome.keyring.service.in
+ gcr/gcr-import-dialog.ui
+ gcr/gcr-certificate-basics-widget.ui
++ui/gnome-keyring-prompt.desktop.in
+diff --git a/ui/Makefile.am b/ui/Makefile.am
+index 5073e46..ded3d50 100644
+--- a/ui/Makefile.am
++++ b/ui/Makefile.am
+@@ -84,3 +84,18 @@ if WITH_GTK3
+ install-exec-hook:
+ 	@test -e "$(DESTDIR)$(libexecdir)/gnome-keyring-prompt" || (cd $(DESTDIR)$(libexecdir) && $(LN_S) gnome-keyring-prompt@GCR_VERSION_SUFFIX@ gnome-keyring-prompt)
+ endif
++
++@INTLTOOL_DESKTOP_RULE@
++desktopdir= $(datadir)/applications
++desktop_in_in_files = gnome-keyring-prompt.desktop.in.in
++desktop_in_files = gnome-keyring-prompt.desktop.in
++desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
++
++EXTRA_DIST += \
++	$(desktop_in_in_files)
++
++CLEANFILES = \
++	$(desktop_DATA)
++
++DISTCLEANFILES = \
++	$(desktop_in_files)
+diff --git a/ui/gnome-keyring-prompt.desktop.in.in b/ui/gnome-keyring-prompt.desktop.in.in
+new file mode 100644
+index 0000000..917b5a0
+--- a/dev/null
++++ b/ui/gnome-keyring-prompt.desktop.in.in
+@@ -0,0 +1,8 @@
++[Desktop Entry]
++_Name=Keyring Access
++_Comment=Unlock access to passwords and other secrets
++Icon=security-medium
++Exec=@LIBEXECDIR@/gnome-keyring-prompt
++Terminal=false
++Type=Application
++NoDisplay=true
+--
+cgit v0.8.3.4

diff --git a/gnome-base/gnome-keyring/files/gnome-keyring-trunk-3.patch b/gnome-base/gnome-keyring/files/gnome-keyring-trunk-3.patch
new file mode 100644
index 0000000..28d9f30
--- /dev/null
+++ b/gnome-base/gnome-keyring/files/gnome-keyring-trunk-3.patch
@@ -0,0 +1,892 @@
+From c8b3144f36edb54f3af4d08bd0cb65acca5bf4e9 Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw@collabora.co.uk>
+Date: Wed, 09 Mar 2011 09:27:51 +0000
+Subject: [dbus] Pass an alias argument along to a CreateCollection dbus method.
+
+This is new in the specification and prevents problems with race
+conditions and multiple applications all trying to create the
+default keyring.
+---
+diff --git a/daemon/dbus/gkd-secret-create.c b/daemon/dbus/gkd-secret-create.c
+index a21a206..bdca3e2 100644
+--- a/daemon/dbus/gkd-secret-create.c
++++ b/daemon/dbus/gkd-secret-create.c
+@@ -22,12 +22,15 @@
+ #include "config.h"
+ 
+ #include "gkd-secret-create.h"
++#include "gkd-secret-dispatch.h"
+ #include "gkd-secret-error.h"
++#include "gkd-secret-objects.h"
+ #include "gkd-secret-prompt.h"
+ #include "gkd-secret-secret.h"
+ #include "gkd-secret-service.h"
+ #include "gkd-secret-session.h"
+ #include "gkd-secret-types.h"
++#include "gkd-secret-unlock.h"
+ #include "gkd-secret-util.h"
+ 
+ #include "egg/egg-error.h"
+@@ -43,12 +46,14 @@
+ 
+ enum {
+ 	PROP_0,
+-	PROP_PKCS11_ATTRIBUTES
++	PROP_PKCS11_ATTRIBUTES,
++	PROP_ALIAS
+ };
+ 
+ struct _GkdSecretCreate {
+ 	GkdSecretPrompt parent;
+ 	GckAttributes *pkcs11_attrs;
++	gchar *alias;
+ 	gchar *result_path;
+ };
+ 
+@@ -93,6 +98,8 @@ static gboolean
+ create_collection_with_secret (GkdSecretCreate *self, GkdSecretSecret *master)
+ {
+ 	DBusError derr = DBUS_ERROR_INIT;
++	GkdSecretService *service;
++	gchar *identifier;
+ 
+ 	g_assert (GKD_SECRET_IS_CREATE (self));
+ 	g_assert (master);
+@@ -106,9 +113,84 @@ create_collection_with_secret (GkdSecretCreate *self, GkdSecretSecret *master)
+ 		return FALSE;
+ 	}
+ 
++	if (self->alias) {
++		if (!gkd_secret_util_parse_path (self->result_path, &identifier, NULL))
++			g_assert_not_reached ();
++		service = gkd_secret_prompt_get_service (GKD_SECRET_PROMPT (self));
++		gkd_secret_service_set_alias (service, self->alias, identifier);
++		g_free (identifier);
++	}
++
+ 	return TRUE;
+ }
+ 
++static gboolean
++locate_alias_collection_if_exists (GkdSecretCreate *self)
++{
++	GkdSecretService *service;
++	GkdSecretObjects *objects;
++	GckObject *collection;
++	const gchar *identifier;
++	const gchar *caller;
++	gchar *path;
++
++	if (!self->alias)
++		return FALSE;
++
++	g_assert (!self->result_path);
++
++	service = gkd_secret_prompt_get_service (GKD_SECRET_PROMPT (self));
++	caller = gkd_secret_prompt_get_caller (GKD_SECRET_PROMPT (self));
++	objects = gkd_secret_prompt_get_objects (GKD_SECRET_PROMPT (self));
++
++	identifier = gkd_secret_service_get_alias (service, self->alias);
++	if (!identifier)
++		return FALSE;
++
++	/* Make sure it actually exists */
++	path = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, -1);
++	collection = gkd_secret_objects_lookup_collection (objects, caller, path);
++
++	if (collection) {
++		self->result_path = path;
++		g_object_unref (collection);
++		return TRUE;
++	} else {
++		g_free (path);
++		return FALSE;
++	}
++}
++
++static void
++unlock_or_complete_this_prompt (GkdSecretCreate *self)
++{
++	GkdSecretUnlock *unlock;
++	GkdSecretPrompt *prompt;
++
++	g_object_ref (self);
++	prompt = GKD_SECRET_PROMPT (self);
++
++	unlock = gkd_secret_unlock_new (gkd_secret_prompt_get_service (prompt),
++	                                gkd_secret_prompt_get_caller (prompt),
++	                                gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (self)));
++	gkd_secret_unlock_queue (unlock, self->result_path);
++
++	/*
++	 * If any need to be unlocked, then replace this prompt
++	 * object with an unlock prompt object, and call the prompt
++	 * method.
++	 */
++	if (gkd_secret_unlock_have_queued (unlock)) {
++		gkd_secret_service_publish_dispatch (gkd_secret_prompt_get_service (prompt),
++		                                     gkd_secret_prompt_get_caller (prompt),
++		                                     GKD_SECRET_DISPATCH (unlock));
++		gkd_secret_unlock_call_prompt (unlock, gkd_secret_prompt_get_window_id (prompt));
++	}
++
++	g_object_unref (unlock);
++	g_object_unref (self);
++}
++
+ /* -----------------------------------------------------------------------------
+  * OBJECT
+  */
+@@ -120,7 +202,15 @@ gkd_secret_create_prompt_ready (GkdSecretPrompt *prompt)
+ 	GkdSecretSecret *master;
+ 
+ 	if (!gku_prompt_has_response (GKU_PROMPT (prompt))) {
+-		prepare_create_prompt (self);
++
++		/* Does the alias exist? */
++		if (locate_alias_collection_if_exists (self))
++			unlock_or_complete_this_prompt (self);
++
++		/* Otherwise we're going to prompt */
++		else
++			prepare_create_prompt (self);
++
+ 		return;
+ 	}
+ 
+@@ -161,10 +251,8 @@ gkd_secret_create_finalize (GObject *obj)
+ 	GkdSecretCreate *self = GKD_SECRET_CREATE (obj);
+ 
+ 	gck_attributes_unref (self->pkcs11_attrs);
+-	self->pkcs11_attrs = NULL;
+-
+ 	g_free (self->result_path);
+-	self->result_path = NULL;
++	g_free (self->alias);
+ 
+ 	G_OBJECT_CLASS (gkd_secret_create_parent_class)->finalize (obj);
+ }
+@@ -181,6 +269,10 @@ gkd_secret_create_set_property (GObject *obj, guint prop_id, const GValue *value
+ 		self->pkcs11_attrs = g_value_dup_boxed (value);
+ 		g_return_if_fail (self->pkcs11_attrs);
+ 		break;
++	case PROP_ALIAS:
++		g_return_if_fail (!self->alias);
++		self->alias = g_value_dup_string (value);
++		break;
+ 	default:
+ 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ 		break;
+@@ -197,6 +289,9 @@ gkd_secret_create_get_property (GObject *obj, guint prop_id, GValue *value,
+ 	case PROP_PKCS11_ATTRIBUTES:
+ 		g_value_set_boxed (value, self->pkcs11_attrs);
+ 		break;
++	case PROP_ALIAS:
++		g_value_set_string (value, self->alias);
++		break;
+ 	default:
+ 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ 		break;
+@@ -219,6 +314,10 @@ gkd_secret_create_class_init (GkdSecretCreateClass *klass)
+ 	g_object_class_install_property (gobject_class, PROP_PKCS11_ATTRIBUTES,
+ 		g_param_spec_boxed ("pkcs11-attributes", "PKCS11 Attributes", "PKCS11 Attributes",
+ 		                     GCK_TYPE_ATTRIBUTES, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
++
++	g_object_class_install_property (gobject_class, PROP_ALIAS,
++		g_param_spec_string ("alias", "Alias", "Collection Alias",
++		                     NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ }
+ 
+ /* -----------------------------------------------------------------------------
+@@ -227,12 +326,13 @@ gkd_secret_create_class_init (GkdSecretCreateClass *klass)
+ 
+ GkdSecretCreate*
+ gkd_secret_create_new (GkdSecretService *service, const gchar *caller,
+-                       GckAttributes *attrs)
++                       GckAttributes *attrs, const gchar *alias)
+ {
+ 	return g_object_new (GKD_SECRET_TYPE_CREATE,
+ 	                     "service", service,
+ 	                     "caller", caller,
+ 	                     "pkcs11-attributes", attrs,
++	                     "alias", alias,
+ 	                     NULL);
+ }
+ 
+diff --git a/daemon/dbus/gkd-secret-create.h b/daemon/dbus/gkd-secret-create.h
+index ad37a58..d24afe9 100644
+--- a/daemon/dbus/gkd-secret-create.h
++++ b/daemon/dbus/gkd-secret-create.h
+@@ -46,7 +46,8 @@ GType               gkd_secret_create_get_type                (void);
+ 
+ GkdSecretCreate*    gkd_secret_create_new                     (GkdSecretService *service,
+                                                                const gchar *caller,
+-                                                               GckAttributes *attrs);
++                                                               GckAttributes *attrs,
++                                                               const gchar *alias);
+ 
+ GckObject*          gkd_secret_create_with_credential         (GckSession *session,
+                                                                GckAttributes *attrs,
+diff --git a/daemon/dbus/gkd-secret-introspect.c b/daemon/dbus/gkd-secret-introspect.c
+index 8fee835..b6f9813 100644
+--- a/daemon/dbus/gkd-secret-introspect.c
++++ b/daemon/dbus/gkd-secret-introspect.c
+@@ -200,7 +200,8 @@ const gchar *gkd_secret_introspect_service =
+ 	"		</method>\n"
+ 	"\n"
+ 	"		<method name='CreateCollection'>\n"
+-	"			<arg name='props' type='a{sv}' direction='in'/>\n"
++	"			<arg name='properties' type='a{sv}' direction='in'/>\n"
++	"			<arg name='alias' type='s' direction='in'/>\n"
+ 	"			<arg name='collection' type='o' direction='out'/>\n"
+ 	"			<arg name='prompt' type='o' direction='out'/>\n"
+ 	"		</method>\n"
+diff --git a/daemon/dbus/gkd-secret-objects.c b/daemon/dbus/gkd-secret-objects.c
+index 1766907..4cfd4e7 100644
+--- a/daemon/dbus/gkd-secret-objects.c
++++ b/daemon/dbus/gkd-secret-objects.c
+@@ -49,7 +49,6 @@ struct _GkdSecretObjects {
+ 	GObject parent;
+ 	GkdSecretService *service;
+ 	GckSlot *pkcs11_slot;
+-	GHashTable *aliases;
+ };
+ 
+ G_DEFINE_TYPE (GkdSecretObjects, gkd_secret_objects, G_TYPE_OBJECT);
+@@ -71,7 +70,7 @@ parse_object_path (GkdSecretObjects *self, const gchar *path, gchar **collection
+ 		return FALSE;
+ 
+ 	if (g_str_has_prefix (path, SECRET_ALIAS_PREFIX)) {
+-		replace = g_hash_table_lookup (self->aliases, *collection);
++		replace = gkd_secret_service_get_alias (self->service, *collection);
+ 		if (!replace) {
+ 
+ 			/*
+@@ -831,7 +830,7 @@ gkd_secret_objects_constructor (GType type, guint n_props, GObjectConstructParam
+ static void
+ gkd_secret_objects_init (GkdSecretObjects *self)
+ {
+-	self->aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
++
+ }
+ 
+ static void
+@@ -858,7 +857,6 @@ gkd_secret_objects_finalize (GObject *obj)
+ {
+ 	GkdSecretObjects *self = GKD_SECRET_OBJECTS (obj);
+ 
+-	g_hash_table_destroy (self->aliases);
+ 	g_assert (!self->pkcs11_slot);
+ 	g_assert (!self->service);
+ 
+@@ -1333,20 +1331,3 @@ gkd_secret_objects_handle_get_secrets (GkdSecretObjects *self, DBusMessage *mess
+ 
+ 	return reply;
+ }
+-
+-const gchar*
+-gkd_secret_objects_get_alias (GkdSecretObjects *self, const gchar *alias)
+-{
+-	g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
+-	g_return_val_if_fail (alias, NULL);
+-	return g_hash_table_lookup (self->aliases, alias);
+-}
+-
+-void
+-gkd_secret_objects_set_alias (GkdSecretObjects *self, const gchar *alias,
+-                              const gchar *identifier)
+-{
+-	g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
+-	g_return_if_fail (alias);
+-	g_hash_table_replace (self->aliases, g_strdup (alias), g_strdup (identifier));
+-}
+diff --git a/daemon/dbus/gkd-secret-objects.h b/daemon/dbus/gkd-secret-objects.h
+index 2f2ffb2..2d54509 100644
+--- a/daemon/dbus/gkd-secret-objects.h
++++ b/daemon/dbus/gkd-secret-objects.h
+@@ -74,11 +74,4 @@ GckObject*          gkd_secret_objects_lookup_item               (GkdSecretObjec
+                                                                   const gchar *caller,
+                                                                   const gchar *path);
+ 
+-const gchar*        gkd_secret_objects_get_alias                 (GkdSecretObjects *self,
+-                                                                  const gchar *alias);
+-
+-void                gkd_secret_objects_set_alias                 (GkdSecretObjects *self,
+-                                                                  const gchar *alias,
+-                                                                  const gchar *identifier);
+-
+ #endif /* __GKD_SECRET_OBJECTS_H__ */
+diff --git a/daemon/dbus/gkd-secret-prompt.c b/daemon/dbus/gkd-secret-prompt.c
+index 1f67599..7ff6c79 100644
+--- a/daemon/dbus/gkd-secret-prompt.c
++++ b/daemon/dbus/gkd-secret-prompt.c
+@@ -48,7 +48,6 @@ enum {
+ #define PROMPT_IKE_GROUP  "ietf-ike-grp-modp-1536"
+ 
+ struct _GkdSecretPromptPrivate {
+-	GkuPrompt parent;
+ 	gchar *object_path;
+ 	GkdSecretService *service;
+ 	GkdSecretSession *session;
+@@ -443,6 +442,13 @@ gkd_secret_prompt_get_caller (GkdSecretPrompt *self)
+ 	return self->pv->caller;
+ }
+ 
++const gchar*
++gkd_secret_prompt_get_window_id (GkdSecretPrompt *self)
++{
++	g_return_val_if_fail (GKD_SECRET_IS_PROMPT (self), NULL);
++	return self->pv->window_id;
++}
++
+ GckSession*
+ gkd_secret_prompt_get_pkcs11_session (GkdSecretPrompt *self)
+ {
+@@ -451,6 +457,14 @@ gkd_secret_prompt_get_pkcs11_session (GkdSecretPrompt *self)
+ 	return gkd_secret_service_get_pkcs11_session (self->pv->service, self->pv->caller);
+ }
+ 
++GkdSecretService*
++gkd_secret_prompt_get_service (GkdSecretPrompt *self)
++{
++	g_return_val_if_fail (GKD_SECRET_IS_PROMPT (self), NULL);
++	g_return_val_if_fail (self->pv->service, NULL);
++	return self->pv->service;
++}
++
+ GkdSecretObjects*
+ gkd_secret_prompt_get_objects (GkdSecretPrompt *self)
+ {
+diff --git a/daemon/dbus/gkd-secret-prompt.h b/daemon/dbus/gkd-secret-prompt.h
+index 1766a5d..4423be2 100644
+--- a/daemon/dbus/gkd-secret-prompt.h
++++ b/daemon/dbus/gkd-secret-prompt.h
+@@ -59,6 +59,8 @@ GType               gkd_secret_prompt_get_type                (void);
+ 
+ const gchar*        gkd_secret_prompt_get_caller              (GkdSecretPrompt *self);
+ 
++const gchar*        gkd_secret_prompt_get_window_id           (GkdSecretPrompt *self);
++
+ GckSession*         gkd_secret_prompt_get_pkcs11_session      (GkdSecretPrompt *self);
+ 
+ GkdSecretService*   gkd_secret_prompt_get_service             (GkdSecretPrompt *self);
+diff --git a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-service.c
+index 9c0071c..198ad65 100644
+--- a/daemon/dbus/gkd-secret-service.c
++++ b/daemon/dbus/gkd-secret-service.c
+@@ -59,6 +59,7 @@ struct _GkdSecretService {
+ 	GHashTable *clients;
+ 	gchar *match_rule;
+ 	GkdSecretObjects *objects;
++	GHashTable *aliases;
+ };
+ 
+ typedef struct _ServiceClient {
+@@ -67,8 +68,7 @@ typedef struct _ServiceClient {
+ 	pid_t caller_pid;
+ 	CK_G_APPLICATION app;
+ 	GckSession *pkcs11_session;
+-	GHashTable *sessions;
+-	GHashTable *prompts;
++	GHashTable *dispatch;
+ } ServiceClient;
+ 
+ /* Forward declaration */
+@@ -93,9 +93,11 @@ update_default (GkdSecretService *self, gboolean force)
+ 	const gchar *identifier;
+ 	gchar *path;
+ 
+-	identifier = gkd_secret_objects_get_alias (self->objects, "default");
+-	if (!force && identifier)
+-		return;
++	if (!force) {
++		identifier = g_hash_table_lookup (self->aliases, "default");
++		if (identifier)
++			return;
++	}
+ 
+ 	path = default_path ();
+ 	if (g_file_get_contents (path, &contents, NULL, NULL)) {
+@@ -107,8 +109,7 @@ update_default (GkdSecretService *self, gboolean force)
+ 	}
+ 	g_free (path);
+ 
+-	gkd_secret_objects_set_alias (self->objects, "default", contents);
+-	g_free (contents);
++	g_hash_table_replace (self->aliases, g_strdup ("default"), contents);
+ }
+ 
+ static void
+@@ -118,7 +119,7 @@ store_default (GkdSecretService *self)
+ 	const gchar *identifier;
+ 	gchar *path;
+ 
+-	identifier = gkd_secret_objects_get_alias (self->objects, "default");
++	identifier = g_hash_table_lookup (self->aliases, "default");
+ 	if (!identifier)
+ 		return;
+ 
+@@ -172,8 +173,7 @@ free_client (gpointer data)
+ 	}
+ 
+ 	/* The sessions and prompts the client has open */
+-	g_hash_table_destroy (client->sessions);
+-	g_hash_table_destroy (client->prompts);
++	g_hash_table_destroy (client->dispatch);
+ 
+ 	g_free (client);
+ }
+@@ -237,8 +237,7 @@ on_get_connection_unix_process_id (DBusPendingCall *pending, gpointer user_data)
+ 		if (caller_pid != 0)
+ 			client->caller_exec = egg_unix_credentials_executable (caller_pid);
+ 		client->app.applicationData = client;
+-		client->sessions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, dispose_and_unref);
+-		client->prompts = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, dispose_and_unref);
++		client->dispatch = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, dispose_and_unref);
+ 
+ 		g_hash_table_replace (self->clients, client->caller_peer, client);
+ 
+@@ -371,10 +370,8 @@ static DBusMessage*
+ service_method_open_session (GkdSecretService *self, DBusMessage *message)
+ {
+ 	GkdSecretSession *session;
+-	ServiceClient *client;
+ 	DBusMessage *reply = NULL;
+ 	const gchar *caller;
+-	const gchar *path;
+ 
+ 	if (!dbus_message_has_signature (message, "sv"))
+ 		return NULL;
+@@ -385,18 +382,11 @@ service_method_open_session (GkdSecretService *self, DBusMessage *message)
+ 	session = gkd_secret_session_new (self, caller);
+ 	reply = gkd_secret_session_handle_open (session, message);
+ 
+-	if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN) {
+-		/* Take ownership of the session */
+-		client = g_hash_table_lookup (self->clients, caller);
+-		g_return_val_if_fail (client, NULL);
+-		path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (session));
+-		g_return_val_if_fail (!g_hash_table_lookup (client->sessions, path), NULL);
+-		g_hash_table_replace (client->sessions, (gpointer)path, session);
+-
+-	} else {
+-		g_object_unref (session);
+-	}
++	if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
++		gkd_secret_service_publish_dispatch (self, caller,
++		                                     GKD_SECRET_DISPATCH (session));
+ 
++	g_object_unref (session);
+ 	return reply;
+ }
+ 
+@@ -406,14 +396,14 @@ service_method_create_collection (GkdSecretService *self, DBusMessage *message)
+ 	DBusMessageIter iter, array;
+ 	GckAttributes *attrs;
+ 	GkdSecretCreate *create;
+-	ServiceClient *client;
+ 	DBusMessage *reply;
+ 	const gchar *path;
++	const gchar *alias;
+ 	const char *caller;
+ 	const gchar *coll;
+ 
+ 	/* Parse the incoming message */
+-	if (!dbus_message_has_signature (message, "a{sv}"))
++	if (!dbus_message_has_signature (message, "a{sv}s"))
+ 		return NULL;
+ 	if (!dbus_message_iter_init (message, &iter))
+ 		g_return_val_if_reached (NULL);
+@@ -424,18 +414,31 @@ service_method_create_collection (GkdSecretService *self, DBusMessage *message)
+ 		return dbus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS,
+ 		                                      "Invalid properties");
+ 	}
++	if (!dbus_message_iter_next (&iter))
++		g_return_val_if_reached (NULL);
++	dbus_message_iter_get_basic (&iter, &alias);
++
++	/* Empty alias is no alias */
++	if (alias) {
++		if (!alias[0]) {
++			alias = NULL;
++		} else if (!g_str_equal (alias, "default")) {
++			gck_attributes_unref (attrs);
++			return dbus_message_new_error (message, DBUS_ERROR_NOT_SUPPORTED,
++			                               "Only the 'default' alias is supported");
++		}
++	}
+ 
+ 	gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
+ 
+ 	/* Create the prompt object, for the password */
+ 	caller = dbus_message_get_sender (message);
+-	create = gkd_secret_create_new (self, caller, attrs);
++	create = gkd_secret_create_new (self, caller, attrs, alias);
+ 	gck_attributes_unref (attrs);
+ 
+ 	path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (create));
+-	client = g_hash_table_lookup (self->clients, caller);
+-	g_return_val_if_fail (client, NULL);
+-	g_hash_table_replace (client->prompts, (gpointer)path, create);
++	gkd_secret_service_publish_dispatch (self, caller,
++	                                     GKD_SECRET_DISPATCH (create));
+ 
+ 	coll = "/";
+ 	reply = dbus_message_new_method_return (message);
+@@ -444,6 +447,7 @@ service_method_create_collection (GkdSecretService *self, DBusMessage *message)
+ 	                          DBUS_TYPE_OBJECT_PATH, &path,
+ 	                          DBUS_TYPE_INVALID);
+ 
++	g_object_unref (create);
+ 	return reply;
+ }
+ 
+@@ -461,7 +465,6 @@ static DBusMessage*
+ service_method_unlock (GkdSecretService *self, DBusMessage *message)
+ {
+ 	GkdSecretUnlock *unlock;
+-	ServiceClient *client;
+ 	DBusMessage *reply;
+ 	const char *caller;
+ 	const gchar *path;
+@@ -474,17 +477,16 @@ service_method_unlock (GkdSecretService *self, DBusMessage *message)
+ 		return NULL;
+ 
+ 	caller = dbus_message_get_sender (message);
+-	unlock = gkd_secret_unlock_new (self, caller);
++	unlock = gkd_secret_unlock_new (self, caller, NULL);
+ 	for (i = 0; i < n_objpaths; ++i)
+ 		gkd_secret_unlock_queue (unlock, objpaths[i]);
+ 	dbus_free_string_array (objpaths);
+ 
+ 	/* So do we need to prompt? */
+ 	if (gkd_secret_unlock_have_queued (unlock)) {
+-		client = g_hash_table_lookup (self->clients, caller);
+-		g_return_val_if_fail (client, NULL);
++		gkd_secret_service_publish_dispatch (self, caller,
++		                                     GKD_SECRET_DISPATCH (unlock));
+ 		path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (unlock));
+-		g_hash_table_replace (client->prompts, (gpointer)path, g_object_ref (unlock));
+ 
+ 	/* No need to prompt */
+ 	} else {
+@@ -546,7 +548,6 @@ static DBusMessage*
+ service_method_change_lock (GkdSecretService *self, DBusMessage *message)
+ {
+ 	GkdSecretChange *change;
+-	ServiceClient *client;
+ 	DBusMessage *reply;
+ 	const char *caller;
+ 	const gchar *path;
+@@ -564,10 +565,9 @@ service_method_change_lock (GkdSecretService *self, DBusMessage *message)
+ 	g_object_unref (collection);
+ 
+ 	change = gkd_secret_change_new (self, caller, path);
+-	client = g_hash_table_lookup (self->clients, caller);
+-	g_return_val_if_fail (client, NULL);
+ 	path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (change));
+-	g_hash_table_replace (client->prompts, (gpointer)path, g_object_ref (change));
++	gkd_secret_service_publish_dispatch (self, caller,
++	                                     GKD_SECRET_DISPATCH (change));
+ 
+ 	reply = dbus_message_new_method_return (message);
+ 	dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
+@@ -588,9 +588,7 @@ service_method_read_alias (GkdSecretService *self, DBusMessage *message)
+ 	if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &alias, DBUS_TYPE_INVALID))
+ 		return NULL;
+ 
+-	update_default (self, FALSE);
+-
+-	identifier = gkd_secret_objects_get_alias (self->objects, alias);
++	identifier = gkd_secret_service_get_alias (self, alias);
+ 	if (identifier)
+ 		path = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, -1);
+ 
+@@ -647,11 +645,9 @@ service_method_set_alias (GkdSecretService *self, DBusMessage *message)
+ 
+ 	g_object_unref (collection);
+ 
+-	gkd_secret_objects_set_alias (self->objects, alias, identifier);
++	gkd_secret_service_set_alias (self, alias, identifier);
+ 	g_free (identifier);
+ 
+-	store_default (self);
+-
+ 	return dbus_message_new_method_return (message);
+ }
+ 
+@@ -907,17 +903,10 @@ service_dispatch_message (GkdSecretService *self, DBusMessage *message)
+ 	path = dbus_message_get_path (message);
+ 	g_return_if_fail (path);
+ 
+-	/* Dispatched to a session, find a session in this client */
+-	if (object_path_has_prefix (path, SECRET_SESSION_PREFIX)) {
+-		object = g_hash_table_lookup (client->sessions, path);
+-		if (object == NULL)
+-			reply = gkd_secret_error_no_such_object (message);
+-		else
+-			reply = gkd_secret_dispatch_message (GKD_SECRET_DISPATCH (object), message);
+-
+-	/* Dispatched to a prompt, find a prompt in this client */
+-	} else if (object_path_has_prefix (path, SECRET_PROMPT_PREFIX)) {
+-		object = g_hash_table_lookup (client->prompts, path);
++	/* Dispatched to a session or prompt */
++	if (object_path_has_prefix (path, SECRET_SESSION_PREFIX) ||
++	    object_path_has_prefix (path, SECRET_PROMPT_PREFIX)) {
++		object = g_hash_table_lookup (client->dispatch, path);
+ 		if (object == NULL)
+ 			reply = gkd_secret_error_no_such_object (message);
+ 		else
+@@ -1064,6 +1053,7 @@ static void
+ gkd_secret_service_init (GkdSecretService *self)
+ {
+ 	self->clients = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_client);
++	self->aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ }
+ 
+ static void
+@@ -1106,6 +1096,9 @@ gkd_secret_service_finalize (GObject *obj)
+ 	g_hash_table_destroy (self->clients);
+ 	self->clients = NULL;
+ 
++	g_hash_table_destroy (self->aliases);
++	self->aliases = NULL;
++
+ 	G_OBJECT_CLASS (gkd_secret_service_parent_class)->finalize (obj);
+ }
+ 
+@@ -1251,6 +1244,7 @@ gkd_secret_service_lookup_session (GkdSecretService *self, const gchar *path,
+                                    const gchar *caller)
+ {
+ 	ServiceClient *client;
++	gpointer object;
+ 
+ 	g_return_val_if_fail (GKD_SECRET_IS_SERVICE (self), NULL);
+ 	g_return_val_if_fail (path, NULL);
+@@ -1259,7 +1253,11 @@ gkd_secret_service_lookup_session (GkdSecretService *self, const gchar *path,
+ 	client = g_hash_table_lookup (self->clients, caller);
+ 	g_return_val_if_fail (client, NULL);
+ 
+-	return g_hash_table_lookup (client->sessions, path);
++	object = g_hash_table_lookup (client->dispatch, path);
++	if (object == NULL || !GKD_SECRET_IS_SESSION (object))
++		return NULL;
++
++	return GKD_SECRET_SESSION (object);
+ }
+ 
+ void
+@@ -1277,5 +1275,53 @@ gkd_secret_service_close_session (GkdSecretService *self, GkdSecretSession *sess
+ 	g_return_if_fail (client);
+ 
+ 	path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (session));
+-	g_hash_table_remove (client->sessions, path);
++	g_hash_table_remove (client->dispatch, path);
++}
++
++const gchar*
++gkd_secret_service_get_alias (GkdSecretService *self, const gchar *alias)
++{
++	const gchar *identifier;
++
++	g_return_val_if_fail (GKD_SECRET_IS_SERVICE (self), NULL);
++	g_return_val_if_fail (alias, NULL);
++
++	identifier =  g_hash_table_lookup (self->aliases, alias);
++	if (!identifier && g_str_equal (alias, "default")) {
++		update_default (self, TRUE);
++		identifier = g_hash_table_lookup (self->aliases, alias);
++	}
++	return identifier;
++}
++
++void
++gkd_secret_service_set_alias (GkdSecretService *self, const gchar *alias,
++                              const gchar *identifier)
++{
++	g_return_if_fail (GKD_SECRET_IS_SERVICE (self));
++	g_return_if_fail (alias);
++
++	g_hash_table_replace (self->aliases, g_strdup (alias), g_strdup (identifier));
++
++	if (g_str_equal (alias, "default"))
++		store_default (self);
++}
++
++void
++gkd_secret_service_publish_dispatch (GkdSecretService *self, const gchar *caller,
++                                     GkdSecretDispatch *object)
++{
++	ServiceClient *client;
++	const gchar *path;
++
++	g_return_if_fail (GKD_SECRET_IS_SERVICE (self));
++	g_return_if_fail (caller);
++	g_return_if_fail (GKD_SECRET_IS_DISPATCH (object));
++
++	/* Take ownership of the session */
++	client = g_hash_table_lookup (self->clients, caller);
++	g_return_if_fail (client);
++	path = gkd_secret_dispatch_get_object_path (object);
++	g_return_if_fail (!g_hash_table_lookup (client->dispatch, path));
++	g_hash_table_replace (client->dispatch, (gpointer)path, g_object_ref (object));
+ }
+diff --git a/daemon/dbus/gkd-secret-service.h b/daemon/dbus/gkd-secret-service.h
+index 6eac4ed..84356c3 100644
+--- a/daemon/dbus/gkd-secret-service.h
++++ b/daemon/dbus/gkd-secret-service.h
+@@ -66,4 +66,15 @@ void                    gkd_secret_service_close_session           (GkdSecretSer
+ void                    gkd_secret_service_send                    (GkdSecretService *self,
+                                                                     DBusMessage *message);
+ 
++const gchar*            gkd_secret_service_get_alias               (GkdSecretService *self,
++                                                                    const gchar *alias);
++
++void                    gkd_secret_service_set_alias               (GkdSecretService *self,
++                                                                    const gchar *alias,
++                                                                    const gchar *identifier);
++
++void                    gkd_secret_service_publish_dispatch        (GkdSecretService *self,
++                                                                    const gchar *caller,
++                                                                    GkdSecretDispatch *object);
++
+ #endif /* ___SECRET_SERVICE_H__ */
+diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-unlock.c
+index 57dad3d..35f672a 100644
+--- a/daemon/dbus/gkd-secret-unlock.c
++++ b/daemon/dbus/gkd-secret-unlock.c
+@@ -267,11 +267,7 @@ prompt_method_prompt (GkdSecretUnlock *self, DBusMessage *message)
+ 		return dbus_message_new_error (message, SECRET_ERROR_ALREADY_EXISTS,
+ 		                               "This prompt has already been shown.");
+ 
+-	g_free (self->window_id);
+-	self->window_id = g_strdup (window_id);
+-
+-	self->prompted = TRUE;
+-	perform_next_unlock (self);
++	gkd_secret_unlock_call_prompt (self, window_id);
+ 
+ 	reply = dbus_message_new_method_return (message);
+ 	dbus_message_append_args (reply, DBUS_TYPE_INVALID);
+@@ -350,7 +346,8 @@ gkd_secret_unlock_constructor (GType type, guint n_props, GObjectConstructParam
+ 	g_return_val_if_fail (self->service, NULL);
+ 
+ 	/* Setup the path for the object */
+-	self->object_path = g_strdup_printf (SECRET_PROMPT_PREFIX "/u%d", ++unique_prompt_number);
++	if (!self->object_path)
++		self->object_path = g_strdup_printf (SECRET_PROMPT_PREFIX "/u%d", ++unique_prompt_number);
+ 
+ 	return G_OBJECT (self);
+ }
+@@ -426,6 +423,10 @@ gkd_secret_unlock_set_property (GObject *obj, guint prop_id, const GValue *value
+ 		g_object_add_weak_pointer (G_OBJECT (self->service),
+ 		                           (gpointer*)&(self->service));
+ 		break;
++	case PROP_OBJECT_PATH:
++		g_return_if_fail (!self->object_path);
++		self->object_path = g_strdup (g_value_get_pointer (value));
++		break;
+ 	default:
+ 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ 		break;
+@@ -472,7 +473,7 @@ gkd_secret_unlock_class_init (GkdSecretUnlockClass *klass)
+ 
+ 	g_object_class_install_property (gobject_class, PROP_OBJECT_PATH,
+ 	        g_param_spec_pointer ("object-path", "Object Path", "DBus Object Path",
+-		                      G_PARAM_READABLE));
++		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ 
+ 	g_object_class_install_property (gobject_class, PROP_SERVICE,
+ 		g_param_spec_object ("service", "Service", "Service which owns this prompt",
+@@ -490,22 +491,27 @@ gkd_secret_dispatch_iface (GkdSecretDispatchIface *iface)
+  */
+ 
+ GkdSecretUnlock*
+-gkd_secret_unlock_new (GkdSecretService *service, const gchar *caller)
++gkd_secret_unlock_new (GkdSecretService *service, const gchar *caller,
++                       const gchar *object_path)
+ {
+-	return g_object_new (GKD_SECRET_TYPE_UNLOCK, "service", service, "caller", caller, NULL);
++	return g_object_new (GKD_SECRET_TYPE_UNLOCK,
++	                     "service", service,
++	                     "caller", caller,
++	                     "object-path", object_path,
++	                     NULL);
+ }
+ 
+ void
+-gkd_secret_unlock_queue (GkdSecretUnlock *self, const gchar *objpath)
++gkd_secret_unlock_queue (GkdSecretUnlock *self, const gchar *unlock_path)
+ {
+ 	gboolean locked = TRUE;
+ 	GckObject *coll;
+ 	gchar *path;
+ 
+ 	g_return_if_fail (GKD_SECRET_IS_UNLOCK (self));
+-	g_return_if_fail (objpath);
++	g_return_if_fail (unlock_path);
+ 
+-	coll = lookup_collection (self, objpath);
++	coll = lookup_collection (self, unlock_path);
+ 	if (coll == NULL)
+ 		return;
+ 
+@@ -515,7 +521,7 @@ gkd_secret_unlock_queue (GkdSecretUnlock *self, const gchar *objpath)
+ 
+ 	}
+ 
+-	path = g_strdup (objpath);
++	path = g_strdup (unlock_path);
+ 	if (locked)
+ 		g_queue_push_tail (self->queued, path);
+ 	else
+@@ -552,6 +558,19 @@ gkd_secret_unlock_reset_results (GkdSecretUnlock *self)
+ 	g_array_set_size (self->results, 0);
+ }
+ 
++void
++gkd_secret_unlock_call_prompt (GkdSecretUnlock *self, const gchar *window_id)
++{
++	g_return_if_fail (GKD_SECRET_IS_UNLOCK (self));
++	g_return_if_fail (!self->prompted);
++
++	g_assert (!self->window_id);
++	self->window_id = g_strdup (window_id);
++
++	self->prompted = TRUE;
++	perform_next_unlock (self);
++}
++
+ gboolean
+ gkd_secret_unlock_with_secret (GckObject *collection, GkdSecretSecret *master,
+                                DBusError *derr)
+diff --git a/daemon/dbus/gkd-secret-unlock.h b/daemon/dbus/gkd-secret-unlock.h
+index 3fde30f..c5e3e50 100644
+--- a/daemon/dbus/gkd-secret-unlock.h
++++ b/daemon/dbus/gkd-secret-unlock.h
+@@ -42,10 +42,11 @@ struct _GkdSecretUnlockClass {
+ GType               gkd_secret_unlock_get_type                (void);
+ 
+ GkdSecretUnlock*    gkd_secret_unlock_new                     (GkdSecretService *service,
+-                                                               const gchar *caller);
++                                                               const gchar *caller,
++                                                               const gchar *object_path);
+ 
+ void                gkd_secret_unlock_queue                   (GkdSecretUnlock *self,
+-                                                               const gchar *objpath);
++                                                               const gchar *unlock_path);
+ 
+ gboolean            gkd_secret_unlock_have_queued             (GkdSecretUnlock *self);
+ 
+@@ -54,6 +55,9 @@ gchar**             gkd_secret_unlock_get_results             (GkdSecretUnlock *
+ 
+ void                gkd_secret_unlock_reset_results           (GkdSecretUnlock *self);
+ 
++void                gkd_secret_unlock_call_prompt             (GkdSecretUnlock *self,
++                                                               const gchar *window_id);
++
+ gboolean            gkd_secret_unlock_with_secret             (GckObject *collection,
+                                                                GkdSecretSecret *master,
+                                                                DBusError *derr);
+--
+cgit v0.8.3.4

diff --git a/gnome-base/gnome-keyring/files/gnome-keyring-trunk-4.patch b/gnome-base/gnome-keyring/files/gnome-keyring-trunk-4.patch
new file mode 100644
index 0000000..5a785d9
--- /dev/null
+++ b/gnome-base/gnome-keyring/files/gnome-keyring-trunk-4.patch
@@ -0,0 +1,21 @@
+From ced422b8770ba321ae0c3271b8344ee031d55748 Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw@collabora.co.uk>
+Date: Wed, 09 Mar 2011 09:29:55 +0000
+Subject: Change warning on bad certificate data to a simple message.
+
+---
+diff --git a/pkcs11/gkm/gkm-certificate.c b/pkcs11/gkm/gkm-certificate.c
+index 866e703..256c747 100644
+--- a/pkcs11/gkm/gkm-certificate.c
++++ b/pkcs11/gkm/gkm-certificate.c
+@@ -380,7 +380,7 @@ gkm_certificate_real_load (GkmSerializable *base, GkmSecret *login, gconstpointe
+ 	/* Parse the ASN1 data */
+ 	res = gkm_data_der_read_certificate (copy, n_data, &asn1);
+ 	if (res != GKM_DATA_SUCCESS) {
+-		g_warning ("couldn't parse certificate data");
++		g_message ("couldn't parse certificate data");
+ 		g_free (copy);
+ 		return FALSE;
+ 	}
+--
+cgit v0.8.3.4

diff --git a/gnome-base/gnome-keyring/files/gnome-keyring-trunk-5.patch b/gnome-base/gnome-keyring/files/gnome-keyring-trunk-5.patch
new file mode 100644
index 0000000..9f18aca
--- /dev/null
+++ b/gnome-base/gnome-keyring/files/gnome-keyring-trunk-5.patch
@@ -0,0 +1,1538 @@
+From 655e0e90a4f96de76348f84cab0c64014078fdbb Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw@collabora.co.uk>
+Date: Wed, 09 Mar 2011 09:41:42 +0000
+Subject: Merge branch 'with-hkdf'
+
+---
+diff --git a/daemon/dbus/gkd-secret-session.c b/daemon/dbus/gkd-secret-session.c
+index 8c99373..81648b9 100644
+--- a/daemon/dbus/gkd-secret-session.c
++++ b/daemon/dbus/gkd-secret-session.c
+@@ -119,20 +119,52 @@ aes_derive_key (GckSession *session, GckObject *priv_key,
+                 gconstpointer input, gsize n_input, GckObject **aes_key)
+ {
+ 	GError *error = NULL;
+-	GckMechanism mech = { CKM_DH_PKCS_DERIVE, input, n_input };
++	GckMechanism mech;
+ 	GckAttributes *attrs;
++	GckObject *dh_key;
++
++	/*
++	 * First we have to generate a secret key from the DH key. The
++	 * length of this key depends on the size of our DH prime
++	 */
++
++	mech.type = CKM_DH_PKCS_DERIVE;
++	mech.parameter = input;
++	mech.n_parameter = n_input;
++
++	attrs = gck_attributes_new ();
++	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
++	gck_attributes_add_ulong (attrs, CKA_KEY_TYPE, CKK_GENERIC_SECRET);
++
++	dh_key = gck_session_derive_key_full (session, priv_key, &mech, attrs, NULL, &error);
++
++	gck_attributes_unref (attrs);
++
++	if (!dh_key) {
++		g_warning ("couldn't derive key from dh key pair: %s", egg_error_message (error));
++		g_clear_error (&error);
++		return FALSE;
++	}
++
++	/*
++	 * Now use HKDF to generate our AES key.
++	 */
++
++	mech.type = CKM_G_HKDF_SHA256_DERIVE;
++	mech.parameter = NULL;
++	mech.n_parameter = 0;
+ 
+ 	attrs = gck_attributes_new ();
+ 	gck_attributes_add_ulong (attrs, CKA_VALUE_LEN, 16UL);
+ 	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
+ 	gck_attributes_add_ulong (attrs, CKA_KEY_TYPE, CKK_AES);
+ 
+-	*aes_key = gck_session_derive_key_full (session, priv_key, &mech, attrs, NULL, &error);
+-
++	*aes_key = gck_session_derive_key_full (session, dh_key, &mech, attrs, NULL, &error);
+ 	gck_attributes_unref (attrs);
++	g_object_unref (dh_key);
+ 
+ 	if (!*aes_key) {
+-		g_warning ("couldn't derive aes key from dh key pair: %s", egg_error_message (error));
++		g_warning ("couldn't derive aes key from dh key: %s", egg_error_message (error));
+ 		g_clear_error (&error);
+ 		return FALSE;
+ 	}
+@@ -529,7 +561,7 @@ gkd_secret_session_handle_open (GkdSecretSession *self, DBusMessage *message)
+ 			                               "The session algorithm input argument was invalid");
+ 		reply = plain_negotiate (self, message);
+ 
+-	} else if (g_str_equal (algorithm, "dh-ietf1024-aes128-cbc-pkcs7")) {
++	} else if (g_str_equal (algorithm, "dh-ietf1024-sha256-aes128-cbc-pkcs7")) {
+ 		if (!g_str_equal ("ay", dbus_message_iter_get_signature (&variant)))
+ 			return dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS,
+ 			                               "The session algorithm input argument was invalid");
+@@ -538,7 +570,7 @@ gkd_secret_session_handle_open (GkdSecretSession *self, DBusMessage *message)
+ 		reply = aes_negotiate (self, message, input, n_input);
+ 
+ 	} else {
+-		reply = dbus_message_new_error_printf (message, SECRET_ERROR_NOT_SUPPORTED,
++		reply = dbus_message_new_error_printf (message, DBUS_ERROR_NOT_SUPPORTED,
+ 		                                       "The algorithm '%s' is not supported", algorithm);
+ 	}
+ 
+diff --git a/daemon/dbus/gkd-secret-types.h b/daemon/dbus/gkd-secret-types.h
+index 3b6aed1..176c92f 100644
+--- a/daemon/dbus/gkd-secret-types.h
++++ b/daemon/dbus/gkd-secret-types.h
+@@ -42,7 +42,6 @@
+ 
+ #define SECRET_ERROR_ALREADY_EXISTS    "org.freedesktop.Secret.Error.AlreadyExists"
+ #define SECRET_ERROR_IS_LOCKED         "org.freedesktop.Secret.Error.IsLocked"
+-#define SECRET_ERROR_NOT_SUPPORTED     "org.freedesktop.Secret.Error.NotSupported"
+ #define SECRET_ERROR_NO_SESSION        "org.freedesktop.Secret.Error.NoSession"
+ #define SECRET_ERROR_NO_SUCH_OBJECT    "org.freedesktop.Secret.Error.NoSuchObject"
+ 
+diff --git a/egg/Makefile.am b/egg/Makefile.am
+index 8b3bd24..3d8e149 100644
+--- a/egg/Makefile.am
++++ b/egg/Makefile.am
+@@ -30,6 +30,7 @@ libegg_la_SOURCES = \
+ 	egg-dn.c egg-dn.h \
+ 	egg-error.h \
+ 	egg-hex.c egg-hex.h \
++	egg-hkdf.c egg-hkdf.h \
+ 	egg-libgcrypt.c egg-libgcrypt.h \
+ 	egg-mkdtemp.c egg-mkdtemp.h \
+ 	egg-oid.c egg-oid.h \
+@@ -98,6 +99,7 @@ libegg_dbus_la_LIBADD = \
+ libegg_prompt_la_SOURCES = \
+ 	egg-dh.c egg-dh.h \
+ 	egg-hex.c egg-hex.h \
++	egg-hkdf.c egg-hkdf.h \
+ 	egg-libgcrypt.c egg-libgcrypt.h \
+ 	egg-padding.c egg-padding.h \
+ 	egg-secure-memory.c egg-secure-memory.h
+diff --git a/egg/egg-dh.c b/egg/egg-dh.c
+index d192aeb..bed524e 100644
+--- a/egg/egg-dh.c
++++ b/egg/egg-dh.c
+@@ -306,12 +306,11 @@ egg_dh_gen_pair (gcry_mpi_t prime, gcry_mpi_t base, guint bits,
+ 
+ gpointer
+ egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
+-                   gcry_mpi_t prime, gsize bytes)
++                   gcry_mpi_t prime, gsize *bytes)
+ {
+ 	gcry_error_t gcry;
+ 	guchar *value;
+ 	gsize n_value;
+-	gsize offset = 0;
+ 	gcry_mpi_t k;
+ 	gint bits;
+ 
+@@ -329,11 +328,8 @@ egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
+ 	/* Write out the secret */
+ 	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n_value, k);
+ 	g_return_val_if_fail (gcry == 0, NULL);
+-	if (n_value < bytes)
+-		offset = bytes - n_value;
+-	value = egg_secure_alloc (n_value + offset);
+-	memset (value, 0, n_value + offset);
+-	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, value + offset, n_value, &n_value, k);
++	value = egg_secure_alloc (n_value);
++	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, value, n_value, &n_value, k);
+ 	g_return_val_if_fail (gcry == 0, NULL);
+ 
+ #if DEBUG_DH_SECRET
+@@ -342,11 +338,7 @@ egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
+ 	gcry_mpi_release (k);
+ #endif
+ 
+-	if (bytes != 0 && bytes < n_value) {
+-		offset = n_value - bytes;
+-		memmove (value, value + offset, bytes);
+-		egg_secure_clear (value + bytes, offset);
+-	}
++	*bytes = n_value;
+ 
+ #if DEBUG_DH_SECRET
+ 	gcry_mpi_scan (&k, GCRYMPI_FMT_USG, value, bytes, NULL);
+diff --git a/egg/egg-dh.h b/egg/egg-dh.h
+index cfdb3d0..ee315e2 100644
+--- a/egg/egg-dh.h
++++ b/egg/egg-dh.h
+@@ -45,6 +45,6 @@ gboolean   egg_dh_gen_pair                                    (gcry_mpi_t prime,
+ gpointer   egg_dh_gen_secret                                  (gcry_mpi_t peer,
+                                                                gcry_mpi_t priv,
+                                                                gcry_mpi_t prime,
+-                                                               gsize bytes);
++                                                               gsize *bytes);
+ 
+ #endif /* EGG_DH_H_ */
+diff --git a/egg/egg-hkdf.c b/egg/egg-hkdf.c
+new file mode 100644
+index 0000000..eaa90fc
+--- a/dev/null
++++ b/egg/egg-hkdf.c
+@@ -0,0 +1,109 @@
++/*
++ * gnome-keyring
++ *
++ * Copyright (C) 2011 Collabora Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General  License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General  License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General
++ * License along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ *
++ * Author: Stef Walter <stefw@collabora.co.uk>
++ */
++
++#include "config.h"
++
++#include "egg-hkdf.h"
++#include "egg-secure-memory.h"
++
++#include <gcrypt.h>
++
++#include <string.h>
++
++gboolean
++egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input,
++                  gconstpointer salt, gsize n_salt, gconstpointer info,
++                  gsize n_info, gpointer output, gsize n_output)
++{
++	gpointer alloc = NULL;
++	gpointer buffer = NULL;
++	gcry_md_hd_t md1, md2;
++	guint hash_len;
++	guchar i;
++	gint flags, algo;
++	gsize step, n_buffer;
++	guchar *at;
++	gcry_error_t gcry;
++
++	algo = gcry_md_map_name (hash_algo);
++	g_return_val_if_fail (algo != 0, FALSE);
++
++	hash_len = gcry_md_get_algo_dlen (algo);
++	g_return_val_if_fail (hash_len != 0, FALSE);
++	g_return_val_if_fail (n_output <= 255 * hash_len, FALSE);
++
++	/* Buffer we need to for intermediate stuff */
++	if (gcry_is_secure (input)) {
++		flags = GCRY_MD_FLAG_SECURE;
++		buffer = gcry_malloc_secure (hash_len);
++	} else {
++		flags = 0;
++		buffer = gcry_malloc (hash_len);
++	}
++
++	g_return_val_if_fail (buffer, FALSE);
++	n_buffer = 0;
++
++	/* Salt defaults to hash_len zeros */
++	if (!salt) {
++		salt = alloc = g_malloc0 (hash_len);
++		n_salt = hash_len;
++	}
++
++	/* Step 1: Extract */
++	gcry = gcry_md_open (&md1, algo, GCRY_MD_FLAG_HMAC);
++	g_return_val_if_fail (gcry == 0, FALSE);
++	gcry = gcry_md_setkey (md1, salt, n_salt);
++	g_return_val_if_fail (gcry == 0, FALSE);
++	gcry_md_write (md1, input, n_input);
++
++	/* Step 2: Expand */
++	gcry = gcry_md_open (&md2, algo, GCRY_MD_FLAG_HMAC);
++	g_return_val_if_fail (gcry == 0, FALSE);
++	gcry = gcry_md_setkey (md2, gcry_md_read (md1, algo), hash_len);
++	g_return_val_if_fail (gcry == 0, FALSE);
++	gcry_md_close (md1);
++
++	at = output;
++	for (i = 1; i < 256; ++i) {
++		gcry_md_reset (md2);
++		gcry_md_write (md2, buffer, n_buffer);
++		gcry_md_write (md2, info, n_info);
++		gcry_md_write (md2, &i, 1);
++
++		n_buffer = hash_len;
++		memcpy (buffer, gcry_md_read (md2, algo), n_buffer);
++
++		step = MIN (n_buffer, n_output);
++		memcpy (at, buffer, step);
++		n_output -= step;
++		at += step;
++
++		if (!n_output)
++			break;
++	}
++
++	g_free (alloc);
++	gcry_free (buffer);
++	return TRUE;
++}
+diff --git a/egg/tests/test-dh.c b/egg/tests/test-dh.c
+index 6a2b37f..13e9c70 100644
+--- a/egg/tests/test-dh.c
++++ b/egg/tests/test-dh.c
+@@ -31,6 +31,7 @@
+ #include <stdio.h>
+ #include <string.h>
+ 
++#include <glib.h>
+ #include <gcrypt.h>
+ 
+ EGG_SECURE_GLIB_DEFINITIONS ();
+@@ -43,6 +44,7 @@ test_perform (void)
+ 	gcry_mpi_t x2, X2;
+ 	gpointer k1, k2;
+ 	gboolean ret;
++	gsize n1, n2;
+ 
+ 	/* Load up the parameters */
+ 	if (!egg_dh_default_params ("ietf-ike-grp-modp-768", &p, &g))
+@@ -55,13 +57,14 @@ test_perform (void)
+ 	g_assert (ret);
+ 
+ 	/* Calculate keys */
+-	k1 = egg_dh_gen_secret (X2, x1, p, 96);
++	k1 = egg_dh_gen_secret (X2, x1, p, &n1);
+ 	g_assert (k1);
+-	k2 = egg_dh_gen_secret (X1, x2, p, 96);
++	k2 = egg_dh_gen_secret (X1, x2, p, &n2);
+ 	g_assert (k2);
+ 
+ 	/* Keys must be the same */
+-	g_assert (memcmp (k1, k2, 96) == 0);
++	egg_assert_cmpsize (n1, ==, n2);
++	g_assert (memcmp (k1, k2, n1) == 0);
+ 
+ 	gcry_mpi_release (p);
+ 	gcry_mpi_release (g);
+@@ -97,7 +100,7 @@ test_short_pair (void)
+ }
+ 
+ static void
+-test_dh_default (const gchar *name, guint bits)
++check_dh_default (const gchar *name, guint bits)
+ {
+ 	gboolean ret;
+ 	gcry_mpi_t p, g, check;
+@@ -134,44 +137,43 @@ test_dh_default (const gchar *name, guint bits)
+ static void
+ test_default_768 (void)
+ {
+-	test_dh_default ("ietf-ike-grp-modp-768", 768);
++	check_dh_default ("ietf-ike-grp-modp-768", 768);
+ }
+ 
+ static void
+ test_default_1024 (void)
+ {
+-	test_dh_default ("ietf-ike-grp-modp-1024", 1024);
++	check_dh_default ("ietf-ike-grp-modp-1024", 1024);
+ }
+ 
+ static void
+ test_default_1536 (void)
+ {
+-	test_dh_default ("ietf-ike-grp-modp-1536", 1536);
++	check_dh_default ("ietf-ike-grp-modp-1536", 1536);
+ }
+ 
+-
+ static void
+ test_default_2048 (void)
+ {
+-	test_dh_default ("ietf-ike-grp-modp-2048", 2048);
++	check_dh_default ("ietf-ike-grp-modp-2048", 2048);
+ }
+ 
+ static void
+ test_default_3072 (void)
+ {
+-	test_dh_default ("ietf-ike-grp-modp-3072", 3072);
++	check_dh_default ("ietf-ike-grp-modp-3072", 3072);
+ }
+ 
+ static void
+ test_default_4096 (void)
+ {
+-	test_dh_default ("ietf-ike-grp-modp-4096", 4096);
++	check_dh_default ("ietf-ike-grp-modp-4096", 4096);
+ }
+ 
+ static void
+ test_default_8192 (void)
+ {
+-	test_dh_default ("ietf-ike-grp-modp-8192", 8192);
++	check_dh_default ("ietf-ike-grp-modp-8192", 8192);
+ }
+ 
+ static void
+diff --git a/egg/tests/test-hkdf.c b/egg/tests/test-hkdf.c
+new file mode 100644
+index 0000000..44c463d
+--- a/dev/null
++++ b/egg/tests/test-hkdf.c
+@@ -0,0 +1,345 @@
++/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
++/* test-hkdf.c: Test egg-hkdf.c
++
++   Copyright (C) 2011 Collabora Ltd.
++
++   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 <stef@collabora.co.uk>
++*/
++
++#include "config.h"
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++
++#include "egg-hkdf.h"
++#include "egg-secure-memory.h"
++#include "egg-testing.h"
++
++#include <gcrypt.h>
++
++EGG_SECURE_GLIB_DEFINITIONS ();
++
++static void
++test_hkdf_test_case_1 (void)
++{
++	/* RFC 5869: A.1 Test Case 1 */
++	const guchar ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
++	                       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
++	                       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
++	const guchar salt[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++	                        0x08, 0x09, 0x0a, 0x0b, 0x0c };
++	const guchar info[] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
++	                        0xf8, 0xf9 };
++	const guchar okm[] = { 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
++	                       0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
++	                       0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
++	                       0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
++	                       0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
++	                       0x58, 0x65 };
++	guchar buffer[sizeof (okm)];
++	gboolean ret;
++
++	egg_assert_cmpsize (sizeof (ikm), ==, 22);
++	egg_assert_cmpsize (sizeof (salt), ==, 13);
++	egg_assert_cmpsize (sizeof (info), ==, 10);
++	egg_assert_cmpsize (sizeof (okm), ==, 42);
++
++	memset (buffer, 0, sizeof (buffer));
++	ret = egg_hkdf_perform ("sha256",
++	                        ikm, sizeof (ikm),
++	                        salt, sizeof (salt),
++	                        info, sizeof (info),
++	                        buffer, sizeof (buffer));
++	g_assert (ret);
++	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
++}
++
++static void
++test_hkdf_test_case_2 (void)
++{
++	/* RFC 5869: A.2 Test Case 2 */
++	const guchar ikm[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++	                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++	                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++	                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
++	                       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++	                       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
++	                       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
++	                       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
++	                       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
++	                       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f };
++	const guchar salt[] = { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
++	                        0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
++	                        0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
++	                        0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
++	                        0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
++	                        0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
++	                        0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
++	                        0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
++	                        0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
++	                        0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf };
++	const guchar info[] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
++	                        0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
++	                        0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
++	                        0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
++	                        0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
++	                        0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
++	                        0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
++	                        0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
++	                        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
++	                        0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
++	const guchar okm[] = { 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1,
++	                       0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34,
++	                       0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
++	                       0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c,
++	                       0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72,
++	                       0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
++	                       0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
++	                       0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71,
++	                       0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87,
++	                       0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f,
++	                       0x1d, 0x87 };
++	guchar buffer[sizeof (okm)];
++	gboolean ret;
++
++	egg_assert_cmpsize (sizeof (ikm), ==, 80);
++	egg_assert_cmpsize (sizeof (salt), ==, 80);
++	egg_assert_cmpsize (sizeof (info), ==, 80);
++	egg_assert_cmpsize (sizeof (okm), ==, 82);
++
++	memset (buffer, 0, sizeof (buffer));
++	ret = egg_hkdf_perform ("sha256",
++	                        ikm, sizeof (ikm),
++	                        salt, sizeof (salt),
++	                        info, sizeof (info),
++	                        buffer, sizeof (buffer));
++	g_assert (ret);
++	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
++}
++
++static void
++test_hkdf_test_case_3 (void)
++{
++	/* RFC 5869: A.3 Test Case 3 */
++	const guchar ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
++	                       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
++	                       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,};
++	const guchar salt[] = { };
++	const guchar info[] = { };
++	const guchar okm[] = { 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f,
++	                       0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31,
++	                       0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
++	                       0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d,
++	                       0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a,
++	                       0x96, 0xc8 };
++	guchar buffer[sizeof (okm)];
++	gboolean ret;
++
++	egg_assert_cmpsize (sizeof (ikm), ==, 22);
++	egg_assert_cmpsize (sizeof (salt), ==, 0);
++	egg_assert_cmpsize (sizeof (info), ==, 0);
++	egg_assert_cmpsize (sizeof (okm), ==, 42);
++
++	memset (buffer, 0, sizeof (buffer));
++	ret = egg_hkdf_perform ("sha256",
++	                        ikm, sizeof (ikm),
++	                        salt, sizeof (salt),
++	                        info, sizeof (info),
++	                        buffer, sizeof (buffer));
++	g_assert (ret);
++	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
++}
++
++static void
++test_hkdf_test_case_4 (void)
++{
++	/* RFC 5869: A.4 Test Case 4 */
++	const guchar ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
++	                       0x0b, 0x0b, 0x0b };
++	const guchar salt[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++	                        0x08, 0x09, 0x0a, 0x0b, 0x0c };
++	const guchar info[] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
++	                        0xf8, 0xf9 };
++	const guchar okm[] = { 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69,
++	                       0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81,
++	                       0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15,
++	                       0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2,
++	                       0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3,
++	                       0xf8, 0x96 };
++	guchar buffer[sizeof (okm)];
++	gboolean ret;
++
++	egg_assert_cmpsize (sizeof (ikm), ==, 11);
++	egg_assert_cmpsize (sizeof (salt), ==, 13);
++	egg_assert_cmpsize (sizeof (info), ==, 10);
++	egg_assert_cmpsize (sizeof (okm), ==, 42);
++
++	memset (buffer, 0, sizeof (buffer));
++	ret = egg_hkdf_perform ("sha1",
++	                        ikm, sizeof (ikm),
++	                        salt, sizeof (salt),
++	                        info, sizeof (info),
++	                        buffer, sizeof (buffer));
++	g_assert (ret);
++	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
++}
++
++static void
++test_hkdf_test_case_5 (void)
++{
++	/* RFC 5869: A.5 Test Case 5 */
++	const guchar ikm[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++	                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++	                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++	                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
++	                       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++	                       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
++	                       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
++	                       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
++	                       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
++	                       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f };
++	const guchar salt[] = { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
++	                        0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
++	                        0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
++	                        0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
++	                        0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
++	                        0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
++	                        0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
++	                        0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
++	                        0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
++	                        0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf };
++	const guchar info[] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
++	                        0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
++	                        0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
++	                        0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
++	                        0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
++	                        0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
++	                        0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
++	                        0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
++	                        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
++	                        0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
++	const guchar okm[] = { 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7,
++	                       0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb,
++	                       0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19,
++	                       0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe,
++	                       0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3,
++	                       0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c,
++	                       0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed,
++	                       0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e,
++	                       0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43,
++	                       0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52,
++	                       0xd3, 0xb4 };
++	guchar buffer[sizeof (okm)];
++	gboolean ret;
++
++	egg_assert_cmpsize (sizeof (ikm), ==, 80);
++	egg_assert_cmpsize (sizeof (salt), ==, 80);
++	egg_assert_cmpsize (sizeof (info), ==, 80);
++	egg_assert_cmpsize (sizeof (okm), ==, 82);
++
++	memset (buffer, 0, sizeof (buffer));
++	ret = egg_hkdf_perform ("sha1",
++	                        ikm, sizeof (ikm),
++	                        salt, sizeof (salt),
++	                        info, sizeof (info),
++	                        buffer, sizeof (buffer));
++	g_assert (ret);
++	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
++}
++
++static void
++test_hkdf_test_case_6 (void)
++{
++	/* RFC 5869: A.6 Test Case 6 */
++	const guchar ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
++	                       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
++	                       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
++	const guchar salt[] = { };
++	const guchar info[] = { };
++	const guchar okm[] = { 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61,
++	                       0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06,
++	                       0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06,
++	                       0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0,
++	                       0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3,
++	                       0x49, 0x18 };
++	guchar buffer[sizeof (okm)];
++	gboolean ret;
++
++	egg_assert_cmpsize (sizeof (ikm), ==, 22);
++	egg_assert_cmpsize (sizeof (salt), ==, 0);
++	egg_assert_cmpsize (sizeof (info), ==, 0);
++	egg_assert_cmpsize (sizeof (okm), ==, 42);
++
++	memset (buffer, 0, sizeof (buffer));
++	ret = egg_hkdf_perform ("sha1",
++	                        ikm, sizeof (ikm),
++	                        salt, sizeof (salt),
++	                        info, sizeof (info),
++	                        buffer, sizeof (buffer));
++	g_assert (ret);
++	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
++}
++
++static void
++test_hkdf_test_case_7 (void)
++{
++	/* RFC 5869: A.7 Test Case 7 */
++	const guchar ikm[] = { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
++	                       0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
++	                       0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c };
++	const guchar *salt = NULL;
++	const guchar info[] = { };
++	const guchar okm[] = { 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3,
++	                       0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a,
++	                       0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23,
++	                       0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5,
++	                       0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac,
++	                       0xfc, 0x48 };
++	guchar buffer[sizeof (okm)];
++	gboolean ret;
++
++	egg_assert_cmpsize (sizeof (ikm), ==, 22);
++	egg_assert_cmpsize (sizeof (info), ==, 0);
++	egg_assert_cmpsize (sizeof (okm), ==, 42);
++
++	memset (buffer, 0, sizeof (buffer));
++	ret = egg_hkdf_perform ("sha1",
++	                        ikm, sizeof (ikm),
++	                        salt, sizeof (salt),
++	                        info, sizeof (info),
++	                        buffer, sizeof (buffer));
++	g_assert (ret);
++	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
++}
++
++int
++main (int argc, char **argv)
++{
++	g_test_init (&argc, &argv, NULL);
++
++	g_test_add_func ("/hkdf/test-case-1", test_hkdf_test_case_1);
++	g_test_add_func ("/hkdf/test-case-2", test_hkdf_test_case_2);
++	g_test_add_func ("/hkdf/test-case-3", test_hkdf_test_case_3);
++	g_test_add_func ("/hkdf/test-case-4", test_hkdf_test_case_4);
++	g_test_add_func ("/hkdf/test-case-5", test_hkdf_test_case_5);
++	g_test_add_func ("/hkdf/test-case-6", test_hkdf_test_case_6);
++	g_test_add_func ("/hkdf/test-case-7", test_hkdf_test_case_7);
++
++	return g_test_run ();
++}
+diff --git a/pkcs11/gkm/Makefile.am b/pkcs11/gkm/Makefile.am
+index 1d4516c..bf6a1c8 100644
+--- a/pkcs11/gkm/Makefile.am
++++ b/pkcs11/gkm/Makefile.am
+@@ -35,6 +35,8 @@ libgkm_la_SOURCES = \
+ 	gkm-dsa-mechanism.c gkm-dsa-mechanism.h \
+ 	gkm-factory.c gkm-factory.h \
+ 	gkm-file-tracker.c gkm-file-tracker.h \
++	gkm-generic-key.c gkm-generic-key.h \
++	gkm-hkdf-mechanism.c gkm-hkdf-mechanism.h \
+ 	gkm-manager.c gkm-manager.h \
+ 	gkm-memory-store.c gkm-memory-store.h \
+ 	gkm-mock.c gkm-mock.h \
+diff --git a/pkcs11/gkm/gkm-aes-key.c b/pkcs11/gkm/gkm-aes-key.c
+index d53e911..71f9e08 100644
+--- a/pkcs11/gkm/gkm-aes-key.c
++++ b/pkcs11/gkm/gkm-aes-key.c
+@@ -22,6 +22,7 @@
+ #include "config.h"
+ 
+ #include "pkcs11/pkcs11.h"
++#include "pkcs11/pkcs11i.h"
+ 
+ #include "gkm-aes-mechanism.h"
+ #include "gkm-attributes.h"
+@@ -41,6 +42,11 @@ struct _GkmAesKey {
+ 
+ G_DEFINE_TYPE (GkmAesKey, gkm_aes_key, GKM_TYPE_SECRET_KEY);
+ 
++static const CK_MECHANISM_TYPE GKM_AES_MECHANISMS[] = {
++	CKM_AES_CBC_PAD,
++	CKM_G_HKDF_SHA256_DERIVE
++};
++
+ /* -----------------------------------------------------------------------------
+  * INTERNAL
+  */
+@@ -139,7 +145,7 @@ factory_create_aes_key (GkmSession *session, GkmTransaction *transaction,
+  */
+ 
+ static CK_RV
+-gkm_aes_key_real_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE *attr)
++gkm_aes_key_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE *attr)
+ {
+ 	GkmAesKey *self = GKM_AES_KEY (base);
+ 
+@@ -148,6 +154,9 @@ gkm_aes_key_real_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBU
+ 	case CKA_KEY_TYPE:
+ 		return gkm_attribute_set_ulong (attr, CKK_AES);
+ 
++	case CKA_DERIVE:
++		return gkm_attribute_set_bool (attr, CK_TRUE);
++
+ 	case CKA_UNWRAP:
+ 	case CKA_WRAP:
+ 		return gkm_attribute_set_bool (attr, CK_TRUE);
+@@ -169,6 +178,14 @@ gkm_aes_key_real_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBU
+ 	return GKM_OBJECT_CLASS (gkm_aes_key_parent_class)->get_attribute (base, session, attr);
+ }
+ 
++static gconstpointer
++gkm_aes_key_get_key_value (GkmSecretKey *key, gsize *n_value)
++{
++	GkmAesKey *self = GKM_AES_KEY (key);
++	*n_value = self->n_value;
++	return self->value;
++}
++
+ static void
+ gkm_aes_key_init (GkmAesKey *self)
+ {
+@@ -195,12 +212,15 @@ gkm_aes_key_class_init (GkmAesKeyClass *klass)
+ {
+ 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ 	GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
++	GkmSecretKeyClass *key_class = GKM_SECRET_KEY_CLASS (klass);
+ 
+ 	gkm_aes_key_parent_class = g_type_class_peek_parent (klass);
+ 
+ 	gobject_class->finalize = gkm_aes_key_finalize;
+ 
+-	gkm_class->get_attribute = gkm_aes_key_real_get_attribute;
++	gkm_class->get_attribute = gkm_aes_key_get_attribute;
++
++	key_class->get_key_value = gkm_aes_key_get_key_value;
+ }
+ 
+ /* -----------------------------------------------------------------------------
+diff --git a/pkcs11/gkm/gkm-aes-mechanism.h b/pkcs11/gkm/gkm-aes-mechanism.h
+index a473d4b..d62d7c0 100644
+--- a/pkcs11/gkm/gkm-aes-mechanism.h
++++ b/pkcs11/gkm/gkm-aes-mechanism.h
+@@ -31,10 +31,6 @@
+ #define GKM_AES_MECHANISM_MIN_LENGTH     16
+ #define GKM_AES_MECHANISM_MAX_LENGTH     32
+ 
+-static const CK_MECHANISM_TYPE GKM_AES_MECHANISMS[] = {
+-	CKM_AES_CBC_PAD
+-};
+-
+ CK_RV                   gkm_aes_mechanism_wrap                 (GkmSession *session,
+                                                                 CK_MECHANISM_PTR mech,
+                                                                 GkmObject *wrapper,
+diff --git a/pkcs11/gkm/gkm-crypto.c b/pkcs11/gkm/gkm-crypto.c
+index 9662612..65336ff 100644
+--- a/pkcs11/gkm/gkm-crypto.c
++++ b/pkcs11/gkm/gkm-crypto.c
+@@ -25,6 +25,7 @@
+ #include "gkm-aes-mechanism.h"
+ #include "gkm-dh-mechanism.h"
+ #include "gkm-dsa-mechanism.h"
++#include "gkm-hkdf-mechanism.h"
+ #include "gkm-null-mechanism.h"
+ #include "gkm-rsa-mechanism.h"
+ #include "gkm-session.h"
+@@ -430,6 +431,9 @@ gkm_crypto_derive_key (GkmSession *session, CK_MECHANISM_PTR mech, GkmObject *ba
+ 	case CKM_DH_PKCS_DERIVE:
+ 		return gkm_dh_mechanism_derive (session, mech, base, attrs,
+ 		                                n_attrs, derived);
++	case CKM_G_HKDF_SHA256_DERIVE:
++		return gkm_hkdf_mechanism_derive (session, "sha256", mech, base,
++		                                  attrs, n_attrs, derived);
+ 	default:
+ 		return CKR_MECHANISM_INVALID;
+ 	}
+diff --git a/pkcs11/gkm/gkm-dh-mechanism.c b/pkcs11/gkm/gkm-dh-mechanism.c
+index 5b29ac3..446defb 100644
+--- a/pkcs11/gkm/gkm-dh-mechanism.c
++++ b/pkcs11/gkm/gkm-dh-mechanism.c
+@@ -209,8 +209,9 @@ gkm_dh_mechanism_derive (GkmSession *session, CK_MECHANISM_PTR mech, GkmObject *
+ 	gcry_error_t gcry;
+ 	CK_ATTRIBUTE attr;
+ 	GArray *array;
++	gsize n_actual = 0;
+ 	CK_ULONG n_value = 0;
+-	gpointer value;
++	guchar *value;
+ 	GkmTransaction *transaction;
+ 	CK_KEY_TYPE type;
+ 
+@@ -239,7 +240,7 @@ gkm_dh_mechanism_derive (GkmSession *session, CK_MECHANISM_PTR mech, GkmObject *
+ 	if (n_value == 0)
+ 		n_value = (gcry_mpi_get_nbits (prime) + 7) / 8;
+ 
+-	value = egg_dh_gen_secret (peer, priv, prime, n_value);
++	value = egg_dh_gen_secret (peer, priv, prime, &n_actual);
+ 	gcry_mpi_release (peer);
+ 
+ 	if (value == NULL)
+@@ -250,8 +251,24 @@ gkm_dh_mechanism_derive (GkmSession *session, CK_MECHANISM_PTR mech, GkmObject *
+ 
+ 	/* Prepend the value */
+ 	attr.type = CKA_VALUE;
+-	attr.pValue = value;
+ 	attr.ulValueLen = n_value;
++
++	/* Is it too long, move to the front and truncate */
++	if (n_actual > n_value) {
++		attr.pValue = value + (n_actual - n_value);
++
++	/* If it's too short, expand with zeros */
++	} else if (n_actual < n_value) {
++		value = egg_secure_realloc (value, n_value);
++		memmove (value + (n_value - n_actual), value, n_actual);
++		memset (value, 0, (n_value - n_actual));
++		attr.pValue = value;
++
++	/* It's just right */
++	} else {
++		attr.pValue = value;
++	}
++
+ 	g_array_append_val (array, attr);
+ 
+ 	/* Add the remainder of the attributes */
+diff --git a/pkcs11/gkm/gkm-generic-key.c b/pkcs11/gkm/gkm-generic-key.c
+new file mode 100644
+index 0000000..834f152
+--- a/dev/null
++++ b/pkcs11/gkm/gkm-generic-key.c
+@@ -0,0 +1,215 @@
++/*
++ * gnome-keyring
++ *
++ * Copyright (C) 2011 Collabora Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ *
++ * Author: Stef Walter <stefw@collabora.co.uk>
++ */
++
++#include "config.h"
++
++#include "pkcs11/pkcs11.h"
++#include "pkcs11/pkcs11i.h"
++
++#include "gkm-attributes.h"
++#include "gkm-generic-key.h"
++#include "gkm-session.h"
++#include "gkm-transaction.h"
++#include "gkm-util.h"
++
++#include "egg/egg-secure-memory.h"
++
++struct _GkmGenericKey {
++	GkmSecretKey parent;
++	gpointer value;
++	gsize n_value;
++};
++
++G_DEFINE_TYPE (GkmGenericKey, gkm_generic_key, GKM_TYPE_SECRET_KEY);
++
++static const CK_MECHANISM_TYPE GKM_GENERIC_MECHANISMS[] = {
++	CKM_G_HKDF_SHA256_DERIVE
++};
++
++/* -----------------------------------------------------------------------------
++ * INTERNAL
++ */
++
++static CK_RV
++attribute_set_check_value (GkmGenericKey *self, CK_ATTRIBUTE *attr)
++{
++	guchar buffer[20];
++
++	g_assert (GKM_IS_GENERIC_KEY (self));
++	g_assert (attr);
++
++	/* Just asking for the length */
++	if (!attr->pValue) {
++		attr->ulValueLen = 3;
++		return CKR_OK;
++	}
++
++	/* Just the a sha1 of the value */
++	gcry_md_hash_buffer (GCRY_MD_SHA1, buffer, self->value, self->n_value);
++
++	/* Use the first three bytes */
++	return gkm_attribute_set_data (attr, buffer, 3);
++}
++
++static GkmObject*
++factory_create_generic_key (GkmSession *session, GkmTransaction *transaction,
++                            CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
++{
++	GkmGenericKey *key;
++	GkmManager *manager;
++	CK_ATTRIBUTE_PTR value;
++
++	value = gkm_attributes_find (attrs, n_attrs, CKA_VALUE);
++	if (value == NULL) {
++		gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
++		return NULL;
++	}
++
++	if (gkm_attributes_find (attrs, n_attrs, CKA_VALUE_LEN)) {
++		gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
++		return NULL;
++	}
++
++	manager = gkm_manager_for_template (attrs, n_attrs, session);
++	key = g_object_new (GKM_TYPE_GENERIC_KEY,
++	                    "module", gkm_session_get_module (session),
++	                    "manager", manager,
++	                    NULL);
++
++	key->value = egg_secure_alloc (value->ulValueLen);
++	key->n_value = value->ulValueLen;
++	memcpy (key->value, value->pValue, key->n_value);
++
++	gkm_attribute_consume (value);
++
++	gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (key),
++	                                      TRUE, attrs, n_attrs);
++	return GKM_OBJECT (key);
++}
++
++/* -----------------------------------------------------------------------------
++ * OBJECT
++ */
++
++static CK_RV
++gkm_generic_key_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE *attr)
++{
++	GkmGenericKey *self = GKM_GENERIC_KEY (base);
++
++	switch (attr->type)
++	{
++	case CKA_KEY_TYPE:
++		return gkm_attribute_set_ulong (attr, CKK_GENERIC_SECRET);
++
++	case CKA_DERIVE:
++		return gkm_attribute_set_bool (attr, CK_TRUE);
++
++	case CKA_UNWRAP:
++	case CKA_WRAP:
++		return gkm_attribute_set_bool (attr, CK_FALSE);
++
++	case CKA_VALUE:
++		return gkm_attribute_set_data (attr, self->value, self->n_value);
++
++	case CKA_VALUE_LEN:
++		return gkm_attribute_set_ulong (attr, self->n_value);
++
++	case CKA_CHECK_VALUE:
++		return attribute_set_check_value (self, attr);
++
++	case CKA_ALLOWED_MECHANISMS:
++		return gkm_attribute_set_data (attr, (CK_VOID_PTR)GKM_GENERIC_MECHANISMS,
++		                               sizeof (GKM_GENERIC_MECHANISMS));
++	};
++
++	return GKM_OBJECT_CLASS (gkm_generic_key_parent_class)->get_attribute (base, session, attr);
++}
++
++static gconstpointer
++gkm_generic_key_get_key_value (GkmSecretKey *key, gsize *n_value)
++{
++	GkmGenericKey *self = GKM_GENERIC_KEY (key);
++	*n_value = self->n_value;
++	return self->value;
++}
++
++static void
++gkm_generic_key_init (GkmGenericKey *self)
++{
++
++}
++
++static void
++gkm_generic_key_finalize (GObject *obj)
++{
++	GkmGenericKey *self = GKM_GENERIC_KEY (obj);
++
++	if (self->value) {
++		egg_secure_clear (self->value, self->n_value);
++		egg_secure_free (self->value);
++		self->value = NULL;
++		self->n_value = 0;
++	}
++
++	G_OBJECT_CLASS (gkm_generic_key_parent_class)->finalize (obj);
++}
++
++static void
++gkm_generic_key_class_init (GkmGenericKeyClass *klass)
++{
++	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
++	GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
++	GkmSecretKeyClass *key_class = GKM_SECRET_KEY_CLASS (klass);
++
++	gkm_generic_key_parent_class = g_type_class_peek_parent (klass);
++
++	gobject_class->finalize = gkm_generic_key_finalize;
++
++	gkm_class->get_attribute = gkm_generic_key_get_attribute;
++
++	key_class->get_key_value = gkm_generic_key_get_key_value;
++}
++
++/* -----------------------------------------------------------------------------
++ * PUBLIC
++ */
++
++GkmFactory*
++gkm_generic_key_get_factory (void)
++{
++	static CK_OBJECT_CLASS klass = CKO_SECRET_KEY;
++	static CK_KEY_TYPE type = CKK_GENERIC_SECRET;
++
++	static CK_ATTRIBUTE attributes[] = {
++		{ CKA_CLASS, &klass, sizeof (klass) },
++		{ CKA_KEY_TYPE, &type, sizeof (type) }
++	};
++
++	static GkmFactory factory = {
++		attributes,
++		G_N_ELEMENTS (attributes),
++		factory_create_generic_key
++	};
++
++	return &factory;
++}
+diff --git a/pkcs11/gkm/gkm-generic-key.h b/pkcs11/gkm/gkm-generic-key.h
+new file mode 100644
+index 0000000..6b4ee0b
+--- a/dev/null
++++ b/pkcs11/gkm/gkm-generic-key.h
+@@ -0,0 +1,52 @@
++/*
++ * gnome-keyring
++ *
++ * Copyright (C) 2011 Collabora Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ *
++ * Author: Stef Walter <stefw@collabora.co.uk>
++ */
++
++#ifndef __GKM_GENERIC_KEY_H__
++#define __GKM_GENERIC_KEY_H__
++
++#include <glib-object.h>
++
++#include "gkm-secret-key.h"
++#include "gkm-types.h"
++
++#define GKM_FACTORY_GENERIC_KEY            (gkm_generic_key_get_factory ())
++
++#define GKM_TYPE_GENERIC_KEY               (gkm_generic_key_get_type ())
++#define GKM_GENERIC_KEY(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKM_TYPE_GENERIC_KEY, GkmGenericKey))
++#define GKM_GENERIC_KEY_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GKM_TYPE_GENERIC_KEY, GkmGenericKeyClass))
++#define GKM_IS_GENERIC_KEY(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GKM_TYPE_GENERIC_KEY))
++#define GKM_IS_GENERIC_KEY_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GKM_TYPE_GENERIC_KEY))
++#define GKM_GENERIC_KEY_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GKM_TYPE_GENERIC_KEY, GkmGenericKeyClass))
++
++typedef struct _GkmGenericKeyClass GkmGenericKeyClass;
++typedef struct _GkmGenericKeyPrivate GkmGenericKeyPrivate;
++
++struct _GkmGenericKeyClass {
++	GkmSecretKeyClass parent_class;
++};
++
++GType                     gkm_generic_key_get_type           (void);
++
++GkmFactory*               gkm_generic_key_get_factory        (void);
++
++#endif /* __GKM_GENERIC_KEY_H__ */
+diff --git a/pkcs11/gkm/gkm-hkdf-mechanism.c b/pkcs11/gkm/gkm-hkdf-mechanism.c
+new file mode 100644
+index 0000000..bbca94f
+--- a/dev/null
++++ b/pkcs11/gkm/gkm-hkdf-mechanism.c
+@@ -0,0 +1,96 @@
++/*
++ * gnome-keyring
++ *
++ * Copyright (C) 2008 Stefan Walter
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General  License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General  License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General
++ * License along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ */
++
++#include "config.h"
++
++#include "gkm-attributes.h"
++#include "gkm-crypto.h"
++#include "gkm-hkdf-mechanism.h"
++#include "gkm-secret-key.h"
++#include "gkm-session.h"
++#include "gkm-transaction.h"
++
++#include "egg/egg-hkdf.h"
++#include "egg/egg-libgcrypt.h"
++#include "egg/egg-secure-memory.h"
++
++CK_RV
++gkm_hkdf_mechanism_derive (GkmSession *session, const char *algo,
++                           CK_MECHANISM_PTR mech, GkmObject *base,
++                           CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs,
++                           GkmObject **derived)
++{
++	CK_ATTRIBUTE attr;
++	GArray *array;
++	gconstpointer value;
++	gpointer output;
++	gsize n_value;
++	CK_ULONG n_output = 0;
++	GkmTransaction *transaction;
++	CK_KEY_TYPE type;
++
++	g_return_val_if_fail (GKM_IS_SECRET_KEY (base), CKR_GENERAL_ERROR);
++
++	/* Get the value of the original key */
++	value = gkm_secret_key_get_key_value (GKM_SECRET_KEY (base), &n_value);
++	g_return_val_if_fail (value, CKR_GENERAL_ERROR);
++
++	/* What length should we truncate to? */
++	if (!gkm_attributes_find_ulong (attrs, n_attrs, CKA_VALUE_LEN, &n_output)) {
++		if (gkm_attributes_find_ulong (attrs, n_attrs, CKA_KEY_TYPE, &type))
++			n_output = gkm_crypto_secret_key_length (type);
++	}
++
++	/* Default to input length */
++	if (n_output == 0)
++		n_output = n_value;
++
++	output = egg_secure_alloc (n_output);
++	if (!egg_hkdf_perform ("sha256", value, n_value, mech->pParameter,
++	                       mech->ulParameterLen, NULL, 0, output, n_output)) {
++		egg_secure_free (output);
++		return CKR_FUNCTION_FAILED;
++	}
++
++	/* Now setup the attributes with our new value */
++	array = g_array_new (FALSE, FALSE, sizeof (CK_ATTRIBUTE));
++
++	/* Prepend the value */
++	attr.type = CKA_VALUE;
++	attr.pValue = output;
++	attr.ulValueLen = n_output;
++
++	g_array_append_val (array, attr);
++
++	/* Add the remainder of the attributes */
++	g_array_append_vals (array, attrs, n_attrs);
++
++	transaction = gkm_transaction_new ();
++
++	/* Now create an object with these attributes */
++	*derived = gkm_session_create_object_for_attributes (session, transaction,
++	                                                     (CK_ATTRIBUTE_PTR)array->data, array->len);
++
++	egg_secure_free (output);
++	g_array_free (array, TRUE);
++
++	return gkm_transaction_complete_and_unref (transaction);
++}
+diff --git a/pkcs11/gkm/gkm-hkdf-mechanism.h b/pkcs11/gkm/gkm-hkdf-mechanism.h
+new file mode 100644
+index 0000000..fc7ffaa
+--- a/dev/null
++++ b/pkcs11/gkm/gkm-hkdf-mechanism.h
+@@ -0,0 +1,46 @@
++/*
++ * gnome-keyring
++ *
++ * Copyright (C) 2011 Collabora Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General  License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General  License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General
++ * License along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ *
++ * Author: Stef Walter <stefw@collabora.co.uk>
++ */
++
++#ifndef GKM_HKDF_MECHANISM_H_
++#define GKM_HKDF_MECHANISM_H_
++
++#include "gkm-types.h"
++
++#include "pkcs11/pkcs11.h"
++#include "pkcs11/pkcs11i.h"
++
++#include <glib.h>
++
++static const CK_MECHANISM_TYPE GKM_HKDF_MECHANISMS[] = {
++	CKM_G_HKDF_SHA256_DERIVE
++};
++
++CK_RV                    gkm_hkdf_mechanism_derive                     (GkmSession *session,
++                                                                        const gchar *algo,
++                                                                        CK_MECHANISM_PTR mech,
++                                                                        GkmObject *base,
++                                                                        CK_ATTRIBUTE_PTR attrs,
++                                                                        CK_ULONG n_attrs,
++                                                                        GkmObject **derived);
++
++#endif /* GKM_HKDF_MECHANISM_H_ */
+diff --git a/pkcs11/gkm/gkm-module.c b/pkcs11/gkm/gkm-module.c
+index bcc5ee6..eecda2f 100644
+--- a/pkcs11/gkm/gkm-module.c
++++ b/pkcs11/gkm/gkm-module.c
+@@ -30,6 +30,7 @@
+ #include "gkm-certificate.h"
+ #include "gkm-credential.h"
+ #include "gkm-factory.h"
++#include "gkm-generic-key.h"
+ #include "gkm-manager.h"
+ #include "gkm-memory-store.h"
+ #include "gkm-module.h"
+@@ -160,9 +161,15 @@ static const MechanismAndInfo mechanism_list[] = {
+ 
+ 	/*
+ 	 * CKM_DH_PKCS_DERIVE
+-	 * For DH derivation the min and max are sizes of prime in bits.
++	 * For DH derivation the min and max are sizes of output key in bytes.
++	 */
++	{ CKM_DH_PKCS_DERIVE, { 1, 255, CKF_DERIVE } },
++
++	/*
++	 * CKM_G_HKDF_DERIVE
++	 * For HKDF derivation the min and max are sizes of prime in bits.
+ 	 */
+-	{ CKM_DH_PKCS_DERIVE, { 768, 8192, CKF_DERIVE } },
++	{ CKM_G_HKDF_SHA256_DERIVE, { 768, 8192, CKF_DERIVE } },
+ 
+ 	/*
+ 	 * CKM_AES_CBC_PAD
+@@ -598,6 +605,7 @@ gkm_module_init (GkmModule *self)
+ 	gkm_module_register_factory (self, GKM_FACTORY_AES_KEY);
+ 	gkm_module_register_factory (self, GKM_FACTORY_CERTIFICATE);
+ 	gkm_module_register_factory (self, GKM_FACTORY_CREDENTIAL);
++	gkm_module_register_factory (self, GKM_FACTORY_GENERIC_KEY);
+ 	gkm_module_register_factory (self, GKM_FACTORY_NULL_KEY);
+ 	gkm_module_register_factory (self, GKM_FACTORY_DH_PRIVATE_KEY);
+ 	gkm_module_register_factory (self, GKM_FACTORY_PRIVATE_XSA_KEY);
+diff --git a/pkcs11/gkm/gkm-secret-key.c b/pkcs11/gkm/gkm-secret-key.c
+index dd46563..72493ff 100644
+--- a/pkcs11/gkm/gkm-secret-key.c
++++ b/pkcs11/gkm/gkm-secret-key.c
+@@ -157,3 +157,14 @@ gkm_secret_key_class_init (GkmSecretKeyClass *klass)
+ /* -----------------------------------------------------------------------------
+  * PUBLIC
+  */
++
++gconstpointer
++gkm_secret_key_get_key_value (GkmSecretKey *self, gsize *n_value)
++{
++	g_return_val_if_fail (GKM_IS_SECRET_KEY (self), NULL);
++	g_return_val_if_fail (n_value, NULL);
++
++	/* Check with the derived class */
++	g_return_val_if_fail (GKM_SECRET_KEY_GET_CLASS (self)->get_key_value, NULL);
++	return GKM_SECRET_KEY_GET_CLASS (self)->get_key_value (self, n_value);
++}
+diff --git a/pkcs11/gkm/gkm-secret-key.h b/pkcs11/gkm/gkm-secret-key.h
+index 4a1d325..865c3f2 100644
+--- a/pkcs11/gkm/gkm-secret-key.h
++++ b/pkcs11/gkm/gkm-secret-key.h
+@@ -44,8 +44,15 @@ struct _GkmSecretKey {
+ 
+ struct _GkmSecretKeyClass {
+ 	GkmObjectClass parent_class;
++
++	/* virtual methods  --------------------------------------------------------- */
++
++	gconstpointer (*get_key_value) (GkmSecretKey *key, gsize *n_value);
+ };
+ 
+ GType                     gkm_secret_key_get_type           (void);
+ 
++gconstpointer             gkm_secret_key_get_key_value      (GkmSecretKey *self,
++                                                             gsize *n_value);
++
+ #endif /* __GKM_SECRET_KEY_H__ */
+diff --git a/pkcs11/gkm/gkm-types.h b/pkcs11/gkm/gkm-types.h
+index 4ed1c4c..d64b92e 100644
+--- a/pkcs11/gkm/gkm-types.h
++++ b/pkcs11/gkm/gkm-types.h
+@@ -31,6 +31,7 @@ typedef struct _GkmDhKey GkmDhKey;
+ typedef struct _GkmDhPrivateKey GkmDhPrivateKey;
+ typedef struct _GkmDhPublicKey GkmDhPublicKey;
+ typedef struct _GkmFactory GkmFactory;
++typedef struct _GkmGenericKey GkmGenericKey;
+ typedef struct _GkmManager GkmManager;
+ typedef struct _GkmModule GkmModule;
+ typedef struct _GkmNullKey GkmNullKey;
+diff --git a/pkcs11/pkcs11i.h b/pkcs11/pkcs11i.h
+index e85e6cf..11a390c 100644
+--- a/pkcs11/pkcs11i.h
++++ b/pkcs11/pkcs11i.h
+@@ -112,6 +112,8 @@ typedef CK_G_APPLICATION* CK_G_APPLICATION_PTR;
+ /* Used for wrapping and unwrapping as null */
+ #define CKM_G_NULL                           (CKM_GNOME + 100)
+ 
++#define CKM_G_HKDF_SHA256_DERIVE             (CKM_GNOME + 101)
++
+ #define CKK_G_NULL                           (CKK_GNOME + 100)
+ 
+ /* -------------------------------------------------------------------
+diff --git a/ui/gku-prompt-tool.c b/ui/gku-prompt-tool.c
+index 51dc42d..cc9e385 100644
+--- a/ui/gku-prompt-tool.c
++++ b/ui/gku-prompt-tool.c
+@@ -28,6 +28,7 @@
+ #include "egg/egg-entry-buffer.h"
+ #include "egg/egg-error.h"
+ #include "egg/egg-hex.h"
++#include "egg/egg-hkdf.h"
+ #include "egg/egg-libgcrypt.h"
+ #include "egg/egg-secure-memory.h"
+ 
+@@ -693,6 +694,8 @@ negotiate_transport_crypto (void)
+ 	gcry_mpi_t base, prime, peer;
+ 	gcry_mpi_t key, pub, priv;
+ 	gboolean ret = FALSE;
++	gpointer ikm;
++	gsize n_ikm;
+ 
+ 	g_assert (!the_key);
+ 	base = prime = peer = NULL;
+@@ -709,9 +712,14 @@ negotiate_transport_crypto (void)
+ 			gku_prompt_util_encode_mpi (output_data, "transport", "public", pub);
+ 
+ 			/* Build up a key we can use */
+-			n_the_key = 16;
+-			the_key = egg_dh_gen_secret (peer, priv, prime, n_the_key);
+-			ret = (the_key != NULL);
++			ikm = egg_dh_gen_secret (peer, priv, prime, &n_ikm);
++			if (ikm != NULL) {
++				n_the_key = 16;
++				the_key = egg_secure_alloc (n_the_key);
++				if (!egg_hkdf_perform ("sha256", ikm, n_ikm, NULL, 0, NULL, 0, the_key, n_the_key))
++					g_return_val_if_reached (FALSE);
++				ret = TRUE;
++			}
+ 		}
+ 	}
+ 
+diff --git a/ui/gku-prompt.c b/ui/gku-prompt.c
+index 167f219..02acdbf 100644
+--- a/ui/gku-prompt.c
++++ b/ui/gku-prompt.c
+@@ -29,6 +29,7 @@
+ #include "egg/egg-dh.h"
+ #include "egg/egg-error.h"
+ #include "egg/egg-hex.h"
++#include "egg/egg-hkdf.h"
+ #include "egg/egg-libgcrypt.h"
+ #include "egg/egg-secure-memory.h"
+ #include "egg/egg-spawn.h"
+@@ -333,7 +334,8 @@ static gconstpointer
+ calculate_transport_key (GkuPrompt *self, gsize *n_key)
+ {
+ 	gcry_mpi_t peer;
+-	gpointer value;
++	gpointer ikm, key;
++	gsize n_ikm;
+ 
+ 	g_assert (self->pv->output);
+ 	g_assert (n_key);
+@@ -348,16 +350,21 @@ calculate_transport_key (GkuPrompt *self, gsize *n_key)
+ 		if (!gku_prompt_util_decode_mpi (self->pv->output, "transport", "public", &peer))
+ 			return NULL;
+ 
+-		value = egg_dh_gen_secret (peer, self->pv->transport->private,
+-		                           self->pv->transport->prime, 16);
++		ikm = egg_dh_gen_secret (peer, self->pv->transport->private,
++		                         self->pv->transport->prime, &n_ikm);
+ 
+ 		gcry_mpi_release (peer);
+ 
+-		if (!value)
++		if (!ikm)
+ 			return NULL;
+ 
++		key = egg_secure_alloc (16);
++		if (!egg_hkdf_perform ("sha256", ikm, n_ikm, NULL, 0, NULL, 0, key, 16))
++			g_return_val_if_reached (NULL);
++
++		egg_secure_free (ikm);
+ 		egg_secure_free (self->pv->transport->key);
+-		self->pv->transport->key = value;
++		self->pv->transport->key = key;
+ 		self->pv->transport->n_key = 16;
+ 	}
+ 
+--
+cgit v0.8.3.4

diff --git a/gnome-base/gnome-keyring/files/gnome-keyring-trunk-6.patch b/gnome-base/gnome-keyring/files/gnome-keyring-trunk-6.patch
new file mode 100644
index 0000000..bc12839
--- /dev/null
+++ b/gnome-base/gnome-keyring/files/gnome-keyring-trunk-6.patch
@@ -0,0 +1,42 @@
+--- /dev/null
++++ egg/egg-hkdf.h
+@@ -0,0 +1,39 @@
++/*
++ * gnome-keyring
++ *
++ * Copyright (C) 2011 Collabora Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General  License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General  License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General
++ * License along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ *
++ * Author: Stef Walter <stefw@collabora.co.uk>
++ */
++
++#ifndef EGG_HKDF_H_
++#define EGG_HKDF_H_
++
++#include <glib.h>
++
++gboolean   egg_hkdf_perform                                   (const gchar *hash_algo,
++                                                               gconstpointer input,
++                                                               gsize n_input,
++                                                               gconstpointer salt,
++                                                               gsize n_salt,
++                                                               gconstpointer info,
++                                                               gsize n_info,
++                                                               gpointer output,
++                                                               gsize n_output);
++
++#endif /* EGG_HKDF_H_ */

diff --git a/gnome-base/gnome-keyring/gnome-keyring-2.91.4-r300.ebuild b/gnome-base/gnome-keyring/gnome-keyring-2.91.91-r300.ebuild
similarity index 91%
rename from gnome-base/gnome-keyring/gnome-keyring-2.91.4-r300.ebuild
rename to gnome-base/gnome-keyring/gnome-keyring-2.91.91-r300.ebuild
index be0a4d9..75fe44a 100644
--- a/gnome-base/gnome-keyring/gnome-keyring-2.91.4-r300.ebuild
+++ b/gnome-base/gnome-keyring/gnome-keyring-2.91.91-r300.ebuild
@@ -6,7 +6,7 @@ EAPI="3"
 GCONF_DEBUG="yes"
 GNOME2_LA_PUNT="yes"
 
-inherit gnome2 multilib pam virtualx
+inherit autotools gnome2 multilib pam virtualx
 
 DESCRIPTION="Password and keyring managing daemon"
 HOMEPAGE="http://www.gnome.org/"
@@ -38,6 +38,7 @@ RDEPEND=">=dev-libs/glib-2.25:2
 #	valgrind? ( dev-util/valgrind )
 DEPEND="${RDEPEND}
 	sys-devel/gettext
+	>=dev-util/gtk-doc-am-1.9
 	>=dev-util/intltool-0.35
 	>=dev-util/pkgconfig-0.9
 	doc? ( >=dev-util/gtk-doc-1.9 )"
@@ -49,7 +50,7 @@ DOCS="AUTHORS ChangeLog NEWS README"
 
 # tests fail in several ways, they should be fixed in the next cycle (bug #340283),
 # revisit then.
-# UPDATE: tests use system-installed libraries, fail with:
+# UPDATE: gcr tests fail with:
 # ** WARNING **: couldn't load PKCS#11 module: /usr/lib64/pkcs11/gnome-keyring-pkcs11.so: Couldn't initialize module: The device was removed or unplugged 
 RESTRICT="test"
 
@@ -61,7 +62,6 @@ pkg_setup() {
 		$(use_enable pam)
 		$(use_with pam pam-dir $(getpam_mod_dir))
 		--with-root-certs=${ROOT}/etc/ssl/certs/
-		--enable-acl-prompts
 		--enable-ssh-agent
 		--enable-gpg-agent
 		--with-gtk=3.0"
@@ -69,8 +69,6 @@ pkg_setup() {
 }
 
 src_prepare() {
-	gnome2_src_prepare
-
 	# Remove silly CFLAGS
 	sed 's:CFLAGS="$CFLAGS -Werror:CFLAGS="$CFLAGS:' \
 		-i configure.in configure || die "sed failed"
@@ -78,6 +76,14 @@ src_prepare() {
 	# Remove DISABLE_DEPRECATED flags
 	sed -e '/-D[A-Z_]*DISABLE_DEPRECATED/d' \
 		-i configure.in configure || die "sed 2 failed"
+
+	for i in 1 2 3 4 5 6; do
+		epatch "${FILESDIR}/${PN}-trunk-$i.patch"
+	done
+
+	eautoreconf
+
+	gnome2_src_prepare
 }
 
 src_test() {

diff --git a/gnome-base/gnome-keyring/gnome-keyring-2.91.4.ebuild b/gnome-base/gnome-keyring/gnome-keyring-2.91.91.ebuild
similarity index 95%
rename from gnome-base/gnome-keyring/gnome-keyring-2.91.4.ebuild
rename to gnome-base/gnome-keyring/gnome-keyring-2.91.91.ebuild
index dc29a2a..e719061 100644
--- a/gnome-base/gnome-keyring/gnome-keyring-2.91.4.ebuild
+++ b/gnome-base/gnome-keyring/gnome-keyring-2.91.91.ebuild
@@ -59,7 +59,6 @@ pkg_setup() {
 		$(use_enable pam)
 		$(use_with pam pam-dir $(getpam_mod_dir))
 		--with-root-certs=${ROOT}/etc/ssl/certs/
-		--enable-acl-prompts
 		--enable-ssh-agent
 		--enable-gpg-agent
 		--with-gtk=2.0"
@@ -67,8 +66,6 @@ pkg_setup() {
 }
 
 src_prepare() {
-	gnome2_src_prepare
-
 	# Remove silly CFLAGS
 	sed 's:CFLAGS="$CFLAGS -Werror:CFLAGS="$CFLAGS:' \
 		-i configure.in configure || die "sed failed"
@@ -76,6 +73,14 @@ src_prepare() {
 	# Remove DISABLE_DEPRECATED flags
 	sed -e '/-D[A-Z_]*DISABLE_DEPRECATED/d' \
 		-i configure.in configure || die "sed 2 failed"
+
+	for i in 1 2 3 4 5 6; do
+		epatch "${FILESDIR}/${PN}-trunk-$i.patch"
+	done
+
+	eautoreconf
+
+	gnome2_src_prepare
 }
 
 src_test() {

diff --git a/gnome-base/gnome-keyring/gnome-keyring-9999.ebuild b/gnome-base/gnome-keyring/gnome-keyring-9999.ebuild
index be0a4d9..de87fa5 100644
--- a/gnome-base/gnome-keyring/gnome-keyring-9999.ebuild
+++ b/gnome-base/gnome-keyring/gnome-keyring-9999.ebuild
@@ -61,7 +61,6 @@ pkg_setup() {
 		$(use_enable pam)
 		$(use_with pam pam-dir $(getpam_mod_dir))
 		--with-root-certs=${ROOT}/etc/ssl/certs/
-		--enable-acl-prompts
 		--enable-ssh-agent
 		--enable-gpg-agent
 		--with-gtk=3.0"



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [gentoo-commits] proj/gnome:master commit in: gnome-base/gnome-keyring/, gnome-base/gnome-keyring/files/
@ 2011-05-21 16:41 Nirbheek Chauhan
  0 siblings, 0 replies; 2+ messages in thread
From: Nirbheek Chauhan @ 2011-05-21 16:41 UTC (permalink / raw
  To: gentoo-commits

commit:     195dcc0febedc607891d19986e922c0ebb7d0d22
Author:     Alexandre Rostovtsev <tetromino <AT> gmail <DOT> com>
AuthorDate: Fri May 20 23:21:14 2011 +0000
Commit:     Nirbheek Chauhan <nirbheek <AT> gentoo <DOT> org>
CommitDate: Sat May 21 16:34:31 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/gnome.git;a=commit;h=195dcc0f

gnome-keyring-3.0.2 version bump + libcap automagic dep fix

* Bump gnome-keyring to 3.0.2-r200 and -r300.
* Correct dependency in 9999 (libcap-ng, not libcap)
* Correct sed in 9999 (no Makefile.in)
* Add patches to make libcap (and libcap-ng, for 9999) dependencies
  non-automagic. Patches submitted to upstream bug 649936

Signed-off-by: Nirbheek Chauhan <nirbheek <AT> gentoo.org>

---
 .../gnome-keyring-3.0.2-automagic-libcap.patch     |   57 +++++++++++++++++++
 .../gnome-keyring-3.1.1-automagic-libcap-ng.patch  |   60 ++++++++++++++++++++
 ...r200.ebuild => gnome-keyring-3.0.2-r200.ebuild} |   15 +++--
 ...r300.ebuild => gnome-keyring-3.0.2-r300.ebuild} |   15 +++--
 gnome-base/gnome-keyring/gnome-keyring-9999.ebuild |   14 +++--
 5 files changed, 143 insertions(+), 18 deletions(-)

diff --git a/gnome-base/gnome-keyring/files/gnome-keyring-3.0.2-automagic-libcap.patch b/gnome-base/gnome-keyring/files/gnome-keyring-3.0.2-automagic-libcap.patch
new file mode 100644
index 0000000..2947af3
--- /dev/null
+++ b/gnome-base/gnome-keyring/files/gnome-keyring-3.0.2-automagic-libcap.patch
@@ -0,0 +1,57 @@
+From b75b9d5aa7f6207eca190b9d8e08059872c99365 Mon Sep 17 00:00:00 2001
+From: Alexandre Rostovtsev <tetromino@gmail.com>
+Date: Fri, 20 May 2011 17:53:43 -0400
+Subject: [PATCH] Fix automagic libcap dependency (GNOME bug #649936)
+
+Backport of the patch by Saleem Abdulrasool <compnerd@compnerd.org>
+to gnome-keyring-3.0.x
+
+Signed-off-by: Alexandre Rostovtsev <tetromino@gmail.com>
+---
+ configure.in |   29 +++++++++++++++++++++--------
+ 1 files changed, 21 insertions(+), 8 deletions(-)
+
+diff --git a/configure.in b/configure.in
+index b2d07a7..88f7e66 100644
+--- a/configure.in
++++ b/configure.in
+@@ -445,16 +445,29 @@ fi
+ # libcap2
+ #
+
+-AC_CHECK_LIB([cap], [cap_get_proc], have_libcap="yes", have_libcap="no")
+-
+-if test $have_libcap = yes; then
+-   AC_DEFINE(HAVE_LIBCAP, 1, [Have libcap2 package, libcap library])
+-   DAEMON_LIBS="$DAEMON_LIBS -lcap"
+-else
+-   AC_MSG_WARN([libcap2 (or development headers) is not installed])
++AC_ARG_WITH([libcap],
++            [AC_HELP_STRING([--without-libcap],
++                            [build without libcap2 (disables Linux capabilities support)])],,
++            [with_libcap=auto])
++
++if test x"$with_libcap" != x"no" ; then
++    AC_CHECK_LIB([cap], [cap_get_proc],
++                 [
++                   with_libcap="yes"
++                   AC_DEFINE([HAVE_LIBCAP], [1], [Have libcap2 package, libcap library])
++                   DAEMON_LIBS="$DAEMON_LIBS -lcap"
++                 ],
++                 [
++                   if test x"$with_libcap" = x"yes" ; then
++                     AC_MSG_ERROR([libcap2 support requested, but package not found])
++                   else
++                     AC_MSG_WARN([libcap2 (or development headers) is not installed])
++                   fi
++                   with_libcap="no"
++                 ])
+ fi
+
+-libcap_status=$have_libcap
++libcap_status=$with_libcap
+
+ # --------------------------------------------------------------------
+ # Debug mode
+--
+1.7.5.rc3

diff --git a/gnome-base/gnome-keyring/files/gnome-keyring-3.1.1-automagic-libcap-ng.patch b/gnome-base/gnome-keyring/files/gnome-keyring-3.1.1-automagic-libcap-ng.patch
new file mode 100644
index 0000000..b87bae3
--- /dev/null
+++ b/gnome-base/gnome-keyring/files/gnome-keyring-3.1.1-automagic-libcap-ng.patch
@@ -0,0 +1,60 @@
+From 8191a26b9717f0b0b8beabdc765cc3c4713b2586 Mon Sep 17 00:00:00 2001
+From: Alexandre Rostovtsev <tetromino@gmail.com>
+Date: Fri, 20 May 2011 18:06:00 -0400
+Subject: [PATCH] Fix automagic libcap-ng dependency (GNOME bug #649936)
+
+A slight modification of the patch by Saleem Abdulrasool
+<compnerd@compnerd.org>. Like his patch, this is for 3.1.x.
+
+Signed-off-by: Alexandre Rostovtsev <tetromino@gmail.com>
+---
+ configure.ac |   32 ++++++++++++++++++++++----------
+ 1 files changed, 22 insertions(+), 10 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index d9e947a..02372d8 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -451,18 +451,30 @@ fi
+ # libcap-ng
+ #
+
+-AC_CHECK_LIB([cap-ng], [capng_clear], have_libcapng="yes", have_libcapng="no")
+-
+-if test "$have_libcapng" = "yes"; then
+-   AC_DEFINE(HAVE_LIBCAPNG, 1, [Have libcap-ng package, libcap-ng library])
+-   DAEMON_LIBS="$DAEMON_LIBS -lcap-ng"
+-else
+-   have_lipcapng="no"
+-   AC_MSG_WARN([libcap-ng (or development headers) is not installed])
++AC_ARG_WITH([libcap-ng],
++            [AC_HELP_STRING([--without-libcap-ng],
++                            [build without libcap-ng (disables Linux capabilities support)])],,
++            [with_libcap_ng=auto])
++
++if test x"$with_libcap_ng" != x"no" ; then
++    AC_CHECK_LIB([cap-ng], [capng_clear],
++                 [
++                   with_libcap_ng="yes"
++                   AC_DEFINE([HAVE_LIBCAPNG], [1], [have libcap-ng headers and library])
++                   DAEMON_LIBS="$DAEMON_LIBS -lcap-ng"
++                 ],
++                 [
++                   if test x"$with_libcap_ng" = x"yes" ; then
++                     AC_MSG_ERROR([libcap-ng support requested, but package not found])
++                   else
++                     AC_MSG_WARN([libcap-ng (or development headers) is not installed])
++                   fi
++                   with_libcap_ng="no"
++                 ])
+ fi
+
+-AM_CONDITIONAL(WITH_CAPS, test "$have_libcapng" = "yes")
+-libcapng_status=$have_libcapng
++AM_CONDITIONAL([WITH_CAPS], [test x"$with_libcap_ng" = x"yes"])
++libcapng_status="$with_libcap_ng"
+
+ # --------------------------------------------------------------------
+ # Debug mode
+--
+1.7.5.rc3

diff --git a/gnome-base/gnome-keyring/gnome-keyring-3.0.1-r200.ebuild b/gnome-base/gnome-keyring/gnome-keyring-3.0.2-r200.ebuild
similarity index 84%
rename from gnome-base/gnome-keyring/gnome-keyring-3.0.1-r200.ebuild
rename to gnome-base/gnome-keyring/gnome-keyring-3.0.2-r200.ebuild
index cfe1dea..bc6d16d 100644
--- a/gnome-base/gnome-keyring/gnome-keyring-3.0.1-r200.ebuild
+++ b/gnome-base/gnome-keyring/gnome-keyring-3.0.2-r200.ebuild
@@ -6,7 +6,7 @@ EAPI="3"
 GCONF_DEBUG="no"
 GNOME2_LA_PUNT="yes"
 
-inherit gnome2 multilib pam virtualx
+inherit autotools eutils gnome2 multilib pam virtualx
 if [[ ${PV} = 9999 ]]; then
 	inherit gnome2-live
 fi
@@ -16,7 +16,7 @@ HOMEPAGE="http://www.gnome.org/"
 
 LICENSE="GPL-2 LGPL-2"
 SLOT="0"
-IUSE="debug doc pam test"
+IUSE="+caps debug doc pam test"
 if [[ ${PV} = 9999 ]]; then
 	KEYWORDS=""
 else
@@ -31,13 +31,13 @@ RDEPEND=">=dev-libs/glib-2.25:2
 	>=sys-apps/dbus-1.0
 	>=dev-libs/libgcrypt-1.2.2
 	>=dev-libs/libtasn1-1
-	sys-libs/libcap
-
+	caps? ( sys-libs/libcap )
 	pam? ( virtual/pam )
 "
 #	valgrind? ( dev-util/valgrind )
 DEPEND="${RDEPEND}
 	sys-devel/gettext
+	>=dev-util/gtk-doc-am-1.9
 	>=dev-util/intltool-0.35
 	>=dev-util/pkgconfig-0.9
 	doc? ( >=dev-util/gtk-doc-1.9 )"
@@ -47,10 +47,10 @@ PDEPEND="gnome-base/libgnome-keyring"
 
 pkg_setup() {
 	DOCS="AUTHORS ChangeLog NEWS README"
-	# XXX: Automagic libcap support
 	G2CONF="${G2CONF}
 		$(use_enable debug)
 		$(use_enable test tests)
+		$(use_with caps libcap)
 		$(use_enable pam)
 		$(use_with pam pam-dir $(getpam_mod_dir))
 		--with-root-certs=${EPREFIX}/etc/ssl/certs/
@@ -64,8 +64,11 @@ src_prepare() {
 	# Disable gcr tests due to weirdness with opensc
 	# ** WARNING **: couldn't load PKCS#11 module: /usr/lib64/pkcs11/gnome-keyring-pkcs11.so: Couldn't initialize module: The device was removed or unplugged
 	sed -e 's/^\(SUBDIRS = \.\)\(.*\)/\1/' \
-		-i gcr/Makefile.am gcr/Makefile.in || die "sed failed"
+		-i gcr/Makefile.* || die "sed failed"
 
+	# https://bugzilla.gnome.org/show_bug.cgi?id=649936
+	epatch "${FILESDIR}"/${P}-automagic-libcap.patch
+	eautoreconf
 	gnome2_src_prepare
 }
 

diff --git a/gnome-base/gnome-keyring/gnome-keyring-3.0.1-r300.ebuild b/gnome-base/gnome-keyring/gnome-keyring-3.0.2-r300.ebuild
similarity index 85%
rename from gnome-base/gnome-keyring/gnome-keyring-3.0.1-r300.ebuild
rename to gnome-base/gnome-keyring/gnome-keyring-3.0.2-r300.ebuild
index 032bc34..257766f 100644
--- a/gnome-base/gnome-keyring/gnome-keyring-3.0.1-r300.ebuild
+++ b/gnome-base/gnome-keyring/gnome-keyring-3.0.2-r300.ebuild
@@ -6,7 +6,7 @@ EAPI="3"
 GCONF_DEBUG="no"
 GNOME2_LA_PUNT="yes"
 
-inherit gnome2 multilib pam virtualx
+inherit autotools eutils gnome2 multilib pam virtualx
 if [[ ${PV} = 9999 ]]; then
 	inherit gnome2-live
 fi
@@ -16,7 +16,7 @@ HOMEPAGE="http://www.gnome.org/"
 
 LICENSE="GPL-2 LGPL-2"
 SLOT="0"
-IUSE="debug doc pam test"
+IUSE="+caps debug doc pam test"
 if [[ ${PV} = 9999 ]]; then
 	KEYWORDS=""
 else
@@ -33,13 +33,13 @@ RDEPEND=">=dev-libs/glib-2.25:2
 	>=sys-apps/dbus-1.0
 	>=dev-libs/libgcrypt-1.2.2
 	>=dev-libs/libtasn1-1
-	sys-libs/libcap
-
+	caps? ( sys-libs/libcap )
 	pam? ( virtual/pam )
 "
 #	valgrind? ( dev-util/valgrind )
 DEPEND="${RDEPEND}
 	sys-devel/gettext
+	>=dev-util/gtk-doc-am-1.9
 	>=dev-util/intltool-0.35
 	>=dev-util/pkgconfig-0.9
 	doc? ( >=dev-util/gtk-doc-1.9 )"
@@ -49,10 +49,10 @@ PDEPEND="gnome-base/libgnome-keyring"
 
 pkg_setup() {
 	DOCS="AUTHORS ChangeLog NEWS README"
-	# XXX: Automagic libcap support
 	G2CONF="${G2CONF}
 		$(use_enable debug)
 		$(use_enable test tests)
+		$(use_with caps libcap)
 		$(use_enable pam)
 		$(use_with pam pam-dir $(getpam_mod_dir))
 		--with-root-certs=${EPREFIX}/etc/ssl/certs/
@@ -66,8 +66,11 @@ src_prepare() {
 	# Disable gcr tests due to weirdness with opensc
 	# ** WARNING **: couldn't load PKCS#11 module: /usr/lib64/pkcs11/gnome-keyring-pkcs11.so: Couldn't initialize module: The device was removed or unplugged
 	sed -e 's/^\(SUBDIRS = \.\)\(.*\)/\1/' \
-		-i gcr/Makefile.am gcr/Makefile.in || die "sed failed"
+		-i gcr/Makefile.* || die "sed failed"
 
+	# https://bugzilla.gnome.org/show_bug.cgi?id=649936
+	epatch "${FILESDIR}"/${P}-automagic-libcap.patch
+	eautoreconf
 	gnome2_src_prepare
 }
 

diff --git a/gnome-base/gnome-keyring/gnome-keyring-9999.ebuild b/gnome-base/gnome-keyring/gnome-keyring-9999.ebuild
index 032bc34..cc9c315 100644
--- a/gnome-base/gnome-keyring/gnome-keyring-9999.ebuild
+++ b/gnome-base/gnome-keyring/gnome-keyring-9999.ebuild
@@ -6,7 +6,7 @@ EAPI="3"
 GCONF_DEBUG="no"
 GNOME2_LA_PUNT="yes"
 
-inherit gnome2 multilib pam virtualx
+inherit autotools eutils gnome2 multilib pam virtualx
 if [[ ${PV} = 9999 ]]; then
 	inherit gnome2-live
 fi
@@ -16,7 +16,7 @@ HOMEPAGE="http://www.gnome.org/"
 
 LICENSE="GPL-2 LGPL-2"
 SLOT="0"
-IUSE="debug doc pam test"
+IUSE="+caps debug doc pam test"
 if [[ ${PV} = 9999 ]]; then
 	KEYWORDS=""
 else
@@ -33,13 +33,13 @@ RDEPEND=">=dev-libs/glib-2.25:2
 	>=sys-apps/dbus-1.0
 	>=dev-libs/libgcrypt-1.2.2
 	>=dev-libs/libtasn1-1
-	sys-libs/libcap
-
+	caps? ( sys-libs/libcap-ng )
 	pam? ( virtual/pam )
 "
 #	valgrind? ( dev-util/valgrind )
 DEPEND="${RDEPEND}
 	sys-devel/gettext
+	>=dev-util/gtk-doc-am-1.9
 	>=dev-util/intltool-0.35
 	>=dev-util/pkgconfig-0.9
 	doc? ( >=dev-util/gtk-doc-1.9 )"
@@ -49,10 +49,10 @@ PDEPEND="gnome-base/libgnome-keyring"
 
 pkg_setup() {
 	DOCS="AUTHORS ChangeLog NEWS README"
-	# XXX: Automagic libcap support
 	G2CONF="${G2CONF}
 		$(use_enable debug)
 		$(use_enable test tests)
+		$(use_with caps libcap-ng)
 		$(use_enable pam)
 		$(use_with pam pam-dir $(getpam_mod_dir))
 		--with-root-certs=${EPREFIX}/etc/ssl/certs/
@@ -66,8 +66,10 @@ src_prepare() {
 	# Disable gcr tests due to weirdness with opensc
 	# ** WARNING **: couldn't load PKCS#11 module: /usr/lib64/pkcs11/gnome-keyring-pkcs11.so: Couldn't initialize module: The device was removed or unplugged
 	sed -e 's/^\(SUBDIRS = \.\)\(.*\)/\1/' \
-		-i gcr/Makefile.am gcr/Makefile.in || die "sed failed"
+		-i gcr/Makefile.* || die "sed failed"
 
+	# https://bugzilla.gnome.org/show_bug.cgi?id=649936
+	epatch "${FILESDIR}"/${PN}-3.1.1-automagic-libcap-ng.patch
 	gnome2_src_prepare
 }
 



^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-05-21 16:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-09 11:34 [gentoo-commits] proj/gnome:master commit in: gnome-base/gnome-keyring/, gnome-base/gnome-keyring/files/ Nirbheek Chauhan
  -- strict thread matches above, loose matches on Subject: below --
2011-05-21 16:41 Nirbheek Chauhan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox