[gnome-keyring: 1/6] Implement calculation of fingerprints for keys.



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]