[gnome-keyring: 1/6] Implement calculation of fingerprints for keys.
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring: 1/6] Implement calculation of fingerprints for keys.
- Date: Tue, 24 May 2011 07:37:59 +0000 (UTC)
commit c150351ec342697aed59ba2ebd396f6c0bd62063
Author: Stef Walter <stefw collabora co uk>
Date: Wed Mar 9 20:06:50 2011 +0100
Implement calculation of fingerprints for keys.
These are derived from subjectPublicKeyInfo
https://bugzilla.gnome.org/show_bug.cgi?id=646905
egg/egg-asn1x.c | 4 +-
egg/egg-asn1x.h | 2 +-
gcr/Makefile.am | 3 +-
gcr/gcr-certificate-renderer.c | 19 ++-
gcr/gcr-fingerprint.c | 255 ++++++++++++++++++++++++++++++++++++++++
gcr/gcr-fingerprint.h | 40 ++++++
gcr/gcr-key-renderer.c | 20 +++-
7 files changed, 331 insertions(+), 12 deletions(-)
---
diff --git a/egg/egg-asn1x.c b/egg/egg-asn1x.c
index 55c73ce..550dae2 100644
--- a/egg/egg-asn1x.c
+++ b/egg/egg-asn1x.c
@@ -2606,7 +2606,7 @@ egg_asn1x_get_integer_as_raw (GNode *node, EggAllocator allocator, gsize *n_data
}
gboolean
-egg_asn1x_set_integer_as_raw (GNode *node, gpointer data, gsize n_data, GDestroyNotify destroy)
+egg_asn1x_set_integer_as_raw (GNode *node, gconstpointer data, gsize n_data, GDestroyNotify destroy)
{
gboolean sign;
guchar *p;
@@ -2624,7 +2624,7 @@ egg_asn1x_set_integer_as_raw (GNode *node, gpointer data, gsize n_data, GDestroy
return FALSE;
}
- anode_encode_tlv_and_enc (node, n_data, anode_encoder_simple, data, destroy);
+ anode_encode_tlv_and_enc (node, n_data, anode_encoder_simple, (gpointer)data, destroy);
return TRUE;
}
diff --git a/egg/egg-asn1x.h b/egg/egg-asn1x.h
index f987f9d..66ccd31 100644
--- a/egg/egg-asn1x.h
+++ b/egg/egg-asn1x.h
@@ -100,7 +100,7 @@ gpointer egg_asn1x_get_integer_as_raw (GNode *node,
gsize *n_data);
gboolean egg_asn1x_set_integer_as_raw (GNode *node,
- gpointer data,
+ gconstpointer data,
gsize n_data,
GDestroyNotify destroy);
diff --git a/gcr/Makefile.am b/gcr/Makefile.am
index bd20723..16ac5dc 100644
--- a/gcr/Makefile.am
+++ b/gcr/Makefile.am
@@ -78,12 +78,13 @@ libgcr GCR_VERSION_SUFFIX@_la_SOURCES = \
gcr-collection.c gcr-collection.h \
gcr-collection-model.c gcr-collection-model.h \
gcr-colons.c gcr-colons.h \
+ gcr-comparable.c gcr-comparable.h \
gcr-debug.c gcr-debug.h \
gcr-display-scrolled.c gcr-display-scrolled.h \
- gcr-comparable.c gcr-comparable.h \
gcr-display-view.c gcr-display-view.h \
gcr-gnupg-collection.c gcr-gnupg-collection.h \
gcr-gnupg-key.c gcr-gnupg-key.h \
+ gcr-fingerprint.c gcr-fingerprint.h \
gcr-icons.c gcr-icons.h \
gcr-import-dialog.c gcr-import-dialog.h \
gcr-importer.c gcr-importer.h \
diff --git a/gcr/gcr-certificate-renderer.c b/gcr/gcr-certificate-renderer.c
index f553048..45a7f40 100644
--- a/gcr/gcr-certificate-renderer.c
+++ b/gcr/gcr-certificate-renderer.c
@@ -23,6 +23,7 @@
#include "gcr-certificate-exporter.h"
#include "gcr-certificate-renderer.h"
#include "gcr-display-view.h"
+#include "gcr-fingerprint.h"
#include "gcr-icons.h"
#include "gcr-simple-certificate.h"
#include "gcr-renderer.h"
@@ -485,6 +486,12 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
}
g_free (display);
+ /* Fingerprints */
+ _gcr_display_view_append_heading (view, renderer, _("Certificate Fingerprints"));
+
+ _gcr_display_view_append_fingerprint (view, renderer, data, n_data, "SHA1", G_CHECKSUM_SHA1);
+ _gcr_display_view_append_fingerprint (view, renderer, data, n_data, "MD5", G_CHECKSUM_MD5);
+
/* Signature */
_gcr_display_view_append_heading (view, renderer, _("Signature"));
@@ -521,18 +528,18 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
g_free (display);
}
+ value = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "tbsCertificate",
+ "subjectPublicKeyInfo", NULL), &n_value);
+ raw = _gcr_fingerprint_from_subject_public_key_info (value, n_value, G_CHECKSUM_SHA1, &n_raw);
+ _gcr_display_view_append_hex (view, renderer, _("Key SHA1 Fingerprint"), raw, n_raw);
+ g_free (raw);
+
raw = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo",
"subjectPublicKey", NULL), NULL, &bits);
g_return_if_fail (raw);
_gcr_display_view_append_hex (view, renderer, _("Public Key"), raw, bits / 8);
g_free (raw);
- /* Fingerprints */
- _gcr_display_view_append_heading (view, renderer, _("Fingerprints"));
-
- _gcr_display_view_append_fingerprint (view, renderer, data, n_data, "SHA1", G_CHECKSUM_SHA1);
- _gcr_display_view_append_fingerprint (view, renderer, data, n_data, "MD5", G_CHECKSUM_MD5);
-
/* Extensions */
for (index = 1; TRUE; ++index) {
if (!append_extension (self, view, asn, data, n_data, index))
diff --git a/gcr/gcr-fingerprint.c b/gcr/gcr-fingerprint.c
new file mode 100644
index 0000000..47dc3da
--- /dev/null
+++ b/gcr/gcr-fingerprint.c
@@ -0,0 +1,255 @@
+/*
+ * gnome-keyring
+ *
+ * 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 License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#include "config.h"
+
+#include "gcr-fingerprint.h"
+
+#include "egg/egg-asn1x.h"
+#include "egg/egg-asn1-defs.h"
+
+#include <glib.h>
+#include <gcrypt.h>
+
+static GQuark OID_PKIX1_RSA = 0;
+static GQuark OID_PKIX1_DSA = 0;
+
+static void
+init_quarks (void)
+{
+ static volatile gsize quarks_inited = 0;
+
+ if (g_once_init_enter (&quarks_inited)) {
+
+ #define QUARK(name, value) \
+ name = g_quark_from_static_string(value)
+
+ QUARK (OID_PKIX1_RSA, "1.2.840.113549.1.1.1");
+ QUARK (OID_PKIX1_DSA, "1.2.840.10040.4.1");
+
+ #undef QUARK
+
+ g_once_init_leave (&quarks_inited, 1);
+ }
+}
+
+gpointer
+_gcr_fingerprint_from_subject_public_key_info (gconstpointer key_info, gsize n_key_info,
+ GChecksumType checksum_type,
+ gsize *n_fingerprint)
+{
+ GChecksum *check;
+ guint8 *fingerprint;
+
+ g_return_val_if_fail (key_info, NULL);
+ g_return_val_if_fail (n_key_info, NULL);
+ g_return_val_if_fail (n_fingerprint, NULL);
+
+ check = g_checksum_new (checksum_type);
+ g_return_val_if_fail (check, NULL);
+
+ g_checksum_update (check, key_info, n_key_info);
+
+ *n_fingerprint = g_checksum_type_get_length (checksum_type);
+ fingerprint = g_malloc (*n_fingerprint);
+ g_checksum_get_digest (check, fingerprint, n_fingerprint);
+
+ g_checksum_free (check);
+ return fingerprint;
+}
+
+static gboolean
+rsa_subject_public_key_from_attributes (GckAttributes *attrs, GNode *info_asn)
+{
+ GckAttribute *attr;
+ GNode *key_asn;
+ gpointer key;
+ gsize n_key;
+
+ init_quarks ();
+
+ key_asn = egg_asn1x_create (pk_asn1_tab, "RSAPublicKey");
+ g_return_val_if_fail (key_asn, FALSE);
+
+ attr = gck_attributes_find (attrs, CKA_MODULUS);
+ g_return_val_if_fail (attr, FALSE);
+ egg_asn1x_set_integer_as_raw (egg_asn1x_node (key_asn, "modulus", NULL),
+ attr->value, attr->length, NULL);
+
+ attr = gck_attributes_find (attrs, CKA_PUBLIC_EXPONENT);
+ g_return_val_if_fail (attr, FALSE);
+ egg_asn1x_set_integer_as_raw (egg_asn1x_node (key_asn, "publicExponent", NULL),
+ attr->value, attr->length, NULL);
+
+ key = egg_asn1x_encode (key_asn, g_realloc, &n_key);
+ egg_asn1x_destroy (key_asn);
+
+ egg_asn1x_set_bits_as_raw (egg_asn1x_node (info_asn, "subjectPublicKey", NULL),
+ key, n_key * 8, g_free);
+
+ egg_asn1x_set_oid_as_quark (egg_asn1x_node (info_asn, "algorithm", "algorithm", NULL), OID_PKIX1_RSA);
+
+ return TRUE;
+}
+
+static gboolean
+dsa_subject_public_key_from_private (GNode *key_asn, GckAttribute *ap,
+ GckAttribute *aq, GckAttribute *ag, GckAttribute *ax)
+{
+ gcry_mpi_t mp, mq, mg, mx, my;
+ size_t n_buffer;
+ gcry_error_t gcry;
+ unsigned char *buffer;
+
+ gcry = gcry_mpi_scan (&mp, GCRYMPI_FMT_USG, ap->value, ap->length, NULL);
+ g_return_val_if_fail (gcry == 0, FALSE);
+
+ gcry = gcry_mpi_scan (&mq, GCRYMPI_FMT_USG, aq->value, aq->length, NULL);
+ g_return_val_if_fail (gcry == 0, FALSE);
+
+ gcry = gcry_mpi_scan (&mg, GCRYMPI_FMT_USG, ag->value, ag->length, NULL);
+ g_return_val_if_fail (gcry == 0, FALSE);
+
+ gcry = gcry_mpi_scan (&mx, GCRYMPI_FMT_USG, ax->value, ax->length, NULL);
+ g_return_val_if_fail (gcry == 0, FALSE);
+
+ /* Calculate the public part from the private */
+ my = gcry_mpi_snew (gcry_mpi_get_nbits (mx));
+ g_return_val_if_fail (my, FALSE);
+ gcry_mpi_powm (my, mg, mx, mp);
+
+ gcry = gcry_mpi_aprint (GCRYMPI_FMT_USG, &buffer, &n_buffer, my);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ egg_asn1x_set_integer_as_raw (key_asn, buffer, n_buffer, gcry_free);
+
+ gcry_mpi_release (mp);
+ gcry_mpi_release (mq);
+ gcry_mpi_release (mg);
+ gcry_mpi_release (mx);
+ gcry_mpi_release (my);
+
+ return TRUE;
+}
+
+static gboolean
+dsa_subject_public_key_from_attributes (GckAttributes *attrs, GNode *info_asn)
+{
+ GckAttribute *value, *g, *q, *p;
+ GNode *key_asn, *params_asn;
+ gpointer key, params;
+ gsize n_key, n_params;
+ gulong klass;
+
+ init_quarks ();
+
+ key_asn = egg_asn1x_create (pk_asn1_tab, "DSAPublicPart");
+ g_return_val_if_fail (key_asn, FALSE);
+
+ params_asn = egg_asn1x_create (pk_asn1_tab, "DSAParameters");
+ g_return_val_if_fail (params_asn, FALSE);
+
+ if (!gck_attributes_find_ulong (attrs, CKA_CLASS, &klass))
+ klass = CKO_PUBLIC_KEY;
+
+ p = gck_attributes_find (attrs, CKA_PRIME);
+ g_return_val_if_fail (p, FALSE);
+ egg_asn1x_set_integer_as_raw (egg_asn1x_node (params_asn, "p", NULL), p->value, p->length, NULL);
+
+ q = gck_attributes_find (attrs, CKA_SUBPRIME);
+ g_return_val_if_fail (q, FALSE);
+ egg_asn1x_set_integer_as_raw (egg_asn1x_node (params_asn, "q", NULL), q->value, q->length, NULL);
+
+ g = gck_attributes_find (attrs, CKA_BASE);
+ g_return_val_if_fail (g, FALSE);
+ egg_asn1x_set_integer_as_raw (egg_asn1x_node (params_asn, "g", NULL), g->value, g->length, NULL);
+
+ value = gck_attributes_find (attrs, CKA_VALUE);
+ g_return_val_if_fail (value, FALSE);
+
+ /* Are these attributes for a public or private key? */
+ if (klass == CKO_PRIVATE_KEY) {
+
+ /* We need to calculate the public from the private key */
+ if (!dsa_subject_public_key_from_private (key_asn, p, q, g, value))
+ g_return_val_if_reached (FALSE);
+
+ } else if (klass == CKO_PUBLIC_KEY) {
+ egg_asn1x_set_integer_as_raw (key_asn, value->value, value->length, NULL);
+ }
+
+ key = egg_asn1x_encode (key_asn, g_realloc, &n_key);
+ egg_asn1x_destroy (key_asn);
+
+ params = egg_asn1x_encode (params_asn, g_realloc, &n_params);
+ egg_asn1x_destroy (params_asn);
+
+ egg_asn1x_set_bits_as_raw (egg_asn1x_node (info_asn, "subjectPublicKey", NULL),
+ key, n_key * 8, g_free);
+ egg_asn1x_set_raw_element (egg_asn1x_node (info_asn, "algorithm", "parameters", NULL),
+ params, n_params, g_free);
+
+ egg_asn1x_set_oid_as_quark (egg_asn1x_node (info_asn, "algorithm", "algorithm", NULL), OID_PKIX1_DSA);
+
+ return TRUE;
+}
+
+gpointer
+_gcr_fingerprint_from_attributes (GckAttributes *attrs, GChecksumType checksum_type,
+ gsize *n_fingerprint)
+{
+ gpointer fingerprint = NULL;
+ gboolean ret = FALSE;
+ GNode *info_asn;
+ gpointer info;
+ gulong key_type;
+ gsize n_info;
+
+ g_return_val_if_fail (attrs, FALSE);
+ g_return_val_if_fail (n_fingerprint, FALSE);
+
+ if (!gck_attributes_find_ulong (attrs, CKA_KEY_TYPE, &key_type))
+ g_return_val_if_reached (FALSE);
+
+ info_asn = egg_asn1x_create (pkix_asn1_tab, "SubjectPublicKeyInfo");
+ g_return_val_if_fail (info_asn, FALSE);
+
+ if (key_type == CKK_RSA)
+ ret = rsa_subject_public_key_from_attributes (attrs, info_asn);
+
+ else if (key_type == CKK_DSA)
+ ret = dsa_subject_public_key_from_attributes (attrs, info_asn);
+
+ else
+ g_return_val_if_reached (FALSE);
+
+ if (ret) {
+ info = egg_asn1x_encode (info_asn, g_realloc, &n_info);
+ fingerprint = _gcr_fingerprint_from_subject_public_key_info (info, n_info,
+ checksum_type,
+ n_fingerprint);
+ g_free (info);
+ }
+
+ egg_asn1x_destroy (info_asn);
+ return fingerprint;
+}
diff --git a/gcr/gcr-fingerprint.h b/gcr/gcr-fingerprint.h
new file mode 100644
index 0000000..091bd81
--- /dev/null
+++ b/gcr/gcr-fingerprint.h
@@ -0,0 +1,40 @@
+/*
+ * gnome-keyring
+ *
+ * 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 License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#ifndef GCR_FINGERPRINT_H
+#define GCR_FINGERPRINT_H
+
+#include <glib.h>
+
+#include "gcr-types.h"
+
+gpointer _gcr_fingerprint_from_subject_public_key_info (gconstpointer key_info,
+ gsize n_key_info,
+ GChecksumType checksum_type,
+ gsize *n_fingerprint);
+
+gpointer _gcr_fingerprint_from_attributes (GckAttributes *attrs,
+ GChecksumType checksum_type,
+ gsize *n_fingerprint);
+
+#endif /* GCR_FINGERPRINT_H_ */
diff --git a/gcr/gcr-key-renderer.c b/gcr/gcr-key-renderer.c
index bf3934c..2273079 100644
--- a/gcr/gcr-key-renderer.c
+++ b/gcr/gcr-key-renderer.c
@@ -21,6 +21,7 @@
#include "gcr-key-renderer.h"
#include "gcr-display-view.h"
+#include "gcr-fingerprint.h"
#include "gcr-icons.h"
#include "gcr-renderer.h"
#include "gcr-viewer.h"
@@ -239,6 +240,8 @@ gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
GcrKeyRenderer *self;
GcrDisplayView *view;
const gchar *text = "";
+ gpointer fingerprint;
+ gsize n_fingerprint;
gchar *display;
gulong klass;
gulong key_type;
@@ -316,8 +319,21 @@ gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
_gcr_display_view_append_value (view, renderer, _("Size"), display, FALSE);
g_free (display);
- /* TODO: We need to have consistent key fingerprints. */
- _gcr_display_view_append_value (view, renderer, _("Fingerprint"), "XX XX XX XX XX XX XX XX XX XX", TRUE);
+ /* Fingerprints */
+ _gcr_display_view_append_heading (view, renderer, _("Fingerprints"));
+
+ fingerprint = _gcr_fingerprint_from_attributes (self->pv->attributes,
+ G_CHECKSUM_SHA1, &n_fingerprint);
+ if (fingerprint) {
+ _gcr_display_view_append_hex (view, renderer, _("SHA1"), fingerprint, n_fingerprint);
+ g_free (fingerprint);
+ }
+ fingerprint = _gcr_fingerprint_from_attributes (self->pv->attributes,
+ G_CHECKSUM_SHA256, &n_fingerprint);
+ if (fingerprint) {
+ _gcr_display_view_append_hex (view, renderer, _("SHA256"), fingerprint, n_fingerprint);
+ g_free (fingerprint);
+ }
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]