* [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-05-21 16:41 [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-03-09 11:34 Nirbheek Chauhan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox