[seahorse] pkcs11: Support for PKCS#11 key generation
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [seahorse] pkcs11: Support for PKCS#11 key generation
- Date: Thu, 24 Nov 2011 07:13:24 +0000 (UTC)
commit 6df2460eb5cef806c1df147b93a7beb3700f4459
Author: Stef Walter <stefw collabora co uk>
Date: Mon Nov 14 07:13:02 2011 +0100
pkcs11: Support for PKCS#11 key generation
* Used to generate keys on smart cards and the like
* Also code for detecting which mechanisms a slot supports.
libseahorse/seahorse-key-manager-store.c | 1 +
pkcs11/Makefile.am | 4 +-
pkcs11/seahorse-pkcs11-backend.c | 51 +++-
pkcs11/seahorse-pkcs11-backend.h | 3 +
pkcs11/seahorse-pkcs11-generate.c | 517 ++++++++++++++++++++++++++++++
pkcs11/seahorse-pkcs11-generate.h | 35 ++
pkcs11/seahorse-pkcs11-generate.xml | 246 ++++++++++++++
pkcs11/seahorse-token.c | 42 +++-
pkcs11/seahorse-token.h | 5 +
9 files changed, 897 insertions(+), 7 deletions(-)
---
diff --git a/libseahorse/seahorse-key-manager-store.c b/libseahorse/seahorse-key-manager-store.c
index 2765978..1e7ccf2 100644
--- a/libseahorse/seahorse-key-manager-store.c
+++ b/libseahorse/seahorse-key-manager-store.c
@@ -646,6 +646,7 @@ seahorse_key_manager_store_new (GcrCollection *collection,
self = g_object_new (SEAHORSE_TYPE_KEY_MANAGER_STORE,
"collection", filtered,
"settings", settings,
+ "mode", GCR_COLLECTION_MODEL_LIST,
NULL);
pred->custom_target = self;
g_object_unref (filtered);
diff --git a/pkcs11/Makefile.am b/pkcs11/Makefile.am
index 118a340..75da6a2 100644
--- a/pkcs11/Makefile.am
+++ b/pkcs11/Makefile.am
@@ -20,6 +20,7 @@ libseahorse_pkcs11_la_SOURCES = \
seahorse-pkcs11-actions.c seahorse-pkcs11-actions.h \
seahorse-pkcs11-backend.c seahorse-pkcs11-backend.h \
seahorse-pkcs11-helpers.c seahorse-pkcs11-helpers.h \
+ seahorse-pkcs11-generate.c seahorse-pkcs11-generate.h \
seahorse-pkcs11-operations.c seahorse-pkcs11-operations.h \
seahorse-pkcs11-properties.c seahorse-pkcs11-properties.h \
seahorse-pkcs11.c seahorse-pkcs11.h \
@@ -30,7 +31,8 @@ libseahorse_pkcs11_la_LIBADD = \
$(top_builddir)/libseahorse/libseahorse.la \
$(GCR_LIBS)
-ui_DATA =
+ui_DATA = \
+ seahorse-pkcs11-generate.xml
EXTRA_DIST = \
$(ui_DATA)
diff --git a/pkcs11/seahorse-pkcs11-backend.c b/pkcs11/seahorse-pkcs11-backend.c
index 273de7f..65c32d7 100644
--- a/pkcs11/seahorse-pkcs11-backend.c
+++ b/pkcs11/seahorse-pkcs11-backend.c
@@ -22,6 +22,7 @@
#include "config.h"
#include "seahorse-pkcs11-backend.h"
+#include "seahorse-pkcs11-generate.h"
#include "seahorse-token.h"
#include "seahorse-backend.h"
@@ -29,6 +30,8 @@
#include "seahorse-registry.h"
#include "seahorse-util.h"
+#include <gcr/gcr-base.h>
+
#include <gck/gck.h>
#include <glib/gi18n.h>
@@ -86,6 +89,8 @@ seahorse_pkcs11_backend_init (SeahorsePkcs11Backend *self)
}
self->blacklist = g_list_prepend (self->blacklist, uri);
}
+
+ seahorse_pkcs11_generate_register ();
}
static gboolean
@@ -95,10 +100,6 @@ is_token_usable (SeahorsePkcs11Backend *self,
{
GList *l;
- if (token->flags & CKF_WRITE_PROTECTED) {
- /* _gcr_debug ("token is not importable: %s: write protected", token->label); */
- return FALSE;
- }
if (!(token->flags & CKF_TOKEN_INITIALIZED)) {
/* _gcr_debug ("token is not importable: %s: not initialized", token->label); */
return FALSE;
@@ -117,7 +118,6 @@ is_token_usable (SeahorsePkcs11Backend *self,
return TRUE;
}
-
static void
on_initialized_registered (GObject *unused,
GAsyncResult *result,
@@ -291,3 +291,44 @@ seahorse_pkcs11_backend_get (void)
g_return_val_if_fail (pkcs11_backend, NULL);
return pkcs11_backend;
}
+
+static gboolean
+on_filter_writable (GObject *object,
+ gpointer user_data)
+{
+ SeahorseToken *token = SEAHORSE_TOKEN (object);
+ guint mechanism = GPOINTER_TO_UINT (user_data);
+ GckTokenInfo *info;
+
+ info = seahorse_token_get_info (token);
+ g_return_val_if_fail (info != NULL, FALSE);
+
+ if (info->flags & CKF_WRITE_PROTECTED)
+ return FALSE;
+
+ if (mechanism != G_MAXUINT) {
+ if (!seahorse_token_has_mechanism (token, (gulong)mechanism))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+GcrCollection *
+seahorse_pkcs11_backend_get_writable_tokens (SeahorsePkcs11Backend *self,
+ gulong with_mechanism)
+{
+ gpointer mechanism;
+
+ self = self ? self : seahorse_pkcs11_backend_get ();
+ g_return_val_if_fail (SEAHORSE_IS_PKCS11_BACKEND (self), NULL);
+
+ if (with_mechanism == GCK_INVALID)
+ mechanism = GUINT_TO_POINTER (G_MAXUINT);
+ else
+ mechanism = GUINT_TO_POINTER (with_mechanism);
+
+ return gcr_filter_collection_new_with_callback (GCR_COLLECTION (self),
+ on_filter_writable,
+ mechanism, NULL);
+}
diff --git a/pkcs11/seahorse-pkcs11-backend.h b/pkcs11/seahorse-pkcs11-backend.h
index b4b040e..e367be1 100644
--- a/pkcs11/seahorse-pkcs11-backend.h
+++ b/pkcs11/seahorse-pkcs11-backend.h
@@ -43,4 +43,7 @@ GType seahorse_pkcs11_backend_get_type (void) G_GNUC_CON
SeahorsePkcs11Backend * seahorse_pkcs11_backend_get (void);
+GcrCollection * seahorse_pkcs11_backend_get_writable_tokens (SeahorsePkcs11Backend *self,
+ gulong with_mechanism);
+
#endif /* SEAHORSE_PKCS11_BACKEND_H_ */
diff --git a/pkcs11/seahorse-pkcs11-generate.c b/pkcs11/seahorse-pkcs11-generate.c
new file mode 100644
index 0000000..f78abea
--- /dev/null
+++ b/pkcs11/seahorse-pkcs11-generate.c
@@ -0,0 +1,517 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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 "seahorse-pkcs11-backend.h"
+#include "seahorse-pkcs11-generate.h"
+#include "seahorse-token.h"
+
+#include "seahorse-action.h"
+#include "seahorse-progress.h"
+#include "seahorse-interaction.h"
+#include "seahorse-registry.h"
+#include "seahorse-util.h"
+
+#include <glib/gi18n.h>
+
+#include <gcr/gcr.h>
+
+#include <gck/gck.h>
+#include <gck/pkcs11.h>
+
+#define SEAHORSE_PKCS11_GENERATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PKCS11_GENERATE, SeahorsePkcs11Generate))
+#define SEAHORSE_IS_PKCS11_GENERATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_PKCS11_GENERATE))
+#define SEAHORSE_PKCS11_GENERATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_PKCS11_GENERATE, SeahorsePkcs11GenerateClass))
+#define SEAHORSE_IS_PKCS11_GENERATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_PKCS11_GENERATE))
+#define SEAHORSE_PKCS11_GENERATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_PKCS11_GENERATE, SeahorsePkcs11GenerateClass))
+
+typedef struct _SeahorsePkcs11Generate SeahorsePkcs11Generate;
+typedef struct _SeahorsePkcs11GenerateClass SeahorsePkcs11GenerateClass;
+
+struct _SeahorsePkcs11Generate {
+ GtkDialog dialog;
+
+ GtkEntry *label_entry;
+
+ SeahorseToken *token;
+ GtkComboBox *token_box;
+ GcrCollectionModel *token_model;
+
+ GckMechanism *mechanism;
+ GtkListStore *mechanism_store;
+ GtkComboBox *mechanism_box;
+
+ GtkSpinButton *bits_entry;
+
+ GCancellable *cancellable;
+ GckAttributes *pub_attrs;
+ GckAttributes *prv_attrs;
+};
+
+struct _SeahorsePkcs11GenerateClass {
+ GtkDialogClass dialog_class;
+};
+
+G_DEFINE_TYPE (SeahorsePkcs11Generate, seahorse_pkcs11_generate, GTK_TYPE_DIALOG);
+
+enum {
+ MECHANISM_LABEL,
+ MECHANISM_TYPE,
+ MECHANISM_N_COLS
+};
+
+static GType MECHANISM_TYPES[] = {
+ G_TYPE_STRING,
+ G_TYPE_ULONG
+};
+
+struct {
+ gulong mechanism_type;
+ const gchar *label;
+} AVAILABLE_MECHANISMS[] = {
+ { CKM_RSA_PKCS_KEY_PAIR_GEN, N_("RSA") },
+};
+
+static void
+seahorse_pkcs11_generate_init (SeahorsePkcs11Generate *self)
+{
+
+}
+
+static void
+update_response (SeahorsePkcs11Generate *self)
+{
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (self), GTK_RESPONSE_OK,
+ self->token != NULL && self->mechanism != NULL);
+}
+
+static void
+complete_generate (SeahorsePkcs11Generate *self,
+ GError **error)
+{
+ g_assert (self->cancellable != NULL);
+ g_assert (error != NULL);
+
+ if (*error != NULL)
+ seahorse_util_handle_error (error, NULL, _("Couldn't generate private key"));
+ else
+ seahorse_token_refresh_async (self->token, self->cancellable, NULL, NULL);
+
+ g_clear_object (&self->cancellable);
+ gck_attributes_unref (self->pub_attrs);
+ gck_attributes_unref (self->prv_attrs);
+ self->pub_attrs = self->prv_attrs = NULL;
+}
+
+static void
+prepare_generate (SeahorsePkcs11Generate *self)
+{
+ CK_BYTE rsa_public_exponent[] = { 0x01, 0x00, 0x01 }; /* 65537 in bytes */
+ const gchar *label;
+
+ g_assert (self->cancellable == NULL);
+ g_assert (self->mechanism);
+
+ self->cancellable = g_cancellable_new ();
+
+ self->pub_attrs = gck_attributes_new ();
+ self->prv_attrs = gck_attributes_new ();
+
+ gck_attributes_add_ulong (self->pub_attrs, CKA_CLASS, CKO_PUBLIC_KEY);
+ gck_attributes_add_ulong (self->prv_attrs, CKA_CLASS, CKO_PRIVATE_KEY);
+
+ gck_attributes_add_boolean (self->pub_attrs, CKA_TOKEN, TRUE);
+ gck_attributes_add_boolean (self->prv_attrs, CKA_TOKEN, TRUE);
+
+ gck_attributes_add_boolean (self->prv_attrs, CKA_PRIVATE, TRUE);
+ gck_attributes_add_boolean (self->prv_attrs, CKA_SENSITIVE, TRUE);
+
+ label = gtk_entry_get_text (self->label_entry);
+ gck_attributes_add_string (self->pub_attrs, CKA_LABEL, label);
+ gck_attributes_add_string (self->prv_attrs, CKA_LABEL, label);
+
+ if (self->mechanism->type == CKM_RSA_PKCS_KEY_PAIR_GEN) {
+ gck_attributes_add_boolean (self->pub_attrs, CKA_ENCRYPT, TRUE);
+ gck_attributes_add_boolean (self->pub_attrs, CKA_VERIFY, TRUE);
+ gck_attributes_add_boolean (self->pub_attrs, CKA_WRAP, TRUE);
+
+ gck_attributes_add_boolean (self->prv_attrs, CKA_DECRYPT, TRUE);
+ gck_attributes_add_boolean (self->prv_attrs, CKA_SIGN, TRUE);
+ gck_attributes_add_boolean (self->prv_attrs, CKA_UNWRAP, TRUE);
+
+ gck_attributes_add_data (self->pub_attrs, CKA_PUBLIC_EXPONENT,
+ rsa_public_exponent, sizeof (rsa_public_exponent));
+ gck_attributes_add_ulong (self->pub_attrs, CKA_MODULUS_BITS,
+ gtk_spin_button_get_value_as_int (self->bits_entry));
+
+ } else {
+ g_warning ("currently no support for this mechanism");
+ }
+}
+
+static void
+on_generate_complete (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ SeahorsePkcs11Generate *self = SEAHORSE_PKCS11_GENERATE (user_data);
+ GError *error = NULL;
+
+ gck_session_generate_key_pair_finish (GCK_SESSION (object), result, NULL, NULL, &error);
+ complete_generate (self, &error);
+
+ g_object_unref (self);
+}
+
+static void
+on_generate_open_session (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ SeahorsePkcs11Generate *self = SEAHORSE_PKCS11_GENERATE (user_data);
+ GError *error = NULL;
+ GckSession *session;
+
+ session = gck_session_open_finish (result, &error);
+ if (session) {
+ gck_session_generate_key_pair_async (session, self->mechanism,
+ self->pub_attrs, self->prv_attrs,
+ self->cancellable, on_generate_complete,
+ g_object_ref (self));
+ g_object_unref (session);
+
+ } else {
+ complete_generate (self, &error);
+ }
+
+ g_object_unref (self);
+}
+
+static const gchar *
+get_available_mechanism_label (gulong type)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (AVAILABLE_MECHANISMS); i++) {
+ if (AVAILABLE_MECHANISMS[i].mechanism_type == type)
+ return AVAILABLE_MECHANISMS[i].label;
+ }
+
+ return NULL;
+}
+
+static void
+on_token_changed (GtkComboBox *combo_box,
+ gpointer user_data)
+{
+ SeahorsePkcs11Generate *self = SEAHORSE_PKCS11_GENERATE (user_data);
+ GtkTreeIter iter;
+ GArray *mechanisms;
+ GObject *object;
+ gulong type, otype;
+ gboolean valid;
+ GtkTreeModel *model;
+ const gchar *label;
+ guint i;
+
+ g_clear_object (&self->token);
+
+ if (gtk_combo_box_get_active_iter (combo_box, &iter)) {
+ object = gcr_collection_model_object_for_iter (self->token_model, &iter);
+ self->token = g_object_ref (object);
+ }
+
+ model = GTK_TREE_MODEL (self->mechanism_store);
+ valid = gtk_tree_model_get_iter_first (model, &iter);
+ if (self->token) {
+ mechanisms = seahorse_token_get_mechanisms (self->token);
+ for (i = 0; mechanisms && i < mechanisms->len; i++) {
+ type = g_array_index (mechanisms, gulong, i);
+ label = get_available_mechanism_label (type);
+ if (label == NULL)
+ continue;
+ while (valid) {
+ gtk_tree_model_get (model, &iter, MECHANISM_TYPE, &otype, -1);
+ if (otype == type)
+ break;
+ valid = gtk_list_store_remove (self->mechanism_store, &iter);
+ }
+ if (!valid)
+ gtk_list_store_append (self->mechanism_store, &iter);
+ gtk_list_store_set (self->mechanism_store, &iter,
+ MECHANISM_TYPE, type,
+ MECHANISM_LABEL, label,
+ -1);
+ }
+ }
+ while (valid)
+ valid = gtk_list_store_remove (self->mechanism_store, &iter);
+
+ /* Select first mechanism if none are selected */
+ if (!gtk_combo_box_get_active_iter (self->mechanism_box, &iter))
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ gtk_combo_box_set_active_iter (self->mechanism_box, &iter);
+
+ update_response (self);
+}
+
+static void
+on_mechanism_changed (GtkComboBox *widget,
+ gpointer user_data)
+{
+ SeahorsePkcs11Generate *self = SEAHORSE_PKCS11_GENERATE (user_data);
+ GckMechanismInfo *info;
+ GtkTreeIter iter;
+ GckSlot *slot;
+ guint min;
+ guint max;
+
+ g_free (self->mechanism);
+ self->mechanism = NULL;
+
+ if (gtk_combo_box_get_active_iter (widget, &iter)) {
+ self->mechanism = g_new0 (GckMechanism, 1);
+ gtk_tree_model_get (GTK_TREE_MODEL (self->mechanism_store), &iter,
+ MECHANISM_TYPE, &self->mechanism->type, -1);
+
+ slot = seahorse_token_get_slot (self->token);
+ info = gck_slot_get_mechanism_info (slot, self->mechanism->type);
+ g_return_if_fail (info != NULL);
+
+ min = info->min_key_size;
+ max = info->max_key_size;
+
+ if (min < 512 && max >= 512)
+ min = 512;
+ if (max > 16384 && min <= 16384)
+ max = 16384;
+ gtk_spin_button_set_range (self->bits_entry, min, max);
+
+ gck_mechanism_info_free (info);
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->bits_entry),
+ self->mechanism != NULL);
+
+ update_response (self);
+}
+
+static gint
+on_mechanism_sort (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer user_data)
+{
+ gchar *label_a = NULL;
+ gchar *label_b = NULL;
+ gint ret;
+
+ gtk_tree_model_get (model, a, MECHANISM_LABEL, &label_a, -1);
+ gtk_tree_model_get (model, b, MECHANISM_LABEL, &label_b, -1);
+ ret = g_strcmp0 (label_a, label_b);
+ g_free (label_a);
+ g_free (label_b);
+
+ return ret;
+}
+
+static void
+seahorse_pkcs11_generate_constructed (GObject *obj)
+{
+ SeahorsePkcs11Generate *self = SEAHORSE_PKCS11_GENERATE (obj);
+ GtkCellRenderer *renderer;
+ GcrCollection *collection;
+ GtkBuilder *builder;
+ const gchar *path;
+ GError *error = NULL;
+ GtkWidget *content;
+ GtkWidget *widget;
+
+ G_OBJECT_CLASS (seahorse_pkcs11_generate_parent_class)->constructed (obj);
+
+ builder = gtk_builder_new ();
+ path = SEAHORSE_UIDIR "/seahorse-pkcs11-generate.xml";
+ gtk_builder_add_from_file (builder, path, &error);
+ if (error != NULL) {
+ g_warning ("couldn't load ui file: %s", path);
+ g_clear_error (&error);
+ g_object_unref (builder);
+ return;
+ }
+
+ gtk_window_set_resizable (GTK_WINDOW (self), FALSE);
+ content = gtk_dialog_get_content_area (GTK_DIALOG (self));
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, "pkcs11-generate"));
+ gtk_container_add (GTK_CONTAINER (content), widget);
+ gtk_widget_show (widget);
+
+ self->bits_entry = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "key-bits"));
+ gtk_spin_button_set_range (self->bits_entry, 0, G_MAXINT); /* updated later */
+ gtk_spin_button_set_increments (self->bits_entry, 128, 128);
+ gtk_spin_button_set_value (self->bits_entry, 2048);
+
+ self->label_entry = GTK_ENTRY (gtk_builder_get_object (builder, "key-label"));
+
+ /* The mechanism */
+ self->mechanism_box = GTK_COMBO_BOX (gtk_builder_get_object (builder, "key-mechanism"));
+ G_STATIC_ASSERT (MECHANISM_N_COLS == G_N_ELEMENTS (MECHANISM_TYPES));
+ self->mechanism_store = gtk_list_store_newv (MECHANISM_N_COLS, MECHANISM_TYPES);
+ gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (self->mechanism_store),
+ on_mechanism_sort, NULL, NULL);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->mechanism_store),
+ GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
+ gtk_combo_box_set_model (self->mechanism_box, GTK_TREE_MODEL (self->mechanism_store));
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self->mechanism_box), renderer, TRUE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self->mechanism_box), renderer, "markup", MECHANISM_LABEL);
+ g_signal_connect (self->mechanism_box, "changed", G_CALLBACK (on_mechanism_changed), self);
+
+ /* The tokens */
+ self->token_box = GTK_COMBO_BOX (gtk_builder_get_object (builder, "key-token"));
+ collection = seahorse_pkcs11_backend_get_writable_tokens (NULL, CKM_RSA_PKCS_KEY_PAIR_GEN);
+ self->token_model = gcr_collection_model_new (collection, GCR_COLLECTION_MODEL_LIST,
+ "icon", G_TYPE_ICON, "label", G_TYPE_STRING, NULL);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->token_model), 1, GTK_SORT_ASCENDING);
+ gtk_combo_box_set_model (self->token_box, GTK_TREE_MODEL (self->token_model));
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (renderer, "stock-size", GTK_ICON_SIZE_BUTTON, NULL);
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self->token_box), renderer, FALSE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self->token_box), renderer, "gicon", 0);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self->token_box), renderer, TRUE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self->token_box), renderer, "text", 1);
+ g_signal_connect (self->token_box, "changed", G_CALLBACK (on_token_changed), self);
+ if (gcr_collection_get_length (collection) > 0)
+ gtk_combo_box_set_active (self->token_box, 0);
+ g_object_unref (collection);
+
+ /* The buttons */
+ gtk_dialog_add_buttons (GTK_DIALOG (self),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ _("Create"), GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
+
+ update_response (self);
+ g_object_unref (builder);
+}
+
+static void
+seahorse_pkcs11_generate_finalize (GObject *obj)
+{
+ SeahorsePkcs11Generate *self = SEAHORSE_PKCS11_GENERATE (obj);
+
+ g_clear_object (&self->token);
+ g_clear_object (&self->token_model);
+
+ g_free (self->mechanism);
+ g_clear_object (&self->mechanism_store);
+
+ g_clear_object (&self->cancellable);
+ gck_attributes_unref (self->pub_attrs);
+ gck_attributes_unref (self->prv_attrs);
+
+ G_OBJECT_CLASS (seahorse_pkcs11_generate_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_pkcs11_generate_response (GtkDialog *dialog,
+ gint response_id)
+{
+ SeahorsePkcs11Generate *self = SEAHORSE_PKCS11_GENERATE (dialog);
+ GTlsInteraction *interaction;
+ GtkWindow *parent;
+
+ if (response_id == GTK_RESPONSE_OK) {
+ g_return_if_fail (self->token);
+
+ prepare_generate (self);
+ parent = gtk_window_get_transient_for (GTK_WINDOW (self));
+ interaction = seahorse_interaction_new (parent);
+
+ gck_session_open_async (seahorse_token_get_slot (self->token),
+ GCK_SESSION_READ_WRITE | GCK_SESSION_LOGIN_USER,
+ interaction, self->cancellable,
+ on_generate_open_session, g_object_ref (self));
+
+ seahorse_progress_show (self->cancellable, _("Generating key"), FALSE);
+ g_object_unref (interaction);
+ }
+
+ gtk_widget_hide (GTK_WIDGET (dialog));
+}
+
+static void
+seahorse_pkcs11_generate_class_init (SeahorsePkcs11GenerateClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
+
+ gobject_class->constructed = seahorse_pkcs11_generate_constructed;
+ gobject_class->finalize = seahorse_pkcs11_generate_finalize;
+
+ dialog_class->response = seahorse_pkcs11_generate_response;
+}
+
+void
+seahorse_pkcs11_generate_prompt (GtkWindow *parent)
+{
+ GtkDialog *dialog;
+
+ g_return_if_fail (GTK_IS_WINDOW (parent));
+
+ dialog = g_object_new (SEAHORSE_TYPE_PKCS11_GENERATE,
+ "transient-for", parent,
+ NULL);
+ g_object_ref_sink (dialog);
+
+ gtk_dialog_run (dialog);
+
+ g_object_unref (dialog);
+}
+
+static void
+on_generate_activate (GtkAction *action,
+ gpointer user_data)
+{
+ GtkWindow *parent;
+
+ parent = seahorse_action_get_window (action);
+ seahorse_pkcs11_generate_prompt (parent);
+}
+
+static const GtkActionEntry ACTION_ENTRIES[] = {
+ { "pkcs11-generate-key", GCR_ICON_KEY_PAIR, N_ ("Private key"), "",
+ N_("Used to request a certificate"), G_CALLBACK (on_generate_activate) }
+};
+
+void
+seahorse_pkcs11_generate_register (void)
+{
+ GtkActionGroup *actions;
+
+ actions = gtk_action_group_new ("pkcs11-generate");
+ gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions (actions, ACTION_ENTRIES, G_N_ELEMENTS (ACTION_ENTRIES), NULL);
+ seahorse_registry_register_object (NULL, G_OBJECT (actions), "generator", NULL);
+}
diff --git a/pkcs11/seahorse-pkcs11-generate.h b/pkcs11/seahorse-pkcs11-generate.h
new file mode 100644
index 0000000..5de6b10
--- /dev/null
+++ b/pkcs11/seahorse-pkcs11-generate.h
@@ -0,0 +1,35 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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 __SEAHORSE_PKCS11_GENERATE_H__
+#define __SEAHORSE_PKCS11_GENERATE_H__
+
+#include <gtk/gtk.h>
+
+#define SEAHORSE_TYPE_PKCS11_GENERATE (seahorse_pkcs11_generate_get_type ())
+
+GType seahorse_pkcs11_generate_get_type (void) G_GNUC_CONST;
+
+void seahorse_pkcs11_generate_prompt (GtkWindow *parent);
+
+void seahorse_pkcs11_generate_register (void);
+
+#endif /* __SEAHORSE_PKCS11_GENERATE_H__ */
diff --git a/pkcs11/seahorse-pkcs11-generate.xml b/pkcs11/seahorse-pkcs11-generate.xml
new file mode 100644
index 0000000..873952d
--- /dev/null
+++ b/pkcs11/seahorse-pkcs11-generate.xml
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <object class="GtkHBox" id="pkcs11-generate">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">7</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkImage" id="key-image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="yalign">0</property>
+ <property name="pixel_size">48</property>
+ <property name="icon_name">gcr-key-pair</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label45">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">Create a new private key</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Label:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Stored at:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="key-label">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â</property>
+ <property name="invisible_char_set">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="key-token">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkExpander" id="expander1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <property name="top_padding">12</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label49">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Key _Type:</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label50">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Key _Strength (bits):</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="key-mechanism">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="key-bits">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â</property>
+ <property name="invisible_char_set">True</property>
+ <property name="climb_rate">64</property>
+ <property name="numeric">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label48">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes"><b>_Advanced key options</b></property>
+ <property name="use_markup">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/pkcs11/seahorse-token.c b/pkcs11/seahorse-token.c
index 9f8f5d1..890955f 100644
--- a/pkcs11/seahorse-token.c
+++ b/pkcs11/seahorse-token.c
@@ -59,6 +59,7 @@ struct _SeahorseTokenPrivate {
GckSlot *slot;
gchar *uri;
GckTokenInfo *info;
+ GArray *mechanisms;
GckSession *session;
GtkActionGroup *actions;
GHashTable *object_for_handle;
@@ -77,6 +78,17 @@ G_DEFINE_TYPE_EXTENDED (SeahorseToken, seahorse_token, G_TYPE_OBJECT, 0,
);
static void
+update_mechanisms (SeahorseToken *self)
+{
+ GArray *mechanisms;
+
+ mechanisms = gck_slot_get_mechanisms (self->pv->slot);
+ if (self->pv->mechanisms != NULL)
+ g_array_unref (self->pv->mechanisms);
+ self->pv->mechanisms = mechanisms;
+}
+
+static void
update_token_info (SeahorseToken *self)
{
GckTokenInfo *info;
@@ -158,6 +170,9 @@ lookup_id_map (SeahorseToken *self,
GPtrArray *objects;
guint i;
+ if (id == NULL)
+ return NULL;
+
objects = g_hash_table_lookup (self->pv->objects_for_id, id);
if (objects == NULL)
return NULL;
@@ -258,7 +273,7 @@ receive_objects (SeahorseToken *self,
object = prev;
}
- id = gck_attributes_find (attrs, CKA_ID);
+ id = attrs ? gck_attributes_find (attrs, CKA_ID) : NULL;
update_id_map (self, object, id);
if (SEAHORSE_IS_CERTIFICATE (object)) {
@@ -864,6 +879,31 @@ seahorse_token_get_unlockable (SeahorseToken *self)
return !is_session_logged_in (self->pv->session);
}
+GArray *
+seahorse_token_get_mechanisms (SeahorseToken *self)
+{
+ g_return_val_if_fail (SEAHORSE_IS_TOKEN (self), NULL);
+
+ if (!self->pv->mechanisms)
+ update_mechanisms (self);
+
+ return self->pv->mechanisms;
+}
+
+gboolean
+seahorse_token_has_mechanism (SeahorseToken *self,
+ gulong mechanism)
+{
+ g_return_val_if_fail (SEAHORSE_IS_TOKEN (self), FALSE);
+
+ if (!self->pv->mechanisms)
+ update_mechanisms (self);
+
+ return gck_mechanisms_check (self->pv->mechanisms,
+ mechanism,
+ GCK_INVALID);
+}
+
void
seahorse_token_remove_object (SeahorseToken *self,
GckObject *object)
diff --git a/pkcs11/seahorse-token.h b/pkcs11/seahorse-token.h
index 0bb7abe..273479b 100644
--- a/pkcs11/seahorse-token.h
+++ b/pkcs11/seahorse-token.h
@@ -62,6 +62,11 @@ gboolean seahorse_token_get_lockable (SeahorseToken *self);
gboolean seahorse_token_get_unlockable (SeahorseToken *self);
+GArray * seahorse_token_get_mechanisms (SeahorseToken *self);
+
+gboolean seahorse_token_has_mechanism (SeahorseToken *self,
+ gulong mechanism);
+
void seahorse_token_remove_object (SeahorseToken *self,
GckObject *object);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]