[gnome-keyring/dbus-api] Simplify creation of secret from DH negotiation.



commit fe841e3e788da74b15ff72770a1da8692943f651
Author: Stef Walter <stef memberwebs com>
Date:   Sat Dec 12 00:02:04 2009 +0000

    Simplify creation of secret from DH negotiation.
    
    PKCS#11 says to use the low order bytes, and that's what we do
    here. This bears more research to make sure we're doing this
    in a standard way.

 daemon/prompt/gkd-prompt-tool.c      |   19 ++--
 daemon/prompt/gkd-prompt-util.c      |   30 -------
 daemon/prompt/gkd-prompt-util.h      |    2 -
 daemon/prompt/gkd-prompt.c           |   18 ++---
 daemon/prompt/tests/unit-test-util.c |   16 +---
 egg/egg-dh.c                         |  150 +++++++++++++--------------------
 egg/egg-dh.h                         |   19 +++--
 egg/tests/unit-test-dh.c             |   56 +++----------
 pkcs11/gck/gck-dh-mechanism.c        |   57 +++----------
 9 files changed, 116 insertions(+), 251 deletions(-)
---
diff --git a/daemon/prompt/gkd-prompt-tool.c b/daemon/prompt/gkd-prompt-tool.c
index efd078d..bd65dbf 100644
--- a/daemon/prompt/gkd-prompt-tool.c
+++ b/daemon/prompt/gkd-prompt-tool.c
@@ -228,26 +228,27 @@ static gboolean
 negotiate_transport_crypto (void)
 {
 	gcry_mpi_t base, prime, peer;
-	gcry_mpi_t key, pub, secret;
+	gcry_mpi_t key, pub, priv;
 	gboolean ret = FALSE;
 
 	g_assert (!the_key);
 	base = prime = peer = NULL;
-	key = pub = secret = NULL;
+	key = pub = priv = NULL;
 
 	/* The DH stuff coming in from our caller */
 	if (gkd_prompt_util_decode_mpi (input_data, "transport", "prime", &prime) &&
 	    gkd_prompt_util_decode_mpi (input_data, "transport", "base", &base) &&
 	    gkd_prompt_util_decode_mpi (input_data, "transport", "public", &peer)) {
 
-		/* Generate our own public/secret, and then a key, send it back */
-		if (egg_dh_gen_pair (prime, base, 0, &pub, &secret) &&
-		    egg_dh_gen_secret (peer, secret, prime, &key)) {
+		/* Generate our own public/priv, and then a key, send it back */
+		if (egg_dh_gen_pair (prime, base, 0, &pub, &priv)) {
 
-			/* Build up a key we can use */
 			gkd_prompt_util_encode_mpi (output_data, "transport", "public", pub);
-			if (gkd_prompt_util_mpi_to_key (key, &the_key, &n_the_key))
-				ret = TRUE;
+
+			/* Build up a key we can use */
+			n_the_key = 16;
+			the_key = egg_dh_gen_secret (peer, priv, prime, n_the_key);
+			ret = (the_key != NULL);
 		}
 	}
 
@@ -256,7 +257,7 @@ negotiate_transport_crypto (void)
 	gcry_mpi_release (peer);
 	gcry_mpi_release (key);
 	gcry_mpi_release (pub);
-	gcry_mpi_release (secret);
+	gcry_mpi_release (priv);
 
 	return ret;
 }
diff --git a/daemon/prompt/gkd-prompt-util.c b/daemon/prompt/gkd-prompt-util.c
index 151940a..66d8453 100644
--- a/daemon/prompt/gkd-prompt-util.c
+++ b/daemon/prompt/gkd-prompt-util.c
@@ -111,36 +111,6 @@ gkd_prompt_util_decode_mpi (GKeyFile *key_file, const gchar *section,
 	return (gcry == 0);
 }
 
-gboolean
-gkd_prompt_util_mpi_to_key (gcry_mpi_t mpi, gpointer *key, gsize *n_key)
-{
-	gcry_error_t gcry;
-	guchar *buffer;
-	gsize n_buffer;
-
-	g_return_val_if_fail (mpi, FALSE);
-	g_return_val_if_fail (key, FALSE);
-	g_return_val_if_fail (n_key, FALSE);
-
-	/* Write the key out to raw data */
-	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n_buffer, mpi);
-	g_return_val_if_fail (gcry == 0, FALSE);
-	buffer = egg_secure_alloc (n_buffer);
-	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, buffer, n_buffer, &n_buffer, mpi);
-	g_return_val_if_fail (gcry == 0, FALSE);
-
-	/* Allocate memory for hashed key */
-	g_assert (16 == gcry_md_get_algo_dlen (GCRY_MD_MD5));
-	*key = egg_secure_alloc (16);
-	*n_key = 16;
-
-	/* Use that as the input to derive a key for 128-bit AES */
-	gcry_md_hash_buffer (GCRY_MD_MD5, *key, buffer, n_buffer);
-
-	egg_secure_free (buffer);
-	return TRUE;
-}
-
 gpointer
 gkd_prompt_util_encrypt_text (gpointer key, gsize n_key, gpointer iv, gsize n_iv,
                               const gchar *text, gsize *n_result)
diff --git a/daemon/prompt/gkd-prompt-util.h b/daemon/prompt/gkd-prompt-util.h
index 50a8c28..56e3c17 100644
--- a/daemon/prompt/gkd-prompt-util.h
+++ b/daemon/prompt/gkd-prompt-util.h
@@ -44,6 +44,4 @@ gpointer    gkd_prompt_util_encrypt_text                 (gpointer key, gsize n_
 gchar*      gkd_prompt_util_decrypt_text                 (gpointer key, gsize n_key, gpointer iv, gsize n_iv,
                                                           gpointer data, gsize n_data);
 
-gboolean    gkd_prompt_util_mpi_to_key                   (gcry_mpi_t mpi, gpointer *key, gsize *n_key);
-
 #endif /* __GKD_PROMPT_H__ */
diff --git a/daemon/prompt/gkd-prompt.c b/daemon/prompt/gkd-prompt.c
index c25fd54..a325f42 100644
--- a/daemon/prompt/gkd-prompt.c
+++ b/daemon/prompt/gkd-prompt.c
@@ -301,28 +301,22 @@ prepare_transport_crypto (GkdPrompt *self)
 static gboolean
 receive_transport_crypto (GkdPrompt *self)
 {
-	gcry_mpi_t key, peer;
-	gboolean ret;
+	gcry_mpi_t peer;
+	gpointer value;
 
 	g_assert (self->pv->output);
 
 	if (!gkd_prompt_util_decode_mpi (self->pv->output, "transport", "public", &peer))
 		return FALSE;
 
-	ret = egg_dh_gen_secret (peer, self->pv->secret, self->pv->prime, &key);
+	value = egg_dh_gen_secret (peer, self->pv->secret, self->pv->prime, 16);
 	gcry_mpi_release (peer);
-	if (!ret)
+	if (!value)
 		return FALSE;
 
 	egg_secure_free (self->pv->key);
-	ret = gkd_prompt_util_mpi_to_key (key, &self->pv->key, &self->pv->n_key);
-	gcry_mpi_release (key);
-
-	if (!ret) {
-		self->pv->key = NULL;
-		self->pv->n_key = 0;
-		return FALSE;
-	}
+	self->pv->key = value;
+	self->pv->n_key = 16;
 
 	return TRUE;
 }
diff --git a/daemon/prompt/tests/unit-test-util.c b/daemon/prompt/tests/unit-test-util.c
index d3c2bde..d37f8c5 100644
--- a/daemon/prompt/tests/unit-test-util.c
+++ b/daemon/prompt/tests/unit-test-util.c
@@ -96,7 +96,6 @@ DEFINE_TEST(decode_nonexistant_hex)
 static void
 do_encrypt_decrypt_text (const gchar *text)
 {
-	gcry_mpi_t mpi;
 	gpointer key, enc;
 	gsize n_key, n_enc;
 	guchar iv[16];
@@ -105,25 +104,18 @@ do_encrypt_decrypt_text (const gchar *text)
 	g_test_message ("prompt encrypt/decrypt text: %s", text);
 
 	/* Test making a key */
-	mpi = gcry_mpi_new (512);
-	gcry_mpi_randomize (mpi, 512, GCRY_WEAK_RANDOM);
-
-	if (!gkd_prompt_util_mpi_to_key (mpi, &key, &n_key))
-		g_assert_not_reached ();
+	n_key = 16;
+	key = egg_secure_alloc (n_key);
+	gcry_randomize (key, n_key, GCRY_WEAK_RANDOM);
 
 	gcry_create_nonce (iv, 16);
 	enc = gkd_prompt_util_encrypt_text (key, n_key, iv, 16, text, &n_enc);
-	egg_secure_clear (key, n_key);
-	egg_secure_free (key);
 
 	g_assert (enc);
 	/* Always greater due to null term */
 	g_assert (n_enc > strlen (text));
 	g_assert (n_enc % 16 == 0);
 
-	if (!gkd_prompt_util_mpi_to_key (mpi, &key, &n_key))
-		g_assert_not_reached ();
-
 	check = gkd_prompt_util_decrypt_text (key, n_key, iv, 16, enc, n_enc);
 	egg_secure_clear (key, n_key);
 	egg_secure_free (key);
@@ -132,8 +124,6 @@ do_encrypt_decrypt_text (const gchar *text)
 	g_assert (check);
 	g_assert (strlen (check) < n_enc);
 	g_assert_cmpstr (check, ==, text);
-
-	gcry_mpi_release (mpi);
 }
 
 DEFINE_TEST(encrypt_decrypt_text)
diff --git a/egg/egg-dh.c b/egg/egg-dh.c
index d90abc0..f162f4d 100644
--- a/egg/egg-dh.c
+++ b/egg/egg-dh.c
@@ -21,9 +21,10 @@
 
 #include "config.h"
 
-#include "egg-asn1.h"
 #include "egg-dh.h"
-#include "egg-openssl.h"
+#include "egg-secure-memory.h"
+
+#define DEBUG_DH_SECRET 0
 
 typedef struct _DHGroup {
 	const gchar *name;
@@ -238,16 +239,18 @@ egg_dh_default_params (const gchar *name, gcry_mpi_t *prime, gcry_mpi_t *base)
 	gcry_error_t gcry;
 
 	g_return_val_if_fail (name, FALSE);
-	g_return_val_if_fail (prime, FALSE);
-	g_return_val_if_fail (base, FALSE);
 
 	for (group = dh_groups; group->name; ++group) {
 		if (g_str_equal (group->name, name)) {
-			gcry = gcry_mpi_scan (prime, GCRYMPI_FMT_USG, group->prime, group->n_prime, NULL);
-			g_return_val_if_fail (gcry == 0, FALSE);
-			g_return_val_if_fail (gcry_mpi_get_nbits (*prime) == group->bits, FALSE);
-			gcry = gcry_mpi_scan (base, GCRYMPI_FMT_USG, group->base, group->n_base, NULL);
-			g_return_val_if_fail (gcry == 0, FALSE);
+			if (prime) {
+				gcry = gcry_mpi_scan (prime, GCRYMPI_FMT_USG, group->prime, group->n_prime, NULL);
+				g_return_val_if_fail (gcry == 0, FALSE);
+				g_return_val_if_fail (gcry_mpi_get_nbits (*prime) == group->bits, FALSE);
+			}
+			if (base) {
+				gcry = gcry_mpi_scan (base, GCRYMPI_FMT_USG, group->base, group->n_base, NULL);
+				g_return_val_if_fail (gcry == 0, FALSE);
+			}
 			return TRUE;
 		}
 	}
@@ -300,91 +303,56 @@ egg_dh_gen_pair (gcry_mpi_t p, gcry_mpi_t g, guint bits,
 	return TRUE;
 }
 
-gboolean
-egg_dh_gen_secret (gcry_mpi_t Y, gcry_mpi_t x,
-                   gcry_mpi_t p, gcry_mpi_t *k)
-{
-	gint bits;
-
-	g_return_val_if_fail (Y, FALSE);
-	g_return_val_if_fail (x, FALSE);
-	g_return_val_if_fail (p, FALSE);
-	g_return_val_if_fail (k, FALSE);
-
-	bits = gcry_mpi_get_nbits (p);
-	g_return_val_if_fail (bits >= 0, FALSE);
-
-	*k = gcry_mpi_snew (bits);
-	g_return_val_if_fail (*k, FALSE);
-	gcry_mpi_powm (*k, Y, x, p);
-
-	return TRUE;
-}
-
-typedef struct _Parameters {
-	gcry_mpi_t p;
-	gcry_mpi_t g;
-} Parameters;
-
-#ifndef EGG_DH_NO_ASN1
-
-static gboolean
-parse_der_pkcs3 (const guchar *data, gsize n_data, Parameters *params)
+gpointer
+egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
+                   gcry_mpi_t prime, gsize bytes)
 {
-	ASN1_TYPE asn;
-	guchar *buf_p, *buf_g;
-	gsize n_buf_p, n_buf_g;
 	gcry_error_t gcry;
+	guchar *value;
+	gsize n_value;
+	gsize offset = 0;
+	gcry_mpi_t k;
+	gint bits;
 
-	asn = egg_asn1_decode ("PK.DHParameter", data, n_data);
-	if (!asn)
-		return FALSE;
-
-	buf_p = egg_asn1_read_value (asn, "prime", &n_buf_p, (EggAllocator)g_realloc);
-	buf_g = egg_asn1_read_value (asn, "base", &n_buf_g, (EggAllocator)g_realloc);
-	g_return_val_if_fail (buf_p && buf_g, FALSE);
-	gcry = gcry_mpi_scan (&params->p, GCRYMPI_FMT_STD, buf_p, n_buf_p, &n_buf_p);
-	g_return_val_if_fail (gcry == 0, FALSE);
-	gcry = gcry_mpi_scan (&params->g, GCRYMPI_FMT_STD, buf_g, n_buf_g, &n_buf_g);
-	g_return_val_if_fail (gcry == 0, FALSE);
-
-	g_free (buf_p);
-	g_free (buf_g);
-	return TRUE;
-}
-
-static void
-parse_openssl_pkcs3 (GQuark type, const guchar *data, gsize n_data,
-                     GHashTable *headers, gpointer user_data)
-{
-	Parameters *params = user_data;
-
-	/* Only parse the first one */
-	if (params->p != NULL)
-		return;
-
-	if (g_quark_try_string ("DH PARAMETERS") == type)
-		parse_der_pkcs3 (data, n_data, params);
-}
-
-gboolean
-egg_dh_parse_pkcs3 (const guchar *data, gsize n_data, gcry_mpi_t *p, gcry_mpi_t *g)
-{
-	Parameters params;
-
-	g_return_val_if_fail (data, FALSE);
-	g_return_val_if_fail (p, FALSE);
-	g_return_val_if_fail (g, FALSE);
+	g_return_val_if_fail (peer, NULL);
+	g_return_val_if_fail (priv, NULL);
+	g_return_val_if_fail (prime, NULL);
+
+	bits = gcry_mpi_get_nbits (prime);
+	g_return_val_if_fail (bits >= 0, NULL);
+
+	k = gcry_mpi_snew (bits);
+	g_return_val_if_fail (k, NULL);
+	gcry_mpi_powm (k, peer, priv, prime);
+
+	/* 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);
+	g_return_val_if_fail (gcry == 0, NULL);
+
+#if DEBUG_DH_SECRET
+	g_printerr ("DH SECRET: ");
+	gcry_mpi_dump (k);
+	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);
+	}
 
-	memset (&params, 0, sizeof (params));
-	if (!parse_der_pkcs3 (data, n_data, &params))
-		egg_openssl_pem_parse (data, n_data, parse_openssl_pkcs3, &params);
+#if DEBUG_DH_SECRET
+	gcry_mpi_scan (&k, GCRYMPI_FMT_USG, value, bytes, NULL);
+	g_printerr ("RAW SECRET: ");
+	gcry_mpi_dump (k);
+	gcry_mpi_release (k);
+#endif
 
-	if (!params.p || !params.g)
-		return FALSE;
-	*p = params.p;
-	*g = params.g;
-	return TRUE;
+	return value;
 }
-
-#endif /* EGG_DH_NO_ASN1 */
diff --git a/egg/egg-dh.h b/egg/egg-dh.h
index 55d4077..cfdb3d0 100644
--- a/egg/egg-dh.h
+++ b/egg/egg-dh.h
@@ -26,7 +26,9 @@
 
 #include <gcrypt.h>
 
-gboolean   egg_dh_default_params   (const gchar *name, gcry_mpi_t *prime, gcry_mpi_t *base);
+gboolean   egg_dh_default_params                              (const gchar *name,
+                                                               gcry_mpi_t *prime,
+                                                               gcry_mpi_t *base);
 
 gboolean   egg_dh_default_params_raw                          (const gchar *name,
                                                                gconstpointer *prime,
@@ -34,12 +36,15 @@ gboolean   egg_dh_default_params_raw                          (const gchar *name
                                                                gconstpointer *base,
                                                                gsize *n_base);
 
-gboolean   egg_dh_gen_pair         (gcry_mpi_t p, gcry_mpi_t g, guint bits, gcry_mpi_t *X, gcry_mpi_t *x);
+gboolean   egg_dh_gen_pair                                    (gcry_mpi_t prime,
+                                                               gcry_mpi_t base,
+                                                               guint bits,
+                                                               gcry_mpi_t *pub,
+                                                               gcry_mpi_t *priv);
 
-gboolean   egg_dh_gen_secret       (gcry_mpi_t Y, gcry_mpi_t x, gcry_mpi_t p, gcry_mpi_t *k);
-
-#ifndef EGG_DH_NO_ASN1
-gboolean   egg_dh_parse_pkcs3      (const guchar *data, gsize n_data, gcry_mpi_t *p, gcry_mpi_t *g);
-#endif
+gpointer   egg_dh_gen_secret                                  (gcry_mpi_t peer,
+                                                               gcry_mpi_t priv,
+                                                               gcry_mpi_t prime,
+                                                               gsize bytes);
 
 #endif /* EGG_DH_H_ */
diff --git a/egg/tests/unit-test-dh.c b/egg/tests/unit-test-dh.c
index 8128a02..1111fd4 100644
--- a/egg/tests/unit-test-dh.c
+++ b/egg/tests/unit-test-dh.c
@@ -1,5 +1,5 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* unit-test-dh.c: Test egg-dh.c
+/* test-dh.c: Test egg-dh.c
 
    Copyright (C) 2009 Stefan Walter
 
@@ -28,49 +28,21 @@
 #include "run-auto-test.h"
 
 #include "egg-dh.h"
+#include "egg-secure-memory.h"
 
 #include <gcrypt.h>
 
-DEFINE_TEST(dh_parse_pkcs3)
-{
-	gcry_mpi_t p, g;
-	guchar *data;
-	gsize n_data;
-	gboolean ret;
-
-	data = test_data_read ("dh-params.pem", &n_data);
-	ret = egg_dh_parse_pkcs3 (data, n_data, &p, &g);
-	g_assert (ret == TRUE);
-	g_assert (gcry_mpi_get_nbits (p) == 1024);
-
-#if 0
-	guchar *output;
-	gsize n_written;
-	gcry_mpi_aprint (GCRYMPI_FMT_HEX, &output, &n_written, p);
-	g_printerr ("\nprime: %s\n", output);
-	gcry_mpi_aprint (GCRYMPI_FMT_HEX, &output, &n_written, g);
-	g_printerr ("\nbase: %s\n", output);
-#endif
-
-	gcry_mpi_release (p);
-	gcry_mpi_release (g);
-	g_free (data);
-}
-
 DEFINE_TEST(dh_perform)
 {
-	guchar *data;
-	gsize n_data;
 	gcry_mpi_t p, g;
-	gcry_mpi_t x1, X1, k1;
-	gcry_mpi_t x2, X2, k2;
+	gcry_mpi_t x1, X1;
+	gcry_mpi_t x2, X2;
+	gpointer k1, k2;
 	gboolean ret;
 
 	/* Load up the parameters */
-	data = test_data_read ("dh-params.pem", &n_data);
-	if (!egg_dh_parse_pkcs3 (data, n_data, &p, &g))
+	if (!egg_dh_default_params ("ietf-ike-grp-modp-768", &p, &g))
 		g_assert_not_reached ();
-	g_free (data);
 
 	/* Generate secrets */
 	ret = egg_dh_gen_pair (p, g, 0, &X1, &x1);
@@ -79,22 +51,22 @@ DEFINE_TEST(dh_perform)
 	g_assert (ret);
 
 	/* Calculate keys */
-	ret = egg_dh_gen_secret (X2, x1, p, &k1);
-	g_assert (ret);
-	ret = egg_dh_gen_secret (X1, x2, p, &k2);
-	g_assert (ret);
+	k1 = egg_dh_gen_secret (X2, x1, p, 96);
+	g_assert (k1);
+	k2 = egg_dh_gen_secret (X1, x2, p, 96);
+	g_assert (k2);
 
 	/* Keys must be the same */
-	g_assert (gcry_mpi_cmp (k1, k2) == 0);
+	g_assert (memcmp (k1, k2, 96) == 0);
 
 	gcry_mpi_release (p);
 	gcry_mpi_release (g);
 	gcry_mpi_release (x1);
 	gcry_mpi_release (X1);
-	gcry_mpi_release (k1);
+	egg_secure_free (k1);
 	gcry_mpi_release (x2);
 	gcry_mpi_release (X2);
-	gcry_mpi_release (k2);
+	egg_secure_free (k2);
 }
 
 DEFINE_TEST(dh_short_pair)
@@ -107,7 +79,7 @@ DEFINE_TEST(dh_short_pair)
 	ret = egg_dh_default_params ("ietf-ike-grp-modp-1024", &p, &g);
 	g_assert (ret);
 	g_assert_cmpuint (gcry_mpi_get_nbits (p), ==, 1024);
-	
+
 	/* Generate secrets */
 	ret = egg_dh_gen_pair (p, g, 512, &X1, &x1);
 	g_assert (ret);
diff --git a/pkcs11/gck/gck-dh-mechanism.c b/pkcs11/gck/gck-dh-mechanism.c
index 54765ca..7478f78 100644
--- a/pkcs11/gck/gck-dh-mechanism.c
+++ b/pkcs11/gck/gck-dh-mechanism.c
@@ -199,42 +199,6 @@ gck_dh_mechanism_generate (GckSession *session, CK_ATTRIBUTE_PTR pub_atts,
 	return rv;
 }
 
-static gpointer
-prepare_and_truncate_secret (gcry_mpi_t secret, CK_ATTRIBUTE_PTR attrs,
-                             CK_ULONG n_attrs, gsize *n_value)
-{
-	CK_ULONG length = 0;
-	CK_KEY_TYPE type;
-	gcry_error_t gcry;
-	guchar *value;
-	gsize offset = 0;
-
-	g_assert (n_value);
-
-	/* What length should we truncate to? */
-	if (!gck_attributes_find_ulong (attrs, n_attrs, CKA_VALUE_LEN, &length)) {
-		if (gck_attributes_find_ulong (attrs, n_attrs, CKA_KEY_TYPE, &type))
-			length = gck_crypto_secret_key_length (type);
-	}
-
-	/* Write out the secret */
-	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, n_value, secret);
-	g_return_val_if_fail (gcry == 0, NULL);
-	if (*n_value < length)
-		offset = length - *n_value;
-	value = egg_secure_alloc (*n_value + offset);
-	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, value + offset, *n_value, n_value, secret);
-	g_return_val_if_fail (gcry == 0, NULL);
-
-	if (length != 0 && length < *n_value) {
-		offset = *n_value - length;
-		memmove (value, value + offset, length);
-		*n_value = length;
-	}
-
-	return value;
-}
-
 CK_RV
 gck_dh_mechanism_derive (GckSession *session, CK_MECHANISM_PTR mech, GckObject *base,
                          CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GckObject **derived)
@@ -242,14 +206,13 @@ gck_dh_mechanism_derive (GckSession *session, CK_MECHANISM_PTR mech, GckObject *
 	gcry_mpi_t peer = NULL;
 	gcry_mpi_t prime;
 	gcry_mpi_t priv;
-	gcry_mpi_t secret;
 	gcry_error_t gcry;
 	CK_ATTRIBUTE attr;
 	GArray *array;
-	gboolean ret;
-	gsize n_value;
+	CK_ULONG n_value;
 	gpointer value;
 	GckTransaction *transaction;
+	CK_KEY_TYPE type;
 
 	g_return_val_if_fail (GCK_IS_DH_PRIVATE_KEY (base), CKR_GENERAL_ERROR);
 
@@ -265,16 +228,20 @@ gck_dh_mechanism_derive (GckSession *session, CK_MECHANISM_PTR mech, GckObject *
 
 	prime = gck_dh_key_get_prime (GCK_DH_KEY (base));
 	priv = gck_dh_private_key_get_value (GCK_DH_PRIVATE_KEY (base));
-	ret = egg_dh_gen_secret (peer, priv, prime, &secret);
+
+	/* What length should we truncate to? */
+	n_value = (gcry_mpi_get_nbits(prime) + 7) / 8;
+	if (!gck_attributes_find_ulong (attrs, n_attrs, CKA_VALUE_LEN, &n_value)) {
+		if (gck_attributes_find_ulong (attrs, n_attrs, CKA_KEY_TYPE, &type))
+			n_value = gck_crypto_secret_key_length (type);
+	}
+
+	value = egg_dh_gen_secret (peer, priv, prime, n_value);
 	gcry_mpi_release (peer);
 
-	if (ret != TRUE)
+	if (value == NULL)
 		return CKR_FUNCTION_FAILED;
 
-	value = prepare_and_truncate_secret (secret, attrs, n_attrs, &n_value);
-	g_return_val_if_fail (value, CKR_GENERAL_ERROR);
-	gcry_mpi_release (secret);
-
 	/* Now setup the attributes with our new value */
 	array = g_array_new (FALSE, FALSE, sizeof (CK_ATTRIBUTE));
 



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