[seahorse] pkcs11: use GtkTemplate for the generate dialog.



commit c7f7faf784a908773aa0f4f0fed07838708e1156
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Sun Aug 12 14:54:19 2018 +0200

    pkcs11: use GtkTemplate for the generate dialog.

 common/config.vapi                 |   6 +
 pkcs11/cryptoki.vapi               | 397 ++++++++++++++++++++++++++++
 pkcs11/meson.build                 |   8 +-
 pkcs11/pkcs11-generate.vala        | 294 +++++++++++++++++++++
 pkcs11/seahorse-pkcs11-backend.c   |   2 -
 pkcs11/seahorse-pkcs11-backend.h   |   2 -
 pkcs11/seahorse-pkcs11-generate.c  | 518 -------------------------------------
 pkcs11/seahorse-pkcs11-generate.h  |  34 ---
 pkcs11/seahorse-pkcs11-generate.ui | 295 +++++++++------------
 src/application.vala               |   4 +-
 10 files changed, 829 insertions(+), 731 deletions(-)
---
diff --git a/common/config.vapi b/common/config.vapi
index d5cda88f..6838ebc0 100644
--- a/common/config.vapi
+++ b/common/config.vapi
@@ -52,6 +52,12 @@ namespace Progress {
 namespace Pgp.Backend {
        public void initialize();
 }
+
+[CCode (cheader_filename = "pkcs11/seahorse-pkcs11-backend.h")]
+public class Pkcs11.Backend {
+       public static void initialize();
+       public static Gcr.Collection get_writable_tokens(Pkcs11.Backend? self, ulong with_mechanism);
+}
 }
 
 namespace Egg {
diff --git a/pkcs11/cryptoki.vapi b/pkcs11/cryptoki.vapi
new file mode 100644
index 00000000..3fb709a0
--- /dev/null
+++ b/pkcs11/cryptoki.vapi
@@ -0,0 +1,397 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2018 Niels De Graef
+ *
+ * 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, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Although there are some VAPI files that take care of the bindings to
+ * Cryptoki, they are woefully inadequate, so maintain our own bindings here
+ * for now.
+ *
+ * Most of these were made by taking some stuff of the header and doing some
+ * regex magix on them.
+ */
+[CCode (cprefix = "CK_")]
+namespace Cryptoki {
+    [CCode (cname = "ulong", cprefix = "CKA_", has_type_id = false)]
+    public enum Attribute {
+        CLASS,
+        TOKEN,
+        PRIVATE,
+        LABEL,
+        APPLICATION,
+        VALUE,
+        OBJECT_ID,
+        CERTIFICATE_TYPE,
+        ISSUER,
+        SERIAL_NUMBER,
+        AC_ISSUER,
+        OWNER,
+        ATTR_TYPES,
+        TRUSTED,
+        CERTIFICATE_CATEGORY,
+        JAVA_MIDP_SECURITY_DOMAIN,
+        URL,
+        HASH_OF_SUBJECT_PUBLIC_KEY,
+        HASH_OF_ISSUER_PUBLIC_KEY,
+        CHECK_VALUE,
+        KEY_TYPE,
+        SUBJECT,
+        ID,
+        SENSITIVE,
+        ENCRYPT,
+        DECRYPT,
+        WRAP,
+        UNWRAP,
+        SIGN,
+        SIGN_RECOVER,
+        VERIFY,
+        VERIFY_RECOVER,
+        DERIVE,
+        START_DATE,
+        END_DATE,
+        MODULUS,
+        MODULUS_BITS,
+        PUBLIC_EXPONENT,
+        PRIVATE_EXPONENT,
+        PRIME_1,
+        PRIME_2,
+        EXPONENT_1,
+        EXPONENT_2,
+        COEFFICIENT,
+        PRIME,
+        SUBPRIME,
+        BASE,
+        PRIME_BITS,
+        SUB_PRIME_BITS,
+        VALUE_BITS,
+        VALUE_LEN,
+        EXTRACTABLE,
+        LOCAL,
+        NEVER_EXTRACTABLE,
+        ALWAYS_SENSITIVE,
+        KEY_GEN_MECHANISM,
+        MODIFIABLE,
+        COPYABLE,
+        ECDSA_PARAMS,
+        EC_PARAMS,
+        EC_POINT,
+        SECONDARY_AUTH,
+        AUTH_PIN_FLAGS,
+        ALWAYS_AUTHENTICATE,
+        WRAP_WITH_TRUSTED,
+        OTP_FORMAT,
+        OTP_LENGTH,
+        OTP_TIME_INTERVAL,
+        OTP_USER_FRIENDLY_MODE,
+        OTP_CHALLENGE_REQUIREMENT,
+        OTP_TIME_REQUIREMENT,
+        OTP_COUNTER_REQUIREMENT,
+        OTP_PIN_REQUIREMENT,
+        OTP_USER_IDENTIFIER,
+        OTP_SERVICE_IDENTIFIER,
+        OTP_SERVICE_LOGO,
+        OTP_SERVICE_LOGO_TYPE,
+        OTP_COUNTER,
+        OTP_TIME,
+        GOSTR3410_PARAMS,
+        GOSTR3411_PARAMS,
+        GOST28147_PARAMS,
+        HW_FEATURE_TYPE,
+        RESET_ON_INIT,
+        HAS_RESET,
+        PIXEL_X,
+        PIXEL_Y,
+        RESOLUTION,
+        CHAR_ROWS,
+        CHAR_COLUMNS,
+        COLOR,
+        BITS_PER_PIXEL,
+        CHAR_SETS,
+        ENCODING_METHODS,
+        MIME_TYPES,
+        MECHANISM_TYPE,
+        REQUIRED_CMS_ATTRIBUTES,
+        DEFAULT_CMS_ATTRIBUTES,
+        SUPPORTED_CMS_ATTRIBUTES,
+        WRAP_TEMPLATE,
+        UNWRAP_TEMPLATE,
+        ALLOWED_MECHANISMS,
+        VENDOR_DEFINED,
+    }
+
+    [CCode (cname = "ulong", cprefix = "CKM_", has_type_id = false)]
+    public enum MechanismType {
+        RSA_PKCS_KEY_PAIR_GEN,
+        RSA_PKCS,
+        RSA_9796,
+        RSA_X_509,
+        MD2_RSA_PKCS,
+        MD5_RSA_PKCS,
+        SHA1_RSA_PKCS,
+        RIPEMD128_RSA_PKCS,
+        RIPEMD160_RSA_PKCS,
+        RSA_PKCS_OAEP,
+        RSA_X9_31_KEY_PAIR_GEN,
+        RSA_X9_31,
+        SHA1_RSA_X9_31,
+        RSA_PKCS_PSS,
+        SHA1_RSA_PKCS_PSS,
+        DSA_KEY_PAIR_GEN,
+        DSA,
+        DSA_SHA1,
+        DH_PKCS_KEY_PAIR_GEN,
+        DH_PKCS_DERIVE,
+        X9_42_DH_KEY_PAIR_GEN,
+        X9_42_DH_DERIVE,
+        X9_42_DH_HYBRID_DERIVE,
+        X9_42_MQV_DERIVE,
+        SHA256_RSA_PKCS,
+        SHA384_RSA_PKCS,
+        SHA512_RSA_PKCS,
+        SHA256_RSA_PKCS_PSS,
+        SHA384_RSA_PKCS_PSS,
+        SHA512_RSA_PKCS_PSS,
+        RC2_KEY_GEN,
+        RC2_ECB,
+        RC2_CBC,
+        RC2_MAC,
+        RC2_MAC_GENERAL,
+        RC2_CBC_PAD,
+        RC4_KEY_GEN,
+        RC4,
+        DES_KEY_GEN,
+        DES_ECB,
+        DES_CBC,
+        DES_MAC,
+        DES_MAC_GENERAL,
+        DES_CBC_PAD,
+        DES2_KEY_GEN,
+        DES3_KEY_GEN,
+        DES3_ECB,
+        DES3_CBC,
+        DES3_MAC,
+        DES3_MAC_GENERAL,
+        DES3_CBC_PAD,
+        CDMF_KEY_GEN,
+        CDMF_ECB,
+        CDMF_CBC,
+        CDMF_MAC,
+        CDMF_MAC_GENERAL,
+        CDMF_CBC_PAD,
+        DES_OFB64,
+        DES_OFB8,
+        DES_CFB64,
+        DES_CFB8,
+        MD2,
+        MD2_HMAC,
+        MD2_HMAC_GENERAL,
+        MD5,
+        MD5_HMAC,
+        MD5_HMAC_GENERAL,
+        SHA_1,
+        SHA_1_HMAC,
+        SHA_1_HMAC_GENERAL,
+        RIPEMD128,
+        RIPEMD128_HMAC,
+        RIPEMD128_HMAC_GENERAL,
+        RIPEMD160,
+        RIPEMD160_HMAC,
+        RIPEMD160_HMAC_GENERAL,
+        SHA256,
+        SHA256_HMAC,
+        SHA256_HMAC_GENERAL,
+        SHA384,
+        SHA384_HMAC,
+        SHA384_HMAC_GENERAL,
+        SHA512,
+        SHA512_HMAC,
+        SHA512_HMAC_GENERAL,
+        SECURID_KEY_GEN,
+        SECURID,
+        HOTP_KEY_GEN,
+        HOTP,
+        ACTI,
+        ACTI_KEY_GEN,
+        CAST_KEY_GEN,
+        CAST_ECB,
+        CAST_CBC,
+        CAST_MAC,
+        CAST_MAC_GENERAL,
+        CAST_CBC_PAD,
+        CAST3_KEY_GEN,
+        CAST3_ECB,
+        CAST3_CBC,
+        CAST3_MAC,
+        CAST3_MAC_GENERAL,
+        CAST3_CBC_PAD,
+        CAST5_KEY_GEN,
+        CAST128_KEY_GEN,
+        CAST5_ECB,
+        CAST128_ECB,
+        CAST5_CBC,
+        CAST128_CBC,
+        CAST5_MAC,
+        CAST128_MAC,
+        CAST5_MAC_GENERAL,
+        CAST128_MAC_GENERAL,
+        CAST5_CBC_PAD,
+        CAST128_CBC_PAD,
+        RC5_KEY_GEN,
+        RC5_ECB,
+        RC5_CBC,
+        RC5_MAC,
+        RC5_MAC_GENERAL,
+        RC5_CBC_PAD,
+        IDEA_KEY_GEN,
+        IDEA_ECB,
+        IDEA_CBC,
+        IDEA_MAC,
+        IDEA_MAC_GENERAL,
+        IDEA_CBC_PAD,
+        GENERIC_SECRET_KEY_GEN,
+        CONCATENATE_BASE_AND_KEY,
+        CONCATENATE_BASE_AND_DATA,
+        CONCATENATE_DATA_AND_BASE,
+        XOR_BASE_AND_DATA,
+        EXTRACT_KEY_FROM_KEY,
+        SSL3_PRE_MASTER_KEY_GEN,
+        SSL3_MASTER_KEY_DERIVE,
+        SSL3_KEY_AND_MAC_DERIVE,
+        SSL3_MASTER_KEY_DERIVE_DH,
+        TLS_PRE_MASTER_KEY_GEN,
+        TLS_MASTER_KEY_DERIVE,
+        TLS_KEY_AND_MAC_DERIVE,
+        TLS_MASTER_KEY_DERIVE_DH,
+        TLS_PRF,
+        SSL3_MD5_MAC,
+        SSL3_SHA1_MAC,
+        MD5_KEY_DERIVATION,
+        MD2_KEY_DERIVATION,
+        SHA1_KEY_DERIVATION,
+        SHA256_KEY_DERIVATION,
+        SHA384_KEY_DERIVATION,
+        SHA512_KEY_DERIVATION,
+        PBE_MD2_DES_CBC,
+        PBE_MD5_DES_CBC,
+        PBE_MD5_CAST_CBC,
+        PBE_MD5_CAST3_CBC,
+        PBE_MD5_CAST5_CBC,
+        PBE_MD5_CAST128_CBC,
+        PBE_SHA1_CAST5_CBC,
+        PBE_SHA1_CAST128_CBC,
+        PBE_SHA1_RC4_128,
+        PBE_SHA1_RC4_40,
+        PBE_SHA1_DES3_EDE_CBC,
+        PBE_SHA1_DES2_EDE_CBC,
+        PBE_SHA1_RC2_128_CBC,
+        PBE_SHA1_RC2_40_CBC,
+        PKCS5_PBKD2,
+        PBA_SHA1_WITH_SHA1_HMAC,
+        WTLS_PRE_MASTER_KEY_GEN,
+        WTLS_MASTER_KEY_DERIVE,
+        WTLS_MASTER_KEY_DERIVE_DH_ECC,
+        WTLS_PRF,
+        WTLS_SERVER_KEY_AND_MAC_DERIVE,
+        WTLS_CLIENT_KEY_AND_MAC_DERIVE,
+        KEY_WRAP_LYNKS,
+        KEY_WRAP_SET_OAEP,
+        CMS_SIG,
+        SKIPJACK_KEY_GEN,
+        SKIPJACK_ECB64,
+        SKIPJACK_CBC64,
+        SKIPJACK_OFB64,
+        SKIPJACK_CFB64,
+        SKIPJACK_CFB32,
+        SKIPJACK_CFB16,
+        SKIPJACK_CFB8,
+        SKIPJACK_WRAP,
+        SKIPJACK_PRIVATE_WRAP,
+        SKIPJACK_RELAYX,
+        KEA_KEY_PAIR_GEN,
+        KEA_KEY_DERIVE,
+        FORTEZZA_TIMESTAMP,
+        BATON_KEY_GEN,
+        BATON_ECB128,
+        BATON_ECB96,
+        BATON_CBC128,
+        BATON_COUNTER,
+        BATON_SHUFFLE,
+        BATON_WRAP,
+        ECDSA_KEY_PAIR_GEN,
+        EC_KEY_PAIR_GEN,
+        ECDSA,
+        ECDSA_SHA1,
+        ECDH1_DERIVE,
+        ECDH1_COFACTOR_DERIVE,
+        ECMQV_DERIVE,
+        JUNIPER_KEY_GEN,
+        JUNIPER_ECB128,
+        JUNIPER_CBC128,
+        JUNIPER_COUNTER,
+        JUNIPER_SHUFFLE,
+        JUNIPER_WRAP,
+        FASTHASH,
+        AES_KEY_GEN,
+        AES_ECB,
+        AES_CBC,
+        AES_MAC,
+        AES_MAC_GENERAL,
+        AES_CBC_PAD,
+        BLOWFISH_KEY_GEN,
+        BLOWFISH_CBC,
+        TWOFISH_KEY_GEN,
+        TWOFISH_CBC,
+        DES_ECB_ENCRYPT_DATA,
+        DES_CBC_ENCRYPT_DATA,
+        DES3_ECB_ENCRYPT_DATA,
+        DES3_CBC_ENCRYPT_DATA,
+        AES_ECB_ENCRYPT_DATA,
+        AES_CBC_ENCRYPT_DATA,
+        GOSTR3410_KEY_PAIR_GEN,
+        GOSTR3410,
+        GOSTR3410_WITH_GOSTR3411,
+        GOSTR3410_KEY_WRAP,
+        GOSTR3410_DERIVE,
+        GOSTR3411,
+        GOSTR3411_HMAC,
+        GOST28147_KEY_GEN,
+        GOST28147_ECB,
+        GOST28147,
+        GOST28147_MAC,
+        GOST28147_KEY_WRAP,
+        DSA_PARAMETER_GEN,
+        DH_PKCS_PARAMETER_GEN,
+        X9_42_DH_PARAMETER_GEN,
+        VENDOR_DEFINED,
+    }
+
+    [CCode (cname = "ulong", cprefix = "CKO_", has_type_id = false)]
+    public enum ObjectClass {
+        DATA,
+        CERTIFICATE,
+        PUBLIC_KEY,
+        PRIVATE_KEY,
+        SECRET_KEY,
+        HW_FEATURE,
+        DOMAIN_PARAMETERS,
+        MECHANISM,
+        OTP_KEY,
+        VENDOR_DEFINED,
+    }
+}
diff --git a/pkcs11/meson.build b/pkcs11/meson.build
index 760b7bf8..4234bab8 100644
--- a/pkcs11/meson.build
+++ b/pkcs11/meson.build
@@ -2,6 +2,7 @@ pkcs11_sources = [
   'certificate-der-exporter.vala',
   'pkcs11-certificate.vala',
   'pkcs11-deleter.vala',
+  'pkcs11-generate.vala',
   'pkcs11-key-deleter.vala',
   'pkcs11-module.vala',
   'pkcs11-private-key.vala',
@@ -9,8 +10,8 @@ pkcs11_sources = [
   'pkcs11-request.vala',
   'pkcs11-token.vala',
 
+  'cryptoki.vapi',
   'seahorse-pkcs11-backend.c',
-  'seahorse-pkcs11-generate.c',
 ]
 
 pkcs11_deps = [
@@ -20,9 +21,14 @@ pkcs11_deps = [
   common_dep,
 ]
 
+pkcs11_vala_args = [
+  '--gresources', resources_xml,
+]
+
 pkcs11_lib = static_library('seahorse-pkcs11',
   pkcs11_sources,
   dependencies: pkcs11_deps,
+  vala_args: pkcs11_vala_args,
 )
 
 pkcs11_dep = declare_dependency(
diff --git a/pkcs11/pkcs11-generate.vala b/pkcs11/pkcs11-generate.vala
new file mode 100644
index 00000000..8e72cd72
--- /dev/null
+++ b/pkcs11/pkcs11-generate.vala
@@ -0,0 +1,294 @@
+/*
+ * 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, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+// FIXME: damn broken bindings
+extern Gcr.CollectionModel gcr_collection_model_new(Gcr.Collection collection,
+                                                    Gcr.CollectionModelMode mode, ...);
+
+[GtkTemplate (ui = "/org/gnome/Seahorse/seahorse-pkcs11-generate.ui")]
+public class Seahorse.Pkcs11.Generate : Gtk.Dialog {
+
+    [GtkChild]
+    private Gtk.Entry label_entry;
+
+    private Pkcs11.Token? token;
+    [GtkChild]
+    private Gtk.ComboBox token_box;
+    private Gcr.CollectionModel? token_model;
+
+    private Gck.Mechanism? mechanism;
+    private Gtk.ListStore? mechanism_store;
+    [GtkChild]
+    private Gtk.ComboBox mechanism_box;
+
+    [GtkChild]
+    private Gtk.SpinButton key_bits;
+
+    private Cancellable? cancellable;
+    private Gck.Attributes? pub_attrs;
+    private Gck.Attributes? prv_attrs;
+
+    private enum Column {
+        LABEL,
+        TYPE,
+        N_COLS
+    }
+
+    private struct Mechanism {
+        ulong mechanism_type;
+        unowned string label;
+    }
+    private const Mechanism[] AVAILABLE_MECHANISMS = {
+        { Cryptoki.MechanismType.RSA_PKCS_KEY_PAIR_GEN, N_("RSA") },
+    };
+
+    construct {
+        this.use_header_bar = 1;
+        this.key_bits.set_range(0, int.MAX); /* updated later */
+        this.key_bits.set_increments(128, 128);
+        this.key_bits.set_value(2048);
+
+        // The mechanism
+        this.mechanism_store = new Gtk.ListStore(2, typeof(string), typeof(ulong));
+        this.mechanism_store.set_default_sort_func(on_mechanism_sort);
+        this.mechanism_store.set_sort_column_id(Gtk.TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, 
Gtk.SortType.ASCENDING);
+        this.mechanism_box.set_model(this.mechanism_store);
+        Gtk.CellRenderer renderer = new Gtk.CellRendererText();
+        this.mechanism_box.pack_start(renderer, true);
+        this.mechanism_box.add_attribute(renderer, "markup", Column.LABEL);
+        this.mechanism_box.changed.connect(on_mechanism_changed);
+
+        // The tokens
+        Gcr.Collection collection = Pkcs11.Backend.get_writable_tokens(null, 
Cryptoki.MechanismType.RSA_PKCS_KEY_PAIR_GEN);
+        this.token_model = gcr_collection_model_new(collection, Gcr.CollectionModelMode.LIST,
+                                                    "icon", typeof(Icon), "label", typeof(string),
+                                                    null);
+        this.token_model.set_sort_column_id(1, Gtk.SortType.ASCENDING);
+        this.token_box.set_model(this.token_model);
+        Gtk.CellRendererPixbuf icon_renderer = new Gtk.CellRendererPixbuf();
+        icon_renderer.stock_size = Gtk.IconSize.BUTTON;
+        this.token_box.pack_start(icon_renderer, false);
+        this.token_box.add_attribute(icon_renderer, "gicon", 0);
+        renderer = new Gtk.CellRendererText();
+        this.token_box.pack_start(renderer, true);
+        this.token_box.add_attribute(renderer, "text", 1);
+        this.token_box.changed.connect(on_token_changed);
+        if (collection.get_length() > 0)
+            this.token_box.active = 0;
+
+        set_default_response (Gtk.ResponseType.OK);
+
+        update_response ();
+    }
+
+    public Generate(Gtk.Window? parent) {
+        GLib.Object(transient_for: parent);
+    }
+
+    ~Generate() {
+        this.token = null;
+        this.token_model = null;
+
+        this.mechanism = null;
+        this.mechanism_store = null;
+
+        this.cancellable = null;
+        this.pub_attrs = this.prv_attrs = null;
+    }
+
+    private void update_response() {
+        set_response_sensitive(Gtk.ResponseType.OK, this.token != null && this.mechanism != null);
+    }
+
+    private unowned string? get_available_mechanism_label (ulong type) {
+        foreach (Mechanism mechanism in AVAILABLE_MECHANISMS) {
+            if (mechanism.mechanism_type == type)
+                return mechanism.label;
+        }
+
+        return null;
+    }
+
+    private void on_token_changed(Gtk.ComboBox combo_box) {
+        this.token = null;
+
+        Gtk.TreeIter iter;
+        if (combo_box.get_active_iter(out iter)) {
+            this.token = (Pkcs11.Token) this.token_model.object_for_iter(iter);
+        }
+
+        bool valid = this.mechanism_store.get_iter_first(out iter);
+        if (this.token != null) {
+            for (uint i = 0; i < this.token.mechanisms.length; i++) {
+                ulong type = this.token.mechanisms.index(i);
+                unowned string? label = get_available_mechanism_label (type);
+                if (label == null)
+                    continue;
+                while (valid) {
+                    ulong otype;
+                    this.mechanism_store.get(iter, Column.TYPE, out otype);
+                    if (otype == type)
+                        break;
+                    valid = this.mechanism_store.remove(ref iter);
+                }
+                if (!valid)
+                    this.mechanism_store.append(out iter);
+                this.mechanism_store.set(iter, Column.TYPE, type,
+                                               Column.LABEL, label);
+                valid = this.mechanism_store.iter_next(ref iter);
+            }
+        }
+        while (valid)
+            valid = this.mechanism_store.remove(ref iter);
+
+        /* Select first mechanism if none are selected */
+        if (!this.mechanism_box.get_active_iter(out iter))
+            if (this.mechanism_store.get_iter_first(out iter))
+                this.mechanism_box.set_active_iter(iter);
+
+        update_response ();
+    }
+
+    private void on_mechanism_changed(Gtk.ComboBox? widget) {
+        this.mechanism = null;
+
+        Gtk.TreeIter iter;
+        if (widget.get_active_iter(out iter)) {
+            this.mechanism = Gck.Mechanism();
+            this.mechanism_store.get(iter, Column.TYPE, out this.mechanism.type);
+
+            Gck.Slot slot = token.slot;
+            Gck.MechanismInfo info = slot.get_mechanism_info(this.mechanism.type);
+
+            ulong min = info.min_key_size;
+            ulong max = info.max_key_size;
+
+            if (min < 512 && max >= 512)
+                min = 512;
+            if (max > 16384 && min <= 16384)
+                max = 16384;
+            this.key_bits.set_range(min, max);
+        }
+
+        this.key_bits.sensitive = (this.mechanism != null);
+
+        update_response();
+    }
+
+    private int on_mechanism_sort (Gtk.TreeModel? model, Gtk.TreeIter a, Gtk.TreeIter b) {
+        string label_a, label_b;
+        model.get(a, Column.LABEL, out label_a);
+        model.get(b, Column.LABEL, out label_b);
+        return label_a.collate(label_b);
+    }
+
+    public override void response (int response_id) {
+        if (response_id == Gtk.ResponseType.OK)
+            generate.begin();
+
+        hide();
+    }
+
+    private async void generate() {
+        assert(this.token != null);
+
+        prepare_generate();
+
+        GLib.TlsInteraction interaction = new Seahorse.Interaction(this.transient_for);
+        Progress.show(this.cancellable, _("Generating key"), false);
+
+        try {
+            Gck.Session session = yield Gck.Session.open_async(this.token.slot,
+                       Gck.SessionOptions.READ_WRITE | Gck.SessionOptions.LOGIN_USER,
+                       interaction, this.cancellable);
+            Gck.Object pub, priv;
+            yield session.generate_key_pair_async(this.mechanism, this.pub_attrs, this.prv_attrs,
+                                                  this.cancellable, out pub, out priv);
+            yield this.token.load(this.cancellable);
+            this.cancellable = null;
+            this.pub_attrs = this.prv_attrs = null;
+        } catch (Error e) {
+            Util.show_error(null, _("Couldn’t generate private key"), e.message);
+        }
+    }
+
+    private void prepare_generate() {
+        const uchar[] rsa_public_exponent = { 0x01, 0x00, 0x01 }; /* 65537 in bytes */
+
+        Gck.Builder publi = new Gck.Builder(Gck.BuilderFlags.SECURE_MEMORY);
+        Gck.Builder priva = new Gck.Builder(Gck.BuilderFlags.SECURE_MEMORY);
+
+        assert (this.cancellable == null);
+        assert (this.mechanism != null);
+
+        publi.add_ulong(Cryptoki.Attribute.CLASS, Cryptoki.ObjectClass.PUBLIC_KEY);
+        priva.add_ulong(Cryptoki.Attribute.CLASS, Cryptoki.ObjectClass.PRIVATE_KEY);
+
+        publi.add_boolean(Cryptoki.Attribute.TOKEN, true);
+        priva.add_boolean(Cryptoki.Attribute.TOKEN, true);
+
+        priva.add_boolean(Cryptoki.Attribute.PRIVATE, true);
+        priva.add_boolean(Cryptoki.Attribute.SENSITIVE, true);
+
+        string label = this.label_entry.text;
+        publi.add_string(Cryptoki.Attribute.LABEL, label);
+        priva.add_string(Cryptoki.Attribute.LABEL, label);
+
+        if (this.mechanism.type == Cryptoki.MechanismType.RSA_PKCS_KEY_PAIR_GEN) {
+            publi.add_boolean(Cryptoki.Attribute.ENCRYPT, true);
+            publi.add_boolean(Cryptoki.Attribute.VERIFY, true);
+            publi.add_boolean(Cryptoki.Attribute.WRAP, true);
+
+            priva.add_boolean(Cryptoki.Attribute.DECRYPT, true);
+            priva.add_boolean(Cryptoki.Attribute.SIGN, true);
+            priva.add_boolean(Cryptoki.Attribute.UNWRAP, true);
+
+            publi.add_data(Cryptoki.Attribute.PUBLIC_EXPONENT, rsa_public_exponent);
+            publi.add_ulong(Cryptoki.Attribute.MODULUS_BITS, this.key_bits.get_value_as_int());
+        } else {
+            warning("currently no support for this mechanism");
+        }
+
+        this.prv_attrs = priva.steal();
+        this.pub_attrs = publi.steal();
+
+        publi.clear();
+        priva.clear();
+    }
+
+    private static void on_generate_activate(Gtk.Action action) {
+        Generate dialog = new Generate(null);
+        dialog.run();
+        dialog.destroy();
+    }
+
+    private const Gtk.ActionEntry ACTION_ENTRIES[] = {
+        { "pkcs11-generate-key", Gcr.ICON_KEY_PAIR, N_ ("Private key"), "",
+          N_("Used to request a certificate"), on_generate_activate }
+    };
+
+    public static void register () {
+        Gtk.ActionGroup actions = new Gtk.ActionGroup("pkcs11-generate");
+        actions.set_translation_domain(Config.GETTEXT_PACKAGE);
+        actions.add_actions(ACTION_ENTRIES, null);
+        Registry.register_object(actions, "generator");
+    }
+}
diff --git a/pkcs11/seahorse-pkcs11-backend.c b/pkcs11/seahorse-pkcs11-backend.c
index 52074130..fe907635 100644
--- a/pkcs11/seahorse-pkcs11-backend.c
+++ b/pkcs11/seahorse-pkcs11-backend.c
@@ -22,8 +22,6 @@
 
 #include "seahorse-pkcs11-backend.h"
 
-#include "seahorse-pkcs11-generate.h"
-
 #include "pkcs11/seahorse-pkcs11.h"
 
 #include "seahorse-common.h"
diff --git a/pkcs11/seahorse-pkcs11-backend.h b/pkcs11/seahorse-pkcs11-backend.h
index d6195ff6..ddcfd2fc 100644
--- a/pkcs11/seahorse-pkcs11-backend.h
+++ b/pkcs11/seahorse-pkcs11-backend.h
@@ -21,8 +21,6 @@
 #ifndef SEAHORSE_PKCS11_BACKEND_H_
 #define SEAHORSE_PKCS11_BACKEND_H_
 
-#include "pkcs11/seahorse-pkcs11.h"
-
 #include <gcr/gcr.h>
 
 #define SEAHORSE_PKCS11_STR                    "pkcs11"
diff --git a/pkcs11/seahorse-pkcs11-generate.ui b/pkcs11/seahorse-pkcs11-generate.ui
index 539c0c48..f240c722 100644
--- a/pkcs11/seahorse-pkcs11-generate.ui
+++ b/pkcs11/seahorse-pkcs11-generate.ui
@@ -1,153 +1,61 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <requires lib="gtk+" version="3.0"/>
-  <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">
+  <requires lib="gtk+" version="3.22"/>
+  <template class="SeahorsePkcs11Generate" parent="GtkDialog">
+    <property name="resizable">False</property>
+    <property name="title" translatable="yes">New private key</property>
+    <child internal-child="vbox">
+      <object class="GtkBox">
         <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>
+        <property name="orientation">vertical</property>
         <child>
-          <object class="GtkGrid" id="grid2">
+          <object class="GtkBox" id="pkcs11-generate">
             <property name="visible">True</property>
+            <property name="orientation">horizontal</property>
             <property name="can_focus">False</property>
-            <property name="row_spacing">6</property>
-            <property name="column_spacing">12</property>
+            <property name="border_width">7</property>
+            <property name="spacing">12</property>
             <child>
-              <object class="GtkLabel" id="label1">
+              <object class="GtkImage" id="key-image">
                 <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>
+                <property name="yalign">0</property>
+                <property name="pixel_size">48</property>
+                <property name="icon_name">gcr-key-pair</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">
+              <object class="GtkBox" id="vbox1">
                 <property name="visible">True</property>
+                <property name="orientation">vertical</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>
+                <property name="spacing">12</property>
                 <child>
-                  <object class="GtkGrid" id="grid1">
+                  <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="label49">
+                      <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">Key _Type:</property>
-                        <property name="use_underline">True</property>
+                        <property name="halign">end</property>
+                        <property name="label" translatable="yes">Label:</property>
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
@@ -157,12 +65,11 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkLabel" id="label50">
+                      <object class="GtkLabel" id="label2">
                         <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>
+                        <property name="label" translatable="yes">Stored at:</property>
+                        <property name="halign">end</property>
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
@@ -172,9 +79,12 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkComboBox" id="key-mechanism">
+                      <object class="GtkEntry" id="label_entry">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</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>
@@ -184,65 +94,108 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkSpinButton" id="key-bits">
+                      <object class="GtkComboBox" id="token_box">
                         <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>
+                        <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>
+                        <property name="left_attach">1</property>
                       </packing>
                     </child>
                     <child>
-                      <placeholder/>
+                      <object class="GtkLabel" id="label48">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">_Advanced key options</property>
+                        <property name="use_underline">True</property>
+                        <property name="halign">start</property>
+                        <attributes>
+                         <attribute name="weight" value="bold"/>
+                        </attributes>
+                      </object>
+                      <packing>
+                        <property name="top_attach">2</property>
+                        <property name="left_attach">0</property>
+                        <property name="width">2</property>
+                      </packing>
                     </child>
                     <child>
-                      <placeholder/>
+                      <object class="GtkLabel" id="label49">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">end</property>
+                        <property name="label" translatable="yes">Key _Type:</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="top_attach">3</property>
+                        <property name="left_attach">0</property>
+                      </packing>
                     </child>
                     <child>
-                      <placeholder/>
+                      <object class="GtkComboBox" id="mechanism_box">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                      </object>
+                      <packing>
+                        <property name="top_attach">3</property>
+                        <property name="left_attach">1</property>
+                      </packing>
                     </child>
                     <child>
-                      <placeholder/>
+                      <object class="GtkLabel" id="label50">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">end</property>
+                        <property name="label" translatable="yes">Key _Strength (bits):</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="top_attach">4</property>
+                        <property name="left_attach">0</property>
+                      </packing>
                     </child>
                     <child>
-                      <placeholder/>
+                      <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="top_attach">4</property>
+                        <property name="left_attach">1</property>
+                      </packing>
                     </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">_Advanced key options</property>
-                <property name="use_underline">True</property>
-                <attributes>
-                 <attribute name="weight" value="bold"/>
-                </attributes>
-              </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>
+
+    <child type="action">
+      <object class="GtkButton" id="button_cancel">
+        <property name="visible">True</property>
+        <property name="label" translatable="yes">Cancel</property>
+      </object>
+    </child>
+    <child type="action">
+      <object class="GtkButton" id="button_ok">
+        <property name="visible">True</property>
+        <property name="can-default">True</property>
+        <property name="label" translatable="yes">Create</property>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="cancel">button_cancel</action-widget>
+      <action-widget response="ok" default="true">button_ok</action-widget>
+    </action-widgets>
+  </template>
 </interface>
diff --git a/src/application.vala b/src/application.vala
index 57bafe36..b07c3c06 100644
--- a/src/application.vala
+++ b/src/application.vala
@@ -21,8 +21,6 @@
  * <http://www.gnu.org/licenses/>.
  */
 
-extern void seahorse_pkcs11_backend_initialize();
-
 public class Seahorse.Application : Gtk.Application {
     private SearchProvider? search_provider;
     private uint search_provider_dbus_id = 0;
@@ -50,7 +48,7 @@ public class Seahorse.Application : Gtk.Application {
         Pgp.Backend.initialize();
 #endif
 #if WITH_PKCS11
-        seahorse_pkcs11_backend_initialize();
+        Pkcs11.Backend.initialize();
 #endif
     }
 



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