From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from ) id 1PxHhx-0003PV-Og for garchives@archives.gentoo.org; Wed, 09 Mar 2011 11:37:39 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id CE4E2E0527; Wed, 9 Mar 2011 11:34:40 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id 26E74E050E for ; Wed, 9 Mar 2011 11:34:40 +0000 (UTC) Received: from pelican.gentoo.org (unknown [66.219.59.40]) (using TLSv1 with cipher ADH-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 5F3241BC0DC for ; Wed, 9 Mar 2011 11:34:39 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by pelican.gentoo.org (Postfix) with ESMTP id 77ABF80072 for ; Wed, 9 Mar 2011 11:34:38 +0000 (UTC) From: "Nirbheek Chauhan" To: gentoo-commits@lists.gentoo.org Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Nirbheek Chauhan" Message-ID: <75ec0b9f144846a5c361f6bf029775e73cd55091.nirbheek@gentoo> Subject: [gentoo-commits] proj/gnome:master commit in: gnome-base/gnome-keyring/, gnome-base/gnome-keyring/files/ X-VCS-Repository: proj/gnome X-VCS-Files: gnome-base/gnome-keyring/files/gnome-keyring-trunk-1.patch gnome-base/gnome-keyring/files/gnome-keyring-trunk-2.patch gnome-base/gnome-keyring/files/gnome-keyring-trunk-3.patch gnome-base/gnome-keyring/files/gnome-keyring-trunk-4.patch gnome-base/gnome-keyring/files/gnome-keyring-trunk-5.patch gnome-base/gnome-keyring/files/gnome-keyring-trunk-6.patch gnome-base/gnome-keyring/gnome-keyring-2.91.4-r300.ebuild gnome-base/gnome-keyring/gnome-keyring-2.91.4.ebuild gnome-base/gnome-keyring/gnome-keyring-2.91.91-r300.ebuild gnome-base/gnome-keyring/gnome-keyring-2.91.91.ebuild gnome-base/gnome-keyring/gnome-keyring-9999.ebuild X-VCS-Directories: gnome-base/gnome-keyring/ gnome-base/gnome-keyring/files/ X-VCS-Committer: nirbheek X-VCS-Committer-Name: Nirbheek Chauhan X-VCS-Revision: 75ec0b9f144846a5c361f6bf029775e73cd55091 Date: Wed, 9 Mar 2011 11:34:38 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: X-Archives-Hash: b6d5919c8c679947bd9da4b4fa68b350 commit: 75ec0b9f144846a5c361f6bf029775e73cd55091 Author: Nirbheek Chauhan gentoo org> AuthorDate: Tue Mar 8 13:26:22 2011 +0000 Commit: Nirbheek Chauhan gentoo org> CommitDate: Wed Mar 9 11:21:11 2011 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/gnome.git;a=3D= commit;h=3D75ec0b9f gnome-base/gnome-keyring: 2.91.4 =E2=86=92 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 =3D> gnome-keyring-2.91.91-r300.ebuild} | 16 +- ...-2.91.4.ebuild =3D> 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 +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; + } +=20 +-#ifdef UNTESTED_CODE +- + static void=20 + append_each_header (gpointer key, gpointer value, gpointer user_data) + { + GString *string =3D (GString*)user_data; +-=09 ++ + 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; +-=09 ++ 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); +=20 + string =3D g_string_sized_new (4096); +-=09 ++ + /* 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, + } +=20 + /* Resize string to fit the base64 data. Algorithm from Glib reference= */ +- length =3D n_data * 4 / 3 + n_data * 4 / (3 * 72) + 7; ++ estimate =3D n_data * 4 / 3 + n_data * 4 / (3 * 65) + 7; + n_prefix =3D string->len; +- g_string_set_size (string, n_prefix + length); +-=09 +- /* The actual base64 data */ ++ g_string_set_size (string, n_prefix + estimate); ++ ++ /* The actual base64 data, without line breaks */ + state =3D save =3D 0; +- length =3D g_base64_encode_step (data, n_data, TRUE,=20 +- string->str + string->len, &state, &sav= e); ++ length =3D g_base64_encode_step (data, n_data, FALSE, ++ string->str + n_prefix, &state, &save); ++ length +=3D g_base64_encode_close (TRUE, string->str + n_prefix + leng= th, ++ &state, &save); ++ ++ g_assert (length <=3D estimate); + g_string_set_size (string, n_prefix + length); +-=09 ++ ++ /* ++ * 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 =3D 64; i < length; i +=3D 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'); +-=09 ++ + *n_result =3D string->len; + return (guchar*)g_string_free (string, FALSE); + } +=20 +-#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 + #include + #include ++#include +=20 + EGG_SECURE_GLIB_DEFINITIONS (); +=20 + 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, gsiz= e n_data, + gboolean res; + const gchar *dekinfo; +=20 ++ g_assert (type); ++ test->reftype =3D type; ++ + g_assert ("no data in PEM callback" && data !=3D NULL); + g_assert ("no data in PEM callback" && n_data > 0); + test->refenc =3D g_memdup (data, n_data); +@@ -129,6 +134,29 @@ test_write_reference (Test *test, gconstpointer unu= sed) + g_assert ("data doesn't match input" && memcmp (encrypted, test->refen= c, n_encrypted) =3D=3D 0); + } +=20 ++static void ++test_write_exactly_same (Test *test, gconstpointer unused) ++{ ++ guchar *result; ++ gsize n_result; ++ guint num; ++ ++ num =3D egg_openssl_pem_parse (test->input, test->n_input, parse_refer= ence, test); ++ g_assert ("couldn't PEM block in reference data" && num =3D=3D 1); ++ ++ result =3D 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, white= space ++ * and line endings. ++ */ ++ ++ egg_assert_cmpmem (test->input, test->n_input, =3D=3D, result, n_resul= t); ++ g_free (result); ++} ++ + /* 29 bytes (prime number, so block length has bad chance of matching *= / + static const guchar *TEST_DATA =3D (guchar*)"ABCDEFGHIJKLMNOPQRSTUVWXYZ= 123"; + const gsize TEST_DATA_L =3D 29; +@@ -175,6 +203,7 @@ main (int argc, char **argv) +=20 + 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_wri= te_exactly_same, teardown); + g_test_add ("/openssl/openssl_roundtrip", Test, NULL, setup, test_open= ssl_roundtrip, teardown); +=20 + 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 +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=3D643229 +--- +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 + ]) +=20 +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 $(DESTD= IR)$(libexecdir) && $(LN_S) gnome-keyring-prompt@GCR_VERSION_SUFFIX@ gnom= e-keyring-prompt) + endif ++ ++@INTLTOOL_DESKTOP_RULE@ ++desktopdir=3D $(datadir)/applications ++desktop_in_in_files =3D gnome-keyring-prompt.desktop.in.in ++desktop_in_files =3D gnome-keyring-prompt.desktop.in ++desktop_DATA =3D $(desktop_in_files:.desktop.in=3D.desktop) ++ ++EXTRA_DIST +=3D \ ++ $(desktop_in_in_files) ++ ++CLEANFILES =3D \ ++ $(desktop_DATA) ++ ++DISTCLEANFILES =3D \ ++ $(desktop_in_files) +diff --git a/ui/gnome-keyring-prompt.desktop.in.in b/ui/gnome-keyring-pr= ompt.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=3DKeyring Access ++_Comment=3DUnlock access to passwords and other secrets ++Icon=3Dsecurity-medium ++Exec=3D@LIBEXECDIR@/gnome-keyring-prompt ++Terminal=3Dfalse ++Type=3DApplication ++NoDisplay=3Dtrue +-- +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 +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-cr= eate.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" +=20 + #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" +=20 + #include "egg/egg-error.h" +@@ -43,12 +46,14 @@ +=20 + enum { + PROP_0, +- PROP_PKCS11_ATTRIBUTES ++ PROP_PKCS11_ATTRIBUTES, ++ PROP_ALIAS + }; +=20 + struct _GkdSecretCreate { + GkdSecretPrompt parent; + GckAttributes *pkcs11_attrs; ++ gchar *alias; + gchar *result_path; + }; +=20 +@@ -93,6 +98,8 @@ static gboolean + create_collection_with_secret (GkdSecretCreate *self, GkdSecretSecret *= master) + { + DBusError derr =3D DBUS_ERROR_INIT; ++ GkdSecretService *service; ++ gchar *identifier; +=20 + g_assert (GKD_SECRET_IS_CREATE (self)); + g_assert (master); +@@ -106,9 +113,84 @@ create_collection_with_secret (GkdSecretCreate *sel= f, GkdSecretSecret *master) + return FALSE; + } +=20 ++ if (self->alias) { ++ if (!gkd_secret_util_parse_path (self->result_path, &identifier, NULL= )) ++ g_assert_not_reached (); ++ service =3D gkd_secret_prompt_get_service (GKD_SECRET_PROMPT (self)); ++ gkd_secret_service_set_alias (service, self->alias, identifier); ++ g_free (identifier); ++ } ++ + return TRUE; + } +=20 ++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 =3D gkd_secret_prompt_get_service (GKD_SECRET_PROMPT (self)); ++ caller =3D gkd_secret_prompt_get_caller (GKD_SECRET_PROMPT (self)); ++ objects =3D gkd_secret_prompt_get_objects (GKD_SECRET_PROMPT (self)); ++ ++ identifier =3D gkd_secret_service_get_alias (service, self->alias); ++ if (!identifier) ++ return FALSE; ++ ++ /* Make sure it actually exists */ ++ path =3D gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identif= ier, -1); ++ collection =3D gkd_secret_objects_lookup_collection (objects, caller, = path); ++ ++ if (collection) { ++ self->result_path =3D 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 =3D GKD_SECRET_PROMPT (self); ++ ++ unlock =3D gkd_secret_unlock_new (gkd_secret_prompt_get_service (promp= t), ++ gkd_secret_prompt_get_caller (prompt), ++ gkd_secret_dispatch_get_object_path (G= KD_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 (p= rompt), ++ gkd_secret_prompt_get_caller (pr= ompt), ++ GKD_SECRET_DISPATCH (unlock)); ++ gkd_secret_unlock_call_prompt (unlock, gkd_secret_prompt_get_window_i= d (prompt)); ++ } ++ ++ g_object_unref (unlock); ++ g_object_unref (self); ++} ++ + /* --------------------------------------------------------------------= --------- + * OBJECT + */ +@@ -120,7 +202,15 @@ gkd_secret_create_prompt_ready (GkdSecretPrompt *pr= ompt) + GkdSecretSecret *master; +=20 + 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; + } +=20 +@@ -161,10 +251,8 @@ gkd_secret_create_finalize (GObject *obj) + GkdSecretCreate *self =3D GKD_SECRET_CREATE (obj); +=20 + gck_attributes_unref (self->pkcs11_attrs); +- self->pkcs11_attrs =3D NULL; +- + g_free (self->result_path); +- self->result_path =3D NULL; ++ g_free (self->alias); +=20 + 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 =3D g_value_dup_boxed (value); + g_return_if_fail (self->pkcs11_attrs); + break; ++ case PROP_ALIAS: ++ g_return_if_fail (!self->alias); ++ self->alias =3D 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= )); + } +=20 + /* --------------------------------------------------------------------= --------- +@@ -227,12 +326,13 @@ gkd_secret_create_class_init (GkdSecretCreateClass= *klass) +=20 + 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); + } +=20 +diff --git a/daemon/dbus/gkd-secret-create.h b/daemon/dbus/gkd-secret-cr= eate.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); +=20 + GkdSecretCreate* gkd_secret_create_new (GkdSecre= tService *service, + const gc= har *caller, +- GckAttri= butes *attrs); ++ GckAttri= butes *attrs, ++ const gc= har *alias); +=20 + GckObject* gkd_secret_create_with_credential (GckSessi= on *session, + GckAttri= butes *attrs, +diff --git a/daemon/dbus/gkd-secret-introspect.c b/daemon/dbus/gkd-secre= t-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 =3D + " \n" + "\n" + " \n" +- " \n" ++ " \n" ++ " \n" + " \n" + " \n" + " \n" +diff --git a/daemon/dbus/gkd-secret-objects.c b/daemon/dbus/gkd-secret-o= bjects.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; + }; +=20 + 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; +=20 + if (g_str_has_prefix (path, SECRET_ALIAS_PREFIX)) { +- replace =3D g_hash_table_lookup (self->aliases, *collection); ++ replace =3D gkd_secret_service_get_alias (self->service, *collection)= ; + if (!replace) { +=20 + /* +@@ -831,7 +830,7 @@ gkd_secret_objects_constructor (GType type, guint n_= props, GObjectConstructParam + static void + gkd_secret_objects_init (GkdSecretObjects *self) + { +- self->aliases =3D g_hash_table_new_full (g_str_hash, g_str_equal, g_fr= ee, g_free); ++ + } +=20 + static void +@@ -858,7 +857,6 @@ gkd_secret_objects_finalize (GObject *obj) + { + GkdSecretObjects *self =3D GKD_SECRET_OBJECTS (obj); +=20 +- g_hash_table_destroy (self->aliases); + g_assert (!self->pkcs11_slot); + g_assert (!self->service); +=20 +@@ -1333,20 +1331,3 @@ gkd_secret_objects_handle_get_secrets (GkdSecretO= bjects *self, DBusMessage *mess +=20 + return reply; + } +- +-const gchar* +-gkd_secret_objects_get_alias (GkdSecretObjects *self, const gchar *alia= s) +-{ +- 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 *alia= s, +- 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 (ident= ifier)); +-} +diff --git a/daemon/dbus/gkd-secret-objects.h b/daemon/dbus/gkd-secret-o= bjects.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); +=20 +-const gchar* gkd_secret_objects_get_alias (GkdSe= cretObjects *self, +- const= gchar *alias); +- +-void gkd_secret_objects_set_alias (GkdSe= cretObjects *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-pr= ompt.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" +=20 + 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; + } +=20 ++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 (GkdSecretProm= pt *self) + return gkd_secret_service_get_pkcs11_session (self->pv->service, self-= >pv->caller); + } +=20 ++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-pr= ompt.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); +=20 + const gchar* gkd_secret_prompt_get_caller (GkdSecre= tPrompt *self); +=20 ++const gchar* gkd_secret_prompt_get_window_id (GkdSecre= tPrompt *self); ++ + GckSession* gkd_secret_prompt_get_pkcs11_session (GkdSecre= tPrompt *self); +=20 + GkdSecretService* gkd_secret_prompt_get_service (GkdSecre= tPrompt *self); +diff --git a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-s= ervice.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; + }; +=20 + 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; +=20 + /* Forward declaration */ +@@ -93,9 +93,11 @@ update_default (GkdSecretService *self, gboolean forc= e) + const gchar *identifier; + gchar *path; +=20 +- identifier =3D gkd_secret_objects_get_alias (self->objects, "default")= ; +- if (!force && identifier) +- return; ++ if (!force) { ++ identifier =3D g_hash_table_lookup (self->aliases, "default"); ++ if (identifier) ++ return; ++ } +=20 + path =3D default_path (); + if (g_file_get_contents (path, &contents, NULL, NULL)) { +@@ -107,8 +109,7 @@ update_default (GkdSecretService *self, gboolean for= ce) + } + g_free (path); +=20 +- gkd_secret_objects_set_alias (self->objects, "default", contents); +- g_free (contents); ++ g_hash_table_replace (self->aliases, g_strdup ("default"), contents); + } +=20 + static void +@@ -118,7 +119,7 @@ store_default (GkdSecretService *self) + const gchar *identifier; + gchar *path; +=20 +- identifier =3D gkd_secret_objects_get_alias (self->objects, "default")= ; ++ identifier =3D g_hash_table_lookup (self->aliases, "default"); + if (!identifier) + return; +=20 +@@ -172,8 +173,7 @@ free_client (gpointer data) + } +=20 + /* 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); +=20 + g_free (client); + } +@@ -237,8 +237,7 @@ on_get_connection_unix_process_id (DBusPendingCall *= pending, gpointer user_data) + if (caller_pid !=3D 0) + client->caller_exec =3D egg_unix_credentials_executable (caller_pid)= ; + client->app.applicationData =3D client; +- client->sessions =3D g_hash_table_new_full (g_str_hash, g_str_equal, = NULL, dispose_and_unref); +- client->prompts =3D g_hash_table_new_full (g_str_hash, g_str_equal, N= ULL, dispose_and_unref); ++ client->dispatch =3D g_hash_table_new_full (g_str_hash, g_str_equal, = NULL, dispose_and_unref); +=20 + g_hash_table_replace (self->clients, client->caller_peer, client); +=20 +@@ -371,10 +370,8 @@ static DBusMessage* + service_method_open_session (GkdSecretService *self, DBusMessage *messa= ge) + { + GkdSecretSession *session; +- ServiceClient *client; + DBusMessage *reply =3D NULL; + const gchar *caller; +- const gchar *path; +=20 + if (!dbus_message_has_signature (message, "sv")) + return NULL; +@@ -385,18 +382,11 @@ service_method_open_session (GkdSecretService *sel= f, DBusMessage *message) + session =3D gkd_secret_session_new (self, caller); + reply =3D gkd_secret_session_handle_open (session, message); +=20 +- if (dbus_message_get_type (reply) =3D=3D DBUS_MESSAGE_TYPE_METHOD_RETU= RN) { +- /* Take ownership of the session */ +- client =3D g_hash_table_lookup (self->clients, caller); +- g_return_val_if_fail (client, NULL); +- path =3D gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (se= ssion)); +- 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) =3D=3D DBUS_MESSAGE_TYPE_METHOD_RETU= RN) ++ gkd_secret_service_publish_dispatch (self, caller, ++ GKD_SECRET_DISPATCH (session)); +=20 ++ g_object_unref (session); + return reply; + } +=20 +@@ -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; +=20 + /* 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_ARG= S, + "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 =3D 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 supporte= d"); ++ } ++ } +=20 + gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE); +=20 + /* Create the prompt object, for the password */ + caller =3D dbus_message_get_sender (message); +- create =3D gkd_secret_create_new (self, caller, attrs); ++ create =3D gkd_secret_create_new (self, caller, attrs, alias); + gck_attributes_unref (attrs); +=20 + path =3D gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (cre= ate)); +- client =3D 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)); +=20 + coll =3D "/"; + reply =3D 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); +=20 ++ g_object_unref (create); + return reply; + } +=20 +@@ -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, DBu= sMessage *message) + return NULL; +=20 + caller =3D dbus_message_get_sender (message); +- unlock =3D gkd_secret_unlock_new (self, caller); ++ unlock =3D gkd_secret_unlock_new (self, caller, NULL); + for (i =3D 0; i < n_objpaths; ++i) + gkd_secret_unlock_queue (unlock, objpaths[i]); + dbus_free_string_array (objpaths); +=20 + /* So do we need to prompt? */ + if (gkd_secret_unlock_have_queued (unlock)) { +- client =3D 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 =3D gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (un= lock)); +- g_hash_table_replace (client->prompts, (gpointer)path, g_object_ref (= unlock)); +=20 + /* No need to prompt */ + } else { +@@ -546,7 +548,6 @@ static DBusMessage* + service_method_change_lock (GkdSecretService *self, DBusMessage *messag= e) + { + 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); +=20 + change =3D gkd_secret_change_new (self, caller, path); +- client =3D g_hash_table_lookup (self->clients, caller); +- g_return_val_if_fail (client, NULL); + path =3D gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (cha= nge)); +- g_hash_table_replace (client->prompts, (gpointer)path, g_object_ref (c= hange)); ++ gkd_secret_service_publish_dispatch (self, caller, ++ GKD_SECRET_DISPATCH (change)); +=20 + reply =3D dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TY= PE_INVALID); +@@ -588,9 +588,7 @@ service_method_read_alias (GkdSecretService *self, D= BusMessage *message) + if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &alias, D= BUS_TYPE_INVALID)) + return NULL; +=20 +- update_default (self, FALSE); +- +- identifier =3D gkd_secret_objects_get_alias (self->objects, alias); ++ identifier =3D gkd_secret_service_get_alias (self, alias); + if (identifier) + path =3D gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identi= fier, -1); +=20 +@@ -647,11 +645,9 @@ service_method_set_alias (GkdSecretService *self, D= BusMessage *message) +=20 + g_object_unref (collection); +=20 +- gkd_secret_objects_set_alias (self->objects, alias, identifier); ++ gkd_secret_service_set_alias (self, alias, identifier); + g_free (identifier); +=20 +- store_default (self); +- + return dbus_message_new_method_return (message); + } +=20 +@@ -907,17 +903,10 @@ service_dispatch_message (GkdSecretService *self, = DBusMessage *message) + path =3D dbus_message_get_path (message); + g_return_if_fail (path); +=20 +- /* Dispatched to a session, find a session in this client */ +- if (object_path_has_prefix (path, SECRET_SESSION_PREFIX)) { +- object =3D g_hash_table_lookup (client->sessions, path); +- if (object =3D=3D NULL) +- reply =3D gkd_secret_error_no_such_object (message); +- else +- reply =3D 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 =3D 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 =3D g_hash_table_lookup (client->dispatch, path); + if (object =3D=3D NULL) + reply =3D gkd_secret_error_no_such_object (message); + else +@@ -1064,6 +1053,7 @@ static void + gkd_secret_service_init (GkdSecretService *self) + { + self->clients =3D g_hash_table_new_full (g_str_hash, g_str_equal, NULL= , free_client); ++ self->aliases =3D g_hash_table_new_full (g_str_hash, g_str_equal, g_fr= ee, g_free); + } +=20 + static void +@@ -1106,6 +1096,9 @@ gkd_secret_service_finalize (GObject *obj) + g_hash_table_destroy (self->clients); + self->clients =3D NULL; +=20 ++ g_hash_table_destroy (self->aliases); ++ self->aliases =3D NULL; ++ + G_OBJECT_CLASS (gkd_secret_service_parent_class)->finalize (obj); + } +=20 +@@ -1251,6 +1244,7 @@ gkd_secret_service_lookup_session (GkdSecretServic= e *self, const gchar *path, + const gchar *caller) + { + ServiceClient *client; ++ gpointer object; +=20 + 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 (GkdSecretServi= ce *self, const gchar *path, + client =3D g_hash_table_lookup (self->clients, caller); + g_return_val_if_fail (client, NULL); +=20 +- return g_hash_table_lookup (client->sessions, path); ++ object =3D g_hash_table_lookup (client->dispatch, path); ++ if (object =3D=3D NULL || !GKD_SECRET_IS_SESSION (object)) ++ return NULL; ++ ++ return GKD_SECRET_SESSION (object); + } +=20 + void +@@ -1277,5 +1275,53 @@ gkd_secret_service_close_session (GkdSecretServic= e *self, GkdSecretSession *sess + g_return_if_fail (client); +=20 + path =3D gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (ses= sion)); +- 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 *alia= s) ++{ ++ const gchar *identifier; ++ ++ g_return_val_if_fail (GKD_SECRET_IS_SERVICE (self), NULL); ++ g_return_val_if_fail (alias, NULL); ++ ++ identifier =3D g_hash_table_lookup (self->aliases, alias); ++ if (!identifier && g_str_equal (alias, "default")) { ++ update_default (self, TRUE); ++ identifier =3D g_hash_table_lookup (self->aliases, alias); ++ } ++ return identifier; ++} ++ ++void ++gkd_secret_service_set_alias (GkdSecretService *self, const gchar *alia= s, ++ 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 (ident= ifier)); ++ ++ if (g_str_equal (alias, "default")) ++ store_default (self); ++} ++ ++void ++gkd_secret_service_publish_dispatch (GkdSecretService *self, const gcha= r *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 =3D g_hash_table_lookup (self->clients, caller); ++ g_return_if_fail (client); ++ path =3D 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-s= ervice.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_sess= ion (GkdSecretSer + void gkd_secret_service_send (Gkd= SecretService *self, + DBu= sMessage *message); +=20 ++const gchar* gkd_secret_service_get_alias (Gkd= SecretService *self, ++ con= st gchar *alias); ++ ++void gkd_secret_service_set_alias (Gkd= SecretService *self, ++ con= st gchar *alias, ++ con= st gchar *identifier); ++ ++void gkd_secret_service_publish_dispatch (Gkd= SecretService *self, ++ con= st gchar *caller, ++ Gkd= SecretDispatch *object); ++ + #endif /* ___SECRET_SERVICE_H__ */ +diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-un= lock.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, DBusMe= ssage *message) + return dbus_message_new_error (message, SECRET_ERROR_ALREADY_EXISTS, + "This prompt has already been shown.")= ; +=20 +- g_free (self->window_id); +- self->window_id =3D g_strdup (window_id); +- +- self->prompted =3D TRUE; +- perform_next_unlock (self); ++ gkd_secret_unlock_call_prompt (self, window_id); +=20 + reply =3D 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_p= rops, GObjectConstructParam + g_return_val_if_fail (self->service, NULL); +=20 + /* Setup the path for the object */ +- self->object_path =3D g_strdup_printf (SECRET_PROMPT_PREFIX "/u%d", ++= unique_prompt_number); ++ if (!self->object_path) ++ self->object_path =3D g_strdup_printf (SECRET_PROMPT_PREFIX "/u%d", += +unique_prompt_number); +=20 + 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 =3D 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) +=20 + g_object_class_install_property (gobject_class, PROP_OBJECT_PATH, + g_param_spec_pointer ("object-path", "Object Path", "DBus Obje= ct Path", +- G_PARAM_READABLE)); ++ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +=20 + g_object_class_install_property (gobject_class, PROP_SERVICE, + g_param_spec_object ("service", "Service", "Service which owns this p= rompt", +@@ -490,22 +491,27 @@ gkd_secret_dispatch_iface (GkdSecretDispatchIface = *iface) + */ +=20 + 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, "call= er", caller, NULL); ++ return g_object_new (GKD_SECRET_TYPE_UNLOCK, ++ "service", service, ++ "caller", caller, ++ "object-path", object_path, ++ NULL); + } +=20 + void +-gkd_secret_unlock_queue (GkdSecretUnlock *self, const gchar *objpath) ++gkd_secret_unlock_queue (GkdSecretUnlock *self, const gchar *unlock_pat= h) + { + gboolean locked =3D TRUE; + GckObject *coll; + gchar *path; +=20 + g_return_if_fail (GKD_SECRET_IS_UNLOCK (self)); +- g_return_if_fail (objpath); ++ g_return_if_fail (unlock_path); +=20 +- coll =3D lookup_collection (self, objpath); ++ coll =3D lookup_collection (self, unlock_path); + if (coll =3D=3D NULL) + return; +=20 +@@ -515,7 +521,7 @@ gkd_secret_unlock_queue (GkdSecretUnlock *self, cons= t gchar *objpath) +=20 + } +=20 +- path =3D g_strdup (objpath); ++ path =3D g_strdup (unlock_path); + if (locked) + g_queue_push_tail (self->queued, path); + else +@@ -552,6 +558,19 @@ gkd_secret_unlock_reset_results (GkdSecretUnlock *s= elf) + g_array_set_size (self->results, 0); + } +=20 ++void ++gkd_secret_unlock_call_prompt (GkdSecretUnlock *self, const gchar *wind= ow_id) ++{ ++ g_return_if_fail (GKD_SECRET_IS_UNLOCK (self)); ++ g_return_if_fail (!self->prompted); ++ ++ g_assert (!self->window_id); ++ self->window_id =3D g_strdup (window_id); ++ ++ self->prompted =3D 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-un= lock.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); +=20 + GkdSecretUnlock* gkd_secret_unlock_new (GkdSecre= tService *service, +- const gc= har *caller); ++ const gc= har *caller, ++ const gc= har *object_path); +=20 + void gkd_secret_unlock_queue (GkdSecre= tUnlock *self, +- const gc= har *objpath); ++ const gc= har *unlock_path); +=20 + gboolean gkd_secret_unlock_have_queued (GkdSecre= tUnlock *self); +=20 +@@ -54,6 +55,9 @@ gchar** gkd_secret_unlock_get_results = (GkdSecretUnlock * +=20 + void gkd_secret_unlock_reset_results (GkdSecre= tUnlock *self); +=20 ++void gkd_secret_unlock_call_prompt (GkdSecre= tUnlock *self, ++ const gc= har *window_id); ++ + gboolean gkd_secret_unlock_with_secret (GckObjec= t *collection, + GkdSecre= tSecret *master, + DBusErro= r *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 +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, Gk= mSecret *login, gconstpointe + /* Parse the ASN1 data */ + res =3D gkm_data_der_read_certificate (copy, n_data, &asn1); + if (res !=3D 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 +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-s= ession.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 *pr= iv_key, + gconstpointer input, gsize n_input, GckObject **aes_key= ) + { + GError *error =3D NULL; +- GckMechanism mech =3D { 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 =3D CKM_DH_PKCS_DERIVE; ++ mech.parameter =3D input; ++ mech.n_parameter =3D n_input; ++ ++ attrs =3D 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 =3D gck_session_derive_key_full (session, priv_key, &mech, attr= s, NULL, &error); ++ ++ gck_attributes_unref (attrs); ++ ++ if (!dh_key) { ++ g_warning ("couldn't derive key from dh key pair: %s", egg_error_mess= age (error)); ++ g_clear_error (&error); ++ return FALSE; ++ } ++ ++ /* ++ * Now use HKDF to generate our AES key. ++ */ ++ ++ mech.type =3D CKM_G_HKDF_SHA256_DERIVE; ++ mech.parameter =3D NULL; ++ mech.n_parameter =3D 0; +=20 + attrs =3D 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); +=20 +- *aes_key =3D gck_session_derive_key_full (session, priv_key, &mech, at= trs, NULL, &error); +- ++ *aes_key =3D gck_session_derive_key_full (session, dh_key, &mech, attr= s, NULL, &error); + gck_attributes_unref (attrs); ++ g_object_unref (dh_key); +=20 + 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_messa= ge (error)); + g_clear_error (&error); + return FALSE; + } +@@ -529,7 +561,7 @@ gkd_secret_session_handle_open (GkdSecretSession *se= lf, DBusMessage *message) + "The session algorithm input argument= was invalid"); + reply =3D plain_negotiate (self, message); +=20 +- } else if (g_str_equal (algorithm, "dh-ietf1024-aes128-cbc-pkcs7")) { ++ } else if (g_str_equal (algorithm, "dh-ietf1024-sha256-aes128-cbc-pkcs= 7")) { + 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 *se= lf, DBusMessage *message) + reply =3D aes_negotiate (self, message, input, n_input); +=20 + } else { +- reply =3D dbus_message_new_error_printf (message, SECRET_ERROR_NOT_SU= PPORTED, ++ reply =3D dbus_message_new_error_printf (message, DBUS_ERROR_NOT_SUPP= ORTED, + "The algorithm '%s' is not sup= ported", algorithm); + } +=20 +diff --git a/daemon/dbus/gkd-secret-types.h b/daemon/dbus/gkd-secret-typ= es.h +index 3b6aed1..176c92f 100644 +--- a/daemon/dbus/gkd-secret-types.h ++++ b/daemon/dbus/gkd-secret-types.h +@@ -42,7 +42,6 @@ +=20 + #define SECRET_ERROR_ALREADY_EXISTS "org.freedesktop.Secret.Error.Al= readyExists" + #define SECRET_ERROR_IS_LOCKED "org.freedesktop.Secret.Error.Is= Locked" +-#define SECRET_ERROR_NOT_SUPPORTED "org.freedesktop.Secret.Error.No= tSupported" + #define SECRET_ERROR_NO_SESSION "org.freedesktop.Secret.Error.No= Session" + #define SECRET_ERROR_NO_SUCH_OBJECT "org.freedesktop.Secret.Error.No= SuchObject" +=20 +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 =3D \ + 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 =3D \ + libegg_prompt_la_SOURCES =3D \ + 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, +=20 + 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 =3D 0; + gcry_mpi_t k; + gint bits; +=20 +@@ -329,11 +328,8 @@ egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv= , + /* Write out the secret */ + gcry =3D gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n_value, k); + g_return_val_if_fail (gcry =3D=3D 0, NULL); +- if (n_value < bytes) +- offset =3D bytes - n_value; +- value =3D egg_secure_alloc (n_value + offset); +- memset (value, 0, n_value + offset); +- gcry =3D gcry_mpi_print (GCRYMPI_FMT_USG, value + offset, n_value, &n_= value, k); ++ value =3D egg_secure_alloc (n_value); ++ gcry =3D gcry_mpi_print (GCRYMPI_FMT_USG, value, n_value, &n_value, k)= ; + g_return_val_if_fail (gcry =3D=3D 0, NULL); +=20 + #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 +=20 +- if (bytes !=3D 0 && bytes < n_value) { +- offset =3D n_value - bytes; +- memmove (value, value + offset, bytes); +- egg_secure_clear (value + bytes, offset); +- } ++ *bytes =3D n_value; +=20 + #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 by= tes); ++ gsize *b= ytes); +=20 + #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 ++ */ ++ ++#include "config.h" ++ ++#include "egg-hkdf.h" ++#include "egg-secure-memory.h" ++ ++#include ++ ++#include ++ ++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 =3D NULL; ++ gpointer buffer =3D 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 =3D gcry_md_map_name (hash_algo); ++ g_return_val_if_fail (algo !=3D 0, FALSE); ++ ++ hash_len =3D gcry_md_get_algo_dlen (algo); ++ g_return_val_if_fail (hash_len !=3D 0, FALSE); ++ g_return_val_if_fail (n_output <=3D 255 * hash_len, FALSE); ++ ++ /* Buffer we need to for intermediate stuff */ ++ if (gcry_is_secure (input)) { ++ flags =3D GCRY_MD_FLAG_SECURE; ++ buffer =3D gcry_malloc_secure (hash_len); ++ } else { ++ flags =3D 0; ++ buffer =3D gcry_malloc (hash_len); ++ } ++ ++ g_return_val_if_fail (buffer, FALSE); ++ n_buffer =3D 0; ++ ++ /* Salt defaults to hash_len zeros */ ++ if (!salt) { ++ salt =3D alloc =3D g_malloc0 (hash_len); ++ n_salt =3D hash_len; ++ } ++ ++ /* Step 1: Extract */ ++ gcry =3D gcry_md_open (&md1, algo, GCRY_MD_FLAG_HMAC); ++ g_return_val_if_fail (gcry =3D=3D 0, FALSE); ++ gcry =3D gcry_md_setkey (md1, salt, n_salt); ++ g_return_val_if_fail (gcry =3D=3D 0, FALSE); ++ gcry_md_write (md1, input, n_input); ++ ++ /* Step 2: Expand */ ++ gcry =3D gcry_md_open (&md2, algo, GCRY_MD_FLAG_HMAC); ++ g_return_val_if_fail (gcry =3D=3D 0, FALSE); ++ gcry =3D gcry_md_setkey (md2, gcry_md_read (md1, algo), hash_len); ++ g_return_val_if_fail (gcry =3D=3D 0, FALSE); ++ gcry_md_close (md1); ++ ++ at =3D output; ++ for (i =3D 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 =3D hash_len; ++ memcpy (buffer, gcry_md_read (md2, algo), n_buffer); ++ ++ step =3D MIN (n_buffer, n_output); ++ memcpy (at, buffer, step); ++ n_output -=3D step; ++ at +=3D 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 + #include +=20 ++#include + #include +=20 + EGG_SECURE_GLIB_DEFINITIONS (); +@@ -43,6 +44,7 @@ test_perform (void) + gcry_mpi_t x2, X2; + gpointer k1, k2; + gboolean ret; ++ gsize n1, n2; +=20 + /* 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); +=20 + /* Calculate keys */ +- k1 =3D egg_dh_gen_secret (X2, x1, p, 96); ++ k1 =3D egg_dh_gen_secret (X2, x1, p, &n1); + g_assert (k1); +- k2 =3D egg_dh_gen_secret (X1, x2, p, 96); ++ k2 =3D egg_dh_gen_secret (X1, x2, p, &n2); + g_assert (k2); +=20 + /* Keys must be the same */ +- g_assert (memcmp (k1, k2, 96) =3D=3D 0); ++ egg_assert_cmpsize (n1, =3D=3D, n2); ++ g_assert (memcmp (k1, k2, n1) =3D=3D 0); +=20 + gcry_mpi_release (p); + gcry_mpi_release (g); +@@ -97,7 +100,7 @@ test_short_pair (void) + } +=20 + 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); + } +=20 + static void + test_default_1024 (void) + { +- test_dh_default ("ietf-ike-grp-modp-1024", 1024); ++ check_dh_default ("ietf-ike-grp-modp-1024", 1024); + } +=20 + static void + test_default_1536 (void) + { +- test_dh_default ("ietf-ike-grp-modp-1536", 1536); ++ check_dh_default ("ietf-ike-grp-modp-1536", 1536); + } +=20 +- + static void + test_default_2048 (void) + { +- test_dh_default ("ietf-ike-grp-modp-2048", 2048); ++ check_dh_default ("ietf-ike-grp-modp-2048", 2048); + } +=20 + static void + test_default_3072 (void) + { +- test_dh_default ("ietf-ike-grp-modp-3072", 3072); ++ check_dh_default ("ietf-ike-grp-modp-3072", 3072); + } +=20 + static void + test_default_4096 (void) + { +- test_dh_default ("ietf-ike-grp-modp-4096", 4096); ++ check_dh_default ("ietf-ike-grp-modp-4096", 4096); + } +=20 + static void + test_default_8192 (void) + { +- test_dh_default ("ietf-ike-grp-modp-8192", 8192); ++ check_dh_default ("ietf-ike-grp-modp-8192", 8192); + } +=20 + 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 ++*/ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++ ++#include "egg-hkdf.h" ++#include "egg-secure-memory.h" ++#include "egg-testing.h" ++ ++#include ++ ++EGG_SECURE_GLIB_DEFINITIONS (); ++ ++static void ++test_hkdf_test_case_1 (void) ++{ ++ /* RFC 5869: A.1 Test Case 1 */ ++ const guchar ikm[] =3D { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0= b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; ++ const guchar salt[] =3D { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x= 07, ++ 0x08, 0x09, 0x0a, 0x0b, 0x0c }; ++ const guchar info[] =3D { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0x= f7, ++ 0xf8, 0xf9 }; ++ const guchar okm[] =3D { 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7= a, ++ 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), =3D=3D, 22); ++ egg_assert_cmpsize (sizeof (salt), =3D=3D, 13); ++ egg_assert_cmpsize (sizeof (info), =3D=3D, 10); ++ egg_assert_cmpsize (sizeof (okm), =3D=3D, 42); ++ ++ memset (buffer, 0, sizeof (buffer)); ++ ret =3D 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), =3D=3D, okm, sizeof (okm))= ; ++} ++ ++static void ++test_hkdf_test_case_2 (void) ++{ ++ /* RFC 5869: A.2 Test Case 2 */ ++ const guchar ikm[] =3D { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0= 7, ++ 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[] =3D { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x= 67, ++ 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[] =3D { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0x= b7, ++ 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[] =3D { 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa= 1, ++ 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), =3D=3D, 80); ++ egg_assert_cmpsize (sizeof (salt), =3D=3D, 80); ++ egg_assert_cmpsize (sizeof (info), =3D=3D, 80); ++ egg_assert_cmpsize (sizeof (okm), =3D=3D, 82); ++ ++ memset (buffer, 0, sizeof (buffer)); ++ ret =3D 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), =3D=3D, okm, sizeof (okm))= ; ++} ++ ++static void ++test_hkdf_test_case_3 (void) ++{ ++ /* RFC 5869: A.3 Test Case 3 */ ++ const guchar ikm[] =3D { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0= b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,}; ++ const guchar salt[] =3D { }; ++ const guchar info[] =3D { }; ++ const guchar okm[] =3D { 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8= f, ++ 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), =3D=3D, 22); ++ egg_assert_cmpsize (sizeof (salt), =3D=3D, 0); ++ egg_assert_cmpsize (sizeof (info), =3D=3D, 0); ++ egg_assert_cmpsize (sizeof (okm), =3D=3D, 42); ++ ++ memset (buffer, 0, sizeof (buffer)); ++ ret =3D 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), =3D=3D, okm, sizeof (okm))= ; ++} ++ ++static void ++test_hkdf_test_case_4 (void) ++{ ++ /* RFC 5869: A.4 Test Case 4 */ ++ const guchar ikm[] =3D { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0= b, ++ 0x0b, 0x0b, 0x0b }; ++ const guchar salt[] =3D { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x= 07, ++ 0x08, 0x09, 0x0a, 0x0b, 0x0c }; ++ const guchar info[] =3D { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0x= f7, ++ 0xf8, 0xf9 }; ++ const guchar okm[] =3D { 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x6= 9, ++ 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), =3D=3D, 11); ++ egg_assert_cmpsize (sizeof (salt), =3D=3D, 13); ++ egg_assert_cmpsize (sizeof (info), =3D=3D, 10); ++ egg_assert_cmpsize (sizeof (okm), =3D=3D, 42); ++ ++ memset (buffer, 0, sizeof (buffer)); ++ ret =3D 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), =3D=3D, okm, sizeof (okm))= ; ++} ++ ++static void ++test_hkdf_test_case_5 (void) ++{ ++ /* RFC 5869: A.5 Test Case 5 */ ++ const guchar ikm[] =3D { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0= 7, ++ 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[] =3D { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x= 67, ++ 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[] =3D { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0x= b7, ++ 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[] =3D { 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf= 7, ++ 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), =3D=3D, 80); ++ egg_assert_cmpsize (sizeof (salt), =3D=3D, 80); ++ egg_assert_cmpsize (sizeof (info), =3D=3D, 80); ++ egg_assert_cmpsize (sizeof (okm), =3D=3D, 82); ++ ++ memset (buffer, 0, sizeof (buffer)); ++ ret =3D 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), =3D=3D, okm, sizeof (okm))= ; ++} ++ ++static void ++test_hkdf_test_case_6 (void) ++{ ++ /* RFC 5869: A.6 Test Case 6 */ ++ const guchar ikm[] =3D { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0= b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; ++ const guchar salt[] =3D { }; ++ const guchar info[] =3D { }; ++ const guchar okm[] =3D { 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x6= 1, ++ 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), =3D=3D, 22); ++ egg_assert_cmpsize (sizeof (salt), =3D=3D, 0); ++ egg_assert_cmpsize (sizeof (info), =3D=3D, 0); ++ egg_assert_cmpsize (sizeof (okm), =3D=3D, 42); ++ ++ memset (buffer, 0, sizeof (buffer)); ++ ret =3D 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), =3D=3D, okm, sizeof (okm))= ; ++} ++ ++static void ++test_hkdf_test_case_7 (void) ++{ ++ /* RFC 5869: A.7 Test Case 7 */ ++ const guchar ikm[] =3D { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0= c, ++ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, ++ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }; ++ const guchar *salt =3D NULL; ++ const guchar info[] =3D { }; ++ const guchar okm[] =3D { 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf= 3, ++ 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), =3D=3D, 22); ++ egg_assert_cmpsize (sizeof (info), =3D=3D, 0); ++ egg_assert_cmpsize (sizeof (okm), =3D=3D, 42); ++ ++ memset (buffer, 0, sizeof (buffer)); ++ ret =3D 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), =3D=3D, 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 =3D \ + 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" +=20 + #include "pkcs11/pkcs11.h" ++#include "pkcs11/pkcs11i.h" +=20 + #include "gkm-aes-mechanism.h" + #include "gkm-attributes.h" +@@ -41,6 +42,11 @@ struct _GkmAesKey { +=20 + G_DEFINE_TYPE (GkmAesKey, gkm_aes_key, GKM_TYPE_SECRET_KEY); +=20 ++static const CK_MECHANISM_TYPE GKM_AES_MECHANISMS[] =3D { ++ CKM_AES_CBC_PAD, ++ CKM_G_HKDF_SHA256_DERIVE ++}; ++ + /* --------------------------------------------------------------------= --------- + * INTERNAL + */ +@@ -139,7 +145,7 @@ factory_create_aes_key (GkmSession *session, GkmTran= saction *transaction, + */ +=20 + static CK_RV +-gkm_aes_key_real_get_attribute (GkmObject *base, GkmSession *session, C= K_ATTRIBUTE *attr) ++gkm_aes_key_get_attribute (GkmObject *base, GkmSession *session, CK_ATT= RIBUTE *attr) + { + GkmAesKey *self =3D GKM_AES_KEY (base); +=20 +@@ -148,6 +154,9 @@ gkm_aes_key_real_get_attribute (GkmObject *base, Gkm= Session *session, CK_ATTRIBU + case CKA_KEY_TYPE: + return gkm_attribute_set_ulong (attr, CKK_AES); +=20 ++ 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, Gk= mSession *session, CK_ATTRIBU + return GKM_OBJECT_CLASS (gkm_aes_key_parent_class)->get_attribute (bas= e, session, attr); + } +=20 ++static gconstpointer ++gkm_aes_key_get_key_value (GkmSecretKey *key, gsize *n_value) ++{ ++ GkmAesKey *self =3D GKM_AES_KEY (key); ++ *n_value =3D 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 =3D G_OBJECT_CLASS (klass); + GkmObjectClass *gkm_class =3D GKM_OBJECT_CLASS (klass); ++ GkmSecretKeyClass *key_class =3D GKM_SECRET_KEY_CLASS (klass); +=20 + gkm_aes_key_parent_class =3D g_type_class_peek_parent (klass); +=20 + gobject_class->finalize =3D gkm_aes_key_finalize; +=20 +- gkm_class->get_attribute =3D gkm_aes_key_real_get_attribute; ++ gkm_class->get_attribute =3D gkm_aes_key_get_attribute; ++ ++ key_class->get_key_value =3D gkm_aes_key_get_key_value; + } +=20 + /* --------------------------------------------------------------------= --------- +diff --git a/pkcs11/gkm/gkm-aes-mechanism.h b/pkcs11/gkm/gkm-aes-mechani= sm.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 +=20 +-static const CK_MECHANISM_TYPE GKM_AES_MECHANISMS[] =3D { +- CKM_AES_CBC_PAD +-}; +- + CK_RV gkm_aes_mechanism_wrap (GkmSess= ion *session, + CK_MECH= ANISM_PTR mech, + GkmObje= ct *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_MECHA= NISM_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_MEC= HANISM_PTR mech, GkmObject * + gcry_error_t gcry; + CK_ATTRIBUTE attr; + GArray *array; ++ gsize n_actual =3D 0; + CK_ULONG n_value =3D 0; +- gpointer value; ++ guchar *value; + GkmTransaction *transaction; + CK_KEY_TYPE type; +=20 +@@ -239,7 +240,7 @@ gkm_dh_mechanism_derive (GkmSession *session, CK_MEC= HANISM_PTR mech, GkmObject * + if (n_value =3D=3D 0) + n_value =3D (gcry_mpi_get_nbits (prime) + 7) / 8; +=20 +- value =3D egg_dh_gen_secret (peer, priv, prime, n_value); ++ value =3D egg_dh_gen_secret (peer, priv, prime, &n_actual); + gcry_mpi_release (peer); +=20 + if (value =3D=3D NULL) +@@ -250,8 +251,24 @@ gkm_dh_mechanism_derive (GkmSession *session, CK_ME= CHANISM_PTR mech, GkmObject * +=20 + /* Prepend the value */ + attr.type =3D CKA_VALUE; +- attr.pValue =3D value; + attr.ulValueLen =3D n_value; ++ ++ /* Is it too long, move to the front and truncate */ ++ if (n_actual > n_value) { ++ attr.pValue =3D value + (n_actual - n_value); ++ ++ /* If it's too short, expand with zeros */ ++ } else if (n_actual < n_value) { ++ value =3D egg_secure_realloc (value, n_value); ++ memmove (value + (n_value - n_actual), value, n_actual); ++ memset (value, 0, (n_value - n_actual)); ++ attr.pValue =3D value; ++ ++ /* It's just right */ ++ } else { ++ attr.pValue =3D value; ++ } ++ + g_array_append_val (array, attr); +=20 + /* 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 ++ */ ++ ++#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[] =3D { ++ 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 =3D 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 *transa= ction, ++ CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs) ++{ ++ GkmGenericKey *key; ++ GkmManager *manager; ++ CK_ATTRIBUTE_PTR value; ++ ++ value =3D gkm_attributes_find (attrs, n_attrs, CKA_VALUE); ++ if (value =3D=3D 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 =3D gkm_manager_for_template (attrs, n_attrs, session); ++ key =3D g_object_new (GKM_TYPE_GENERIC_KEY, ++ "module", gkm_session_get_module (session), ++ "manager", manager, ++ NULL); ++ ++ key->value =3D egg_secure_alloc (value->ulValueLen); ++ key->n_value =3D 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 =3D 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_MECHANI= SMS, ++ 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 =3D GKM_GENERIC_KEY (key); ++ *n_value =3D self->n_value; ++ return self->value; ++} ++ ++static void ++gkm_generic_key_init (GkmGenericKey *self) ++{ ++ ++} ++ ++static void ++gkm_generic_key_finalize (GObject *obj) ++{ ++ GkmGenericKey *self =3D GKM_GENERIC_KEY (obj); ++ ++ if (self->value) { ++ egg_secure_clear (self->value, self->n_value); ++ egg_secure_free (self->value); ++ self->value =3D NULL; ++ self->n_value =3D 0; ++ } ++ ++ G_OBJECT_CLASS (gkm_generic_key_parent_class)->finalize (obj); ++} ++ ++static void ++gkm_generic_key_class_init (GkmGenericKeyClass *klass) ++{ ++ GObjectClass *gobject_class =3D G_OBJECT_CLASS (klass); ++ GkmObjectClass *gkm_class =3D GKM_OBJECT_CLASS (klass); ++ GkmSecretKeyClass *key_class =3D GKM_SECRET_KEY_CLASS (klass); ++ ++ gkm_generic_key_parent_class =3D g_type_class_peek_parent (klass); ++ ++ gobject_class->finalize =3D gkm_generic_key_finalize; ++ ++ gkm_class->get_attribute =3D gkm_generic_key_get_attribute; ++ ++ key_class->get_key_value =3D gkm_generic_key_get_key_value; ++} ++ ++/* --------------------------------------------------------------------= --------- ++ * PUBLIC ++ */ ++ ++GkmFactory* ++gkm_generic_key_get_factory (void) ++{ ++ static CK_OBJECT_CLASS klass =3D CKO_SECRET_KEY; ++ static CK_KEY_TYPE type =3D CKK_GENERIC_SECRET; ++ ++ static CK_ATTRIBUTE attributes[] =3D { ++ { CKA_CLASS, &klass, sizeof (klass) }, ++ { CKA_KEY_TYPE, &type, sizeof (type) } ++ }; ++ ++ static GkmFactory factory =3D { ++ 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 ++ */ ++ ++#ifndef __GKM_GENERIC_KEY_H__ ++#define __GKM_GENERIC_KEY_H__ ++ ++#include ++ ++#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 ((k= lass), 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 ((k= lass), 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-mecha= nism.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 =3D 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 =3D gkm_secret_key_get_key_value (GKM_SECRET_KEY (base), &n_valu= e); ++ 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_outp= ut)) { ++ if (gkm_attributes_find_ulong (attrs, n_attrs, CKA_KEY_TYPE, &type)) ++ n_output =3D gkm_crypto_secret_key_length (type); ++ } ++ ++ /* Default to input length */ ++ if (n_output =3D=3D 0) ++ n_output =3D n_value; ++ ++ output =3D 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 =3D g_array_new (FALSE, FALSE, sizeof (CK_ATTRIBUTE)); ++ ++ /* Prepend the value */ ++ attr.type =3D CKA_VALUE; ++ attr.pValue =3D output; ++ attr.ulValueLen =3D n_output; ++ ++ g_array_append_val (array, attr); ++ ++ /* Add the remainder of the attributes */ ++ g_array_append_vals (array, attrs, n_attrs); ++ ++ transaction =3D gkm_transaction_new (); ++ ++ /* Now create an object with these attributes */ ++ *derived =3D gkm_session_create_object_for_attributes (session, transa= ction, ++ (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-mecha= nism.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 ++ */ ++ ++#ifndef GKM_HKDF_MECHANISM_H_ ++#define GKM_HKDF_MECHANISM_H_ ++ ++#include "gkm-types.h" ++ ++#include "pkcs11/pkcs11.h" ++#include "pkcs11/pkcs11i.h" ++ ++#include ++ ++static const CK_MECHANISM_TYPE GKM_HKDF_MECHANISMS[] =3D { ++ 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[] =3D = { +=20 + /* + * 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 } }, +=20 + /* + * 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 { +=20 + struct _GkmSecretKeyClass { + GkmObjectClass parent_class; ++ ++ /* virtual methods --------------------------------------------------= ------- */ ++ ++ gconstpointer (*get_key_value) (GkmSecretKey *key, gsize *n_value); + }; +=20 + GType gkm_secret_key_get_type (void); +=20 ++gconstpointer gkm_secret_key_get_key_value (GkmSecretK= ey *self, ++ gsize *n_v= alue); ++ + #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) +=20 ++#define CKM_G_HKDF_SHA256_DERIVE (CKM_GNOME + 101) ++ + #define CKK_G_NULL (CKK_GNOME + 100) +=20 + /* ------------------------------------------------------------------- +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" +=20 +@@ -693,6 +694,8 @@ negotiate_transport_crypto (void) + gcry_mpi_t base, prime, peer; + gcry_mpi_t key, pub, priv; + gboolean ret =3D FALSE; ++ gpointer ikm; ++ gsize n_ikm; +=20 + g_assert (!the_key); + base =3D prime =3D peer =3D NULL; +@@ -709,9 +712,14 @@ negotiate_transport_crypto (void) + gku_prompt_util_encode_mpi (output_data, "transport", "public", pub)= ; +=20 + /* Build up a key we can use */ +- n_the_key =3D 16; +- the_key =3D egg_dh_gen_secret (peer, priv, prime, n_the_key); +- ret =3D (the_key !=3D NULL); ++ ikm =3D egg_dh_gen_secret (peer, priv, prime, &n_ikm); ++ if (ikm !=3D NULL) { ++ n_the_key =3D 16; ++ the_key =3D 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 =3D TRUE; ++ } + } + } +=20 +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; +=20 + 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", "publ= ic", &peer)) + return NULL; +=20 +- value =3D egg_dh_gen_secret (peer, self->pv->transport->private, +- self->pv->transport->prime, 16); ++ ikm =3D egg_dh_gen_secret (peer, self->pv->transport->private, ++ self->pv->transport->prime, &n_ikm); +=20 + gcry_mpi_release (peer); +=20 +- if (!value) ++ if (!ikm) + return NULL; +=20 ++ key =3D egg_secure_alloc (16); ++ if (!egg_hkdf_perform ("sha256", ikm, n_ikm, NULL, 0, NULL, 0, key, 1= 6)) ++ g_return_val_if_reached (NULL); ++ ++ egg_secure_free (ikm); + egg_secure_free (self->pv->transport->key); +- self->pv->transport->key =3D value; ++ self->pv->transport->key =3D key; + self->pv->transport->n_key =3D 16; + } +=20 +-- +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 ++ */ ++ ++#ifndef EGG_HKDF_H_ ++#define EGG_HKDF_H_ ++ ++#include ++ ++gboolean egg_hkdf_perform (const gc= har *hash_algo, ++ gconstpo= inter input, ++ gsize n_= input, ++ gconstpo= inter salt, ++ gsize n_= salt, ++ gconstpo= inter 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=3D"3" GCONF_DEBUG=3D"yes" GNOME2_LA_PUNT=3D"yes" =20 -inherit gnome2 multilib pam virtualx +inherit autotools gnome2 multilib pam virtualx =20 DESCRIPTION=3D"Password and keyring managing daemon" HOMEPAGE=3D"http://www.gnome.org/" @@ -38,6 +38,7 @@ RDEPEND=3D">=3Ddev-libs/glib-2.25:2 # valgrind? ( dev-util/valgrind ) DEPEND=3D"${RDEPEND} sys-devel/gettext + >=3Ddev-util/gtk-doc-am-1.9 >=3Ddev-util/intltool-0.35 >=3Ddev-util/pkgconfig-0.9 doc? ( >=3Ddev-util/gtk-doc-1.9 )" @@ -49,7 +50,7 @@ DOCS=3D"AUTHORS ChangeLog NEWS README" =20 # tests fail in several ways, they should be fixed in the next cycle (bu= g #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-k= eyring-pkcs11.so: Couldn't initialize module: The device was removed or u= nplugged=20 RESTRICT=3D"test" =20 @@ -61,7 +62,6 @@ pkg_setup() { $(use_enable pam) $(use_with pam pam-dir $(getpam_mod_dir)) --with-root-certs=3D${ROOT}/etc/ssl/certs/ - --enable-acl-prompts --enable-ssh-agent --enable-gpg-agent --with-gtk=3D3.0" @@ -69,8 +69,6 @@ pkg_setup() { } =20 src_prepare() { - gnome2_src_prepare - # Remove silly CFLAGS sed 's:CFLAGS=3D"$CFLAGS -Werror:CFLAGS=3D"$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 } =20 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=3D${ROOT}/etc/ssl/certs/ - --enable-acl-prompts --enable-ssh-agent --enable-gpg-agent --with-gtk=3D2.0" @@ -67,8 +66,6 @@ pkg_setup() { } =20 src_prepare() { - gnome2_src_prepare - # Remove silly CFLAGS sed 's:CFLAGS=3D"$CFLAGS -Werror:CFLAGS=3D"$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 } =20 src_test() { diff --git a/gnome-base/gnome-keyring/gnome-keyring-9999.ebuild b/gnome-b= ase/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=3D${ROOT}/etc/ssl/certs/ - --enable-acl-prompts --enable-ssh-agent --enable-gpg-agent --with-gtk=3D3.0"