[libgnome-keyring/with-hkdf] Use HKDF for digesting of DH secret key.



commit 100aa1788d784334247b095ae6a1c621e539ba94
Author: Stef Walter <stefw collabora co uk>
Date:   Wed Feb 23 12:34:39 2011 +0100

    Use HKDF for digesting of DH secret key.
    
     * Previously we truncated the key, which was broken.
     * Secret service spec has been updated.
     * Now we use HKDF + SHA256 to digest the DH secret key into the right
       size usable by AES.
     * The library temporarily still supports the old method in case
       its talking to a daemon that doesn't support this fix.

 .gitignore                      |    2 +
 configure.in                    |    4 +
 egg/Makefile.am                 |    3 +-
 egg/egg-dh.c                    |   16 +--
 egg/egg-dh.h                    |    2 +-
 egg/egg-hkdf.c                  |  109 ++++++++++++
 egg/egg-hkdf.h                  |   39 +++++
 egg/egg-testing.c               |   72 ++++++++
 egg/egg-testing.h               |   14 ++
 egg/tests/Makefile.am           |    5 +
 egg/tests/test-dh.c             |    8 +-
 egg/tests/test-hkdf.c           |  345 +++++++++++++++++++++++++++++++++++++++
 library/gkr-session.c           |  173 +++++++++++++++++++-
 library/tests/Makefile.am       |    3 +-
 library/tests/test-any-daemon.c |   78 +++++++++
 15 files changed, 847 insertions(+), 26 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index f193699..bf96df7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -103,6 +103,7 @@ run-auto-test.h
 /egg/tests/Makefile.in
 /egg/tests/test-dh
 /egg/tests/test-secmem
+/egg/tests/test-hkdf
 
 # /library
 /library/*.pc
@@ -112,6 +113,7 @@ run-auto-test.h
 # /library/tests
 /library/tests/Makefile
 /library/tests/Makefile.in
+/library/tests/test-any-daemon
 /library/tests/test-prompting
 /library/tests/test-keyrings
 /library/tests/test-memory
diff --git a/configure.in b/configure.in
index bacdf7a..dd70207 100644
--- a/configure.in
+++ b/configure.in
@@ -24,6 +24,10 @@ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
 LIB_GNOME_KEYRING_LT_VERSION=1:1:1
 AC_SUBST(LIB_GNOME_KEYRING_LT_VERSION)
 
+version_bits=`echo $VERSION | tr '.' ' '`
+full_version=`printf %03d%03d%03d $version_bits`
+AC_DEFINE_UNQUOTED(GKR_VERSION, $full_version, [The libgnome-keyring version as a number])
+
 AC_TYPE_PID_T
 AC_TYPE_SIGNAL
 AC_TYPE_SIZE_T
diff --git a/egg/Makefile.am b/egg/Makefile.am
index 7fce691..ee0c111 100644
--- a/egg/Makefile.am
+++ b/egg/Makefile.am
@@ -14,9 +14,10 @@ libegg_la_CFLAGS = \
 libegg_la_SOURCES = \
 	egg-dbus.c egg-dbus.h \
 	egg-dh.c egg-dh.h \
+	egg-hkdf.c egg-hkdf.h \
 	egg-libgcrypt.c egg-libgcrypt.h \
 	egg-secure-memory.c egg-secure-memory.h \
-	egg-testing.h
+	egg-testing.c egg-testing.h
 
 # -------------------------------------------------------------------
 
diff --git a/egg/egg-dh.c b/egg/egg-dh.c
index d192aeb..bed524e 100644
--- a/egg/egg-dh.c
+++ b/egg/egg-dh.c
@@ -306,12 +306,11 @@ egg_dh_gen_pair (gcry_mpi_t prime, gcry_mpi_t base, guint bits,
 
 gpointer
 egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
-                   gcry_mpi_t prime, gsize bytes)
+                   gcry_mpi_t prime, gsize *bytes)
 {
 	gcry_error_t gcry;
 	guchar *value;
 	gsize n_value;
-	gsize offset = 0;
 	gcry_mpi_t k;
 	gint bits;
 
@@ -329,11 +328,8 @@ egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
 	/* Write out the secret */
 	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n_value, k);
 	g_return_val_if_fail (gcry == 0, NULL);
-	if (n_value < bytes)
-		offset = bytes - n_value;
-	value = egg_secure_alloc (n_value + offset);
-	memset (value, 0, n_value + offset);
-	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, value + offset, n_value, &n_value, k);
+	value = egg_secure_alloc (n_value);
+	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, value, n_value, &n_value, k);
 	g_return_val_if_fail (gcry == 0, NULL);
 
 #if DEBUG_DH_SECRET
@@ -342,11 +338,7 @@ egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
 	gcry_mpi_release (k);
 #endif
 
-	if (bytes != 0 && bytes < n_value) {
-		offset = n_value - bytes;
-		memmove (value, value + offset, bytes);
-		egg_secure_clear (value + bytes, offset);
-	}
+	*bytes = n_value;
 
 #if DEBUG_DH_SECRET
 	gcry_mpi_scan (&k, GCRYMPI_FMT_USG, value, bytes, NULL);
diff --git a/egg/egg-dh.h b/egg/egg-dh.h
index cfdb3d0..ee315e2 100644
--- a/egg/egg-dh.h
+++ b/egg/egg-dh.h
@@ -45,6 +45,6 @@ gboolean   egg_dh_gen_pair                                    (gcry_mpi_t prime,
 gpointer   egg_dh_gen_secret                                  (gcry_mpi_t peer,
                                                                gcry_mpi_t priv,
                                                                gcry_mpi_t prime,
-                                                               gsize bytes);
+                                                               gsize *bytes);
 
 #endif /* EGG_DH_H_ */
diff --git a/egg/egg-hkdf.c b/egg/egg-hkdf.c
new file mode 100644
index 0000000..eaa90fc
--- /dev/null
+++ b/egg/egg-hkdf.c
@@ -0,0 +1,109 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#include "config.h"
+
+#include "egg-hkdf.h"
+#include "egg-secure-memory.h"
+
+#include <gcrypt.h>
+
+#include <string.h>
+
+gboolean
+egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input,
+                  gconstpointer salt, gsize n_salt, gconstpointer info,
+                  gsize n_info, gpointer output, gsize n_output)
+{
+	gpointer alloc = NULL;
+	gpointer buffer = NULL;
+	gcry_md_hd_t md1, md2;
+	guint hash_len;
+	guchar i;
+	gint flags, algo;
+	gsize step, n_buffer;
+	guchar *at;
+	gcry_error_t gcry;
+
+	algo = gcry_md_map_name (hash_algo);
+	g_return_val_if_fail (algo != 0, FALSE);
+
+	hash_len = gcry_md_get_algo_dlen (algo);
+	g_return_val_if_fail (hash_len != 0, FALSE);
+	g_return_val_if_fail (n_output <= 255 * hash_len, FALSE);
+
+	/* Buffer we need to for intermediate stuff */
+	if (gcry_is_secure (input)) {
+		flags = GCRY_MD_FLAG_SECURE;
+		buffer = gcry_malloc_secure (hash_len);
+	} else {
+		flags = 0;
+		buffer = gcry_malloc (hash_len);
+	}
+
+	g_return_val_if_fail (buffer, FALSE);
+	n_buffer = 0;
+
+	/* Salt defaults to hash_len zeros */
+	if (!salt) {
+		salt = alloc = g_malloc0 (hash_len);
+		n_salt = hash_len;
+	}
+
+	/* Step 1: Extract */
+	gcry = gcry_md_open (&md1, algo, GCRY_MD_FLAG_HMAC);
+	g_return_val_if_fail (gcry == 0, FALSE);
+	gcry = gcry_md_setkey (md1, salt, n_salt);
+	g_return_val_if_fail (gcry == 0, FALSE);
+	gcry_md_write (md1, input, n_input);
+
+	/* Step 2: Expand */
+	gcry = gcry_md_open (&md2, algo, GCRY_MD_FLAG_HMAC);
+	g_return_val_if_fail (gcry == 0, FALSE);
+	gcry = gcry_md_setkey (md2, gcry_md_read (md1, algo), hash_len);
+	g_return_val_if_fail (gcry == 0, FALSE);
+	gcry_md_close (md1);
+
+	at = output;
+	for (i = 1; i < 256; ++i) {
+		gcry_md_reset (md2);
+		gcry_md_write (md2, buffer, n_buffer);
+		gcry_md_write (md2, info, n_info);
+		gcry_md_write (md2, &i, 1);
+
+		n_buffer = hash_len;
+		memcpy (buffer, gcry_md_read (md2, algo), n_buffer);
+
+		step = MIN (n_buffer, n_output);
+		memcpy (at, buffer, step);
+		n_output -= step;
+		at += step;
+
+		if (!n_output)
+			break;
+	}
+
+	g_free (alloc);
+	gcry_free (buffer);
+	return TRUE;
+}
diff --git a/egg/egg-hkdf.h b/egg/egg-hkdf.h
new file mode 100644
index 0000000..430d331
--- /dev/null
+++ b/egg/egg-hkdf.h
@@ -0,0 +1,39 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#ifndef EGG_HKDF_H_
+#define EGG_HKDF_H_
+
+#include <glib.h>
+
+gboolean   egg_hkdf_perform                                   (const gchar *hash_algo,
+                                                               gconstpointer input,
+                                                               gsize n_input,
+                                                               gconstpointer salt,
+                                                               gsize n_salt,
+                                                               gconstpointer info,
+                                                               gsize n_info,
+                                                               gpointer output,
+                                                               gsize n_output);
+
+#endif /* EGG_HKDF_H_ */
diff --git a/egg/egg-testing.c b/egg/egg-testing.c
new file mode 100644
index 0000000..458b71f
--- /dev/null
+++ b/egg/egg-testing.c
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ *
+ * Stef Walter <stefw collabora co uk>
+ */
+
+#include "config.h"
+
+#include "egg-testing.h"
+
+static const char HEXC[] = "0123456789ABCDEF";
+
+static gchar*
+hex_dump (const guchar *data, gsize n_data)
+{
+	GString *result;
+	gsize i;
+	guchar j;
+
+	g_assert (data);
+
+	result = g_string_sized_new (n_data * 2 + 1);
+	for (i = 0; i < n_data; ++i) {
+		g_string_append (result, "\\x");
+
+		j = data[i] >> 4 & 0xf;
+		g_string_append_c (result, HEXC[j]);
+		j = data[i] & 0xf;
+		g_string_append_c (result, HEXC[j]);
+	}
+
+	return g_string_free (result, FALSE);
+}
+
+void
+egg_assertion_message_cmpmem (const char     *domain,
+                              const char     *file,
+                              int             line,
+                              const char     *func,
+                              const char     *expr,
+                              gconstpointer   arg1,
+                              gsize           n_arg1,
+                              const char     *cmp,
+                              gconstpointer   arg2,
+                              gsize           n_arg2)
+{
+  char *a1, *a2, *s;
+  a1 = arg1 ? hex_dump (arg1, n_arg1) : g_strdup ("NULL");
+  a2 = arg2 ? hex_dump (arg2, n_arg2) : g_strdup ("NULL");
+  s = g_strdup_printf ("assertion failed (%s): (%s %s %s)", expr, a1, cmp, a2);
+  g_free (a1);
+  g_free (a2);
+  g_assertion_message (domain, file, line, func, s);
+  g_free (s);
+}
diff --git a/egg/egg-testing.h b/egg/egg-testing.h
index ef27cfe..14bc8e9 100644
--- a/egg/egg-testing.h
+++ b/egg/egg-testing.h
@@ -25,8 +25,22 @@
 #define EGG_TESTING_H_
 
 #include <glib.h>
+#include <string.h>
 
 #define egg_assert_cmpsize(a, o, b) \
 	g_assert_cmpuint ((guint)(a), o, (guint)(b))
 
+#define egg_assert_cmpmem(a, na, cmp, b, nb) \
+	do { gconstpointer __p1 = (a), __p2 = (b); gsize __n1 = (na), __n2 = (nb); \
+	     if (__n1 cmp __n2 && memcmp (__p1, __p2, __n1) cmp 0) ; else \
+	        egg_assertion_message_cmpmem (G_LOG_DOMAIN, __FILE__, __LINE__, \
+	            G_STRFUNC, #a "[" #na"] " #cmp " " #b "[" #nb "]", \
+                    __p1, __n1, #cmp, __p2, __n2); } while (0)
+
+void       egg_assertion_message_cmpmem        (const char *domain, const char *file,
+                                                int line, const char *func,
+                                                const char *expr, gconstpointer arg1,
+                                                gsize n_arg1, const char *cmp,
+                                                gconstpointer arg2, gsize n_arg2);
+
 #endif /* EGG_DH_H_ */
diff --git a/egg/tests/Makefile.am b/egg/tests/Makefile.am
index 13fd068..240fad0 100644
--- a/egg/tests/Makefile.am
+++ b/egg/tests/Makefile.am
@@ -9,6 +9,7 @@ LDADD =  \
 
 TEST_PROGS = \
 	test-dh \
+	test-hkdf \
 	test-secmem
 
 check_PROGRAMS = $(TEST_PROGS)
@@ -17,3 +18,7 @@ test: ${TEST_PROGS}
 	gtester -k --verbose ${TEST_PROGS}
 
 check-local: test
+
+if WITH_TESTS
+all-local: $(check_PROGRAMS)
+endif
diff --git a/egg/tests/test-dh.c b/egg/tests/test-dh.c
index 81cf0d7..4a62fd1 100644
--- a/egg/tests/test-dh.c
+++ b/egg/tests/test-dh.c
@@ -44,6 +44,7 @@ test_dh_perform (void)
 	gcry_mpi_t x2, X2;
 	gpointer k1, k2;
 	gboolean ret;
+	gsize n1, n2;
 
 	/* Load up the parameters */
 	if (!egg_dh_default_params ("ietf-ike-grp-modp-768", &p, &g))
@@ -56,13 +57,14 @@ test_dh_perform (void)
 	g_assert (ret);
 
 	/* Calculate keys */
-	k1 = egg_dh_gen_secret (X2, x1, p, 96);
+	k1 = egg_dh_gen_secret (X2, x1, p, &n1);
 	g_assert (k1);
-	k2 = egg_dh_gen_secret (X1, x2, p, 96);
+	k2 = egg_dh_gen_secret (X1, x2, p, &n2);
 	g_assert (k2);
 
 	/* Keys must be the same */
-	g_assert (memcmp (k1, k2, 96) == 0);
+	egg_assert_cmpsize (n1, ==, n2);
+	g_assert (memcmp (k1, k2, n1) == 0);
 
 	gcry_mpi_release (p);
 	gcry_mpi_release (g);
diff --git a/egg/tests/test-hkdf.c b/egg/tests/test-hkdf.c
new file mode 100644
index 0000000..44c463d
--- /dev/null
+++ b/egg/tests/test-hkdf.c
@@ -0,0 +1,345 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* test-hkdf.c: Test egg-hkdf.c
+
+   Copyright (C) 2011 Collabora Ltd.
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef collabora co uk>
+*/
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "egg-hkdf.h"
+#include "egg-secure-memory.h"
+#include "egg-testing.h"
+
+#include <gcrypt.h>
+
+EGG_SECURE_GLIB_DEFINITIONS ();
+
+static void
+test_hkdf_test_case_1 (void)
+{
+	/* RFC 5869: A.1 Test Case 1 */
+	const guchar ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	                       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	                       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
+	const guchar salt[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	                        0x08, 0x09, 0x0a, 0x0b, 0x0c };
+	const guchar info[] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+	                        0xf8, 0xf9 };
+	const guchar okm[] = { 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
+	                       0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
+	                       0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
+	                       0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
+	                       0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
+	                       0x58, 0x65 };
+	guchar buffer[sizeof (okm)];
+	gboolean ret;
+
+	egg_assert_cmpsize (sizeof (ikm), ==, 22);
+	egg_assert_cmpsize (sizeof (salt), ==, 13);
+	egg_assert_cmpsize (sizeof (info), ==, 10);
+	egg_assert_cmpsize (sizeof (okm), ==, 42);
+
+	memset (buffer, 0, sizeof (buffer));
+	ret = egg_hkdf_perform ("sha256",
+	                        ikm, sizeof (ikm),
+	                        salt, sizeof (salt),
+	                        info, sizeof (info),
+	                        buffer, sizeof (buffer));
+	g_assert (ret);
+	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+static void
+test_hkdf_test_case_2 (void)
+{
+	/* RFC 5869: A.2 Test Case 2 */
+	const guchar ikm[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	                       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	                       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+	                       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	                       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	                       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+	                       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f };
+	const guchar salt[] = { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+	                        0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+	                        0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+	                        0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+	                        0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	                        0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+	                        0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	                        0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+	                        0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	                        0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf };
+	const guchar info[] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	                        0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+	                        0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+	                        0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+	                        0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+	                        0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+	                        0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+	                        0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+	                        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+	                        0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
+	const guchar okm[] = { 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1,
+	                       0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34,
+	                       0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
+	                       0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c,
+	                       0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72,
+	                       0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
+	                       0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
+	                       0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71,
+	                       0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87,
+	                       0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f,
+	                       0x1d, 0x87 };
+	guchar buffer[sizeof (okm)];
+	gboolean ret;
+
+	egg_assert_cmpsize (sizeof (ikm), ==, 80);
+	egg_assert_cmpsize (sizeof (salt), ==, 80);
+	egg_assert_cmpsize (sizeof (info), ==, 80);
+	egg_assert_cmpsize (sizeof (okm), ==, 82);
+
+	memset (buffer, 0, sizeof (buffer));
+	ret = egg_hkdf_perform ("sha256",
+	                        ikm, sizeof (ikm),
+	                        salt, sizeof (salt),
+	                        info, sizeof (info),
+	                        buffer, sizeof (buffer));
+	g_assert (ret);
+	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+static void
+test_hkdf_test_case_3 (void)
+{
+	/* RFC 5869: A.3 Test Case 3 */
+	const guchar ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	                       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	                       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,};
+	const guchar salt[] = { };
+	const guchar info[] = { };
+	const guchar okm[] = { 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f,
+	                       0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31,
+	                       0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
+	                       0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d,
+	                       0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a,
+	                       0x96, 0xc8 };
+	guchar buffer[sizeof (okm)];
+	gboolean ret;
+
+	egg_assert_cmpsize (sizeof (ikm), ==, 22);
+	egg_assert_cmpsize (sizeof (salt), ==, 0);
+	egg_assert_cmpsize (sizeof (info), ==, 0);
+	egg_assert_cmpsize (sizeof (okm), ==, 42);
+
+	memset (buffer, 0, sizeof (buffer));
+	ret = egg_hkdf_perform ("sha256",
+	                        ikm, sizeof (ikm),
+	                        salt, sizeof (salt),
+	                        info, sizeof (info),
+	                        buffer, sizeof (buffer));
+	g_assert (ret);
+	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+static void
+test_hkdf_test_case_4 (void)
+{
+	/* RFC 5869: A.4 Test Case 4 */
+	const guchar ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	                       0x0b, 0x0b, 0x0b };
+	const guchar salt[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	                        0x08, 0x09, 0x0a, 0x0b, 0x0c };
+	const guchar info[] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+	                        0xf8, 0xf9 };
+	const guchar okm[] = { 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69,
+	                       0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81,
+	                       0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15,
+	                       0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2,
+	                       0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3,
+	                       0xf8, 0x96 };
+	guchar buffer[sizeof (okm)];
+	gboolean ret;
+
+	egg_assert_cmpsize (sizeof (ikm), ==, 11);
+	egg_assert_cmpsize (sizeof (salt), ==, 13);
+	egg_assert_cmpsize (sizeof (info), ==, 10);
+	egg_assert_cmpsize (sizeof (okm), ==, 42);
+
+	memset (buffer, 0, sizeof (buffer));
+	ret = egg_hkdf_perform ("sha1",
+	                        ikm, sizeof (ikm),
+	                        salt, sizeof (salt),
+	                        info, sizeof (info),
+	                        buffer, sizeof (buffer));
+	g_assert (ret);
+	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+static void
+test_hkdf_test_case_5 (void)
+{
+	/* RFC 5869: A.5 Test Case 5 */
+	const guchar ikm[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	                       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	                       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+	                       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	                       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	                       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+	                       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f };
+	const guchar salt[] = { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+	                        0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+	                        0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+	                        0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+	                        0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	                        0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+	                        0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	                        0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+	                        0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	                        0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf };
+	const guchar info[] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	                        0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+	                        0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+	                        0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+	                        0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+	                        0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+	                        0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+	                        0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+	                        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+	                        0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
+	const guchar okm[] = { 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7,
+	                       0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb,
+	                       0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19,
+	                       0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe,
+	                       0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3,
+	                       0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c,
+	                       0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed,
+	                       0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e,
+	                       0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43,
+	                       0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52,
+	                       0xd3, 0xb4 };
+	guchar buffer[sizeof (okm)];
+	gboolean ret;
+
+	egg_assert_cmpsize (sizeof (ikm), ==, 80);
+	egg_assert_cmpsize (sizeof (salt), ==, 80);
+	egg_assert_cmpsize (sizeof (info), ==, 80);
+	egg_assert_cmpsize (sizeof (okm), ==, 82);
+
+	memset (buffer, 0, sizeof (buffer));
+	ret = egg_hkdf_perform ("sha1",
+	                        ikm, sizeof (ikm),
+	                        salt, sizeof (salt),
+	                        info, sizeof (info),
+	                        buffer, sizeof (buffer));
+	g_assert (ret);
+	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+static void
+test_hkdf_test_case_6 (void)
+{
+	/* RFC 5869: A.6 Test Case 6 */
+	const guchar ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	                       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	                       0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
+	const guchar salt[] = { };
+	const guchar info[] = { };
+	const guchar okm[] = { 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61,
+	                       0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06,
+	                       0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06,
+	                       0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0,
+	                       0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3,
+	                       0x49, 0x18 };
+	guchar buffer[sizeof (okm)];
+	gboolean ret;
+
+	egg_assert_cmpsize (sizeof (ikm), ==, 22);
+	egg_assert_cmpsize (sizeof (salt), ==, 0);
+	egg_assert_cmpsize (sizeof (info), ==, 0);
+	egg_assert_cmpsize (sizeof (okm), ==, 42);
+
+	memset (buffer, 0, sizeof (buffer));
+	ret = egg_hkdf_perform ("sha1",
+	                        ikm, sizeof (ikm),
+	                        salt, sizeof (salt),
+	                        info, sizeof (info),
+	                        buffer, sizeof (buffer));
+	g_assert (ret);
+	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+static void
+test_hkdf_test_case_7 (void)
+{
+	/* RFC 5869: A.7 Test Case 7 */
+	const guchar ikm[] = { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	                       0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	                       0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c };
+	const guchar *salt = NULL;
+	const guchar info[] = { };
+	const guchar okm[] = { 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3,
+	                       0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a,
+	                       0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23,
+	                       0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5,
+	                       0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac,
+	                       0xfc, 0x48 };
+	guchar buffer[sizeof (okm)];
+	gboolean ret;
+
+	egg_assert_cmpsize (sizeof (ikm), ==, 22);
+	egg_assert_cmpsize (sizeof (info), ==, 0);
+	egg_assert_cmpsize (sizeof (okm), ==, 42);
+
+	memset (buffer, 0, sizeof (buffer));
+	ret = egg_hkdf_perform ("sha1",
+	                        ikm, sizeof (ikm),
+	                        salt, sizeof (salt),
+	                        info, sizeof (info),
+	                        buffer, sizeof (buffer));
+	g_assert (ret);
+	egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+int
+main (int argc, char **argv)
+{
+	g_test_init (&argc, &argv, NULL);
+
+	g_test_add_func ("/hkdf/test-case-1", test_hkdf_test_case_1);
+	g_test_add_func ("/hkdf/test-case-2", test_hkdf_test_case_2);
+	g_test_add_func ("/hkdf/test-case-3", test_hkdf_test_case_3);
+	g_test_add_func ("/hkdf/test-case-4", test_hkdf_test_case_4);
+	g_test_add_func ("/hkdf/test-case-5", test_hkdf_test_case_5);
+	g_test_add_func ("/hkdf/test-case-6", test_hkdf_test_case_6);
+	g_test_add_func ("/hkdf/test-case-7", test_hkdf_test_case_7);
+
+	return g_test_run ();
+}
diff --git a/library/gkr-session.c b/library/gkr-session.c
index 9869f59..9fc5332 100644
--- a/library/gkr-session.c
+++ b/library/gkr-session.c
@@ -30,6 +30,7 @@
 #include <gcrypt.h>
 
 #include "egg/egg-dh.h"
+#include "egg/egg-hkdf.h"
 #include "egg/egg-libgcrypt.h"
 #include "egg/egg-secure-memory.h"
 
@@ -256,19 +257,42 @@ decode_open_session_aes (DBusMessage *message, gcry_mpi_t *peer, const char **pa
 	return (gcry == 0);
 }
 
+/*
+ * This less secure algorithm is supported by some old versions of
+ * gnome-keyring-daemon. We support it purely as an interim thing,
+ * while all version of gnome-keyring-daemon are being upgraded.
+ */
+
+#if GKR_VERSION >= 003001000
+  #error "Support for dh-ietf1024-aes128-cbc-pkcs7 should be removed in 3.1.x"
+#else
+
+static gboolean
+reply_says_not_supported (DBusMessage *reply)
+{
+	/*
+	 * In old versions of the spec we used
+	 * org.freedesktop.Secret.Error.NotSupported instead of the standard
+	 * dbus not supported error.
+	 */
+	return (dbus_message_is_error (reply, DBUS_ERROR_NOT_SUPPORTED) ||
+	        dbus_message_is_error (reply, "org.freedesktop.Secret.Error.NotSupported"));
+}
+
 static void
-on_open_session_aes (GkrOperation *op, DBusMessage *reply, gpointer user_data)
+on_open_session_broken (GkrOperation *op, DBusMessage *reply, gpointer user_data)
 {
 	gcry_mpi_t priv, prime, peer;
 	GkrSession *session;
 	const char *path;
-	gpointer key;
+	gpointer ikm;
+	gsize n_ikm;
 
 	g_assert (op);
 	g_assert (user_data);
 
-	/* If AES is not supported then skip on over to plain */
-	if (dbus_message_is_error (reply, DBUS_ERROR_NOT_SUPPORTED)) {
+	/* If 'broken' is not supported then skip on over to plain */
+	if (reply_says_not_supported (reply)) {
 		session_negotiate_plain (op);
 		return;
 	}
@@ -287,13 +311,14 @@ on_open_session_aes (GkrOperation *op, DBusMessage *reply, gpointer user_data)
 	if (!egg_dh_default_params ("ietf-ike-grp-modp-1024", &prime, NULL))
 		g_return_if_reached ();
 
+	/* Generate the actual secret */
 	priv = user_data;
-	key = egg_dh_gen_secret (peer, priv, prime, 16);
+	ikm = egg_dh_gen_secret (peer, priv, prime, &n_ikm);
 
 	gcry_mpi_release (peer);
 	gcry_mpi_release (prime);
 
-	if (key == NULL) {
+	if (ikm == NULL) {
 		g_message ("couldn't negotiate a valid session key");
 		gkr_operation_complete (op, GNOME_KEYRING_RESULT_IO_ERROR);
 		return;
@@ -301,9 +326,141 @@ on_open_session_aes (GkrOperation *op, DBusMessage *reply, gpointer user_data)
 
 	session = session_new ();
 	session->path = g_strdup (path);
-	session->key = key;
 	session->n_key = 16;
 
+	/* Now truncate this into our aes key. This is the 'broken' part*/
+	session->key = egg_secure_alloc (session->n_key);
+	g_assert (session->n_key < n_ikm);
+	memcpy (session->key, (guchar*)ikm + (n_ikm - session->n_key),
+	        session->n_key);
+	egg_secure_free (ikm);
+
+	G_LOCK (session_globals);
+	{
+		if (the_session)
+			gkr_session_unref (the_session);
+		the_session = gkr_session_ref (session);
+	}
+	G_UNLOCK (session_globals);
+
+	gkr_callback_invoke_op_session (gkr_operation_pop (op), session);
+	gkr_session_unref (session);
+}
+
+static void
+session_negotiate_broken (GkrOperation *op)
+{
+	/* The old broken algorithm, without digesting the dh result */
+	const char *algorithm = "dh-ietf1024-aes128-cbc-pkcs7";
+	DBusMessageIter iter, variant, array;
+	gcry_mpi_t prime, base, pub, priv;
+	gboolean ret;
+	guchar *buffer;
+	gsize n_buffer;
+	gcry_error_t gcry;
+	DBusMessage *req;
+
+	g_assert (op);
+
+	egg_libgcrypt_initialize ();
+
+	prime = base = pub = priv = NULL;
+	ret = egg_dh_default_params ("ietf-ike-grp-modp-1024", &prime, &base) &&
+	      egg_dh_gen_pair (prime, base, 0, &pub, &priv);
+
+	gcry_mpi_release (prime);
+	gcry_mpi_release (base);
+
+	if (ret == TRUE) {
+		req = dbus_message_new_method_call (gkr_service_name (), SERVICE_PATH,
+		                                    SERVICE_INTERFACE, "OpenSession");
+
+		dbus_message_iter_init_append (req, &iter);
+		dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &algorithm);
+		dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "ay", &variant);
+		dbus_message_iter_open_container (&variant, DBUS_TYPE_ARRAY, "y", &array);
+
+		gcry = gcry_mpi_aprint (GCRYMPI_FMT_USG, &buffer, &n_buffer, pub);
+		g_return_if_fail (gcry == 0);
+		dbus_message_iter_append_fixed_array (&array, DBUS_TYPE_BYTE, &buffer, n_buffer);
+		gcry_free (buffer);
+
+		dbus_message_iter_close_container (&variant, &array);
+		dbus_message_iter_close_container (&iter, &variant);
+
+		gkr_operation_push (op, on_open_session_broken, GKR_CALLBACK_OP_MSG,
+		                    priv, (GDestroyNotify)gcry_mpi_release);
+		priv = NULL;
+
+		gkr_operation_request (op, req);
+		dbus_message_unref (req);
+	}
+
+	gcry_mpi_release (pub);
+	gcry_mpi_release (priv);
+
+	if (ret == FALSE)
+		gkr_operation_complete_later (op, GNOME_KEYRING_RESULT_IO_ERROR);
+}
+
+#endif /* GKR_VERSION >= 003001000 */
+
+static void
+on_open_session_aes (GkrOperation *op, DBusMessage *reply, gpointer user_data)
+{
+	gcry_mpi_t priv, prime, peer;
+	GkrSession *session;
+	const char *path;
+	gpointer ikm;
+	gsize n_ikm;
+
+	g_assert (op);
+	g_assert (user_data);
+
+	/* If AES is not supported then try the old 'broken' method */
+	if (reply_says_not_supported (reply)) {
+		session_negotiate_broken (op);
+		return;
+	}
+
+	/* Handle any other errors */
+	if (gkr_operation_handle_errors (op, reply))
+		return;
+
+	/* Parse the result from OpenSession */
+	if (!decode_open_session_aes (reply, &peer, &path)) {
+		g_message ("received an invalid response to Service.OpenSession()");
+		gkr_operation_complete (op, GNOME_KEYRING_RESULT_IO_ERROR);
+		return;
+	}
+
+	if (!egg_dh_default_params ("ietf-ike-grp-modp-1024", &prime, NULL))
+		g_return_if_reached ();
+
+	/* Generate the actual secret */
+	priv = user_data;
+	ikm = egg_dh_gen_secret (peer, priv, prime, &n_ikm);
+
+	gcry_mpi_release (peer);
+	gcry_mpi_release (prime);
+
+	if (ikm == NULL) {
+		g_message ("couldn't negotiate a valid session key");
+		gkr_operation_complete (op, GNOME_KEYRING_RESULT_IO_ERROR);
+		return;
+	}
+
+	session = session_new ();
+	session->path = g_strdup (path);
+	session->n_key = 16;
+
+	/* Now digest this into our aes key */
+	session->key = egg_secure_alloc (session->n_key);
+	if (!egg_hkdf_perform ("sha256", ikm, n_ikm, NULL, 0, NULL, 0,
+	                       session->key, session->n_key))
+		g_return_if_reached ();
+	egg_secure_free (ikm);
+
 	G_LOCK (session_globals);
 	{
 		if (the_session)
@@ -319,9 +476,9 @@ on_open_session_aes (GkrOperation *op, DBusMessage *reply, gpointer user_data)
 static void
 session_negotiate_aes (GkrOperation *op)
 {
+	const char *algorithm = "dh-ietf1024-sha256-aes128-cbc-pkcs7";
 	DBusMessageIter iter, variant, array;
 	gcry_mpi_t prime, base, pub, priv;
-	const char *algorithm = "dh-ietf1024-aes128-cbc-pkcs7";
 	gboolean ret;
 	guchar *buffer;
 	gsize n_buffer;
diff --git a/library/tests/Makefile.am b/library/tests/Makefile.am
index 00d3ed5..0909356 100644
--- a/library/tests/Makefile.am
+++ b/library/tests/Makefile.am
@@ -11,7 +11,8 @@ LDADD =  \
 TEST_PROGS = \
 	test-memory \
 	test-keyrings \
-	test-other
+	test-other \
+	test-any-daemon
 
 check_PROGRAMS = \
 	test-prompting \
diff --git a/library/tests/test-any-daemon.c b/library/tests/test-any-daemon.c
new file mode 100644
index 0000000..5561fc0
--- /dev/null
+++ b/library/tests/test-any-daemon.c
@@ -0,0 +1,78 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* test-session.c: Test reading a secret
+
+   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 <stefw collabora co uk>
+*/
+
+#include "config.h"
+
+#include "gnome-keyring.h"
+#include <glib.h>
+
+static void
+test_create_find_read_password (void)
+{
+	GnomeKeyringResult res;
+	GnomeKeyringAttributeList* attrs;
+	GnomeKeyringFound* f;
+	guint id;
+	GList *found;
+	guint num;
+
+	/* Unique for every run */
+	num  = time (NULL);
+
+	attrs = gnome_keyring_attribute_list_new ();
+	gnome_keyring_attribute_list_append_string (attrs, "dog", "woof");
+	gnome_keyring_attribute_list_append_string (attrs, "bird", "cheep");
+	gnome_keyring_attribute_list_append_string (attrs, "iguana", "");
+	gnome_keyring_attribute_list_append_uint32 (attrs, "num", num);
+
+	/* Create the item */
+	res = gnome_keyring_item_create_sync ("session", GNOME_KEYRING_ITEM_GENERIC_SECRET,
+	                                      "Barnyard", attrs, "the very secret", TRUE, &id);
+	g_assert_cmpint (GNOME_KEYRING_RESULT_OK, ==, res);
+
+	/* Now try to find it */
+	res = gnome_keyring_find_items_sync (GNOME_KEYRING_ITEM_GENERIC_SECRET, attrs, &found);
+	g_assert_cmpint (GNOME_KEYRING_RESULT_OK, ==, res);
+
+	g_assert_cmpint (g_list_length (found), ==, 1);
+	f = (GnomeKeyringFound*)found->data;
+
+	g_assert_cmpstr (f->keyring, ==, "session");
+	g_assert_cmpstr (f->secret, ==, "the very secret");
+
+	gnome_keyring_found_list_free (found);
+}
+
+int
+main (int argc, char **argv)
+{
+	g_test_init (&argc, &argv, NULL);
+
+	if (!gnome_keyring_is_available ()) {
+		g_printerr ("skipping any-daemon tests, no daemon is running");
+		return 0;
+	}
+
+	g_test_add_func ("/any-daemon/create-find-ready-password", test_create_find_read_password);
+	return g_test_run ();
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]