[gnome-keyring/dbus-api] [pkcs11] Add support for AES secret keys and DH derive.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-keyring/dbus-api] [pkcs11] Add support for AES secret keys and DH derive.
- Date: Wed, 18 Nov 2009 18:05:07 +0000 (UTC)
commit 3e324f117fd8c1ae4c4cf9ebd8511737c3482d9b
Author: Stef Walter <stef memberwebs com>
Date: Wed Nov 18 17:31:34 2009 +0000
[pkcs11] Add support for AES secret keys and DH derive.
Implement CKM_DH_PKCS_DERIVE and CKK_AES related stuff.
pkcs11/gck/Makefile.am | 3 +
pkcs11/gck/gck-aes-key.c | 226 +++++++++++++++++++++++++++++++++++++++
pkcs11/gck/gck-aes-key.h | 50 +++++++++
pkcs11/gck/gck-aes-mechanism.h | 33 ++++++
pkcs11/gck/gck-crypto.c | 38 +++++++-
pkcs11/gck/gck-crypto.h | 9 ++
pkcs11/gck/gck-dh-key.c | 7 ++
pkcs11/gck/gck-dh-key.h | 2 +
pkcs11/gck/gck-dh-mechanism.c | 99 +++++++++++++++++
pkcs11/gck/gck-dh-mechanism.h | 7 ++
pkcs11/gck/gck-dh-private-key.c | 7 ++
pkcs11/gck/gck-dh-private-key.h | 2 +
pkcs11/gck/gck-module.c | 2 +
pkcs11/gck/gck-object.c | 40 +++++++
pkcs11/gck/gck-object.h | 10 ++
pkcs11/gck/gck-secret-key.c | 160 +++++++++++++++++++++++++++
pkcs11/gck/gck-secret-key.h | 51 +++++++++
pkcs11/gck/gck-session.c | 65 ++++++++++--
pkcs11/gck/gck-session.h | 5 +
pkcs11/gck/gck-types.h | 2 +
20 files changed, 808 insertions(+), 10 deletions(-)
---
diff --git a/pkcs11/gck/Makefile.am b/pkcs11/gck/Makefile.am
index 8a82d67..fc9f983 100644
--- a/pkcs11/gck/Makefile.am
+++ b/pkcs11/gck/Makefile.am
@@ -17,6 +17,8 @@ BUILT_SOURCES = \
asn1-def-pk.h asn1-def-pkix.h
libgck_la_SOURCES = \
+ gck-aes-key.c gck-aes-key.h \
+ gck-aes-mechanism.h \
gck-attributes.c gck-attributes.h \
gck-certificate.c gck-certificate.h \
gck-certificate-key.c gck-certificate-key.h \
@@ -42,6 +44,7 @@ libgck_la_SOURCES = \
gck-private-xsa-key.c gck-private-xsa-key.h \
gck-public-xsa-key.c gck-public-xsa-key.h \
gck-secret.c gck-secret.h \
+ gck-secret-key.c gck-secret-key.h \
gck-serializable.c gck-serializable.h \
gck-session.c gck-session.h \
gck-sexp.c gck-sexp.h \
diff --git a/pkcs11/gck/gck-aes-key.c b/pkcs11/gck/gck-aes-key.c
new file mode 100644
index 0000000..ee97b2c
--- /dev/null
+++ b/pkcs11/gck/gck-aes-key.c
@@ -0,0 +1,226 @@
+/*
+ * 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-aes-key.h"
+#include "gck-session.h"
+#include "gck-transaction.h"
+#include "gck-util.h"
+
+#include "egg/egg-secure-memory.h"
+
+struct _GckAesKey {
+ GckSecretKey parent;
+ gpointer value;
+ gsize n_value;
+};
+
+G_DEFINE_TYPE (GckAesKey, gck_aes_key, GCK_TYPE_SECRET_KEY);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static int
+algorithm_for_length (gsize length)
+{
+ switch (length) {
+ case 16:
+ return GCRY_CIPHER_AES128;
+ case 24:
+ return GCRY_CIPHER_AES192;
+ case 32:
+ return GCRY_CIPHER_AES256;
+ default:
+ return 0;
+ }
+}
+
+static CK_RV
+attribute_set_check_value (GckAesKey *self, CK_ATTRIBUTE *attr)
+{
+ gcry_cipher_hd_t cih;
+ gcry_error_t gcry;
+ int algorithm;
+ gpointer data;
+ CK_RV rv;
+
+ g_assert (GCK_IS_AES_KEY (self));
+ g_assert (attr);
+
+ /* Just asking for the length */
+ if (!attr->pValue) {
+ attr->ulValueLen = 3;
+ return CKR_OK;
+ }
+
+ algorithm = algorithm_for_length (self->n_value);
+ g_return_val_if_fail (algorithm != 0, CKR_GENERAL_ERROR);
+
+ gcry = gcry_cipher_open (&cih, algorithm, GCRY_CIPHER_MODE_ECB, 0);
+ if (gcry != 0) {
+ g_warning ("couldn't open %s cipher in ECB mode: %s",
+ gcry_cipher_algo_name (algorithm), gcry_strerror (gcry));
+ return CKR_FUNCTION_FAILED;
+ }
+
+ /* Setup the key */
+ gcry = gcry_cipher_setkey (cih, self->value, self->n_value);
+ g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+
+ /* Buffer of zeros */
+ data = g_malloc0 (self->n_value);
+
+ /* Encrypt it */
+ gcry = gcry_cipher_encrypt (cih, data, self->n_value, NULL, 0);
+ g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+
+ /* Use the first three bytes */
+ g_assert (self->n_value > 3);
+ rv = gck_attribute_set_data (attr, data, 3);
+
+ gcry_cipher_close (cih);
+ g_free (data);
+
+ return rv;
+}
+
+static void
+factory_create_aes_key (GckSession *session, GckTransaction *transaction,
+ CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GckObject **object)
+{
+ GckAesKey *key;
+ GckManager *manager;
+ CK_ATTRIBUTE_PTR value;
+
+ value = gck_attributes_find (attrs, n_attrs, CKA_VALUE);
+ if (value == NULL)
+ return gck_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
+
+ if (algorithm_for_length (value->ulValueLen) == 0)
+ return gck_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
+
+ manager = gck_manager_for_template (attrs, n_attrs, session);
+ *object = g_object_new (GCK_TYPE_AES_KEY,
+ "module", gck_session_get_module (session),
+ "manager", manager,
+ NULL);
+ key = GCK_AES_KEY (*object);
+
+ key->value = egg_secure_alloc (value->ulValueLen);
+ key->n_value = value->ulValueLen;
+ memcpy (key->value, value->pValue, key->n_value);
+
+ gck_attribute_consume (value);
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static CK_RV
+gck_aes_key_real_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE *attr)
+{
+ GckAesKey *self = GCK_AES_KEY (base);
+
+ switch (attr->type)
+ {
+ case CKA_KEY_TYPE:
+ return gck_attribute_set_ulong (attr, CKK_AES);
+
+ case CKA_VALUE:
+ return gck_attribute_set_data (attr, self->value, self->n_value);
+
+ case CKA_VALUE_LEN:
+ return gck_attribute_set_ulong (attr, self->n_value);
+
+ case CKA_CHECK_VALUE:
+ return attribute_set_check_value (self, attr);
+
+ case CKA_ALLOWED_MECHANISMS:
+ return gck_attribute_set_empty (attr);
+ };
+
+ return GCK_OBJECT_CLASS (gck_aes_key_parent_class)->get_attribute (base, session, attr);
+}
+
+static void
+gck_aes_key_init (GckAesKey *self)
+{
+
+}
+
+static void
+gck_aes_key_finalize (GObject *obj)
+{
+ GckAesKey *self = GCK_AES_KEY (obj);
+
+ if (self->value) {
+ egg_secure_clear (self->value, self->n_value);
+ egg_secure_free (self->value);
+ self->value = NULL;
+ self->n_value = 0;
+ }
+
+ G_OBJECT_CLASS (gck_aes_key_parent_class)->finalize (obj);
+}
+
+static void
+gck_aes_key_class_init (GckAesKeyClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+
+ gck_aes_key_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = gck_aes_key_finalize;
+
+ gck_class->get_attribute = gck_aes_key_real_get_attribute;
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+GckFactory*
+gck_aes_key_get_factory (void)
+{
+ static CK_OBJECT_CLASS klass = CKO_SECRET_KEY;
+ static CK_KEY_TYPE type = CKK_AES;
+
+ 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_aes_key
+ };
+
+ return &factory;
+}
diff --git a/pkcs11/gck/gck-aes-key.h b/pkcs11/gck/gck-aes-key.h
new file mode 100644
index 0000000..168485e
--- /dev/null
+++ b/pkcs11/gck/gck-aes-key.h
@@ -0,0 +1,50 @@
+/*
+ * 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_AES_KEY_H__
+#define __GCK_AES_KEY_H__
+
+#include <glib-object.h>
+
+#include "gck-secret-key.h"
+#include "gck-types.h"
+
+#define GCK_FACTORY_AES_KEY (gck_aes_key_get_factory ())
+
+#define GCK_TYPE_AES_KEY (gck_aes_key_get_type ())
+#define GCK_AES_KEY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_AES_KEY, GckAesKey))
+#define GCK_AES_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_AES_KEY, GckAesKeyClass))
+#define GCK_IS_AES_KEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_AES_KEY))
+#define GCK_IS_AES_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_AES_KEY))
+#define GCK_AES_KEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_AES_KEY, GckAesKeyClass))
+
+typedef struct _GckAesKeyClass GckAesKeyClass;
+typedef struct _GckAesKeyPrivate GckAesKeyPrivate;
+
+struct _GckAesKeyClass {
+ GckSecretKeyClass parent_class;
+};
+
+GType gck_aes_key_get_type (void);
+
+GckFactory* gck_aes_key_get_factory (void);
+
+#endif /* __GCK_AES_KEY_H__ */
diff --git a/pkcs11/gck/gck-aes-mechanism.h b/pkcs11/gck/gck-aes-mechanism.h
new file mode 100644
index 0000000..1f1dd66
--- /dev/null
+++ b/pkcs11/gck/gck-aes-mechanism.h
@@ -0,0 +1,33 @@
+/*
+ * 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_AES_MECHANISM_H_
+#define GCK_AES_MECHANISM_H_
+
+#include "gck-types.h"
+
+#include "pkcs11/pkcs11.h"
+
+#include <glib.h>
+
+#define GCK_AES_MECHANISM_KEY_LENGTH 16
+
+#endif /* GCK_AES_MECHANISM_H_ */
diff --git a/pkcs11/gck/gck-crypto.c b/pkcs11/gck/gck-crypto.c
index f85a918..db139fd 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-aes-mechanism.h"
#include "gck-dh-mechanism.h"
#include "gck-mechanism-dsa.h"
#include "gck-mechanism-rsa.h"
@@ -404,6 +405,29 @@ gck_crypto_generate_key_pair (GckSession *session, CK_MECHANISM_TYPE mech,
}
}
+CK_RV
+gck_crypto_derive_key (GckSession *session, CK_MECHANISM_PTR mech, GckObject *base,
+ CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GckObject **derived)
+{
+ g_return_val_if_fail (GCK_IS_SESSION (session), CKR_GENERAL_ERROR);
+ g_return_val_if_fail (GCK_IS_OBJECT (base), CKR_GENERAL_ERROR);
+ g_return_val_if_fail (derived, CKR_GENERAL_ERROR);
+
+ if (!gck_object_has_attribute_ulong (base, session, CKA_ALLOWED_MECHANISMS, mech->mechanism))
+ return CKR_KEY_TYPE_INCONSISTENT;
+
+ if (!gck_object_has_attribute_boolean (base, session, CKA_DERIVE, TRUE))
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ switch (mech->mechanism) {
+ case CKM_DH_PKCS_DERIVE:
+ return gck_dh_mechanism_derive (session, mech, base, attrs,
+ n_attrs, derived);
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+}
+
/* ----------------------------------------------------------------------------
* PREPARE FUNCTIONS
*/
@@ -441,7 +465,7 @@ gck_crypto_prepare_xsa (GckSession *session, CK_MECHANISM_TYPE mech, GckObject *
}
/* --------------------------------------------------------------------------
- * INITIALIZATION
+ * UTILITY
*/
@@ -450,3 +474,15 @@ gck_crypto_initialize (void)
{
egg_libgcrypt_initialize ();
}
+
+gulong
+gck_crypto_secret_key_length (CK_KEY_TYPE type)
+{
+ switch (type) {
+ case CKK_AES:
+ return GCK_AES_MECHANISM_KEY_LENGTH;
+ default:
+ return 0;
+ }
+}
+
diff --git a/pkcs11/gck/gck-crypto.h b/pkcs11/gck/gck-crypto.h
index 2b8ef2e..a32a95e 100644
--- a/pkcs11/gck/gck-crypto.h
+++ b/pkcs11/gck/gck-crypto.h
@@ -131,4 +131,13 @@ CK_RV gck_crypto_generate_key_pair (GckSessi
GckObject **pub_key,
GckObject **priv_key);
+CK_RV gck_crypto_derive_key (GckSession *session,
+ CK_MECHANISM_PTR mech,
+ GckObject *base,
+ CK_ATTRIBUTE_PTR attrs,
+ CK_ULONG n_attrs,
+ GckObject **derived);
+
+gulong gck_crypto_secret_key_length (CK_KEY_TYPE type);
+
#endif /* GCKCRYPTO_H_ */
diff --git a/pkcs11/gck/gck-dh-key.c b/pkcs11/gck/gck-dh-key.c
index 2c0ef64..a4e7d86 100644
--- a/pkcs11/gck/gck-dh-key.c
+++ b/pkcs11/gck/gck-dh-key.c
@@ -146,3 +146,10 @@ gck_dh_key_initialize (GckDhKey *self, gcry_mpi_t prime, gcry_mpi_t base,
self->pv->id = id;
self->pv->n_id = n_id;
}
+
+gcry_mpi_t
+gck_dh_key_get_prime (GckDhKey *self)
+{
+ g_return_val_if_fail (GCK_IS_DH_KEY (self), NULL);
+ return self->pv->prime;
+}
diff --git a/pkcs11/gck/gck-dh-key.h b/pkcs11/gck/gck-dh-key.h
index bb7e68c..17c0707 100644
--- a/pkcs11/gck/gck-dh-key.h
+++ b/pkcs11/gck/gck-dh-key.h
@@ -54,4 +54,6 @@ void gck_dh_key_initialize (GckDhKey *self,
gpointer id,
gsize n_id);
+gcry_mpi_t gck_dh_key_get_prime (GckDhKey *self);
+
#endif /* __GCK_DH_KEY_H__ */
diff --git a/pkcs11/gck/gck-dh-mechanism.c b/pkcs11/gck/gck-dh-mechanism.c
index 4f901dd..c16e1da 100644
--- a/pkcs11/gck/gck-dh-mechanism.c
+++ b/pkcs11/gck/gck-dh-mechanism.c
@@ -22,6 +22,7 @@
#include "config.h"
#include "gck-attributes.h"
+#include "gck-crypto.h"
#include "gck-dh-mechanism.h"
#include "gck-dh-private-key.h"
#include "gck-dh-public-key.h"
@@ -111,3 +112,101 @@ gck_dh_mechanism_generate (GckSession *session, CK_ATTRIBUTE_PTR pub_atts,
g_free (buffer);
return CKR_OK;
}
+
+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)
+{
+ 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;
+ gpointer value;
+ CK_RV rv;
+
+ g_return_val_if_fail (GCK_IS_DH_PRIVATE_KEY (base), CKR_GENERAL_ERROR);
+
+ if (mech->ulParameterLen && mech->pParameter) {
+ gcry = gcry_mpi_scan (&peer, GCRYMPI_FMT_USG, mech->pParameter,
+ mech->ulParameterLen, NULL);
+ if (gcry != 0)
+ peer = NULL;
+ }
+
+ if (peer == NULL)
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ 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);
+ gcry_mpi_release (peer);
+
+ if (ret != TRUE)
+ 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));
+
+ /* Prepend the value */
+ attr.type = CKA_VALUE;
+ attr.pValue = value;
+ attr.ulValueLen = n_value;
+ g_array_append_val (array, attr);
+
+ /* Add the remainder of the attributes */
+ g_array_append_vals (array, attrs, n_attrs);
+
+ /* Now create an object with these attributes */
+ rv = gck_session_create_object_for_attributes (session, (CK_ATTRIBUTE_PTR)array->data,
+ array->len, derived);
+
+ egg_secure_free (value);
+ g_array_free (array, TRUE);
+
+ return rv;
+}
diff --git a/pkcs11/gck/gck-dh-mechanism.h b/pkcs11/gck/gck-dh-mechanism.h
index 38624b2..3a3ea85 100644
--- a/pkcs11/gck/gck-dh-mechanism.h
+++ b/pkcs11/gck/gck-dh-mechanism.h
@@ -42,4 +42,11 @@ CK_RV gck_dh_mechanism_generate (GckSessi
GckObject **pub_key,
GckObject **priv_key);
+CK_RV gck_dh_mechanism_derive (GckSession *session,
+ CK_MECHANISM_PTR mech,
+ GckObject *base,
+ CK_ATTRIBUTE_PTR attrs,
+ CK_ULONG n_attrs,
+ GckObject **derived);
+
#endif /* GCK_DH_MECHANISM_H_ */
diff --git a/pkcs11/gck/gck-dh-private-key.c b/pkcs11/gck/gck-dh-private-key.c
index ac894ae..4017275 100644
--- a/pkcs11/gck/gck-dh-private-key.c
+++ b/pkcs11/gck/gck-dh-private-key.c
@@ -205,3 +205,10 @@ gck_dh_private_key_new (GckModule *module, GckManager *manager,
key->value = value;
return key;
}
+
+gcry_mpi_t
+gck_dh_private_key_get_value (GckDhPrivateKey *self)
+{
+ g_return_val_if_fail (GCK_IS_DH_PRIVATE_KEY (self), NULL);
+ return self->value;
+}
diff --git a/pkcs11/gck/gck-dh-private-key.h b/pkcs11/gck/gck-dh-private-key.h
index 88b0b64..bc7911c 100644
--- a/pkcs11/gck/gck-dh-private-key.h
+++ b/pkcs11/gck/gck-dh-private-key.h
@@ -54,4 +54,6 @@ GckDhPrivateKey* gck_dh_private_key_new (GckModule *modul
gpointer id,
gsize n_id);
+gcry_mpi_t gck_dh_private_key_get_value (GckDhPrivateKey *self);
+
#endif /* __GCK_DH_PRIVATE_KEY_H__ */
diff --git a/pkcs11/gck/gck-module.c b/pkcs11/gck/gck-module.c
index 160ad54..3301cd2 100644
--- a/pkcs11/gck/gck-module.c
+++ b/pkcs11/gck/gck-module.c
@@ -25,6 +25,7 @@
#include "pkcs11/pkcs11g.h"
#include "pkcs11/pkcs11i.h"
+#include "gck-aes-key.h"
#include "gck-attributes.h"
#include "gck-certificate.h"
#include "gck-credential.h"
@@ -574,6 +575,7 @@ 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_AES_KEY);
gck_module_register_factory (self, GCK_FACTORY_CERTIFICATE);
gck_module_register_factory (self, GCK_FACTORY_CREDENTIAL);
gck_module_register_factory (self, GCK_FACTORY_DH_PRIVATE_KEY);
diff --git a/pkcs11/gck/gck-object.c b/pkcs11/gck/gck-object.c
index 06ed1ec..0cb20c3 100644
--- a/pkcs11/gck/gck-object.c
+++ b/pkcs11/gck/gck-object.c
@@ -744,6 +744,46 @@ gck_object_get_attribute_data (GckObject *self, GckSession *session,
return attr.pValue;
}
+gboolean
+gck_object_has_attribute_ulong (GckObject *self, GckSession *session,
+ CK_ATTRIBUTE_TYPE type, gulong value)
+{
+ gulong *data;
+ gsize n_data, i;
+
+ g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
+ g_return_val_if_fail (GCK_IS_SESSION (session), FALSE);
+
+ data = gck_object_get_attribute_data (self, session, type, &n_data);
+ if (data == NULL)
+ return FALSE;
+
+ g_return_val_if_fail (n_data % sizeof (gulong) == 0, FALSE);
+ for (i = 0; i < n_data / sizeof (gulong); ++i) {
+ if (data[i] == value) {
+ g_free (data);
+ return TRUE;
+ }
+ }
+
+ g_free (data);
+ return FALSE;
+}
+
+gboolean
+gck_object_has_attribute_boolean (GckObject *self, GckSession *session,
+ CK_ATTRIBUTE_TYPE type, gboolean value)
+{
+ gboolean data;
+
+ g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
+ g_return_val_if_fail (GCK_IS_SESSION (session), FALSE);
+
+ if (!gck_object_get_attribute_boolean (self, session, type, &data))
+ return FALSE;
+ return data == value;
+}
+
void
gck_object_destroy (GckObject *self, GckTransaction *transaction)
{
diff --git a/pkcs11/gck/gck-object.h b/pkcs11/gck/gck-object.h
index 75fa935..d9b28d1 100644
--- a/pkcs11/gck/gck-object.h
+++ b/pkcs11/gck/gck-object.h
@@ -140,4 +140,14 @@ void* gck_object_get_attribute_data (GckObject *self,
CK_ATTRIBUTE_TYPE type,
gsize *n_data);
+gboolean gck_object_has_attribute_ulong (GckObject *self,
+ GckSession *session,
+ CK_ATTRIBUTE_TYPE type,
+ gulong value);
+
+gboolean gck_object_has_attribute_boolean (GckObject *self,
+ GckSession *session,
+ CK_ATTRIBUTE_TYPE type,
+ gboolean value);
+
#endif /* __GCK_OBJECT_H__ */
diff --git a/pkcs11/gck/gck-secret-key.c b/pkcs11/gck/gck-secret-key.c
new file mode 100644
index 0000000..dedc790
--- /dev/null
+++ b/pkcs11/gck/gck-secret-key.c
@@ -0,0 +1,160 @@
+/*
+ * 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-secret-key.h"
+#include "gck-session.h"
+#include "gck-util.h"
+
+struct _GckSecretKeyPrivate {
+ gpointer id;
+ gsize n_id;
+};
+
+G_DEFINE_TYPE (GckSecretKey, gck_secret_key, GCK_TYPE_OBJECT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC_SECRET_KEY
+ */
+
+static CK_RV
+gck_secret_key_real_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE* attr)
+{
+ GckSecretKey *self = GCK_SECRET_KEY (base);
+
+ switch (attr->type)
+ {
+ case CKA_CLASS:
+ return gck_attribute_set_ulong (attr, CKO_SECRET_KEY);
+
+ case CKA_SENSITIVE:
+ case CKA_ENCRYPT:
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_VERIFY:
+ case CKA_WRAP:
+ case CKA_UNWRAP:
+ case CKA_DERIVE:
+ 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_TRUSTED:
+ return gck_attribute_set_bool (attr, FALSE);
+
+ case CKA_WRAP_TEMPLATE:
+ case CKA_UNWRAP_TEMPLATE:
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+
+ 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_ID:
+ return gck_attribute_set_data (attr, self->pv->id, self->pv->n_id);
+
+ case CKA_KEY_GEN_MECHANISM:
+ return gck_attribute_set_ulong (attr, CK_UNAVAILABLE_INFORMATION);
+ };
+
+ return GCK_OBJECT_CLASS (gck_secret_key_parent_class)->get_attribute (base, session, attr);
+}
+
+static void
+gck_secret_key_real_create_attributes (GckObject *object, GckSession *session, GckTransaction *transaction,
+ CK_ATTRIBUTE *attrs, CK_ULONG n_attrs)
+{
+ GckSecretKey *self = GCK_SECRET_KEY (object);
+ CK_ATTRIBUTE_PTR id;
+
+ if (!self->pv->n_id) {
+ id = gck_attributes_find (attrs, n_attrs, CKA_ID);
+ if (id == NULL) {
+ self->pv->id = NULL;
+ self->pv->n_id = 0;
+ } else {
+ self->pv->id = g_memdup (id->pValue, id->ulValueLen);
+ self->pv->n_id = id->ulValueLen;
+ gck_attribute_consume (id);
+ }
+ }
+}
+
+static void
+gck_secret_key_init (GckSecretKey *self)
+{
+ self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_SECRET_KEY, GckSecretKeyPrivate);
+}
+
+static void
+gck_secret_key_finalize (GObject *obj)
+{
+ GckSecretKey *self = GCK_SECRET_KEY (obj);
+
+ g_free (self->pv->id);
+ self->pv->id = NULL;
+ self->pv->n_id = 0;
+
+ G_OBJECT_CLASS (gck_secret_key_parent_class)->finalize (obj);
+}
+
+static void
+gck_secret_key_class_init (GckSecretKeyClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+
+ gck_secret_key_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = gck_secret_key_finalize;
+
+ gck_class->get_attribute = gck_secret_key_real_get_attribute;
+ gck_class->create_attributes = gck_secret_key_real_create_attributes;
+
+ g_type_class_add_private (klass, sizeof (GckSecretKeyPrivate));
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
diff --git a/pkcs11/gck/gck-secret-key.h b/pkcs11/gck/gck-secret-key.h
new file mode 100644
index 0000000..c3dfe3c
--- /dev/null
+++ b/pkcs11/gck/gck-secret-key.h
@@ -0,0 +1,51 @@
+/*
+ * 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_SECRET_KEY_H__
+#define __GCK_SECRET_KEY_H__
+
+#include <glib-object.h>
+
+#include "gck-object.h"
+#include "gck-types.h"
+
+#define GCK_TYPE_SECRET_KEY (gck_secret_key_get_type ())
+#define GCK_SECRET_KEY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_SECRET_KEY, GckSecretKey))
+#define GCK_SECRET_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_SECRET_KEY, GckSecretKeyClass))
+#define GCK_IS_SECRET_KEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_SECRET_KEY))
+#define GCK_IS_SECRET_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_SECRET_KEY))
+#define GCK_SECRET_KEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_SECRET_KEY, GckSecretKeyClass))
+
+typedef struct _GckSecretKeyClass GckSecretKeyClass;
+typedef struct _GckSecretKeyPrivate GckSecretKeyPrivate;
+
+struct _GckSecretKey {
+ GckObject parent;
+ GckSecretKeyPrivate *pv;
+};
+
+struct _GckSecretKeyClass {
+ GckObjectClass parent_class;
+};
+
+GType gck_secret_key_get_type (void);
+
+#endif /* __GCK_SECRET_KEY_H__ */
diff --git a/pkcs11/gck/gck-session.c b/pkcs11/gck/gck-session.c
index dda5260..f321cb3 100644
--- a/pkcs11/gck/gck-session.c
+++ b/pkcs11/gck/gck-session.c
@@ -905,6 +905,22 @@ gck_session_create_object_for_factory (GckSession *self, GckFactory *factory,
return rv;
}
+CK_RV
+gck_session_create_object_for_attributes (GckSession *self, CK_ATTRIBUTE_PTR attrs,
+ CK_ULONG n_attrs, GckObject **object)
+{
+ GckFactory *factory;
+
+ g_return_val_if_fail (GCK_IS_SESSION (self), CKR_GENERAL_ERROR);
+
+ /* Find out if we can create such an object */
+ factory = gck_module_find_factory (gck_session_get_module (self), attrs, n_attrs);
+ if (factory == NULL)
+ return CKR_TEMPLATE_INCOMPLETE;
+
+ return gck_session_create_object_for_factory (self, factory, attrs, n_attrs, object);
+}
+
/* -----------------------------------------------------------------------------
* PKCS#11
*/
@@ -967,7 +983,6 @@ gck_session_C_CreateObject (GckSession* self, CK_ATTRIBUTE_PTR template,
CK_ULONG count, CK_OBJECT_HANDLE_PTR new_object)
{
GckObject *object = NULL;
- GckFactory *factory;
CK_RV rv;
g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
@@ -976,12 +991,7 @@ gck_session_C_CreateObject (GckSession* self, CK_ATTRIBUTE_PTR template,
if (!(!count || template))
return CKR_ARGUMENTS_BAD;
- /* Find out if we can create such an object */
- factory = gck_module_find_factory (gck_session_get_module (self), template, count);
- if (!factory)
- return CKR_TEMPLATE_INCOMPLETE;
-
- rv = gck_session_create_object_for_factory (self, factory, template, count, &object);
+ rv = gck_session_create_object_for_attributes (self, template, count, &object);
if (rv == CKR_OK) {
g_assert (object);
*new_object = gck_object_get_handle (object);
@@ -1548,8 +1558,45 @@ gck_session_C_DeriveKey (GckSession* self, CK_MECHANISM_PTR mechanism,
CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR template,
CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
{
- /* Our keys don't support derivation */
- return CKR_FUNCTION_NOT_SUPPORTED;
+ GckTransaction *transaction;
+ GckObject *base = NULL;
+ GckObject *derived = NULL;
+ CK_RV rv;
+
+ g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+ if (!mechanism)
+ return CKR_ARGUMENTS_BAD;
+ if (!(!count || template))
+ return CKR_ARGUMENTS_BAD;
+ if (!key)
+ return CKR_ARGUMENTS_BAD;
+
+ rv = gck_session_lookup_readable_object (self, base_key, &base);
+ if (rv != CKR_OK)
+ return rv;
+
+ /*
+ * Duplicate the memory for the attributes (but not values) so we
+ * can 'consume' in the generator and create object functions.
+ */
+ template = g_memdup (template, count * sizeof (CK_ATTRIBUTE));
+ transaction = gck_transaction_new ();
+
+ /* Actually do the object creation */
+ rv = gck_crypto_derive_key (self, mechanism, base, template, count, &derived);
+ if (rv != CKR_OK)
+ gck_transaction_fail (transaction, rv);
+
+ g_free (template);
+
+ gck_transaction_complete (transaction);
+ rv = gck_transaction_get_result (transaction);
+ g_object_unref (transaction);
+
+ if (rv == CKR_OK)
+ *key = gck_object_get_handle (derived);
+
+ return rv;
}
CK_RV
diff --git a/pkcs11/gck/gck-session.h b/pkcs11/gck/gck-session.h
index 6afb563..6904509 100644
--- a/pkcs11/gck/gck-session.h
+++ b/pkcs11/gck/gck-session.h
@@ -116,6 +116,11 @@ CK_RV gck_session_create_object_for_factory (GckSess
CK_ULONG n_attrs,
GckObject **object);
+CK_RV gck_session_create_object_for_attributes (GckSession *self,
+ CK_ATTRIBUTE_PTR attrs,
+ CK_ULONG n_attrs,
+ GckObject **object);
+
CK_RV gck_session_C_GetFunctionStatus (GckSession *self);
CK_RV gck_session_C_CancelFunction (GckSession *self);
diff --git a/pkcs11/gck/gck-types.h b/pkcs11/gck/gck-types.h
index b7361e2..1920f8f 100644
--- a/pkcs11/gck/gck-types.h
+++ b/pkcs11/gck/gck-types.h
@@ -22,6 +22,7 @@
#ifndef __GCK_TYPES_H__
#define __GCK_TYPES_H__
+typedef struct _GckAesKey GckAesKey;
typedef struct _GckCertificate GckCertificate;
typedef struct _GckCertificateKey GckCertificateKey;
typedef struct _GckCertificateTrust GckCertificateTrust;
@@ -36,6 +37,7 @@ typedef struct _GckObject GckObject;
typedef struct _GckPrivateXsaKey GckPrivateXsaKey;
typedef struct _GckPublicXsaKey GckPublicXsaKey;
typedef struct _GckSecret GckSecret;
+typedef struct _GckSecretKey GckSecretKey;
typedef struct _GckSession GckSession;
typedef struct _GckSessionPrivateKey GckSessionPrivateKey;
typedef struct _GckSessionPublicKey GckSessionPublicKey;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]