[gnome-keyring/dbus-api] [pkcs11] Implement DH key pair generation.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-keyring/dbus-api] [pkcs11] Implement DH key pair generation.
- Date: Wed, 18 Nov 2009 18:05:02 +0000 (UTC)
commit ad805c86202fd561fe6e9ae79ba8bf53c0471bf3
Author: Stef Walter <stef memberwebs com>
Date: Mon Nov 16 20:59:16 2009 +0000
[pkcs11] Implement DH key pair generation.
Also rework how the DH stuff works in the egg component.
daemon/prompt/gkd-prompt-tool.c | 4 +-
daemon/prompt/gkd-prompt.c | 4 +-
egg/egg-dh.c | 32 ++++--
egg/egg-dh.h | 4 +-
egg/tests/unit-test-dh.c | 30 +++++-
pkcs11/gck/Makefile.am | 4 +
pkcs11/gck/gck-crypto.c | 21 ++++
pkcs11/gck/gck-crypto.h | 9 ++
pkcs11/gck/gck-dh-key.c | 148 ++++++++++++++++++++++++++++
pkcs11/gck/gck-dh-key.h | 57 +++++++++++
pkcs11/gck/gck-dh-mechanism.c | 113 +++++++++++++++++++++
pkcs11/gck/gck-dh-mechanism.h | 45 +++++++++
pkcs11/gck/gck-dh-private-key.c | 207 +++++++++++++++++++++++++++++++++++++++
pkcs11/gck/gck-dh-private-key.h | 57 +++++++++++
pkcs11/gck/gck-dh-public-key.c | 186 +++++++++++++++++++++++++++++++++++
pkcs11/gck/gck-dh-public-key.h | 57 +++++++++++
pkcs11/gck/gck-module.c | 22 ++++-
pkcs11/gck/gck-session.c | 150 ++++++++++++++++++++---------
pkcs11/gck/gck-types.h | 3 +
19 files changed, 1084 insertions(+), 69 deletions(-)
---
diff --git a/daemon/prompt/gkd-prompt-tool.c b/daemon/prompt/gkd-prompt-tool.c
index 26bc2f1..efd078d 100644
--- a/daemon/prompt/gkd-prompt-tool.c
+++ b/daemon/prompt/gkd-prompt-tool.c
@@ -241,8 +241,8 @@ negotiate_transport_crypto (void)
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_secret (prime, base, &pub, &secret) &&
- egg_dh_gen_key (peer, secret, prime, &key)) {
+ if (egg_dh_gen_pair (prime, base, 0, &pub, &secret) &&
+ egg_dh_gen_secret (peer, secret, prime, &key)) {
/* Build up a key we can use */
gkd_prompt_util_encode_mpi (output_data, "transport", "public", pub);
diff --git a/daemon/prompt/gkd-prompt.c b/daemon/prompt/gkd-prompt.c
index 8f735e7..c25fd54 100644
--- a/daemon/prompt/gkd-prompt.c
+++ b/daemon/prompt/gkd-prompt.c
@@ -286,7 +286,7 @@ prepare_transport_crypto (GkdPrompt *self)
/* Figure out our prime, base, public and secret bits */
if (!egg_dh_default_params ("ietf-ike-grp-modp-1536", &self->pv->prime, &base) ||
- !egg_dh_gen_secret (self->pv->prime, base, &pub, &self->pv->secret))
+ !egg_dh_gen_pair (self->pv->prime, base, 0, &pub, &self->pv->secret))
g_return_if_reached ();
/* Send over the prime, base, and public bits */
@@ -309,7 +309,7 @@ receive_transport_crypto (GkdPrompt *self)
if (!gkd_prompt_util_decode_mpi (self->pv->output, "transport", "public", &peer))
return FALSE;
- ret = egg_dh_gen_key (peer, self->pv->secret, self->pv->prime, &key);
+ ret = egg_dh_gen_secret (peer, self->pv->secret, self->pv->prime, &key);
gcry_mpi_release (peer);
if (!ret)
return FALSE;
diff --git a/egg/egg-dh.c b/egg/egg-dh.c
index e68cb7b..ea1b4b6 100644
--- a/egg/egg-dh.c
+++ b/egg/egg-dh.c
@@ -206,19 +206,24 @@ egg_dh_default_params (const gchar *name, gcry_mpi_t *prime, gcry_mpi_t *base)
}
gboolean
-egg_dh_gen_secret (gcry_mpi_t p, gcry_mpi_t g,
- gcry_mpi_t *X, gcry_mpi_t *x)
+egg_dh_gen_pair (gcry_mpi_t p, gcry_mpi_t g, guint bits,
+ gcry_mpi_t *X, gcry_mpi_t *x)
{
- gint bits;
+ guint pbits;
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);
+ pbits = gcry_mpi_get_nbits (p);
+ g_return_val_if_fail (pbits > 1, FALSE);
+
+ if (bits == 0) {
+ bits = pbits;
+ } else if (bits > pbits) {
+ g_return_val_if_reached (FALSE);
+ }
/*
* Generate a strong random number of bits, and not zero.
@@ -229,9 +234,16 @@ egg_dh_gen_secret (gcry_mpi_t p, gcry_mpi_t g,
*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);
+ gcry_mpi_randomize (*x, bits, GCRY_STRONG_RANDOM);
+
+ /* Secret key value must be less than half of p */
+ if (gcry_mpi_get_nbits (*x) > bits)
+ gcry_mpi_clear_highbit (*x, bits);
+ if (gcry_mpi_get_nbits (*x) > pbits - 1)
+ gcry_mpi_clear_highbit (*x, pbits - 1);
+ g_assert (gcry_mpi_cmp (p, *x) > 0);
- *X = gcry_mpi_new (bits);
+ *X = gcry_mpi_new (gcry_mpi_get_nbits (*x));
g_return_val_if_fail (*X, FALSE);
gcry_mpi_powm (*X, g, *x, p);
@@ -239,8 +251,8 @@ egg_dh_gen_secret (gcry_mpi_t p, gcry_mpi_t g,
}
gboolean
-egg_dh_gen_key (gcry_mpi_t Y, gcry_mpi_t x,
- gcry_mpi_t p, gcry_mpi_t *k)
+egg_dh_gen_secret (gcry_mpi_t Y, gcry_mpi_t x,
+ gcry_mpi_t p, gcry_mpi_t *k)
{
gint bits;
diff --git a/egg/egg-dh.h b/egg/egg-dh.h
index bee18c1..83ffd0b 100644
--- a/egg/egg-dh.h
+++ b/egg/egg-dh.h
@@ -28,9 +28,9 @@
gboolean egg_dh_default_params (const gchar *name, gcry_mpi_t *prime, gcry_mpi_t *base);
-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_pair (gcry_mpi_t p, gcry_mpi_t g, guint bits, 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_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);
diff --git a/egg/tests/unit-test-dh.c b/egg/tests/unit-test-dh.c
index 17b11f3..e96613b 100644
--- a/egg/tests/unit-test-dh.c
+++ b/egg/tests/unit-test-dh.c
@@ -73,15 +73,15 @@ DEFINE_TEST(dh_perform)
g_free (data);
/* Generate secrets */
- ret = egg_dh_gen_secret (p, g, &X1, &x1);
+ ret = egg_dh_gen_pair (p, g, 0, &X1, &x1);
g_assert (ret);
- ret = egg_dh_gen_secret (p, g, &X2, &x2);
+ ret = egg_dh_gen_pair (p, g, 0, &X2, &x2);
g_assert (ret);
/* Calculate keys */
- ret = egg_dh_gen_key (X2, x1, p, &k1);
+ ret = egg_dh_gen_secret (X2, x1, p, &k1);
g_assert (ret);
- ret = egg_dh_gen_key (X1, x2, p, &k2);
+ ret = egg_dh_gen_secret (X1, x2, p, &k2);
g_assert (ret);
/* Keys must be the same */
@@ -97,6 +97,28 @@ DEFINE_TEST(dh_perform)
gcry_mpi_release (k2);
}
+DEFINE_TEST(dh_short_pair)
+{
+ gcry_mpi_t p, g;
+ gcry_mpi_t x1, X1;
+ gboolean ret;
+
+ /* Load up the parameters */
+ 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);
+ g_assert_cmpuint (gcry_mpi_get_nbits (x1), <=, 512);
+
+ gcry_mpi_release (p);
+ gcry_mpi_release (g);
+ gcry_mpi_release (x1);
+ gcry_mpi_release (X1);
+}
+
static void
test_dh_default (const gchar *name, guint bits)
{
diff --git a/pkcs11/gck/Makefile.am b/pkcs11/gck/Makefile.am
index 0833682..8a82d67 100644
--- a/pkcs11/gck/Makefile.am
+++ b/pkcs11/gck/Makefile.am
@@ -27,6 +27,10 @@ libgck_la_SOURCES = \
gck-data-der.c gck-data-der.h \
gck-data-file.c gck-data-file.h \
gck-data-types.h \
+ gck-dh-key.c gdk-dh-key.h \
+ gck-dh-mechanism.c gck-dh-mechanism.h \
+ gck-dh-private-key.c gck-dh-private-key.h \
+ gck-dh-public-key.c gck-dh-public-key.h \
gck-factory.c gck-factory.h \
gck-file-tracker.c gck-file-tracker.h \
gck-manager.c gck-manager.h \
diff --git a/pkcs11/gck/gck-crypto.c b/pkcs11/gck/gck-crypto.c
index d2a1429..f85a918 100644
--- a/pkcs11/gck/gck-crypto.c
+++ b/pkcs11/gck/gck-crypto.c
@@ -22,6 +22,7 @@
#include "config.h"
#include "gck-crypto.h"
+#include "gck-dh-mechanism.h"
#include "gck-mechanism-dsa.h"
#include "gck-mechanism-rsa.h"
#include "gck-session.h"
@@ -383,6 +384,26 @@ gck_crypto_perform (GckSession *session, CK_MECHANISM_TYPE mech, CK_ATTRIBUTE_TY
}
}
+CK_RV
+gck_crypto_generate_key_pair (GckSession *session, CK_MECHANISM_TYPE mech,
+ CK_ATTRIBUTE_PTR pub_atts, CK_ULONG n_pub_atts,
+ CK_ATTRIBUTE_PTR priv_atts, CK_ULONG n_priv_atts,
+ GckObject **pub_key, GckObject **priv_key)
+{
+ g_return_val_if_fail (GCK_IS_SESSION (session), CKR_GENERAL_ERROR);
+ g_return_val_if_fail (pub_key, CKR_GENERAL_ERROR);
+ g_return_val_if_fail (priv_key, CKR_GENERAL_ERROR);
+
+ switch (mech) {
+ case CKM_DH_PKCS_KEY_PAIR_GEN:
+ return gck_dh_mechanism_generate (session, pub_atts, n_pub_atts,
+ priv_atts, n_priv_atts,
+ pub_key, priv_key);
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+}
+
/* ----------------------------------------------------------------------------
* PREPARE FUNCTIONS
*/
diff --git a/pkcs11/gck/gck-crypto.h b/pkcs11/gck/gck-crypto.h
index 1b2598a..2b8ef2e 100644
--- a/pkcs11/gck/gck-crypto.h
+++ b/pkcs11/gck/gck-crypto.h
@@ -122,4 +122,13 @@ CK_RV gck_crypto_data_to_sexp (const gc
CK_ULONG n_data,
gcry_sexp_t *sexp);
+CK_RV gck_crypto_generate_key_pair (GckSession *session,
+ CK_MECHANISM_TYPE mech,
+ CK_ATTRIBUTE_PTR pub_atts,
+ CK_ULONG n_pub_atts,
+ CK_ATTRIBUTE_PTR priv_atts,
+ CK_ULONG n_priv_atts,
+ GckObject **pub_key,
+ GckObject **priv_key);
+
#endif /* GCKCRYPTO_H_ */
diff --git a/pkcs11/gck/gck-dh-key.c b/pkcs11/gck/gck-dh-key.c
new file mode 100644
index 0000000..2c0ef64
--- /dev/null
+++ b/pkcs11/gck/gck-dh-key.c
@@ -0,0 +1,148 @@
+/*
+ * 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 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.
+ */
+
+#include "config.h"
+
+#include "pkcs11/pkcs11.h"
+
+#include "gck-attributes.h"
+#include "gck-crypto.h"
+#include "gck-dh-key.h"
+#include "gck-dh-mechanism.h"
+#include "gck-session.h"
+#include "gck-util.h"
+
+struct _GckDhKeyPrivate {
+ gcry_mpi_t prime;
+ gcry_mpi_t base;
+ gpointer id;
+ gsize n_id;
+};
+
+G_DEFINE_TYPE (GckDhKey, gck_dh_key, GCK_TYPE_OBJECT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC_DH_KEY
+ */
+
+static CK_RV
+gck_dh_key_real_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE* attr)
+{
+ GckDhKey *self = GCK_DH_KEY (base);
+
+ switch (attr->type)
+ {
+
+ case CKA_KEY_TYPE:
+ return gck_attribute_set_ulong (attr, CKK_DH);
+
+ case CKA_START_DATE:
+ case CKA_END_DATE:
+ return gck_attribute_set_empty (attr);
+
+ case CKA_LOCAL:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_KEY_GEN_MECHANISM:
+ return gck_attribute_set_ulong (attr, CK_UNAVAILABLE_INFORMATION);
+
+ case CKA_ALLOWED_MECHANISMS:
+ return gck_attribute_set_data (attr, (CK_VOID_PTR)GCK_DH_MECHANISMS,
+ sizeof (GCK_DH_MECHANISMS));
+
+ case CKA_ID:
+ return gck_attribute_set_data (attr, self->pv->id, self->pv->n_id);
+
+ case CKA_SUBJECT:
+ return gck_attribute_set_empty (attr);
+
+ case CKA_PRIME:
+ return gck_attribute_set_mpi (attr, self->pv->prime);
+
+ case CKA_BASE:
+ return gck_attribute_set_mpi (attr, self->pv->base);
+ };
+
+ return GCK_OBJECT_CLASS (gck_dh_key_parent_class)->get_attribute (base, session, attr);
+}
+
+static void
+gck_dh_key_init (GckDhKey *self)
+{
+ self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_DH_KEY, GckDhKeyPrivate);
+}
+
+static void
+gck_dh_key_finalize (GObject *obj)
+{
+ GckDhKey *self = GCK_DH_KEY (obj);
+
+ gcry_mpi_release (self->pv->prime);
+ self->pv->prime = NULL;
+
+ gcry_mpi_release (self->pv->base);
+ self->pv->base = NULL;
+
+ g_free (self->pv->id);
+ self->pv->id = NULL;
+ self->pv->n_id = 0;
+
+ G_OBJECT_CLASS (gck_dh_key_parent_class)->finalize (obj);
+}
+
+static void
+gck_dh_key_class_init (GckDhKeyClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+
+ gck_dh_key_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = gck_dh_key_finalize;
+
+ gck_class->get_attribute = gck_dh_key_real_get_attribute;
+
+ g_type_class_add_private (klass, sizeof (GckDhKeyPrivate));
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+void
+gck_dh_key_initialize (GckDhKey *self, gcry_mpi_t prime, gcry_mpi_t base,
+ gpointer id, gsize n_id)
+{
+ g_return_if_fail (GCK_IS_DH_KEY (self));
+ g_return_if_fail (base);
+ g_return_if_fail (prime);
+ g_return_if_fail (!self->pv->base);
+ g_return_if_fail (!self->pv->prime);
+
+ self->pv->base = base;
+ self->pv->prime = prime;
+ self->pv->id = id;
+ self->pv->n_id = n_id;
+}
diff --git a/pkcs11/gck/gck-dh-key.h b/pkcs11/gck/gck-dh-key.h
new file mode 100644
index 0000000..bb7e68c
--- /dev/null
+++ b/pkcs11/gck/gck-dh-key.h
@@ -0,0 +1,57 @@
+/*
+ * 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 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.
+ */
+
+#ifndef __GCK_DH_KEY_H__
+#define __GCK_DH_KEY_H__
+
+#include <glib-object.h>
+
+#include "gck-object.h"
+#include "gck-types.h"
+
+#define GCK_TYPE_DH_KEY (gck_dh_key_get_type ())
+#define GCK_DH_KEY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_DH_KEY, GckDhKey))
+#define GCK_DH_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_DH_KEY, GckDhKeyClass))
+#define GCK_IS_DH_KEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_DH_KEY))
+#define GCK_IS_DH_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_DH_KEY))
+#define GCK_DH_KEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_DH_KEY, GckDhKeyClass))
+
+typedef struct _GckDhKeyClass GckDhKeyClass;
+typedef struct _GckDhKeyPrivate GckDhKeyPrivate;
+
+struct _GckDhKey {
+ GckObject parent;
+ GckDhKeyPrivate *pv;
+};
+
+struct _GckDhKeyClass {
+ GckObjectClass parent_class;
+};
+
+GType gck_dh_key_get_type (void);
+
+void gck_dh_key_initialize (GckDhKey *self,
+ gcry_mpi_t prime,
+ gcry_mpi_t base,
+ gpointer id,
+ gsize n_id);
+
+#endif /* __GCK_DH_KEY_H__ */
diff --git a/pkcs11/gck/gck-dh-mechanism.c b/pkcs11/gck/gck-dh-mechanism.c
new file mode 100644
index 0000000..4f901dd
--- /dev/null
+++ b/pkcs11/gck/gck-dh-mechanism.c
@@ -0,0 +1,113 @@
+/*
+ * 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 "gck-attributes.h"
+#include "gck-dh-mechanism.h"
+#include "gck-dh-private-key.h"
+#include "gck-dh-public-key.h"
+#include "gck-session.h"
+
+#include "egg/egg-dh.h"
+#include "egg/egg-libgcrypt.h"
+#include "egg/egg-secure-memory.h"
+
+CK_RV
+gck_dh_mechanism_generate (GckSession *session, CK_ATTRIBUTE_PTR pub_atts,
+ CK_ULONG n_pub_atts, CK_ATTRIBUTE_PTR priv_atts,
+ CK_ULONG n_priv_atts, GckObject **pub_key,
+ GckObject **priv_key)
+{
+ gcry_mpi_t prime = NULL;
+ gcry_mpi_t base = NULL;
+ gcry_mpi_t pub = NULL;
+ gcry_mpi_t priv = NULL;
+ gcry_error_t gcry;
+ guchar *buffer, *id;
+ gsize n_buffer, n_id;
+ GckManager *manager;
+ GckModule *module;
+ gulong bits;
+
+ g_return_val_if_fail (GCK_IS_SESSION (session), CKR_GENERAL_ERROR);
+ g_return_val_if_fail (pub_key, CKR_GENERAL_ERROR);
+ g_return_val_if_fail (priv_key, CKR_GENERAL_ERROR);
+
+ if (!gck_attributes_find_mpi (pub_atts, n_pub_atts, CKA_PRIME, &prime) ||
+ !gck_attributes_find_mpi (pub_atts, n_pub_atts, CKA_BASE, &base)) {
+ gcry_mpi_release (prime);
+ gcry_mpi_release (base);
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ gck_attributes_consume (pub_atts, n_pub_atts, CKA_PRIME, CKA_BASE, G_MAXULONG);
+
+ if (!gck_attributes_find_ulong (priv_atts, n_priv_atts, CKA_VALUE_BITS, &bits))
+ bits = gcry_mpi_get_nbits (prime);
+
+ gck_attributes_consume (priv_atts, n_priv_atts, CKA_VALUE_BITS, G_MAXULONG);
+
+ /* The private key must be less than or equal to prime */
+ if (bits > gcry_mpi_get_nbits (prime)) {
+ gcry_mpi_release (prime);
+ gcry_mpi_release (base);
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ if (!egg_dh_gen_pair (prime, base, bits, &priv, &pub)) {
+ gcry_mpi_release (prime);
+ gcry_mpi_release (base);
+ return CKR_FUNCTION_FAILED;
+ }
+
+ /* Write the public key out to raw data, so we can use it for an ID */
+ gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n_buffer, pub);
+ g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+ buffer = g_malloc (n_buffer);
+ gcry = gcry_mpi_print (GCRYMPI_FMT_USG, buffer, n_buffer, &n_buffer, pub);
+ g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+ if (n_buffer < 16) {
+ n_id = n_buffer;
+ id = g_memdup (buffer, n_id);
+ } else {
+ n_id = 16;
+ id = g_memdup (buffer + (n_buffer - 16), n_id);
+ }
+
+ manager = gck_manager_for_template (pub_atts, n_pub_atts, session);
+ module = gck_session_get_module (session);
+
+ *pub_key = GCK_OBJECT (gck_dh_public_key_new (module, manager, prime, base,
+ pub, id, n_id));
+
+ id = g_memdup (id, n_id);
+ prime = gcry_mpi_copy (prime);
+ base = gcry_mpi_copy (base);
+
+ *priv_key = GCK_OBJECT (gck_dh_private_key_new (module, manager, prime, base,
+ priv, id, n_id));
+
+ gck_attributes_consume (pub_atts, n_pub_atts, CKA_PRIME, CKA_BASE, G_MAXULONG);
+
+ g_free (buffer);
+ return CKR_OK;
+}
diff --git a/pkcs11/gck/gck-dh-mechanism.h b/pkcs11/gck/gck-dh-mechanism.h
new file mode 100644
index 0000000..38624b2
--- /dev/null
+++ b/pkcs11/gck/gck-dh-mechanism.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef GCK_DH_MECHANISM_H_
+#define GCK_DH_MECHANISM_H_
+
+#include "gck-types.h"
+
+#include "pkcs11/pkcs11.h"
+
+#include <glib.h>
+
+#include <gcrypt.h>
+
+static const CK_MECHANISM_TYPE GCK_DH_MECHANISMS[] = {
+ CKM_DH_PKCS_DERIVE
+};
+
+CK_RV gck_dh_mechanism_generate (GckSession *session,
+ CK_ATTRIBUTE_PTR pub_atts,
+ CK_ULONG n_pub_atts,
+ CK_ATTRIBUTE_PTR priv_atts,
+ CK_ULONG n_priv_atts,
+ GckObject **pub_key,
+ GckObject **priv_key);
+
+#endif /* GCK_DH_MECHANISM_H_ */
diff --git a/pkcs11/gck/gck-dh-private-key.c b/pkcs11/gck/gck-dh-private-key.c
new file mode 100644
index 0000000..ac894ae
--- /dev/null
+++ b/pkcs11/gck/gck-dh-private-key.c
@@ -0,0 +1,207 @@
+/*
+ * 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 Private 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 Private License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Private
+ * 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 "pkcs11/pkcs11.h"
+
+#include "gck-attributes.h"
+#include "gck-crypto.h"
+#include "gck-factory.h"
+#include "gck-dh-private-key.h"
+#include "gck-session.h"
+#include "gck-transaction.h"
+#include "gck-util.h"
+
+struct _GckDhPrivateKey {
+ GckDhKey parent;
+ gcry_mpi_t value;
+};
+
+G_DEFINE_TYPE (GckDhPrivateKey, gck_dh_private_key, GCK_TYPE_DH_KEY);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static void
+factory_create_dh_private_key (GckSession *session, GckTransaction *transaction,
+ CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GckObject **object)
+{
+ GckManager *manager;
+ gcry_mpi_t prime = NULL;
+ gcry_mpi_t base = NULL;
+ gcry_mpi_t value = NULL;
+ CK_ATTRIBUTE_PTR idattr;
+
+ if (!gck_attributes_find_mpi (attrs, n_attrs, CKA_PRIME, &prime) ||
+ !gck_attributes_find_mpi (attrs, n_attrs, CKA_BASE, &base) ||
+ !gck_attributes_find_mpi (attrs, n_attrs, CKA_VALUE, &value)) {
+ gcry_mpi_release (prime);
+ gcry_mpi_release (base);
+ gcry_mpi_release (value);
+ return gck_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
+ }
+
+ manager = gck_manager_for_template (attrs, n_attrs, session);
+ idattr = gck_attributes_find (attrs, n_attrs, CKA_ID);
+
+ *object = GCK_OBJECT (gck_dh_private_key_new (gck_session_get_module (session),
+ manager, prime, base, value,
+ idattr ? g_memdup (idattr->pValue, idattr->ulValueLen) : NULL,
+ idattr ? idattr->ulValueLen : 0));
+ gck_attributes_consume (attrs, n_attrs, CKA_PRIME, CKA_BASE, CKA_VALUE, G_MAXULONG);
+}
+
+/* -----------------------------------------------------------------------------
+ * DH_PRIVATE_KEY
+ */
+
+static CK_RV
+gck_dh_private_key_real_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE* attr)
+{
+ GckDhPrivateKey *self = GCK_DH_PRIVATE_KEY (base);
+
+ switch (attr->type)
+ {
+
+ case CKA_CLASS:
+ return gck_attribute_set_ulong (attr, CKO_PRIVATE_KEY);
+
+ case CKA_PRIVATE:
+ return gck_attribute_set_bool (attr, TRUE);
+
+ case CKA_SENSITIVE:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_DECRYPT:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_SIGN:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_SIGN_RECOVER:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_DERIVE:
+ return gck_attribute_set_bool (attr, TRUE);
+
+ case CKA_UNWRAP:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_EXTRACTABLE:
+ return gck_attribute_set_bool (attr, TRUE);
+
+ case CKA_ALWAYS_SENSITIVE:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_NEVER_EXTRACTABLE:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_WRAP_WITH_TRUSTED:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_UNWRAP_TEMPLATE:
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+
+ case CKA_ALWAYS_AUTHENTICATE:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_VALUE:
+ return gck_attribute_set_mpi (attr, self->value);
+
+ case CKA_VALUE_BITS:
+ return gck_attribute_set_ulong (attr, gcry_mpi_get_nbits (self->value));
+ };
+
+ return GCK_OBJECT_CLASS (gck_dh_private_key_parent_class)->get_attribute (base, session, attr);
+}
+
+static void
+gck_dh_private_key_init (GckDhPrivateKey *self)
+{
+
+}
+
+static void
+gck_dh_private_key_finalize (GObject *obj)
+{
+ GckDhPrivateKey *self = GCK_DH_PRIVATE_KEY (obj);
+
+ gcry_mpi_release (self->value);
+ self->value = NULL;
+
+ G_OBJECT_CLASS (gck_dh_private_key_parent_class)->finalize (obj);
+}
+
+static void
+gck_dh_private_key_class_init (GckDhPrivateKeyClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+
+ gck_dh_private_key_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = gck_dh_private_key_finalize;
+
+ gck_class->get_attribute = gck_dh_private_key_real_get_attribute;
+}
+
+/* -----------------------------------------------------------------------------
+ * PRIVATE
+ */
+
+GckFactory*
+gck_dh_private_key_get_factory (void)
+{
+ static CK_OBJECT_CLASS klass = CKO_PRIVATE_KEY;
+ static CK_KEY_TYPE type = CKK_DH;
+
+ static CK_ATTRIBUTE attributes[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_KEY_TYPE, &type, sizeof (type) }
+ };
+
+ static GckFactory factory = {
+ attributes,
+ G_N_ELEMENTS (attributes),
+ factory_create_dh_private_key
+ };
+
+ return &factory;
+}
+
+GckDhPrivateKey*
+gck_dh_private_key_new (GckModule *module, GckManager *manager,
+ gcry_mpi_t prime, gcry_mpi_t base, gcry_mpi_t value,
+ gpointer id, gsize n_id)
+{
+ GckDhPrivateKey *key;
+
+ key = g_object_new (GCK_TYPE_DH_PRIVATE_KEY,
+ "manager", manager,
+ "module", module,
+ NULL);
+
+ gck_dh_key_initialize (GCK_DH_KEY (key), prime, base, id, n_id);
+ key->value = value;
+ return key;
+}
diff --git a/pkcs11/gck/gck-dh-private-key.h b/pkcs11/gck/gck-dh-private-key.h
new file mode 100644
index 0000000..88b0b64
--- /dev/null
+++ b/pkcs11/gck/gck-dh-private-key.h
@@ -0,0 +1,57 @@
+/*
+ * 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 Private 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 Private License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Private
+ * 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 __GCK_DH_PRIVATE_KEY_H__
+#define __GCK_DH_PRIVATE_KEY_H__
+
+#include <glib-object.h>
+
+#include "gck-dh-key.h"
+#include "gck-types.h"
+
+#define GCK_FACTORY_DH_PRIVATE_KEY (gck_dh_private_key_get_factory ())
+
+#define GCK_TYPE_DH_PRIVATE_KEY (gck_dh_private_key_get_type ())
+#define GCK_DH_PRIVATE_KEY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_DH_PRIVATE_KEY, GckDhPrivateKey))
+#define GCK_DH_PRIVATE_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_DH_PRIVATE_KEY, GckDhPrivateKeyClass))
+#define GCK_IS_DH_PRIVATE_KEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_DH_PRIVATE_KEY))
+#define GCK_IS_DH_PRIVATE_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_DH_PRIVATE_KEY))
+#define GCK_DH_PRIVATE_KEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_DH_PRIVATE_KEY, GckDhPrivateKeyClass))
+
+typedef struct _GckDhPrivateKeyClass GckDhPrivateKeyClass;
+
+struct _GckDhPrivateKeyClass {
+ GckDhKeyClass parent_class;
+};
+
+GType gck_dh_private_key_get_type (void);
+
+GckFactory* gck_dh_private_key_get_factory (void);
+
+GckDhPrivateKey* gck_dh_private_key_new (GckModule *module,
+ GckManager *manager,
+ gcry_mpi_t prime,
+ gcry_mpi_t base,
+ gcry_mpi_t value,
+ gpointer id,
+ gsize n_id);
+
+#endif /* __GCK_DH_PRIVATE_KEY_H__ */
diff --git a/pkcs11/gck/gck-dh-public-key.c b/pkcs11/gck/gck-dh-public-key.c
new file mode 100644
index 0000000..41f7c40
--- /dev/null
+++ b/pkcs11/gck/gck-dh-public-key.c
@@ -0,0 +1,186 @@
+/*
+ * 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 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.
+ */
+
+#include "config.h"
+
+#include "pkcs11/pkcs11.h"
+
+#include "gck-attributes.h"
+#include "gck-crypto.h"
+#include "gck-factory.h"
+#include "gck-dh-public-key.h"
+#include "gck-session.h"
+#include "gck-transaction.h"
+#include "gck-util.h"
+
+struct _GckDhPublicKey {
+ GckDhKey parent;
+ gcry_mpi_t value;
+};
+
+G_DEFINE_TYPE (GckDhPublicKey, gck_dh_public_key, GCK_TYPE_DH_KEY);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static void
+factory_create_dh_public_key (GckSession *session, GckTransaction *transaction,
+ CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GckObject **object)
+{
+ GckManager *manager;
+ gcry_mpi_t prime = NULL;
+ gcry_mpi_t base = NULL;
+ gcry_mpi_t value = NULL;
+ CK_ATTRIBUTE_PTR idattr;
+
+ if (!gck_attributes_find_mpi (attrs, n_attrs, CKA_PRIME, &prime) ||
+ !gck_attributes_find_mpi (attrs, n_attrs, CKA_BASE, &base) ||
+ !gck_attributes_find_mpi (attrs, n_attrs, CKA_VALUE, &value)) {
+ gcry_mpi_release (prime);
+ gcry_mpi_release (base);
+ gcry_mpi_release (value);
+ return gck_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
+ }
+
+ manager = gck_manager_for_template (attrs, n_attrs, session);
+ idattr = gck_attributes_find (attrs, n_attrs, CKA_ID);
+
+ *object = GCK_OBJECT (gck_dh_public_key_new (gck_session_get_module (session),
+ manager, prime, base, value,
+ idattr ? g_memdup (idattr->pValue, idattr->ulValueLen) : NULL,
+ idattr ? idattr->ulValueLen : 0));
+ gck_attributes_consume (attrs, n_attrs, CKA_PRIME, CKA_BASE, CKA_VALUE, G_MAXULONG);
+}
+
+/* -----------------------------------------------------------------------------
+ * DH_PUBLIC_KEY
+ */
+
+static CK_RV
+gck_dh_public_key_real_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE* attr)
+{
+ GckDhPublicKey *self = GCK_DH_PUBLIC_KEY (base);
+
+ switch (attr->type)
+ {
+
+ case CKA_CLASS:
+ return gck_attribute_set_ulong (attr, CKO_PUBLIC_KEY);
+
+ case CKA_DERIVE:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_ENCRYPT:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_VERIFY:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_VERIFY_RECOVER:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_WRAP:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_TRUSTED:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_WRAP_TEMPLATE:
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+
+ case CKA_VALUE:
+ return gck_attribute_set_mpi (attr, self->value);
+ };
+
+ return GCK_OBJECT_CLASS (gck_dh_public_key_parent_class)->get_attribute (base, session, attr);
+}
+
+static void
+gck_dh_public_key_init (GckDhPublicKey *self)
+{
+
+}
+
+static void
+gck_dh_public_key_finalize (GObject *obj)
+{
+ GckDhPublicKey *self = GCK_DH_PUBLIC_KEY (obj);
+
+ gcry_mpi_release (self->value);
+ self->value = NULL;
+
+ G_OBJECT_CLASS (gck_dh_public_key_parent_class)->finalize (obj);
+}
+
+static void
+gck_dh_public_key_class_init (GckDhPublicKeyClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+
+ gck_dh_public_key_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = gck_dh_public_key_finalize;
+
+ gck_class->get_attribute = gck_dh_public_key_real_get_attribute;
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+GckFactory*
+gck_dh_public_key_get_factory (void)
+{
+ static CK_OBJECT_CLASS klass = CKO_PUBLIC_KEY;
+ static CK_KEY_TYPE type = CKK_DH;
+
+ static CK_ATTRIBUTE attributes[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_KEY_TYPE, &type, sizeof (type) }
+ };
+
+ static GckFactory factory = {
+ attributes,
+ G_N_ELEMENTS (attributes),
+ factory_create_dh_public_key
+ };
+
+ return &factory;
+}
+
+GckDhPublicKey*
+gck_dh_public_key_new (GckModule *module, GckManager *manager,
+ gcry_mpi_t prime, gcry_mpi_t base, gcry_mpi_t value,
+ gpointer id, gsize n_id)
+{
+ GckDhPublicKey *key;
+
+ key = g_object_new (GCK_TYPE_DH_PUBLIC_KEY,
+ "manager", manager,
+ "module", module,
+ NULL);
+
+ key->value = value;
+ gck_dh_key_initialize (GCK_DH_KEY (key), prime, base, id, n_id);
+ return key;
+}
diff --git a/pkcs11/gck/gck-dh-public-key.h b/pkcs11/gck/gck-dh-public-key.h
new file mode 100644
index 0000000..fd41136
--- /dev/null
+++ b/pkcs11/gck/gck-dh-public-key.h
@@ -0,0 +1,57 @@
+/*
+ * 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 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.
+ */
+
+#ifndef __GCK_DH_PUBLIC_KEY_H__
+#define __GCK_DH_PUBLIC_KEY_H__
+
+#include <glib-object.h>
+
+#include "gck-dh-key.h"
+#include "gck-types.h"
+
+#define GCK_FACTORY_DH_PUBLIC_KEY (gck_dh_public_key_get_factory ())
+
+#define GCK_TYPE_DH_PUBLIC_KEY (gck_dh_public_key_get_type ())
+#define GCK_DH_PUBLIC_KEY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_DH_PUBLIC_KEY, GckDhPublicKey))
+#define GCK_DH_PUBLIC_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_DH_PUBLIC_KEY, GckDhPublicKeyClass))
+#define GCK_IS_DH_PUBLIC_KEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_DH_PUBLIC_KEY))
+#define GCK_IS_DH_PUBLIC_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_DH_PUBLIC_KEY))
+#define GCK_DH_PUBLIC_KEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_DH_PUBLIC_KEY, GckDhPublicKeyClass))
+
+typedef struct _GckDhPublicKeyClass GckDhPublicKeyClass;
+
+struct _GckDhPublicKeyClass {
+ GckDhKeyClass parent_class;
+};
+
+GType gck_dh_public_key_get_type (void);
+
+GckFactory* gck_dh_public_key_get_factory (void);
+
+GckDhPublicKey* gck_dh_public_key_new (GckModule *module,
+ GckManager *manager,
+ gcry_mpi_t prime,
+ gcry_mpi_t base,
+ gcry_mpi_t value,
+ gpointer id,
+ gsize n_id);
+
+#endif /* __GCK_DH_PUBLIC_KEY_H__ */
diff --git a/pkcs11/gck/gck-module.c b/pkcs11/gck/gck-module.c
index e23b8ce..160ad54 100644
--- a/pkcs11/gck/gck-module.c
+++ b/pkcs11/gck/gck-module.c
@@ -32,7 +32,9 @@
#include "gck-manager.h"
#include "gck-memory-store.h"
#include "gck-module.h"
+#include "gck-dh-private-key.h"
#include "gck-private-xsa-key.h"
+#include "gck-dh-public-key.h"
#include "gck-public-xsa-key.h"
#include "gck-session.h"
#include "gck-store.h"
@@ -145,7 +147,19 @@ static const MechanismAndInfo mechanism_list[] = {
* CKM_DSA
* For DSA, min and max are the minimum and maximum modulus in bits
*/
- { CKM_DSA, { 512, 1024, CKF_SIGN | CKF_VERIFY } }
+ { CKM_DSA, { 512, 1024, CKF_SIGN | CKF_VERIFY } },
+
+ /*
+ * CKM_DH_PKCS_KEY_PAIR_GEN
+ * For DH derivation the min and max are sizes of prime in bits.
+ */
+ { CKM_DH_PKCS_KEY_PAIR_GEN, { 768, 8192, CKF_GENERATE_KEY_PAIR } },
+
+ /*
+ * CKM_DH_PKCS_DERIVE
+ * For DH derivation the min and max are sizes of prime in bits.
+ */
+ { CKM_DH_PKCS_DERIVE, { 768, 8192, CKF_DERIVE } }
};
/* Hidden function that you should not use */
@@ -560,10 +574,12 @@ gck_module_init (GckModule *self)
self->pv->transient_objects = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, gck_util_dispose_unref);
/* Register session object factories */
- gck_module_register_factory (self, GCK_FACTORY_PRIVATE_XSA_KEY);
gck_module_register_factory (self, GCK_FACTORY_CERTIFICATE);
- gck_module_register_factory (self, GCK_FACTORY_PUBLIC_XSA_KEY);
gck_module_register_factory (self, GCK_FACTORY_CREDENTIAL);
+ gck_module_register_factory (self, GCK_FACTORY_DH_PRIVATE_KEY);
+ gck_module_register_factory (self, GCK_FACTORY_PRIVATE_XSA_KEY);
+ gck_module_register_factory (self, GCK_FACTORY_DH_PUBLIC_KEY);
+ gck_module_register_factory (self, GCK_FACTORY_PUBLIC_XSA_KEY);
}
static void
diff --git a/pkcs11/gck/gck-session.c b/pkcs11/gck/gck-session.c
index 44c9175..dda5260 100644
--- a/pkcs11/gck/gck-session.c
+++ b/pkcs11/gck/gck-session.c
@@ -377,6 +377,52 @@ attributes_find_boolean (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs,
return FALSE;
}
+static void
+finish_up_object_creation (GckSession *self, GckObject *object, GckTransaction *transaction,
+ CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
+{
+ gboolean is_private;
+ gulong i;
+
+ g_assert (GCK_IS_SESSION (self));
+ g_assert (GCK_IS_OBJECT (object));
+ g_assert (GCK_IS_TRANSACTION (transaction));
+ g_assert (!gck_transaction_get_failed (transaction));
+
+ gck_object_create_attributes (object, self, transaction, attrs, n_attrs);
+ if (gck_transaction_get_failed (transaction))
+ return;
+
+ /* See if we can create due to read-only */
+ if (gck_object_is_token (object)) {
+ if (!gck_object_is_transient (object) &&
+ gck_module_get_write_protected (self->pv->module))
+ return gck_transaction_fail (transaction, CKR_TOKEN_WRITE_PROTECTED);
+ else if (self->pv->read_only)
+ return gck_transaction_fail (transaction, CKR_SESSION_READ_ONLY);
+ }
+
+ /* Can only create public objects unless logged in */
+ if (gck_session_get_logged_in (self) != CKU_USER &&
+ gck_object_get_attribute_boolean (object, self, CKA_PRIVATE, &is_private) &&
+ is_private == TRUE) {
+ return gck_transaction_fail (transaction, CKR_USER_NOT_LOGGED_IN);
+ }
+
+ /* Find somewhere to store the object */
+ if (gck_object_is_token (object))
+ gck_module_store_token_object (self->pv->module, transaction, object);
+ else
+ add_object (self, transaction, object);
+
+ /* Next go through and set all attributes that weren't used initially */
+ gck_attributes_consume (attrs, n_attrs, CKA_TOKEN, G_MAXULONG);
+ for (i = 0; i < n_attrs && !gck_transaction_get_failed (transaction); ++i) {
+ if (!gck_attribute_consumed (&attrs[i]))
+ gck_object_set_attribute (object, self, transaction, &attrs[i]);
+ }
+}
+
/* -----------------------------------------------------------------------------
* OBJECT
*/
@@ -819,9 +865,6 @@ gck_session_create_object_for_factory (GckSession *self, GckFactory *factory,
GckObject **object)
{
GckTransaction *transaction;
- CK_ATTRIBUTE_PTR attrs;
- CK_ULONG n_attrs, i;
- gboolean is_private;
CK_RV rv;
g_return_val_if_fail (GCK_IS_SESSION (self), CKR_GENERAL_ERROR);
@@ -836,55 +879,19 @@ gck_session_create_object_for_factory (GckSession *self, GckFactory *factory,
* Duplicate the memory for the attributes (but not values) so we
* can 'consume' in the factory function
*/
- attrs = g_memdup (template, count * sizeof (CK_ATTRIBUTE));
- n_attrs = count;
+ template = g_memdup (template, count * sizeof (CK_ATTRIBUTE));
/* Actually create the object */
*object = NULL;
- (factory->func) (self, transaction, attrs, n_attrs, object);
+ (factory->func) (self, transaction, template, count, object);
- /* Give the object a chance to create additional attributes */
+ /* Complete creation, and do storage */
if (!gck_transaction_get_failed (transaction)) {
g_return_val_if_fail (*object, CKR_GENERAL_ERROR);
- gck_object_create_attributes (*object, self, transaction, attrs, n_attrs);
+ finish_up_object_creation (self, *object, transaction, template, count);
}
- /* See if we can create due to read-only */
- if (!gck_transaction_get_failed (transaction)) {
- if (gck_object_is_token (*object)) {
- if (!gck_object_is_transient (*object) &&
- gck_module_get_write_protected (self->pv->module))
- gck_transaction_fail (transaction, CKR_TOKEN_WRITE_PROTECTED);
- else if (self->pv->read_only)
- gck_transaction_fail (transaction, CKR_SESSION_READ_ONLY);
- }
- }
-
- /* Can only create public objects unless logged in */
- if (!gck_transaction_get_failed (transaction)) {
- if (gck_session_get_logged_in (self) != CKU_USER &&
- gck_object_get_attribute_boolean (*object, self, CKA_PRIVATE, &is_private) &&
- is_private == TRUE) {
- gck_transaction_fail (transaction, CKR_USER_NOT_LOGGED_IN);
- }
- }
-
- /* Find somewhere to store the object */
- if (!gck_transaction_get_failed (transaction)) {
- if (gck_object_is_token (*object))
- gck_module_store_token_object (self->pv->module, transaction, *object);
- else
- add_object (self, transaction, *object);
- }
-
- /* Next go through and set all attributes that weren't used initially */
- gck_attributes_consume (attrs, n_attrs, CKA_TOKEN, G_MAXULONG);
- for (i = 0; i < n_attrs && !gck_transaction_get_failed (transaction); ++i) {
- if (!gck_attribute_consumed (&attrs[i]))
- gck_object_set_attribute (*object, self, transaction, &attrs[i]);
- }
-
- g_free (attrs);
+ g_free (template);
gck_transaction_complete (transaction);
rv = gck_transaction_get_result (transaction);
@@ -1462,8 +1469,59 @@ gck_session_C_GenerateKeyPair (GckSession* self, CK_MECHANISM_PTR mechanism,
CK_ATTRIBUTE_PTR priv_template, CK_ULONG priv_count,
CK_OBJECT_HANDLE_PTR pub_key, CK_OBJECT_HANDLE_PTR priv_key)
{
- /* TODO: We need to implement this */
- return CKR_FUNCTION_NOT_SUPPORTED;
+ GckObject *pub = NULL;
+ GckObject *priv = NULL;
+ GckTransaction *transaction;
+ CK_RV rv;
+
+ g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+ if (!mechanism)
+ return CKR_ARGUMENTS_BAD;
+ if (!(!pub_count || pub_template))
+ return CKR_ARGUMENTS_BAD;
+ if (!(!priv_count || priv_template))
+ return CKR_ARGUMENTS_BAD;
+ if (!pub_key || !priv_key)
+ return CKR_ARGUMENTS_BAD;
+
+ /*
+ * Duplicate the memory for the attributes (but not values) so we
+ * can 'consume' in the generator and create object functions.
+ */
+ pub_template = g_memdup (pub_template, pub_count * sizeof (CK_ATTRIBUTE));
+ priv_template = g_memdup (priv_template, priv_count * sizeof (CK_ATTRIBUTE));
+ transaction = gck_transaction_new ();
+
+ /* Actually do the object creation */
+ rv = gck_crypto_generate_key_pair (self, mechanism->mechanism, pub_template, pub_count,
+ priv_template, priv_count, &pub, &priv);
+ if (rv != CKR_OK)
+ gck_transaction_fail (transaction, rv);
+
+ if (!gck_transaction_get_failed (transaction))
+ finish_up_object_creation (self, pub, transaction, pub_template, pub_count);
+ if (!gck_transaction_get_failed (transaction))
+ finish_up_object_creation (self, priv, transaction, priv_template, priv_count);
+
+ g_free (pub_template);
+ g_free (priv_template);
+
+ gck_transaction_complete (transaction);
+ rv = gck_transaction_get_result (transaction);
+ g_object_unref (transaction);
+
+ if (rv == CKR_OK) {
+ *pub_key = gck_object_get_handle (pub);
+ *priv_key = gck_object_get_handle (priv);
+ }
+
+ /* Objects are owned by storage */
+ if (pub != NULL)
+ g_object_unref (pub);
+ if (priv != NULL)
+ g_object_unref (priv);
+
+ return rv;
}
CK_RV
diff --git a/pkcs11/gck/gck-types.h b/pkcs11/gck/gck-types.h
index 5ad1c76..b7361e2 100644
--- a/pkcs11/gck/gck-types.h
+++ b/pkcs11/gck/gck-types.h
@@ -26,6 +26,9 @@ typedef struct _GckCertificate GckCertificate;
typedef struct _GckCertificateKey GckCertificateKey;
typedef struct _GckCertificateTrust GckCertificateTrust;
typedef struct _GckCredential GckCredential;
+typedef struct _GckDhKey GckDhKey;
+typedef struct _GckDhPrivateKey GckDhPrivateKey;
+typedef struct _GckDhPublicKey GckDhPublicKey;
typedef struct _GckFactory GckFactory;
typedef struct _GckManager GckManager;
typedef struct _GckModule GckModule;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]