]> git.sommitrealweird.co.uk Git - onak.git/blob - keyid.c
c75f0a178854b3146bb8aa252cc1b4f27c43af07
[onak.git] / keyid.c
1 /*
2  * keyid.c - Routines to calculate key IDs.
3  *
4  * Copyright 2002,2011 Jonathan McDowell <noodles@earth.li>
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program; if not, write to the Free Software Foundation, Inc., 51
17  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include <string.h>
21 #include <sys/types.h>
22 #include <arpa/inet.h>
23
24 #include "config.h"
25 #include "keyid.h"
26 #include "keystructs.h"
27 #include "log.h"
28 #include "parsekey.h"
29 #include "mem.h"
30 #include "merge.h"
31
32 #ifdef HAVE_NETTLE
33 #include <nettle/md5.h>
34 #include <nettle/sha.h>
35 #else
36 #include "md5.h"
37 #include "sha1.h"
38 #endif
39
40
41 /**
42  *      get_keyid - Given a public key returns the keyid.
43  *      @publickey: The key to calculate the id for.
44  */
45 uint64_t get_keyid(struct openpgp_publickey *publickey)
46 {
47         return (get_packetid(publickey->publickey));
48 }
49
50 /**
51  *      get_fingerprint - Given a public key returns the fingerprint.
52  *      @publickey: The key to calculate the id for.
53  *      @fingerprint: The fingerprint (must be at least 20 bytes of space). 
54  *      @len: The length of the returned fingerprint.
55  *
56  *      This function returns the fingerprint for a given public key. As Type 3
57  *      fingerprints are 16 bytes and Type 4 are 20 the len field indicates
58  *      which we've returned.
59  */
60 unsigned char *get_fingerprint(struct openpgp_packet *packet,
61         unsigned char *fingerprint,
62         size_t *len)
63 {
64         struct sha1_ctx sha_ctx;
65         struct md5_ctx md5_context;
66         unsigned char c;
67         size_t         modlen, explen;
68
69         log_assert(fingerprint != NULL);
70         log_assert(len != NULL);
71
72         *len = 0;
73
74         switch (packet->data[0]) {
75         case 2:
76         case 3:
77                 md5_init(&md5_context);
78
79                 /*
80                  * MD5 the modulus and exponent.
81                  */
82                 modlen = ((packet->data[8] << 8) +
83                          packet->data[9] + 7) >> 3;
84                 md5_update(&md5_context, modlen, &packet->data[10]);
85
86                 explen = ((packet->data[10+modlen] << 8) +
87                          packet->data[11+modlen] + 7) >> 3;
88                 md5_update(&md5_context, explen, &packet->data[12 + modlen]);
89
90                 *len = 16;
91                 md5_digest(&md5_context, *len, fingerprint);
92
93                 break;
94
95         case 4:
96                 sha1_init(&sha_ctx);
97                 /*
98                  * TODO: Can this be 0x99? Are all public key packets old
99                  * format with 2 bytes of length data?
100                  */
101                 c = 0x99;
102                 sha1_update(&sha_ctx, sizeof(c), &c);
103                 c = packet->length >> 8;
104                 sha1_update(&sha_ctx, sizeof(c), &c);
105                 c = packet->length & 0xFF;
106                 sha1_update(&sha_ctx, sizeof(c), &c);
107                 sha1_update(&sha_ctx, packet->length,
108                         packet->data);
109                 *len = 20;
110                 sha1_digest(&sha_ctx, *len, fingerprint);
111
112                 break;
113         default:
114                 logthing(LOGTHING_ERROR, "Unknown key type: %d",
115                                 packet->data[0]);
116         }
117
118         return fingerprint;
119 }
120
121
122 /**
123  *      get_packetid - Given a PGP packet returns the keyid.
124  *      @packet: The packet to calculate the id for.
125  */
126 uint64_t get_packetid(struct openpgp_packet *packet)
127 {
128         uint64_t        keyid = 0;
129         int             offset = 0;
130         int             i = 0;
131         size_t          length = 0;
132         unsigned char   buff[20];
133
134         log_assert(packet != NULL);
135
136         switch (packet->data[0]) {
137         case 2:
138         case 3:
139                 /*
140                  * For a type 2 or 3 key the keyid is the last 64 bits of the
141                  * public modulus n, which is stored as an MPI from offset 8
142                  * onwards.
143                  */
144                 offset = (packet->data[8] << 8) +
145                         packet->data[9];
146                 offset = ((offset + 7) / 8) + 2;
147
148                 for (keyid = 0, i = 0; i < 8; i++) {
149                         keyid <<= 8;
150                         keyid += packet->data[offset++];
151                 }
152                 /*
153                  * Check for an RSA key; if not then log but accept anyway.
154                  * 1 == RSA
155                  * 2 == RSA Encrypt-Only
156                  * 3 == RSA Sign-Only
157                  */
158                 if (packet->data[7] < 1 || packet->data[7] > 3) {
159                         logthing(LOGTHING_NOTICE,
160                                 "Type 2 or 3 key, but not RSA: %llx (type %d)",
161                                 keyid,
162                                 packet->data[7]);
163                 }
164                 break;
165         case 4:
166                 get_fingerprint(packet, buff, &length);
167                 
168                 for (keyid = 0, i = 12; i < 20; i++) {
169                         keyid <<= 8;
170                         keyid += buff[i];
171                 }
172
173                 break;
174         default:
175                 logthing(LOGTHING_ERROR, "Unknown key type: %d",
176                                 packet->data[0]);
177         }
178
179         return keyid;
180 }
181
182 static struct openpgp_packet_list *sortpackets(struct openpgp_packet_list
183                                                         *packets)
184 {
185         struct openpgp_packet_list *sorted, **cur, *next;
186
187         sorted = NULL;
188         while (packets != NULL) {
189                 cur = &sorted;
190                 while (*cur != NULL && compare_packets((*cur)->packet,
191                                 packets->packet) < 0) {
192                         cur = &((*cur)->next);
193                 }
194                 next = *cur;
195                 *cur = packets;
196                 packets = packets->next;
197                 (*cur)->next = next;
198         }
199
200         return sorted;
201 }
202
203 void get_skshash(struct openpgp_publickey *key, struct skshash *hash)
204 {
205         struct openpgp_packet_list *packets = NULL, *list_end = NULL;
206         struct openpgp_packet_list *curpacket;
207         struct md5_ctx md5_context;
208         struct openpgp_publickey *next;
209         uint32_t tmp;
210
211         /*
212          * We only want a single key, so clear any link to the next
213          * one for the period during the flatten.
214          */
215         next = key->next;
216         key->next = NULL;
217         flatten_publickey(key, &packets, &list_end);
218         key->next = next;
219         packets = sortpackets(packets);
220
221         md5_init(&md5_context);
222
223         for (curpacket = packets; curpacket != NULL;
224                         curpacket = curpacket->next) {
225                 tmp = htonl(curpacket->packet->tag);
226                 md5_update(&md5_context, sizeof(tmp), (void *) &tmp);
227                 tmp = htonl(curpacket->packet->length);
228                 md5_update(&md5_context, sizeof(tmp), (void *) &tmp);
229                 md5_update(&md5_context,
230                                 curpacket->packet->length,
231                                 curpacket->packet->data);
232         }
233
234         md5_digest(&md5_context, 16, (uint8_t *) &hash->hash);
235         free_packet_list(packets);
236 }
237
238 uint8_t hexdigit(char c)
239 {
240         if (c >= '0' && c <= '9')
241                 return c - '0';
242         else if (c >= 'a' && c <= 'f')
243                 return c - 'a' + 10;
244         else if (c >= 'A' && c <= 'F')
245                 return c - 'A' + 10;
246         else
247                 return 0;
248 }
249
250 int parse_skshash(char *search, struct skshash *hash)
251 {
252         int i, len;
253
254         len = strlen(search);
255         if (len > 32) {
256                 return 0;
257         }
258
259         for (i = 0; i < len; i += 2) {
260                 hash->hash[i >> 1] = (hexdigit(search[i]) << 4) +
261                                 hexdigit(search[i + 1]);
262         }
263
264         return 1;
265 }