From: Jonathan McDowell <noodles@earth.li>
Date: Mon, 25 Apr 2011 02:06:06 +0000 (-0700)
Subject: Add support for calculating SKS style key hashes
X-Git-Url: https://git.sommitrealweird.co.uk/onak.git/commitdiff_plain/3cdd1ba5400b97412d8e69fdcf59284b7cde6e28?ds=sidebyside

Add support for calculating SKS style key hashes

  SKS uses an MD5 hash over the sorted packets from a key as a token
  for its gossip protocol. Add support for calculating this hash and a
  structure for passing it around within onak.
---

diff --git a/keyid.c b/keyid.c
index 2bec710..0516f47 100644
--- a/keyid.c
+++ b/keyid.c
@@ -7,11 +7,15 @@
  */
 
 #include <sys/types.h>
+#include <arpa/inet.h>
 
 #include "keyid.h"
 #include "keystructs.h"
 #include "log.h"
+#include "parsekey.h"
 #include "md5.h"
+#include "mem.h"
+#include "merge.h"
 #include "sha1.h"
 
 
@@ -156,3 +160,59 @@ uint64_t get_packetid(struct openpgp_packet *packet)
 
 	return keyid;
 }
+
+static struct openpgp_packet_list *sortpackets(struct openpgp_packet_list
+							*packets)
+{
+	struct openpgp_packet_list *sorted, **cur, *next;
+
+	sorted = NULL;
+	while (packets != NULL) {
+		cur = &sorted;
+		while (*cur != NULL && compare_packets((*cur)->packet,
+				packets->packet) < 0) {
+			cur = &((*cur)->next);
+		}
+		next = *cur;
+		*cur = packets;
+		packets = packets->next;
+		(*cur)->next = next;
+	}
+
+	return sorted;
+}
+
+void get_skshash(struct openpgp_publickey *key, struct skshash *hash)
+{
+	struct openpgp_packet_list *packets = NULL, *list_end = NULL;
+	struct openpgp_packet_list *curpacket;
+	struct md5_ctx md5_context;
+	struct openpgp_publickey *next;
+	uint32_t tmp;
+
+	/*
+	 * We only want a single key, so clear any link to the next
+	 * one for the period during the flatten.
+	 */
+	next = key->next;
+	key->next = NULL;
+	flatten_publickey(key, &packets, &list_end);
+	key->next = next;
+	packets = sortpackets(packets);
+
+	md5_init_ctx(&md5_context);
+
+	for (curpacket = packets; curpacket != NULL;
+			curpacket = curpacket->next) {
+		tmp = htonl(curpacket->packet->tag);
+		md5_process_bytes(&tmp, sizeof(tmp), &md5_context);
+		tmp = htonl(curpacket->packet->length);
+		md5_process_bytes(&tmp, sizeof(tmp), &md5_context);
+		md5_process_bytes(curpacket->packet->data,
+				curpacket->packet->length,
+				&md5_context);
+	}
+
+	md5_finish_ctx(&md5_context, &hash->hash);
+	free_packet_list(packets);
+}
diff --git a/keyid.h b/keyid.h
index 61ff6b8..202a4a0 100644
--- a/keyid.h
+++ b/keyid.h
@@ -43,4 +43,16 @@ unsigned char *get_fingerprint(struct openpgp_packet *packet,
  */
 uint64_t get_packetid(struct openpgp_packet *packet);
 
+/**
+ *	get_skshash - Given a public key returns the SKS hash for it.
+ *	@publickey: The key to calculate the hash for.
+ *	@skshash: Hash structure to sort the result in.
+ *
+ *	This function returns the SKS hash for a given public key. This
+ *	is an MD5 hash over a sorted list of all of the packets that
+ *	make up the key. The caller should allocate the memory for the
+ *	hash.
+ */
+void get_skshash(struct openpgp_publickey *publickey, struct skshash *hash);
+
 #endif /* __KEYID_H__ */
diff --git a/keystructs.h b/keystructs.h
index 33c6226..c77e346 100644
--- a/keystructs.h
+++ b/keystructs.h
@@ -104,4 +104,12 @@ struct stats_key {
 	bool revoked;
 };
 
+/**
+ *	struct skshash - holds an SKS key hash (md5 over sorted packet list)
+ *	@hash: The 128 bit MD5 hash of the sorted packet list from the key
+ */
+struct skshash {
+	uint8_t hash[16];
+};
+
 #endif /* __KEYSTRUCTS_H__ */