[gnome-keyring/dbus-api: 3/5] [egg] Add DH functions for use by IPC.



commit e5435bab28b5b2bb12ad3d3fbcfebb3c59a1f482
Author: Stef Walter <stef memberwebs com>
Date:   Sun Oct 4 18:18:31 2009 +0000

    [egg] Add DH functions for use by IPC.

 egg/Makefile.am                   |    1 +
 egg/egg-dh.c                      |  144 +++++++++++++++++++++++++++++++++++++
 egg/egg-dh.h                      |   35 +++++++++
 egg/tests/Makefile.am             |    1 +
 egg/tests/test-data/dh-params.pem |    5 ++
 egg/tests/unit-test-dh.c          |   89 +++++++++++++++++++++++
 6 files changed, 275 insertions(+), 0 deletions(-)
---
diff --git a/egg/Makefile.am b/egg/Makefile.am
index 7aa281e..b42bc5f 100644
--- a/egg/Makefile.am
+++ b/egg/Makefile.am
@@ -22,6 +22,7 @@ libegg_la_SOURCES = \
 	egg-asn1.c egg-asn1.h \
 	egg-buffer.c egg-buffer.h \
 	egg-cleanup.c egg-cleanup.h \
+	egg-dh.c egg-dh.h \
 	egg-hex.c egg-hex.h \
 	egg-libgcrypt.c egg-libgcrypt.h \
 	egg-oid.c egg-oid.h \
diff --git a/egg/egg-dh.c b/egg/egg-dh.c
new file mode 100644
index 0000000..bc14f36
--- /dev/null
+++ b/egg/egg-dh.c
@@ -0,0 +1,144 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2009 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 "egg-asn1.h"
+#include "egg-dh.h"
+#include "egg-openssl.h"
+
+gboolean
+egg_dh_gen_secret (gcry_mpi_t p, gcry_mpi_t g,
+                   gcry_mpi_t *X, gcry_mpi_t *x)
+{
+	gint bits;
+
+	g_return_val_if_fail (g, FALSE);
+	g_return_val_if_fail (p, FALSE);
+	g_return_val_if_fail (X, FALSE);
+	g_return_val_if_fail (x, FALSE);
+
+	/* Secret key value must be less than half of p */
+	bits = gcry_mpi_get_nbits (p) - 1;
+	g_return_val_if_fail (bits >= 0, FALSE);
+
+	/*
+	 * Generate a strong random number of bits, and not zero.
+	 * gcry_mpi_randomize bumps up to the next byte. Since we
+	 * need to have a value less than half of p, we make sure
+	 * we bump down.
+	 */
+	*x = gcry_mpi_snew (bits);
+	g_return_val_if_fail (*x, FALSE);
+	while (gcry_mpi_cmp_ui (*x, 0) == 0)
+		gcry_mpi_randomize (*x, (bits / 8) * 8, GCRY_STRONG_RANDOM);
+
+	*X = gcry_mpi_new (bits);
+	g_return_val_if_fail (*X, FALSE);
+	gcry_mpi_powm (*X, g, *x, p);
+
+	return TRUE;
+}
+
+gboolean
+egg_dh_gen_key (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;
+
+static gboolean
+parse_der_pkcs3 (const guchar *data, gsize n_data, Parameters *params)
+{
+	ASN1_TYPE asn;
+	guchar *buf_p, *buf_g;
+	gsize n_buf_p, n_buf_g;
+	gcry_error_t gcry;
+
+	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);
+
+	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 (!params.p || !params.g)
+		return FALSE;
+	*p = params.p;
+	*g = params.g;
+	return TRUE;
+}
diff --git a/egg/egg-dh.h b/egg/egg-dh.h
new file mode 100644
index 0000000..aa92808
--- /dev/null
+++ b/egg/egg-dh.h
@@ -0,0 +1,35 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef EGG_DH_H_
+#define EGG_DH_H_
+
+#include <glib.h>
+
+#include <gcrypt.h>
+
+gboolean   egg_dh_gen_secret    (gcry_mpi_t p, gcry_mpi_t g, gcry_mpi_t *X, gcry_mpi_t *x);
+
+gboolean   egg_dh_gen_key       (gcry_mpi_t Y, gcry_mpi_t x, gcry_mpi_t p, gcry_mpi_t *k);
+
+gboolean   egg_dh_parse_pkcs3   (const guchar *data, gsize n_data, gcry_mpi_t *p, gcry_mpi_t *g);
+
+#endif /* EGG_DH_H_ */
diff --git a/egg/tests/Makefile.am b/egg/tests/Makefile.am
index b9b490e..50b2d4d 100644
--- a/egg/tests/Makefile.am
+++ b/egg/tests/Makefile.am
@@ -10,6 +10,7 @@ UNIT_AUTO = \
 	unit-test-secmem.c \
 	unit-test-symkey.c \
 	unit-test-openssl.c \
+	unit-test-dh.c
 	asn1-def-test.h
 
 UNIT_PROMPT = 
diff --git a/egg/tests/test-data/dh-params.pem b/egg/tests/test-data/dh-params.pem
new file mode 100644
index 0000000..cc0afd8
--- /dev/null
+++ b/egg/tests/test-data/dh-params.pem
@@ -0,0 +1,5 @@
+-----BEGIN DH PARAMETERS-----
+MIGHAoGBAOmZHLx3BXvrPoFlAl6DOHIr2wApepEOpEESnqhO0JGvnaVWgaGS5+fC
+g/9vqexageA6jAmZ9msZ34C+hn0KebHbPkKufsH8oFeInz7WZuhsPCSKpHyOaZmX
+GDx6gJMkLA10HOXU4bqZy1rOiVxTuS2bn+aw2CA7WoKGVnuOnCozAgEC
+-----END DH PARAMETERS-----
diff --git a/egg/tests/unit-test-dh.c b/egg/tests/unit-test-dh.c
new file mode 100644
index 0000000..a190da3
--- /dev/null
+++ b/egg/tests/unit-test-dh.c
@@ -0,0 +1,89 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-dh.c: Test egg-dh.c
+
+   Copyright (C) 2009 Stefan Walter
+
+   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 memberwebs com>
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+
+#include "egg-dh.h"
+
+#include <gcrypt.h>
+
+DEFINE_TEST(dh_parse_pkcs3)
+{
+	gcry_mpi_t p, g;
+	guchar *data;
+	gsize n_data;
+	gboolean ret;
+
+	data = test_read_testdata ("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);
+
+	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;
+	gboolean ret;
+
+	/* Load up the parameters */
+	data = test_read_testdata ("dh-params.pem", &n_data);
+	if (!egg_dh_parse_pkcs3 (data, n_data, &p, &g))
+		g_assert_not_reached ();
+	g_free (data);
+
+	/* Generate secrets */
+	ret = egg_dh_gen_secret (p, g, &X1, &x1);
+	g_assert (ret);
+	ret = egg_dh_gen_secret (p, g, &X2, &x2);
+	g_assert (ret);
+
+	/* Calculate keys */
+	ret = egg_dh_gen_key (X2, x1, p, &k1);
+	g_assert (ret);
+	ret = egg_dh_gen_key (X1, x2, p, &k2);
+	g_assert (ret);
+
+	/* Keys must be the same */
+	g_assert (gcry_mpi_cmp (k1, k2) == 0);
+
+	gcry_mpi_release (p);
+	gcry_mpi_release (g);
+	gcry_mpi_release (x1);
+	gcry_mpi_release (X1);
+	gcry_mpi_release (k1);
+	gcry_mpi_release (x2);
+	gcry_mpi_release (X2);
+	gcry_mpi_release (k2);
+}



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