gnome-keyring r1405 - in trunk: . pkcs11 pkcs11/dot-ssh pkcs11/dot-ssh/tests pkcs11/dot-ssh/tests/test-data pkcs11/gck pkcs11/gck/tests pkcs11/rpc tests
- From: nnielsen svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-keyring r1405 - in trunk: . pkcs11 pkcs11/dot-ssh pkcs11/dot-ssh/tests pkcs11/dot-ssh/tests/test-data pkcs11/gck pkcs11/gck/tests pkcs11/rpc tests
- Date: Mon, 22 Dec 2008 23:31:40 +0000 (UTC)
Author: nnielsen
Date: Mon Dec 22 23:31:40 2008
New Revision: 1405
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1405&view=rev
Log:
* pkcs11/gck/gck-crypto.c:
* pkcs11/gck/gck-crypto.h:
* pkcs11/gck/gck-data-der.c:
* pkcs11/gck/gck-data-openssl.c:
* pkcs11/gck/gck-data-openssl.h:
* pkcs11/gck/tests/unit-test-crypto.c:
* pkcs11/gck/tests/unit-test-data-openssl.c: Add support for specifying
length of password to various PBE algorithms.
* pkcs11/Makefile.am:
* pkcs11/dot-ssh/*: (added)
* pkcs11/dot-ssh/tests/*: (added)
* pkcs11/dot-ssh/tests/test-data/*: (added)
* pkcs11/gck/gck-data-types.h:
* pkcs11/gck/gck-module.h:
* pkcs11/gck/gck-private-key.c:
* pkcs11/gck/gck-util.c:
* pkcs11/gck/gck-util.h:
* tests/gtest.make:
* configure.in: Add incomplete but speced dot-ssh PKCS#11 component.
Added:
trunk/pkcs11/dot-ssh/ (props changed)
trunk/pkcs11/dot-ssh/Makefile.am
trunk/pkcs11/dot-ssh/gck-ssh-module.c
trunk/pkcs11/dot-ssh/gck-ssh-module.h
trunk/pkcs11/dot-ssh/gck-ssh-openssh.c
trunk/pkcs11/dot-ssh/gck-ssh-openssh.h
trunk/pkcs11/dot-ssh/gck-ssh-private-key.c
trunk/pkcs11/dot-ssh/gck-ssh-private-key.h
trunk/pkcs11/dot-ssh/gck-ssh-public-key.c
trunk/pkcs11/dot-ssh/gck-ssh-public-key.h
trunk/pkcs11/dot-ssh/tests/ (props changed)
trunk/pkcs11/dot-ssh/tests/Makefile.am
trunk/pkcs11/dot-ssh/tests/test-data/
trunk/pkcs11/dot-ssh/tests/test-data/id_dsa_encrypted
trunk/pkcs11/dot-ssh/tests/test-data/id_dsa_plain
trunk/pkcs11/dot-ssh/tests/test-data/id_dsa_test.pub
trunk/pkcs11/dot-ssh/tests/test-data/id_rsa_encrypted
trunk/pkcs11/dot-ssh/tests/test-data/id_rsa_plain
trunk/pkcs11/dot-ssh/tests/test-data/id_rsa_test.pub
trunk/pkcs11/dot-ssh/tests/unit-test-ssh-openssh.c
Modified:
trunk/ChangeLog
trunk/configure.in
trunk/pkcs11/Makefile.am
trunk/pkcs11/gck/gck-crypto.c
trunk/pkcs11/gck/gck-crypto.h
trunk/pkcs11/gck/gck-data-der.c
trunk/pkcs11/gck/gck-data-openssl.c
trunk/pkcs11/gck/gck-data-openssl.h
trunk/pkcs11/gck/gck-data-types.h
trunk/pkcs11/gck/gck-module.h
trunk/pkcs11/gck/gck-private-key.c
trunk/pkcs11/gck/gck-util.c
trunk/pkcs11/gck/gck-util.h
trunk/pkcs11/gck/tests/unit-test-crypto.c
trunk/pkcs11/gck/tests/unit-test-data-openssl.c
trunk/pkcs11/rpc/ (props changed)
trunk/tests/gtest.make
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Mon Dec 22 23:31:40 2008
@@ -513,6 +513,8 @@
pam/Makefile
pam/tests/Makefile
pkcs11/Makefile
+pkcs11/dot-ssh/Makefile
+pkcs11/dot-ssh/tests/Makefile
pkcs11/gck/Makefile
pkcs11/gck/tests/Makefile
pkcs11/rpc/Makefile
Modified: trunk/pkcs11/Makefile.am
==============================================================================
--- trunk/pkcs11/Makefile.am (original)
+++ trunk/pkcs11/Makefile.am Mon Dec 22 23:31:40 2008
@@ -41,5 +41,5 @@
TESTS_DIR =
endif
-SUBDIRS = . rpc gck $(TESTS_DIR)
+SUBDIRS = . rpc gck dot-ssh $(TESTS_DIR)
Added: trunk/pkcs11/dot-ssh/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/Makefile.am Mon Dec 22 23:31:40 2008
@@ -0,0 +1,35 @@
+
+INCLUDES = \
+ -I$(top_builddir) \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/pkcs11 \
+ $(GOBJECT_CFLAGS) \
+ $(LIBGCRYPT_CFLAGS) \
+ $(GLIB_CFLAGS)
+
+# ------------------------------------------------------------------------------
+# The openssh component code
+
+noinst_LTLIBRARIES = \
+ libgck-dot-ssh.la
+
+libgck_dot_ssh_la_SOURCES = \
+ gck-ssh-module.c gck-ssh-module.h \
+ gck-ssh-openssh.c gck-ssh-openssh.h \
+ gck-ssh-private-key.c gck-ssh-private-key.h \
+ gck-ssh-public-key.c gck-ssh-public-key.h
+
+libgck_dot_ssh_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(LIBGCRYPT_LIBS) \
+ $(top_builddir)/pkcs11/gck/libgck.la
+
+# -------------------------------------------------------------------------------
+
+if WITH_TESTS
+TESTS_DIR = tests
+else
+TESTS_DIR =
+endif
+
+SUBDIRS = . $(TESTS_DIR)
Added: trunk/pkcs11/dot-ssh/gck-ssh-module.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/gck-ssh-module.c Mon Dec 22 23:31:40 2008
@@ -0,0 +1,183 @@
+/*
+ * 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 "gck-ssh-module.h"
+#include "gck-ssh-private-key.h"
+#include "gck-ssh-public-key.h"
+
+#include "gck/gck-file-tracker.h"
+
+#include <string.h>
+
+struct _GckSshModule {
+ GObject parent;
+ GckFileTracker *tracker;
+ GHashTable *keys_by_path;
+};
+
+G_DEFINE_TYPE (GckSshModule, gck_ssh_module, GCK_TYPE_MODULE);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static gchar*
+private_path_for_public (const gchar *public_path)
+{
+ gsize length;
+
+ g_assert (public_path);
+
+ length = strlen (public_path);
+ if (length > 4 && g_str_equal (public_path + (length - 4), ".pub"))
+ return g_strndup (public_path, length - 4);
+
+ return NULL;
+}
+
+static void
+file_load (GckFileTracker *tracker, const gchar *path, GckSshModule *self)
+{
+ GckSshPrivateKey *key;
+ GckSshPublicKey *pubkey;
+ gchar *private_path;
+ GckManager *manager;
+ GError *error = NULL;
+
+ g_return_if_fail (path);
+ g_return_if_fail (GCK_IS_SSH_MODULE (self));
+
+ private_path = private_path_for_public (path);
+ if (!private_path || !g_file_test (private_path, G_FILE_TEST_IS_REGULAR)) {
+ g_message ("no private key present for public key: %s", path);
+ g_free (private_path);
+ return;
+ }
+
+ /* Create a key if necessary */
+ key = g_hash_table_lookup (self->keys_by_path, path);
+ if (key == NULL) {
+ key = gck_ssh_private_key_new ();
+ g_hash_table_replace (self->keys_by_path, g_strdup (path), key);
+ }
+
+ /* Parse the data into the key */
+ if (!gck_ssh_private_key_parse (key, path, private_path, &error)) {
+ g_message ("couldn't parse data: %s: %s", path,
+ error && error->message ? error->message : "");
+ g_clear_error (&error);
+
+ /* When successful register with the object manager */
+ } else {
+ manager = gck_module_get_manager (GCK_MODULE (self));
+
+ /* Make sure the private key has the right manager */
+ if (!gck_object_get_manager (GCK_OBJECT (key)))
+ gck_manager_register_object (manager, GCK_OBJECT (key));
+
+ pubkey = gck_ssh_private_key_get_public_key (key);
+ if (!gck_object_get_manager (GCK_OBJECT (pubkey)))
+ gck_manager_register_object (manager, GCK_OBJECT (pubkey));
+ }
+}
+
+static void
+file_remove (GckFileTracker *tracker, const gchar *path, GckSshModule *self)
+{
+ g_return_if_fail (path);
+ g_return_if_fail (GCK_IS_SSH_MODULE (self));
+ g_hash_table_remove (self->keys_by_path, path);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static CK_RV
+gck_ssh_module_real_refresh_token (GckModule *base)
+{
+ GckSshModule *self = GCK_SSH_MODULE (base);
+ gck_file_tracker_refresh (self->tracker, FALSE);
+ return CKR_OK;
+}
+
+static GObject*
+gck_ssh_module_constructor (GType type, guint n_props, GObjectConstructParam *props)
+{
+ GckSshModule *self = GCK_SSH_MODULE (G_OBJECT_CLASS (gck_ssh_module_parent_class)->constructor(type, n_props, props));
+ g_return_val_if_fail (self, NULL);
+
+
+
+ return G_OBJECT (self);
+}
+
+static void
+gck_ssh_module_init (GckSshModule *self)
+{
+ self->tracker = gck_file_tracker_new ("~/.ssh", "*.pub", NULL);
+ g_signal_connect (self->tracker, "file-added", G_CALLBACK (file_load), self);
+ g_signal_connect (self->tracker, "file-changed", G_CALLBACK (file_load), self);
+ g_signal_connect (self->tracker, "file-removed", G_CALLBACK (file_remove), self);
+}
+
+static void
+gck_ssh_module_dispose (GObject *obj)
+{
+ GckSshModule *self = GCK_SSH_MODULE (obj);
+
+ if (self->tracker)
+ g_object_unref (self->tracker);
+ self->tracker = NULL;
+
+ G_OBJECT_CLASS (gck_ssh_module_parent_class)->dispose (obj);
+}
+
+static void
+gck_ssh_module_finalize (GObject *obj)
+{
+ GckSshModule *self = GCK_SSH_MODULE (obj);
+
+ g_assert (self->tracker == NULL);
+
+ G_OBJECT_CLASS (gck_ssh_module_parent_class)->finalize (obj);
+}
+
+static void
+gck_ssh_module_class_init (GckSshModuleClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GckModuleClass *module_class = GCK_MODULE_CLASS (klass);
+
+ gobject_class->constructor = gck_ssh_module_constructor;
+ gobject_class->dispose = gck_ssh_module_dispose;
+ gobject_class->finalize = gck_ssh_module_finalize;
+
+ module_class->refresh_token = gck_ssh_module_real_refresh_token;
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
Added: trunk/pkcs11/dot-ssh/gck-ssh-module.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/gck-ssh-module.h Mon Dec 22 23:31:40 2008
@@ -0,0 +1,45 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2008 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General 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_SSH_MODULE_H__
+#define __GCK_SSH_MODULE_H__
+
+#include <glib-object.h>
+
+#include "gck/gck-module.h"
+
+#define GCK_TYPE_SSH_MODULE (gck_ssh_module_get_type ())
+#define GCK_SSH_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_SSH_MODULE, GckSshModule))
+#define GCK_SSH_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_SSH_MODULE, GckSshModuleClass))
+#define GCK_IS_SSH_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_SSH_MODULE))
+#define GCK_IS_SSH_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_SSH_MODULE))
+#define GCK_SSH_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_SSH_MODULE, GckSshModuleClass))
+
+typedef struct _GckSshModule GckSshModule;
+typedef struct _GckSshModuleClass GckSshModuleClass;
+
+struct _GckSshModuleClass {
+ GckModuleClass parent_class;
+};
+
+GType gck_ssh_module_get_type (void);
+
+#endif /* __GCK_SSH_MODULE_H__ */
Added: trunk/pkcs11/dot-ssh/gck-ssh-openssh.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/gck-ssh-openssh.c Mon Dec 22 23:31:40 2008
@@ -0,0 +1,360 @@
+
+#include "gck-ssh-openssh.h"
+
+#include "gck/gck-data-asn1.h"
+#include "gck/gck-data-der.h"
+#include "gck/gck-data-openssl.h"
+#include "gck/gck-data-pem.h"
+#include "gck/gck-data-types.h"
+
+#include "common/gkr-buffer.h"
+#include "common/gkr-secure-memory.h"
+
+typedef struct _ParsePrivate {
+ gcry_sexp_t sexp;
+ gboolean seen;
+ GckDataResult result;
+ const gchar *password;
+ gssize n_password;
+} ParsePrivate;
+
+/* ------------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static int
+keytype_to_algo (const gchar *salgo)
+{
+ g_return_val_if_fail (salgo, 0);
+ if (strcmp (salgo, "ssh-rsa") == 0)
+ return GCRY_PK_RSA;
+ else if (strcmp (salgo, "ssh-dss") == 0)
+ return GCRY_PK_DSA;
+ return 0;
+}
+
+static gboolean
+read_mpi (GkrBuffer *req, gsize *offset, gcry_mpi_t *mpi)
+{
+ const guchar *data;
+ gsize len;
+ gcry_error_t gcry;
+
+ if (!gkr_buffer_get_byte_array (req, *offset, offset, &data, &len))
+ return FALSE;
+
+ gcry = gcry_mpi_scan (mpi, GCRYMPI_FMT_USG, data, len, NULL);
+ if (gcry)
+ return FALSE;
+
+ return TRUE;
+}
+
+#define SEXP_PUBLIC_DSA \
+ "(public-key" \
+ " (dsa" \
+ " (p %m)" \
+ " (q %m)" \
+ " (g %m)" \
+ " (y %m)))"
+
+static gboolean
+read_public_dsa (GkrBuffer *req, gsize *offset, gcry_sexp_t *sexp)
+{
+ gcry_mpi_t p, q, g, y;
+ int gcry;
+
+ if (!read_mpi (req, offset, &p) ||
+ !read_mpi (req, offset, &q) ||
+ !read_mpi (req, offset, &g) ||
+ !read_mpi (req, offset, &y))
+ return FALSE;
+
+ gcry = gcry_sexp_build (sexp, NULL, SEXP_PUBLIC_DSA, p, q, g, y);
+ if (gcry) {
+ g_warning ("couldn't parse incoming public DSA key: %s", gcry_strerror (gcry));
+ return FALSE;
+ }
+
+ gcry_mpi_release (p);
+ gcry_mpi_release (q);
+ gcry_mpi_release (g);
+ gcry_mpi_release (y);
+
+ return TRUE;
+}
+
+#define SEXP_PUBLIC_RSA \
+ "(public-key" \
+ " (rsa" \
+ " (n %m)" \
+ " (e %m)))"
+
+static gboolean
+read_public_rsa (GkrBuffer *req, gsize *offset, gcry_sexp_t *sexp)
+{
+ gcry_mpi_t n, e;
+ int gcry;
+
+ if (!read_mpi (req, offset, &e) ||
+ !read_mpi (req, offset, &n))
+ return FALSE;
+
+ gcry = gcry_sexp_build (sexp, NULL, SEXP_PUBLIC_RSA, n, e);
+ if (gcry) {
+ g_warning ("couldn't parse incoming public RSA key: %s", gcry_strerror (gcry));
+ return FALSE;
+ }
+
+ gcry_mpi_release (n);
+ gcry_mpi_release (e);
+
+ return TRUE;
+}
+
+static gboolean
+read_public (GkrBuffer *req, gsize *offset, gcry_sexp_t *key, int *algo)
+{
+ gboolean ret;
+ gchar *stype;
+ int alg;
+
+ /* The string algorithm */
+ if (!gkr_buffer_get_string (req, *offset, offset, &stype, (GkrBufferAllocator)g_realloc))
+ return FALSE;
+
+ alg = keytype_to_algo (stype);
+ g_free (stype);
+
+ if (!alg) {
+ g_warning ("unsupported algorithm from SSH: %s", stype);
+ return FALSE;
+ }
+
+ switch (alg) {
+ case GCRY_PK_RSA:
+ ret = read_public_rsa (req, offset, key);
+ break;
+ case GCRY_PK_DSA:
+ ret = read_public_dsa (req, offset, key);
+ break;
+ default:
+ g_assert_not_reached ();
+ return FALSE;
+ }
+
+ if (!ret) {
+ g_warning ("couldn't read incoming SSH private key");
+ return FALSE;
+ }
+
+ if (algo)
+ *algo = alg;
+ return TRUE;
+}
+
+static GckDataResult
+load_encrypted_key (const guchar *data, gsize n_data, const gchar *dekinfo,
+ const gchar *password, gssize n_password, gcry_sexp_t *skey)
+{
+ guchar *decrypted = NULL;
+ gsize n_decrypted = 0;
+ GckDataResult ret;
+ gboolean res;
+ gint length;
+
+ /* Decrypt, this will result in garble if invalid password */
+ res = gck_data_openssl_decrypt_block (dekinfo, password, n_password,
+ data, n_data, &decrypted, &n_decrypted);
+ if (!res)
+ return FALSE;
+
+ g_assert (decrypted);
+
+ /* Unpad the DER data */
+ length = gck_data_asn1_element_length (decrypted, n_decrypted);
+ if (length > 0)
+ n_decrypted = length;
+
+ /* Try to parse */
+ ret = gck_data_der_read_private_key (decrypted, n_decrypted, skey);
+ gkr_secure_free (decrypted);
+
+ if (ret != GCK_DATA_UNRECOGNIZED)
+ return ret;
+
+ return GCK_DATA_LOCKED;
+}
+
+static void
+parsed_pem_block (GQuark type, const guchar *data, gsize n_data,
+ GHashTable *headers, gpointer user_data)
+{
+ static GQuark PEM_RSA_PRIVATE_KEY;
+ static GQuark PEM_DSA_PRIVATE_KEY;
+ static gsize quarks_inited = 0;
+
+ ParsePrivate *ctx = (ParsePrivate*)user_data;
+ const gchar *dekinfo;
+
+ /* Initialize the first time through */
+ if (g_once_init_enter (&quarks_inited)) {
+ PEM_RSA_PRIVATE_KEY = g_quark_from_static_string ("RSA PRIVATE KEY");
+ PEM_DSA_PRIVATE_KEY = g_quark_from_static_string ("DSA PRIVATE KEY");
+ g_once_init_leave (&quarks_inited, 1);
+ }
+
+ /* Only handle SSHv2 private keys */
+ if (type != PEM_RSA_PRIVATE_KEY && type != PEM_DSA_PRIVATE_KEY)
+ return;
+
+ ctx->seen = TRUE;
+
+ /* Only parse first key in the file */
+ if (ctx->sexp)
+ return;
+
+ /* If it's encrypted ... */
+ dekinfo = gck_data_openssl_get_dekinfo (headers);
+ if (dekinfo) {
+ ctx->result = load_encrypted_key (data, n_data, dekinfo, ctx->password,
+ ctx->n_password, &ctx->sexp);
+
+ /* not encryted, just load the data */
+ } else {
+ ctx->result = gck_data_der_read_private_key (data, n_data, &ctx->sexp);
+ }
+}
+
+/* ------------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+GckDataResult
+gck_ssh_openssh_parse_public_key (const guchar *data, gsize n_data,
+ gcry_sexp_t *sexp, gchar **comment)
+{
+ GkrBuffer buf;
+ const guchar *at;
+ guchar *decoded;
+ gsize n_decoded;
+ gsize offset;
+ gchar *val;
+ gboolean ret;
+ gint state, algo;
+ guint save;
+
+ g_return_val_if_fail (data, FALSE);
+ g_return_val_if_fail (sexp, FALSE);
+
+ /* Look for a key line */
+ for (;;) {
+ /* Eat space at the front */
+ while (n_data > 0 && g_ascii_isspace (data[0])) {
+ ++data;
+ --n_data;
+ }
+
+ /* Not a comment or blank line? Then parse... */
+ if (data[0] != '#')
+ break;
+
+ /* Skip to the next line */
+ at = memchr (data, '\n', n_data);
+ if (!at)
+ return GCK_DATA_UNRECOGNIZED;
+ at += 1;
+ n_data -= (at - data);
+ data = at;
+ }
+
+ /* Limit to use only the first line */
+ at = memchr (data, '\n', n_data);
+ if (at != NULL)
+ n_data = at - data;
+
+ /* Find the first space */
+ at = memchr (data, ' ', n_data);
+ if (!at) {
+ g_message ("SSH public key missing space");
+ return GCK_DATA_UNRECOGNIZED;
+ }
+
+ /* Parse the key type */
+ val = g_strndup ((gchar*)data, at - data);
+ algo = keytype_to_algo (val);
+ if (!algo)
+ g_message ("Unsupported or unknown SSH key algorithm: %s", val);
+ g_free (val);
+ if (!algo)
+ return GCK_DATA_UNRECOGNIZED;
+
+ /* Skip more whitespace */
+ n_data -= (at - data);
+ data = at;
+ while (n_data > 0 && (data[0] == ' ' || data[0] == '\t')) {
+ ++data;
+ --n_data;
+ }
+
+ /* Find the next whitespace, or the end */
+ at = memchr (data, ' ', n_data);
+ if (at == NULL)
+ at = data + n_data;
+
+ /* Decode the base64 key */
+ save = state = 0;
+ decoded = g_malloc (n_data * 3 / 4);
+ n_decoded = g_base64_decode_step ((gchar*)data, n_data, decoded, &state, &save);
+
+ /* Parse the actual key */
+ gkr_buffer_init_static (&buf, decoded, n_decoded);
+ offset = 0;
+ ret = read_public (&buf, &offset, sexp, NULL);
+ g_free (decoded);
+ if (!ret) {
+ g_message ("failed to parse base64 part of SSH key");
+ return GCK_DATA_FAILURE;
+ }
+
+ /* Skip more whitespace */
+ n_data -= (at - data);
+ data = at;
+ while (n_data > 0 && (data[0] == ' ' || data[0] == '\t')) {
+ ++data;
+ --n_data;
+ }
+
+ /* If there's data left, its the comment */
+ if (comment)
+ *comment = n_data ? g_strndup ((gchar*)data, n_data) : NULL;
+
+ return GCK_DATA_SUCCESS;
+}
+
+GckDataResult
+gck_ssh_openssh_parse_private_key (const guchar *data, gsize n_data,
+ const gchar *password, gssize n_password,
+ gcry_sexp_t *sexp)
+{
+ ParsePrivate ctx;
+ guint num;
+
+ memset (&ctx, 0, sizeof (ctx));
+ ctx.result = FALSE;
+ ctx.seen = FALSE;
+ ctx.sexp = NULL;
+ ctx.password = password;
+ ctx.n_password = n_password;
+
+ num = gck_data_pem_parse (data, n_data, parsed_pem_block, &ctx);
+
+ /* Didn't find any private key there */
+ if (num == 0 || !ctx.seen) {
+ g_message ("no private keys found in file");
+ return GCK_DATA_UNRECOGNIZED;
+ }
+
+ *sexp = ctx.sexp;
+ return ctx.result;
+}
Added: trunk/pkcs11/dot-ssh/gck-ssh-openssh.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/gck-ssh-openssh.h Mon Dec 22 23:31:40 2008
@@ -0,0 +1,21 @@
+#ifndef GCKSSHOPENSSH_H_
+#define GCKSSHOPENSSH_H_
+
+#include <glib.h>
+
+#include <gcrypt.h>
+
+#include "gck/gck-data-types.h"
+
+GckDataResult gck_ssh_openssh_parse_public_key (const guchar *data,
+ gsize n_data,
+ gcry_sexp_t *sexp,
+ gchar **comment);
+
+GckDataResult gck_ssh_openssh_parse_private_key (const guchar *data,
+ gsize n_data,
+ const gchar *password,
+ gssize n_password,
+ gcry_sexp_t *sexp);
+
+#endif /* GCKSSHOPENSSH_H_ */
Added: trunk/pkcs11/dot-ssh/gck-ssh-private-key.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/gck-ssh-private-key.c Mon Dec 22 23:31:40 2008
@@ -0,0 +1,318 @@
+/*
+ * 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 "gck-ssh-openssh.h"
+#include "gck-ssh-private-key.h"
+
+#include "gck/gck-manager.h"
+#include "gck/gck-object.h"
+#include "gck/gck-sexp.h"
+#include "gck/gck-util.h"
+
+#include <glib/gi18n.h>
+
+enum {
+ PROP_0,
+ PROP_LABEL,
+ PROP_PUBLIC_KEY
+};
+
+struct _GckSshPrivateKey {
+ GckPrivateKey parent;
+
+ GckSshPublicKey *pubkey;
+ gchar *label;
+ guchar *private_data;
+ gsize n_private_data;
+
+ GckSexp *private_sexp;
+ gboolean is_encrypted;
+};
+
+G_DEFINE_TYPE (GckSshPrivateKey, gck_ssh_private_key, GCK_TYPE_PRIVATE_KEY);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static CK_RV
+unlock_private_key (GckSshPrivateKey *self, const gchar *password, gssize n_password)
+{
+ GckDataResult res;
+ gcry_sexp_t sexp;
+ GckSexp *wrapper;
+
+ g_assert (GCK_IS_SSH_PRIVATE_KEY (self));
+
+ res = gck_ssh_openssh_parse_private_key (self->private_data,
+ self->n_private_data,
+ password, -1, &sexp);
+
+ switch (res) {
+ case GCK_DATA_LOCKED:
+ self->is_encrypted = TRUE;
+ return CKR_PIN_INCORRECT;
+ case GCK_DATA_FAILURE:
+ g_message ("couldn't parse private SSH key: %s", self->label);
+ return CKR_GENERAL_ERROR;
+ case GCK_DATA_UNRECOGNIZED:
+ g_message ("invalid or unrecognized private SSH key: %s", self->label);
+ return CKR_FUNCTION_FAILED;
+ case GCK_DATA_SUCCESS:
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if (!password || !password[0])
+ self->is_encrypted = FALSE;
+
+ wrapper = gck_sexp_new (sexp);
+ gck_private_key_store_private (GCK_PRIVATE_KEY (self), wrapper, self->is_encrypted ? 1 : 0);
+ gck_sexp_unref (wrapper);
+
+ return CKR_OK;
+}
+
+static void
+realize_and_take_data (GckSshPrivateKey *self, gcry_sexp_t sexp, gchar *comment,
+ guchar *private_data, gsize n_private_data)
+{
+ GckSexp *wrapper;
+
+ g_assert (GCK_IS_SSH_PRIVATE_KEY (self));
+
+ /* The base public key gets setup. */
+ wrapper = gck_sexp_new (sexp);
+ gck_key_set_base_sexp (GCK_KEY (self), wrapper);
+ gck_key_set_base_sexp (GCK_KEY (self->pubkey), wrapper);
+ gck_sexp_unref (wrapper);
+
+ /* Own the comment */
+ gck_ssh_public_key_set_label (self->pubkey, comment);
+ gck_ssh_private_key_set_label (self, comment);
+ g_free (comment);
+
+ /* Own the data */
+ g_free (self->private_data);
+ self->private_data = private_data;
+ self->n_private_data = n_private_data;
+
+ /* Try to parse the private data, and note if it's not actually encrypted */
+ self->is_encrypted = TRUE;
+ if (unlock_private_key (self, "", 0) == CKR_OK)
+ self->is_encrypted = FALSE;
+
+ /* Force parsing next time required */
+ gck_private_key_store_private (GCK_PRIVATE_KEY (self), NULL, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static CK_RV
+gck_ssh_private_key_get_attribute (GckObject *base, CK_ATTRIBUTE_PTR attr)
+{
+ GckSshPrivateKey *self = GCK_SSH_PRIVATE_KEY (base);
+
+ switch (attr->type) {
+ case CKA_LABEL:
+ return gck_util_set_string (attr, self->label ? self->label : "");
+ }
+
+ return GCK_OBJECT_GET_CLASS (base)->get_attribute (base, attr);
+}
+
+static CK_RV
+gck_ssh_private_key_unlock (GckObject *base, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
+{
+ GckSshPrivateKey *self = GCK_SSH_PRIVATE_KEY (base);
+ return unlock_private_key (self, (const gchar*)pin, n_pin);
+}
+
+static void
+gck_ssh_private_key_init (GckSshPrivateKey *self)
+{
+ self->pubkey = gck_ssh_public_key_new ();
+}
+
+static void
+gck_ssh_private_key_dispose (GObject *obj)
+{
+ GckSshPrivateKey *self = GCK_SSH_PRIVATE_KEY (obj);
+
+ if (self->pubkey)
+ g_object_unref (self->pubkey);
+ self->pubkey = NULL;
+
+ G_OBJECT_CLASS (gck_ssh_private_key_parent_class)->dispose (obj);
+}
+
+static void
+gck_ssh_private_key_finalize (GObject *obj)
+{
+ GckSshPrivateKey *self = GCK_SSH_PRIVATE_KEY (obj);
+
+ g_assert (self->pubkey == NULL);
+
+ g_free (self->private_data);
+ self->private_data = NULL;
+
+ g_free (self->label);
+ self->label = NULL;
+
+ G_OBJECT_CLASS (gck_ssh_private_key_parent_class)->finalize (obj);
+}
+
+static void
+gck_ssh_private_key_set_property (GObject *obj, guint prop_id, const GValue *value,
+ GParamSpec *pspec)
+{
+ GckSshPrivateKey *self = GCK_SSH_PRIVATE_KEY (obj);
+
+ switch (prop_id) {
+ case PROP_LABEL:
+ gck_ssh_private_key_set_label (self, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gck_ssh_private_key_get_property (GObject *obj, guint prop_id, GValue *value,
+ GParamSpec *pspec)
+{
+ GckSshPrivateKey *self = GCK_SSH_PRIVATE_KEY (obj);
+
+ switch (prop_id) {
+ case PROP_LABEL:
+ g_value_set_string (value, gck_ssh_private_key_get_label (self));
+ break;
+ case PROP_PUBLIC_KEY:
+ g_value_set_object (value, gck_ssh_private_key_get_public_key (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gck_ssh_private_key_class_init (GckSshPrivateKeyClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = gck_ssh_private_key_dispose;
+ gobject_class->finalize = gck_ssh_private_key_finalize;
+ gobject_class->set_property = gck_ssh_private_key_set_property;
+ gobject_class->get_property = gck_ssh_private_key_get_property;
+
+ gck_class->get_attribute = gck_ssh_private_key_get_attribute;
+ gck_class->unlock = gck_ssh_private_key_unlock;
+
+ g_object_class_install_property (gobject_class, PROP_LABEL,
+ g_param_spec_string ("label", "Label", "Object Label",
+ "", G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_PUBLIC_KEY,
+ g_param_spec_object ("public-key", "Public Key", "Public key belonging to this private key",
+ GCK_TYPE_SSH_PUBLIC_KEY, G_PARAM_READABLE));
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+GckSshPrivateKey*
+gck_ssh_private_key_new (void)
+{
+ return g_object_new (GCK_TYPE_SSH_PRIVATE_KEY, NULL);
+}
+
+gboolean
+gck_ssh_private_key_parse (GckSshPrivateKey *self, const gchar *public_path,
+ const gchar *private_path, GError **error)
+{
+ guchar *public_data, *private_data;
+ gsize n_public_data, n_private_data;
+ GckDataResult res;
+ gcry_sexp_t sexp;
+ gchar *comment;
+
+ g_return_val_if_fail (GCK_IS_SSH_PRIVATE_KEY (self), FALSE);
+ g_return_val_if_fail (private_path, FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ /* Read in the public key */
+ if (!g_file_get_contents (public_path, (gchar**)&public_data, &n_public_data, error))
+ return FALSE;
+
+ /* Parse it */
+ res = gck_ssh_openssh_parse_public_key (public_data, n_public_data, &sexp, &comment);
+ g_free (public_data);
+
+ if (res != GCK_DATA_SUCCESS) {
+ g_set_error_literal (error, GCK_DATA_ERROR, res, _("Couldn't parse public SSH key"));
+ return FALSE;
+ }
+
+ /* Read in the private key */
+ if (!g_file_get_contents (private_path, (gchar**)&private_data, &n_private_data, error)) {
+ g_free (comment);
+ gcry_sexp_release (sexp);
+ return FALSE;
+ }
+
+ if (comment == NULL)
+ comment = g_path_get_basename (private_path);
+
+ realize_and_take_data (self, sexp, comment, private_data, n_private_data);
+ return TRUE;
+}
+
+const gchar*
+gck_ssh_private_key_get_label (GckSshPrivateKey *self)
+{
+ g_return_val_if_fail (GCK_IS_SSH_PRIVATE_KEY (self), NULL);
+ return self->label;
+}
+
+void
+gck_ssh_private_key_set_label (GckSshPrivateKey *self, const gchar *label)
+{
+ g_return_if_fail (GCK_IS_SSH_PRIVATE_KEY (self));
+ g_free (self->label);
+ self->label = g_strdup (label);
+ g_object_notify (G_OBJECT (self), "label");
+}
+
+GckSshPublicKey*
+gck_ssh_private_key_get_public_key (GckSshPrivateKey *self)
+{
+ g_return_val_if_fail (GCK_IS_SSH_PRIVATE_KEY (self), NULL);
+ return self->pubkey;
+}
Added: trunk/pkcs11/dot-ssh/gck-ssh-private-key.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/gck-ssh-private-key.h Mon Dec 22 23:31:40 2008
@@ -0,0 +1,61 @@
+/*
+ * 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_SSH_PRIVATE_KEY_H__
+#define __GCK_SSH_PRIVATE_KEY_H__
+
+#include <glib-object.h>
+
+#include "gck-ssh-public-key.h"
+
+#include "gck/gck-private-key.h"
+
+#define GCK_TYPE_SSH_PRIVATE_KEY (gck_ssh_private_key_get_type ())
+#define GCK_SSH_PRIVATE_KEY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_SSH_PRIVATE_KEY, GckSshPrivateKey))
+#define GCK_SSH_PRIVATE_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_SSH_PRIVATE_KEY, GckSshPrivateKeyClass))
+#define GCK_IS_SSH_PRIVATE_KEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_SSH_PRIVATE_KEY))
+#define GCK_IS_SSH_PRIVATE_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_SSH_PRIVATE_KEY))
+#define GCK_SSH_PRIVATE_KEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_SSH_PRIVATE_KEY, GckSshPrivateKeyClass))
+
+typedef struct _GckSshPrivateKey GckSshPrivateKey;
+typedef struct _GckSshPrivateKeyClass GckSshPrivateKeyClass;
+
+struct _GckSshPrivateKeyClass {
+ GckPrivateKeyClass parent_class;
+};
+
+GType gck_ssh_private_key_get_type (void);
+
+GckSshPrivateKey* gck_ssh_private_key_new (void);
+
+gboolean gck_ssh_private_key_parse (GckSshPrivateKey *self,
+ const gchar *public_path,
+ const gchar *private_path,
+ GError **error);
+
+const gchar* gck_ssh_private_key_get_label (GckSshPrivateKey *key);
+
+void gck_ssh_private_key_set_label (GckSshPrivateKey *key,
+ const gchar *label);
+
+GckSshPublicKey* gck_ssh_private_key_get_public_key (GckSshPrivateKey *self);
+
+#endif /* __GCK_SSH_PRIVATE_KEY_H__ */
Added: trunk/pkcs11/dot-ssh/gck-ssh-public-key.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/gck-ssh-public-key.c Mon Dec 22 23:31:40 2008
@@ -0,0 +1,150 @@
+/*
+ * 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 "gck-ssh-public-key.h"
+
+#include "gck/gck-object.h"
+#include "gck/gck-util.h"
+
+#include <glib/gi18n.h>
+
+enum {
+ PROP_0,
+ PROP_LABEL
+};
+
+struct _GckSshPublicKey {
+ GckPublicKey parent;
+ gchar *label;
+};
+
+G_DEFINE_TYPE (GckSshPublicKey, gck_ssh_public_key, GCK_TYPE_PUBLIC_KEY);
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static CK_RV
+gck_ssh_public_key_get_attribute (GckObject *base, CK_ATTRIBUTE_PTR attr)
+{
+ GckSshPublicKey *self = GCK_SSH_PUBLIC_KEY (base);
+
+ switch (attr->type) {
+ case CKA_LABEL:
+ return gck_util_set_string (attr, self->label ? self->label : "");
+ }
+
+ return GCK_OBJECT_GET_CLASS (base)->get_attribute (base, attr);
+}
+
+static void
+gck_ssh_public_key_init (GckSshPublicKey *self)
+{
+
+}
+
+static void
+gck_ssh_public_key_finalize (GObject *obj)
+{
+ GckSshPublicKey *self = GCK_SSH_PUBLIC_KEY (obj);
+
+ g_free (self->label);
+ self->label = NULL;
+
+ G_OBJECT_CLASS (gck_ssh_public_key_parent_class)->finalize (obj);
+}
+
+static void
+gck_ssh_public_key_set_property (GObject *obj, guint prop_id, const GValue *value,
+ GParamSpec *pspec)
+{
+ GckSshPublicKey *self = GCK_SSH_PUBLIC_KEY (obj);
+
+ switch (prop_id) {
+ case PROP_LABEL:
+ gck_ssh_public_key_set_label (self, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gck_ssh_public_key_get_property (GObject *obj, guint prop_id, GValue *value,
+ GParamSpec *pspec)
+{
+ GckSshPublicKey *self = GCK_SSH_PUBLIC_KEY (obj);
+
+ switch (prop_id) {
+ case PROP_LABEL:
+ g_value_set_string (value, gck_ssh_public_key_get_label (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gck_ssh_public_key_class_init (GckSshPublicKeyClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = gck_ssh_public_key_finalize;
+ gobject_class->set_property = gck_ssh_public_key_set_property;
+ gobject_class->get_property = gck_ssh_public_key_get_property;
+
+ gck_class->get_attribute = gck_ssh_public_key_get_attribute;
+
+ g_object_class_install_property (gobject_class, PROP_LABEL,
+ g_param_spec_string ("label", "Label", "Object Label",
+ "", G_PARAM_READWRITE));
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+GckSshPublicKey*
+gck_ssh_public_key_new (void)
+{
+ return g_object_new (GCK_TYPE_SSH_PUBLIC_KEY, NULL);
+}
+
+const gchar*
+gck_ssh_public_key_get_label (GckSshPublicKey *self)
+{
+ g_return_val_if_fail (GCK_IS_SSH_PUBLIC_KEY (self), NULL);
+ return self->label;
+}
+
+void
+gck_ssh_public_key_set_label (GckSshPublicKey *self, const gchar *label)
+{
+ g_return_if_fail (GCK_IS_SSH_PUBLIC_KEY (self));
+ g_free (self->label);
+ self->label = g_strdup (label);
+ g_object_notify (G_OBJECT (self), "label");
+}
Added: trunk/pkcs11/dot-ssh/gck-ssh-public-key.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/gck-ssh-public-key.h Mon Dec 22 23:31:40 2008
@@ -0,0 +1,52 @@
+/*
+ * 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_SSH_PUBLIC_KEY_H__
+#define __GCK_SSH_PUBLIC_KEY_H__
+
+#include <glib-object.h>
+
+#include "gck/gck-public-key.h"
+
+#define GCK_TYPE_SSH_PUBLIC_KEY (gck_ssh_public_key_get_type ())
+#define GCK_SSH_PUBLIC_KEY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_SSH_PUBLIC_KEY, GckSshPublicKey))
+#define GCK_SSH_PUBLIC_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_SSH_PUBLIC_KEY, GckSshPublicKeyClass))
+#define GCK_IS_SSH_PUBLIC_KEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_SSH_PUBLIC_KEY))
+#define GCK_IS_SSH_PUBLIC_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_SSH_PUBLIC_KEY))
+#define GCK_SSH_PUBLIC_KEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_SSH_PUBLIC_KEY, GckSshPublicKeyClass))
+
+typedef struct _GckSshPublicKey GckSshPublicKey;
+typedef struct _GckSshPublicKeyClass GckSshPublicKeyClass;
+
+struct _GckSshPublicKeyClass {
+ GckPublicKeyClass parent_class;
+};
+
+GType gck_ssh_public_key_get_type (void);
+
+GckSshPublicKey* gck_ssh_public_key_new (void);
+
+const gchar* gck_ssh_public_key_get_label (GckSshPublicKey *key);
+
+void gck_ssh_public_key_set_label (GckSshPublicKey *key,
+ const gchar *label);
+
+#endif /* __GCK_SSH_PUBLIC_KEY_H__ */
Added: trunk/pkcs11/dot-ssh/tests/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/tests/Makefile.am Mon Dec 22 23:31:40 2008
@@ -0,0 +1,11 @@
+UNIT_AUTO = \
+ unit-test-ssh-openssh.c
+
+UNIT_PROMPT =
+
+UNIT_LIBS = \
+ $(top_builddir)/pkcs11/dot-ssh/libgck-dot-ssh.la \
+ $(top_builddir)/pkcs11/gck/libgck.la \
+ $(top_builddir)/common/libgkr-module-common.la
+
+include $(top_srcdir)/tests/gtest.make
Added: trunk/pkcs11/dot-ssh/tests/test-data/id_dsa_encrypted
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/tests/test-data/id_dsa_encrypted Mon Dec 22 23:31:40 2008
@@ -0,0 +1,15 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1ED7C6189634877B
+
+lex6pFMAspyvnqSktXA1NX/x80/Ebb9BGFaIcJAPvLduCrDR02fgwc3oE+dwSwwe
+PXZ8vJK8+AP+Z8Rkedya/3OT4vaAuSENZFCfJA+P6lXglVQplA57R4U5/P9580Ee
+l/VTumnh5Gz84hJ5TuEspDOLrq8atkc31qFbEJ+zjMLygGNGbIOzecLou2pBt1Ol
+ncx1MPIznoJl2b1NQt7rgPpcbqzCHo+/qgLgvGs7osIg8xzzp+E2ifWuwCnY4NmW
+dxLRABi4I97q7kShH7OblBQLKxDreg28sojJQ0h0y0fd6xVcoscFCvfanFh8xx/D
+rI+JV3HCRCrlB9YS6U3zB5vpbc1UQ1EaE4AxSmrSLdKsvrPGc7M+grwy/DjYerqO
+WGwFWnz/OrlXruJG9Nwyltq/YmXAxFGoSWrunkm42xUxYs8RElddQOFC0ZyfVWOi
+IOS2Bv2HkNW+lMTRoR/RIbDc90wzO0HL0Xx4v6LYSbVBZIcaOJU+stoNLeE8Fu53
+G47YU+Fd7WswdlIdXtrPjyyiWapf6+xNdhRrqB+40JJQRi2mL1NyYZ2bZkjEd0Or
+DsfFH/+DlZrjEdlqWTK2ow==
+-----END DSA PRIVATE KEY-----
Added: trunk/pkcs11/dot-ssh/tests/test-data/id_dsa_plain
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/tests/test-data/id_dsa_plain Mon Dec 22 23:31:40 2008
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQDCyZij6148cb6Gp2XazVJr+zrcfSkbN1MyeR5hCgACTqcn1D4R
+huf79uWe7lvyYuPyXNedfde0iFP7Ff9k1T9i3thyYjs1scdwpbqxnAVnmN4SNv/v
+fFXPp6w0EDNqmAOwg+Pqwue7juiPVJyPBcsSPZZKTOMDCS/2fVibFCXgswIVAOW6
+ngNCg6d4Cn+GHQtEbNVtZpRdAoGAP2LhEH+zUCYri0xi32l9bMnlqDCBdw2zOMbe
+G2XDRt40W4ObiE1+PPNp/CDFuYrOjD4s7Cl4s/U+iop4DKsPcLwbdr3CoWE6hEuO
+dH0jkzcvt8kZ5Ymtm3OiqEW2ARi8rUwVJ9+bRbkfRerNrDeH/PQzwCWf7Lzp9lPT
+NVjCDtsCgYANW+HtuJWVmfXRRDJ1goMK+GXixDvBLBbFSDf74kYInt3vUBm4MKpr
+HbmC27TLRymb6IOH1ENpYT3MffZJusQTqqZJKPba5nwLvPP9lzN60bJAtqiWUsqf
+wHEh6Jx+qoMggm8i6ogJJO2zDlki5Twf1ilN+tinHdOL/2CmPPRMgAIVALKfUS61
+xqFTOY5fG1+rLwlPGvL9
+-----END DSA PRIVATE KEY-----
Added: trunk/pkcs11/dot-ssh/tests/test-data/id_dsa_test.pub
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/tests/test-data/id_dsa_test.pub Mon Dec 22 23:31:40 2008
@@ -0,0 +1,7 @@
+# A comment should be ignored
+
+# Blank lines should be ignored
+
+ssh-dss AAAAB3NzaC1kc3MAAACBANHNmw2YHEodUj4Ae27i8Rm8uoLnpS68QEiCJx8bv9P1o0AaD0w55sH+TBzlo7vtAEDlAzIOBY3PMpy5WarELTIeXmFPzKfHL8tuxMbOPaN/wDkDZNnJZsqlyRwlQKStPcAlvLBNuMjA53u2ndMTVghtUHXETQzwxKhXf7TmvfLBAAAAFQDnF/Y8MgFCP0PpRC5ZAQo1dyDEwwAAAIEAr4iOpTeZx8i1QgQpRl+dmbBAtHTXbPiophzNJBge9lixqF0T3egN2B9wGGnumIXmnst9RPPjuu+cHCLfxhXHzLlW8MLwoiF6ZQOx9M8WcfWIl5oiGyr2e969woRf5OcMGQPOQBdws6MEtemRqq5gu6dqDqVl3xfhSZSP9LpqAI8AAACAUjiuQ3qGErsCz++qd0qrR++QA185XGXAPZqQEHcr4iKSlO17hSUYA03kOWtDaeRtJOlxjIjl9iLo3juKGFgxUfo2StScOSO2saTWFGjA4MybHCK1+mIYXRcYrq314yK2Tmbql/UGDWpcCCGXLWpSFHTaXTbJjPd6VL+TO9/8tFk= A public key comment
+
+# blah blah
Added: trunk/pkcs11/dot-ssh/tests/test-data/id_rsa_encrypted
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/tests/test-data/id_rsa_encrypted Mon Dec 22 23:31:40 2008
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C7CA72E4022D0E83
+
+me0oewaJEzC9jiS1EaEN1dgXwc6QpVa9YeZLOmuhWbKhJI7B4eB7ZzdCRZv07wKv
+kCSkM+/rk6Env7QjkRhREF2Uc1jGwZAh5SttP/eGlWe4tcJ0o246rNgtPmyrlmh4
+7jESkZICnv7kv9nam4W0GU/4UHTGZsx4z6l0XUnbI5mDwUC4QL7mF9Bu3tZ3+hlY
+V4Pr7OklILzopGuoaYaJABhbu/EtU3R8+g9gXJZFkLJUo41Q53BjBlZb1XEKSBE/
+3TL+sDVklBOZlqgIiBnN7buGeC/0VFzmworpMvti1SIBtfKCuYGYcrqoeUmP8+CK
+lAOpfFGWuh89YpVsWG57pJg6YJo8SrqwmUO0ksv3SA2Lf4hoecX3Ikp6vNKYlZ27
+uKWtmWV79gtsOKARh2v72ZFChRS6AQFkU1ZMA56rKEaW/Mvlm/7HF9G4k7SEftR1
+r06FUKp5uUCbvWOfyYM/69HdB8aZROU24zUPkYu49kZ/QCl7q7LxG+ODJIybyklR
+RxZVO0qcb14umRP0iC+9jNw3J/hECS6JzHW7NbCplzi/AEbXZGUrhfzpri3CTs81
+l9WSywbZINUyesYO4TfttfmCgBuLRc0x2C/wrn8MG09Gl7c2aw2pxhaMPGF3j/G8
+shV7FwTGsKm8G+eMSiFXkm58Biz/nAITimAqe36VsmkcqjAuX0YVAiLVkux9YmQ2
+5hmCoBaZIx88YGgCwsigwPQPGQrXlZinlFfYluG6trA42pl2BD/6U/AJEZ8RUsD0
+OshlvRxxR0/zCqMufRWxBb1BUftglKunfiF6iHgTshIoOUmvLblzaEDB8Jf5UMS1
+tZMH0RQSLH3gQ+kp7/2mW2jGbdIhusru729yykb/9iinoGMEgdsfFr62nDj5zPYb
+kltEUwjVWnuL/O/38exZjrIZkf1uaFkjLXqrHIz3MuoHSoVd/AVBeEU4BvKO4aoM
+mgcT/Nc+jNWhOOewDtvtYxcPjrvmg69huLG0XoCgQ8P2GQJD2rSVc2MTe3hqmJj8
+SKqSUdlq4Sb+8K/hh++gCQkrJb5q7zIdXxULA7xf8PD2yhrVgO/h9mzaDxR77zBJ
+lab2dSxEH9vdGQKqGT6ZndEZo6Gopn2pXtn7bYVN2K0GojYa2MiLNbuhqxtZvg5Z
+Y49acItEd49objc40IU6WAAwz5w6jl6lybTq6EiNSMsmtekugUwyFQCOpTfYdOwZ
+9zrbmzwiWWAiQQTYuPESS1FpQEvAilzoSmwmbNkaAbMZfguX429+cSW1Kdu0/AWq
+SGx7AFpZpbKLd7hdKy25ZRIyRqu0goTsqA/r28faLKhjhKMF2Dl+Pgtkny7t/k1Z
+ZJXGmt++mHIck1UvGZR37thqpqd5IF9e96Pos1nQPfkV3cxXOT6mMOf9F3yCYW6d
+VclJPaM0lTEobbt2q/cDIM86Mo7G3cYHtfe7O+ard5Uhz+KVXhczduXeiwR4XNmP
+xQj/mgGTGCZIEWMJ32576B/vjEThY1RkA/wvdiMmV4gskXBbu/rhcX/RX51yBalP
+FU0DCN56t7vrXacEcdilMJIWLFZiqQCvYFHigNhwVsfBhNZHDxRODg==
+-----END RSA PRIVATE KEY-----
Added: trunk/pkcs11/dot-ssh/tests/test-data/id_rsa_plain
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/tests/test-data/id_rsa_plain Mon Dec 22 23:31:40 2008
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAoD6VKqkhay6pKHSRjAGWWfFPU8xfsi2gnOwP/B1UHDoztx3c
+zhO+py/fTlhCnSP1jsjkrVIZcnzah2fUNFFRgS4+jROBtvbgHsS72V1E6+ZogV+m
+BJWWAhw0iPrmQ3Kvm38D3PByo5Y7yKO5kIG2LloYLjosJ5F4sx2xh0uz2wXNtnY1
+b5xhe2+VEksm9OB+FXaUkZC2fQrTNo8ZGFJQSFd8kUhIfbUDJmlYuZ+vvHM+A3Lc
+9rHyW4IPaRyxFQciRmb+ZQqU2uSdOXAhg17lskuX/q8yCI5Hy5eDicC222oUMdJT
+tYgwX4dQCU8TICWhxb3x4RCV+g7D99+tkIvv+wIBIwKCAQEAm6qCRrLtQ4xpz4cu
+TX3ig0Ivzb84Y/HPOVpYq8S4G2u9NYq5PTfAhScwsoGfy9nJ+GthzPCrAYCZxV2M
+UBR7D8aF6CGT85C8dakrgrJgNZ3/HpduExT4H06Zbx+d2x7zu5/1H8UBpjorcnMp
+SoyiWOnOWMrLzqqSghzYV4teQnkhDmMTDgP/L39k9oLh/gvDHkxQET/IirrM3iT3
+rpZsXjsA+vAOrDrrsauPP9uAswaRGOH1O+xdAc/QH6/j2RK6ew/uICl0V9xYddSw
+9LSkk0gre2sdd7zz/r2t1oMFFsq+MaQ5Uynz0zmwpe/wyQjWY1ILy/wcIdOpLyOS
+PUaMSwKBgQDMULEsX+QChX3Od9gnwfbu4it7KYOV8V495al1YsaEyZcmcPQNKGrG
+iHyjDTWjj9w0THhrzF2ZfkWw3+N3SHfYqRx0+bzMgttEEJbaACOqBJPMmOwmi30I
+9ILcmsSMyOk+W9bHKPQ4OjwIVruiyvsFoLfhcFm0hispibWCKnlhUQKBgQDIx+aT
+kFnnVBvPnLAHgDfN32X0KR5Kk3PRe0cdNoeJHb/VHgLC0SuzZwdl+bzLdEyDaKht
+MGiPtblEhrjeTvwCHpwFOyMb33lYc1En8L2DNDjL0CASzRoHbvcKkin/L78wKmkV
+TY5uFyZ7Q/5S0YNlGSKL02+XURE/F/4FzKRJiwKBgQC6zW7JfD4uMOgNOl86SvBl
+YRHPsO1V4/5kejSIlNLCjGzv8j436nBAfMm5pa1iV6TCGgezA/3OKk5Yki8N+R0d
+3HHKCOchYbKHX5/dQfS4s7pUqRJsYkZulmkENbsEX+sxsw2C4511PI6oidAfz4Zr
+i6DOHZPYQCd2b0bdaKl9iwKBgQCD8RPdUDsUW9fC8fAE7duHSall7yKIx0wb8ezn
+T7gm56nycs6dR6Bf8z9gRQcJWw21cKkxz1qnlKzyhGrbOzfkIr5MlJNqFoLw+1KW
+luLv0dwuKa6tRPPY/8bpsIH/dyXd0roVUDkGhD3b+Xs9vOFREIRqg6EaSzc4FxSk
+ua3J7QKBgBVAzKSD3ya+VYKFD3E8GaiLQoClJF2t9Zkzr3yyJ657CwugA/2uU2/x
+3YNU3vK9hyypTXulbtteifRceSLDxEBQ67f0F3gvBqU6ZU2FmD7YTTv82Jvl0Ue2
+49ouxRjON9nXmr+6qe/yr5vIRlcRjKlfaIxDL7V6OTgwedUwqCuY
+-----END RSA PRIVATE KEY-----
Added: trunk/pkcs11/dot-ssh/tests/test-data/id_rsa_test.pub
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/tests/test-data/id_rsa_test.pub Mon Dec 22 23:31:40 2008
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAoD6VKqkhay6pKHSRjAGWWfFPU8xfsi2gnOwP/B1UHDoztx3czhO+py/fTlhCnSP1jsjkrVIZcnzah2fUNFFRgS4+jROBtvbgHsS72V1E6+ZogV+mBJWWAhw0iPrmQ3Kvm38D3PByo5Y7yKO5kIG2LloYLjosJ5F4sx2xh0uz2wXNtnY1b5xhe2+VEksm9OB+FXaUkZC2fQrTNo8ZGFJQSFd8kUhIfbUDJmlYuZ+vvHM+A3Lc9rHyW4IPaRyxFQciRmb+ZQqU2uSdOXAhg17lskuX/q8yCI5Hy5eDicC222oUMdJTtYgwX4dQCU8TICWhxb3x4RCV+g7D99+tkIvv+w== A public key comment
Added: trunk/pkcs11/dot-ssh/tests/unit-test-ssh-openssh.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/dot-ssh/tests/unit-test-ssh-openssh.c Mon Dec 22 23:31:40 2008
@@ -0,0 +1,130 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-ssh-openssh.c: Test OpenSSH parsing
+
+ Copyright (C) 2008 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "run-auto-test.h"
+
+#include "gck-ssh-openssh.h"
+
+#include "gck/gck-crypto.h"
+
+#include <glib.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+static const gchar *PRIVATE_FILES[] = {
+ "id_rsa_encrypted",
+ "id_rsa_plain",
+ "id_dsa_encrypted",
+ "id_dsa_plain"
+};
+
+static const gchar *PUBLIC_FILES[] = {
+ "id_rsa_test.pub",
+ "id_dsa_test.pub"
+};
+
+#define COMMENT "A public key comment"
+
+static void
+read_file (const gchar *filename, guchar **contents, gsize *len)
+{
+ gchar *path;
+ gboolean ret;
+
+ path = g_build_filename (g_get_current_dir (), "test-data", filename, NULL);
+ ret = g_file_get_contents (path, (gchar**)contents, len, NULL);
+ g_assert ("couldn't read in file" && ret);
+
+ g_free (path);
+}
+
+DEFINE_TEST(parse_public)
+{
+ gcry_sexp_t sexp;
+ gchar *comment;
+ guchar *data;
+ gsize n_data;
+ int algorithm;
+ gboolean is_private;
+ guint i;
+ GckDataResult res;
+
+
+ for (i = 0; i < G_N_ELEMENTS (PUBLIC_FILES); ++i) {
+
+ read_file (PUBLIC_FILES[i], &data, &n_data);
+
+ res = gck_ssh_openssh_parse_public_key (data, n_data, &sexp, &comment);
+ if (res != GCK_DATA_SUCCESS) {
+ g_warning ("couldn't parse public key: %s", PUBLIC_FILES[i]);
+ g_assert_cmpint (res, ==, GCK_DATA_SUCCESS);
+ }
+
+ if (!gck_crypto_sexp_parse_key (sexp, &algorithm, &is_private, NULL))
+ g_assert_not_reached ();
+
+ g_assert_cmpstr (comment, ==, COMMENT);
+ g_assert_cmpint (algorithm, !=, 0);
+ g_assert (!is_private);
+
+ g_free (data);
+ g_free (comment);
+ gcry_sexp_release (sexp);
+ }
+}
+
+DEFINE_TEST(parse_private)
+{
+ gcry_sexp_t sexp;
+ guchar *data;
+ gsize n_data;
+ int algorithm;
+ gboolean is_private;
+ guint i;
+ GckDataResult res;
+
+
+ for (i = 0; i < G_N_ELEMENTS (PRIVATE_FILES); ++i) {
+
+ read_file (PRIVATE_FILES[i], &data, &n_data);
+
+ res = gck_ssh_openssh_parse_private_key (data, n_data, "password", 8, &sexp);
+ if (res != GCK_DATA_SUCCESS) {
+ g_warning ("couldn't parse private key: %s", PRIVATE_FILES[i]);
+ g_assert_cmpint (res, ==, GCK_DATA_SUCCESS);
+ }
+
+ if (!gck_crypto_sexp_parse_key (sexp, &algorithm, &is_private, NULL))
+ g_assert_not_reached ();
+
+ g_assert_cmpint (algorithm, !=, 0);
+ g_assert (is_private);
+
+ g_free (data);
+ gcry_sexp_release (sexp);
+ }
+}
\ No newline at end of file
Modified: trunk/pkcs11/gck/gck-crypto.c
==============================================================================
--- trunk/pkcs11/gck/gck-crypto.c (original)
+++ trunk/pkcs11/gck/gck-crypto.c Mon Dec 22 23:31:40 2008
@@ -895,9 +895,9 @@
gboolean
gck_crypto_symkey_generate_simple (int cipher_algo, int hash_algo,
- const gchar *password, const guchar *salt,
- gsize n_salt, int iterations, guchar **key,
- guchar **iv)
+ const gchar *password, gssize n_password,
+ const guchar *salt, gsize n_salt, int iterations,
+ guchar **key, guchar **iv)
{
gcry_md_hd_t mdh;
gcry_error_t gcry;
@@ -913,6 +913,11 @@
g_return_val_if_fail (iterations >= 1, FALSE);
+ if (!password)
+ n_password = 0;
+ if (n_password == -1)
+ n_password = strlen (password);
+
/*
* If cipher algo needs more bytes than hash algo has available
* then the entire hashing process is done again (with the previous
@@ -952,7 +957,7 @@
gcry_md_write (mdh, digest, n_digest);
if (password)
- gcry_md_write (mdh, password, strlen (password));
+ gcry_md_write (mdh, password, n_password);
if (salt && n_salt)
gcry_md_write (mdh, salt, n_salt);
gcry_md_final (mdh);
@@ -996,7 +1001,7 @@
gboolean
gck_crypto_symkey_generate_pbe (int cipher_algo, int hash_algo, const gchar *password,
- const guchar *salt, gsize n_salt, int iterations,
+ gssize n_password, const guchar *salt, gsize n_salt, int iterations,
guchar **key, guchar **iv)
{
gcry_md_hd_t mdh;
@@ -1011,6 +1016,11 @@
g_return_val_if_fail (iterations >= 1, FALSE);
+ if (!password)
+ n_password = 0;
+ if (n_password == -1)
+ n_password = strlen (password);
+
/*
* We only do one pass here.
*
@@ -1051,7 +1061,7 @@
*iv = g_new0 (guchar, needed_iv);
if (password)
- gcry_md_write (mdh, password, strlen (password));
+ gcry_md_write (mdh, password, n_password);
if (salt && n_salt)
gcry_md_write (mdh, salt, n_salt);
gcry_md_final (mdh);
@@ -1082,11 +1092,12 @@
static gboolean
generate_pkcs12 (int hash_algo, int type, const gchar *utf8_password,
- const guchar *salt, gsize n_salt, int iterations,
- guchar *output, gsize n_output)
+ gssize n_password, const guchar *salt, gsize n_salt,
+ int iterations, guchar *output, gsize n_output)
{
gcry_mpi_t num_b1, num_ij;
guchar *hash, *buf_i, *buf_b;
+ const gchar *end_password;
gcry_md_hd_t mdh;
const gchar *p2;
guchar *p;
@@ -1099,6 +1110,13 @@
n_hash = gcry_md_get_algo_dlen (hash_algo);
g_return_val_if_fail (n_hash > 0, FALSE);
+ if (!utf8_password)
+ n_password = 0;
+ if (n_password == -1)
+ end_password = utf8_password + strlen (utf8_password);
+ else
+ end_password = utf8_password + n_password;
+
gcry = gcry_md_open (&mdh, hash_algo, 0);
if (gcry) {
g_warning ("couldn't create '%s' hash context: %s",
@@ -1126,13 +1144,21 @@
if (utf8_password) {
p2 = utf8_password;
for (i = 0; i < 64; i += 2) {
- unich = *p2 ? g_utf8_get_char (p2) : 0;
- *(p++) = (unich & 0xFF00) >> 8;
- *(p++) = (unich & 0xFF);
- if (*p2) /* Loop back to beginning if more bytes are needed */
+
+ /* Get a character from the string */
+ if (p2 < end_password) {
+ unich = g_utf8_get_char (p2);
p2 = g_utf8_next_char (p2);
- else
+
+ /* Get zero null terminator, and loop back to beginning */
+ } else {
+ unich = 0;
p2 = utf8_password;
+ }
+
+ /* Encode the bytes received */
+ *(p++) = (unich & 0xFF00) >> 8;
+ *(p++) = (unich & 0xFF);
}
} else {
memset (p, 0, 64);
@@ -1195,7 +1221,7 @@
gboolean
gck_crypto_symkey_generate_pkcs12 (int cipher_algo, int hash_algo, const gchar *password,
- const guchar *salt, gsize n_salt,
+ gssize n_password, const guchar *salt, gsize n_salt,
int iterations, guchar **key, guchar **iv)
{
gsize n_block, n_key;
@@ -1208,7 +1234,7 @@
n_key = gcry_cipher_get_algo_keylen (cipher_algo);
n_block = gcry_cipher_get_algo_blklen (cipher_algo);
- if (password && !g_utf8_validate (password, -1, NULL)) {
+ if (password && !g_utf8_validate (password, n_password, NULL)) {
g_warning ("invalid non-UTF8 password");
g_return_val_if_reached (FALSE);
}
@@ -1222,7 +1248,7 @@
if (key) {
*key = gkr_secure_alloc (n_key);
g_return_val_if_fail (*key != NULL, FALSE);
- ret = generate_pkcs12 (hash_algo, 1, password, salt, n_salt,
+ ret = generate_pkcs12 (hash_algo, 1, password, n_password, salt, n_salt,
iterations, *key, n_key);
}
@@ -1230,7 +1256,7 @@
if (ret && iv) {
if (n_block > 1) {
*iv = g_malloc (n_block);
- ret = generate_pkcs12 (hash_algo, 2, password, salt, n_salt,
+ ret = generate_pkcs12 (hash_algo, 2, password, n_password, salt, n_salt,
iterations, *iv, n_block);
} else {
*iv = NULL;
@@ -1326,11 +1352,11 @@
gboolean
gck_crypto_symkey_generate_pbkdf2 (int cipher_algo, int hash_algo,
- const gchar *password, const guchar *salt,
- gsize n_salt, int iterations,
+ const gchar *password, gssize n_password,
+ const guchar *salt, gsize n_salt, int iterations,
guchar **key, guchar **iv)
{
- gsize n_key, n_block, n_password;
+ gsize n_key, n_block;
gboolean ret = TRUE;
g_return_val_if_fail (hash_algo, FALSE);
@@ -1344,8 +1370,11 @@
*key = NULL;
if (iv)
*iv = NULL;
-
- n_password = password ? strlen (password) : 0;
+
+ if (!password)
+ n_password = 0;
+ if (n_password == -1)
+ n_password = strlen (password);
/* Generate us an key */
if (key) {
Modified: trunk/pkcs11/gck/gck-crypto.h
==============================================================================
--- trunk/pkcs11/gck/gck-crypto.h (original)
+++ trunk/pkcs11/gck/gck-crypto.h Mon Dec 22 23:31:40 2008
@@ -162,6 +162,7 @@
gboolean gck_crypto_symkey_generate_simple (int cipher_algo,
int hash_algo,
const gchar *password,
+ gssize n_password,
const guchar *salt,
gsize n_salt,
int iterations,
@@ -170,7 +171,8 @@
gboolean gck_crypto_symkey_generate_pbe (int cipher_algo,
int hash_algo,
- const gchar *password,
+ const gchar *password,
+ gssize n_password,
const guchar *salt,
gsize n_salt,
int iterations,
@@ -179,7 +181,8 @@
gboolean gck_crypto_symkey_generate_pkcs12 (int cipher_algo,
int hash_algo,
- const gchar *password,
+ const gchar *password,
+ gssize n_password,
const guchar *salt,
gsize n_salt,
int iterations,
@@ -188,7 +191,8 @@
gboolean gck_crypto_symkey_generate_pbkdf2 (int cipher_algo,
int hash_algo,
- const gchar *password,
+ const gchar *password,
+ gssize n_password,
const guchar *salt,
gsize n_salt,
int iterations,
Modified: trunk/pkcs11/gck/gck-data-der.c
==============================================================================
--- trunk/pkcs11/gck/gck-data-der.c (original)
+++ trunk/pkcs11/gck/gck-data-der.c Mon Dec 22 23:31:40 2008
@@ -106,7 +106,7 @@
}
}
-#endif UNTESTED_CODE
+#endif /* UNTESTED_CODE */
/* -----------------------------------------------------------------------------
* KEY PARSING
Modified: trunk/pkcs11/gck/gck-data-openssl.c
==============================================================================
--- trunk/pkcs11/gck/gck-data-openssl.c (original)
+++ trunk/pkcs11/gck/gck-data-openssl.c Mon Dec 22 23:31:40 2008
@@ -279,7 +279,7 @@
GckDataResult
gck_data_openssl_decrypt_block (const gchar *dekinfo, const gchar *password,
- const guchar *data, gsize n_data,
+ gssize n_password, const guchar *data, gsize n_data,
guchar **decrypted, gsize *n_decrypted)
{
gcry_cipher_hd_t ch;
@@ -299,7 +299,7 @@
/* IV is already set from the DEK info */
if (!gck_crypto_symkey_generate_simple (algo, GCRY_MD_MD5, password,
- iv, 8, 1, &key, NULL)) {
+ n_password, iv, 8, 1, &key, NULL)) {
g_free (iv);
return GCK_DATA_FAILURE;
}
@@ -334,7 +334,7 @@
gboolean
gck_data_openssl_encrypt_block (const gchar *dekinfo, const gchar *password,
- const guchar *data, gsize n_data,
+ gssize n_password, const guchar *data, gsize n_data,
guchar **encrypted, gsize *n_encrypted)
{
gsize n_overflow, n_batch, n_padding;
@@ -356,7 +356,7 @@
/* IV is already set from the DEK info */
if (!gck_crypto_symkey_generate_simple (algo, GCRY_MD_MD5, password,
- iv, 8, 1, &key, NULL))
+ n_password, iv, 8, 1, &key, NULL))
g_return_val_if_reached (FALSE);
gcry = gcry_cipher_open (&ch, algo, mode, 0);
Modified: trunk/pkcs11/gck/gck-data-openssl.h
==============================================================================
--- trunk/pkcs11/gck/gck-data-openssl.h (original)
+++ trunk/pkcs11/gck/gck-data-openssl.h Mon Dec 22 23:31:40 2008
@@ -29,11 +29,11 @@
int gck_data_openssl_parse_algo (const gchar *name, int *mode);
gboolean gck_data_openssl_encrypt_block (const gchar *dekinfo, const gchar *password,
- const guchar *data, gsize n_data,
+ gssize n_password, const guchar *data, gsize n_data,
guchar **encrypted, gsize *n_encrypted);
GckDataResult gck_data_openssl_decrypt_block (const gchar *dekinfo, const gchar *password,
- const guchar *data, gsize n_data,
+ gssize n_password, const guchar *data, gsize n_data,
guchar **decrypted, gsize *n_decrypted);
const gchar* gck_data_openssl_get_dekinfo (GHashTable *headers);
Modified: trunk/pkcs11/gck/gck-data-types.h
==============================================================================
--- trunk/pkcs11/gck/gck-data-types.h (original)
+++ trunk/pkcs11/gck/gck-data-types.h Mon Dec 22 23:31:40 2008
@@ -5,10 +5,13 @@
typedef enum _GckDataResult {
GCK_DATA_FAILURE = -2,
+ GCK_DATA_LOCKED = -1,
GCK_DATA_UNRECOGNIZED = 0,
GCK_DATA_SUCCESS = 1
} GckDataResult;
typedef void* (*GckDataAllocator) (void* p, unsigned long len);
+#define GCK_DATA_ERROR (g_quark_from_static_string ("gck-data-error"))
+
#endif /* GCKDATA_H_ */
Modified: trunk/pkcs11/gck/gck-module.h
==============================================================================
--- trunk/pkcs11/gck/gck-module.h (original)
+++ trunk/pkcs11/gck/gck-module.h Mon Dec 22 23:31:40 2008
@@ -24,6 +24,10 @@
#include <glib-object.h>
+#include "pkcs11/pkcs11.h"
+
+#include "gck-manager.h"
+
typedef struct _GckSession GckSession;
#define GCK_TYPE_MODULE (gck_module_get_type ())
Modified: trunk/pkcs11/gck/gck-private-key.c
==============================================================================
--- trunk/pkcs11/gck/gck-private-key.c (original)
+++ trunk/pkcs11/gck/gck-private-key.c Mon Dec 22 23:31:40 2008
@@ -280,13 +280,11 @@
gck_private_key_store_private (GckPrivateKey *self, GckSexp *sexp, guint num_uses)
{
g_return_if_fail (GCK_IS_PRIVATE_KEY (self));
- g_return_if_fail (sexp);
- g_return_if_fail (num_uses > 0);
- gck_sexp_ref (sexp);
+ if (sexp)
+ gck_sexp_ref (sexp);
if (self->pv->sexp)
gck_sexp_unref (self->pv->sexp);
self->pv->sexp = sexp;
self->pv->sexp_uses = num_uses;
}
-
Modified: trunk/pkcs11/gck/gck-util.c
==============================================================================
--- trunk/pkcs11/gck/gck-util.c (original)
+++ trunk/pkcs11/gck/gck-util.c Mon Dec 22 23:31:40 2008
@@ -67,6 +67,13 @@
}
CK_RV
+gck_util_set_string (CK_ATTRIBUTE_PTR attr, const gchar* string)
+{
+ g_return_val_if_fail (string, CKR_GENERAL_ERROR);
+ return gck_util_set_data (attr, string, strlen (string));
+}
+
+CK_RV
gck_util_set_data (CK_ATTRIBUTE_PTR attr, CK_VOID_PTR value, CK_ULONG n_value)
{
return gck_util_return_data (attr->pValue, &(attr->ulValueLen), value, n_value);
Modified: trunk/pkcs11/gck/gck-util.h
==============================================================================
--- trunk/pkcs11/gck/gck-util.h (original)
+++ trunk/pkcs11/gck/gck-util.h Mon Dec 22 23:31:40 2008
@@ -43,6 +43,9 @@
CK_RV gck_util_set_ulong (CK_ATTRIBUTE_PTR attr,
CK_ULONG value);
+CK_RV gck_util_set_string (CK_ATTRIBUTE_PTR attr,
+ const gchar* string);
+
CK_RV gck_util_set_data (CK_ATTRIBUTE_PTR attr,
CK_VOID_PTR value,
CK_ULONG n_value);
Modified: trunk/pkcs11/gck/tests/unit-test-crypto.c
==============================================================================
--- trunk/pkcs11/gck/tests/unit-test-crypto.c (original)
+++ trunk/pkcs11/gck/tests/unit-test-crypto.c Mon Dec 22 23:31:40 2008
@@ -128,7 +128,7 @@
ret = gck_crypto_symkey_generate_simple (all_generation_tests[i].cipher_algo,
all_generation_tests[i].hash_algo,
- all_generation_tests[i].password,
+ all_generation_tests[i].password, -1,
(guchar*)all_generation_tests[i].salt, 8,
all_generation_tests[i].iterations,
&key, NULL);
@@ -154,7 +154,7 @@
ret = gck_crypto_symkey_generate_pkcs12 (all_generation_tests[i].cipher_algo,
all_generation_tests[i].hash_algo,
- all_generation_tests[i].password,
+ all_generation_tests[i].password, -1,
(guchar*)all_generation_tests[i].salt, 8,
all_generation_tests[i].iterations,
&key, NULL);
@@ -180,7 +180,7 @@
ret = gck_crypto_symkey_generate_pbkdf2 (all_generation_tests[i].cipher_algo,
all_generation_tests[i].hash_algo,
- all_generation_tests[i].password,
+ all_generation_tests[i].password, -1,
(guchar*)all_generation_tests[i].salt, 8,
all_generation_tests[i].iterations,
&key, NULL);
@@ -206,7 +206,7 @@
ret = gck_crypto_symkey_generate_pbe (all_generation_tests[i].cipher_algo,
all_generation_tests[i].hash_algo,
- all_generation_tests[i].password,
+ all_generation_tests[i].password, -1,
(guchar*)all_generation_tests[i].salt, 8,
all_generation_tests[i].iterations,
&key, NULL);
Modified: trunk/pkcs11/gck/tests/unit-test-data-openssl.c
==============================================================================
--- trunk/pkcs11/gck/tests/unit-test-data-openssl.c (original)
+++ trunk/pkcs11/gck/tests/unit-test-data-openssl.c Mon Dec 22 23:31:40 2008
@@ -80,7 +80,7 @@
dekinfo = gck_data_openssl_get_dekinfo (headers);
g_assert ("no dekinfo in headers" && dekinfo != NULL);
- res = gck_data_openssl_decrypt_block (dekinfo, "booo", data, n_data, &refdata, &n_refdata);
+ res = gck_data_openssl_decrypt_block (dekinfo, "booo", 4, data, n_data, &refdata, &n_refdata);
g_assert ("couldn't openssl decrypt block" && res == GCK_DATA_SUCCESS);
g_assert ("no data returned from openssl decrypt" && refdata != NULL);
g_assert ("invalid amount of data returned from openssl decrypt" && n_refdata == n_data);
@@ -110,7 +110,7 @@
dekinfo = gck_data_openssl_get_dekinfo (refheaders);
g_assert ("no dekinfo in headers" && dekinfo != NULL);
- ret = gck_data_openssl_encrypt_block (dekinfo, "booo", refdata, n_refdata, &encrypted, &n_encrypted);
+ ret = gck_data_openssl_encrypt_block (dekinfo, "booo", 4, refdata, n_refdata, &encrypted, &n_encrypted);
g_assert ("couldn't openssl encrypt block" && ret == TRUE);
g_assert ("no data returned from openssl encrypt" && encrypted != NULL);
g_assert ("invalid amount of data returned from openssl encrypt" && n_refdata <= n_encrypted);
@@ -134,12 +134,12 @@
dekinfo = gck_data_openssl_prep_dekinfo (refheaders);
- ret = gck_data_openssl_encrypt_block (dekinfo, "password", TEST_DATA, TEST_DATA_L, &encrypted, &n_encrypted);
+ ret = gck_data_openssl_encrypt_block (dekinfo, "password", -1, TEST_DATA, TEST_DATA_L, &encrypted, &n_encrypted);
g_assert ("couldn't openssl encrypt block" && ret == TRUE);
g_assert ("no data returned from openssl encrypt" && encrypted != NULL);
g_assert ("invalid amount of data returned from openssl encrypt" && TEST_DATA_L <= n_encrypted);
- res = gck_data_openssl_decrypt_block (dekinfo, "password", encrypted, n_encrypted, &decrypted, &n_decrypted);
+ res = gck_data_openssl_decrypt_block (dekinfo, "password", 8, encrypted, n_encrypted, &decrypted, &n_decrypted);
g_assert ("couldn't openssl decrypt block" && res == GCK_DATA_SUCCESS);
g_assert ("no data returned from openssl decrypt" && decrypted != NULL);
Modified: trunk/tests/gtest.make
==============================================================================
--- trunk/tests/gtest.make (original)
+++ trunk/tests/gtest.make Mon Dec 22 23:31:40 2008
@@ -20,9 +20,8 @@
$(GTHREAD_LIBS)
noinst_PROGRAMS= \
- run-auto-test \
- run-prompt-test
-
+ run-auto-test
+
run-auto-test.c: $(UNIT_AUTO) Makefile.am $(top_srcdir)/tests/prep-gtest.sh
sh $(top_srcdir)/tests/prep-gtest.sh -b run-auto-test $(UNIT_AUTO)
@@ -37,25 +36,8 @@
run_auto_test_CFLAGS = \
$(UNIT_FLAGS)
-run-prompt-test.c: $(UNIT_PROMPT) Makefile.am $(top_srcdir)/tests/prep-gtest.sh
- sh $(top_srcdir)/tests/prep-gtest.sh -b run-prompt-test $(UNIT_PROMPT)
-
-run_prompt_test_SOURCES = \
- run-prompt-test.c run-prompt-test.h \
- $(UNIT_PROMPT)
-
-run_prompt_test_LDADD = \
- $(UNIT_LIBS) \
- $(DAEMON_LIBS)
-
-run_prompt_test_CFLAGS = \
- $(UNIT_FLAGS)
-
# ------------------------------------------------------------------------------
# Run the tests
test-auto: $(noinst_PROGRAMS)
gtester -k -m=slow ./run-auto-test
-
-test-prompt: $(noinst_PROGRAMS)
- gtester -k -m=slow ./run-prompt-test
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]