[egg] Add DH functions for use by IPC.
authorStef Walter <stef@memberwebs.com>
Sun, 4 Oct 2009 18:18:31 +0000 (18:18 +0000)
committerStef Walter <stef@memberwebs.com>
Sun, 4 Oct 2009 18:18:31 +0000 (18:18 +0000)
egg/Makefile.am
egg/egg-dh.c [new file with mode: 0644]
egg/egg-dh.h [new file with mode: 0644]
egg/tests/Makefile.am
egg/tests/test-data/dh-params.pem [new file with mode: 0644]
egg/tests/unit-test-dh.c [new file with mode: 0644]

index f3aec93..a0bf0db 100644 (file)
@@ -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 (file)
index 0000000..bc14f36
--- /dev/null
@@ -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 (file)
index 0000000..aa92808
--- /dev/null
@@ -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_ */
index a7fa687..f205fae 100644 (file)
@@ -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 (file)
index 0000000..cc0afd8
--- /dev/null
@@ -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 (file)
index 0000000..a190da3
--- /dev/null
@@ -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);
+}