]> the.earth.li Git - onak.git/blob - keyid.c
Change SHA_DIGEST_LENGTH to SHA1_DIGEST_SIZE to match nettle
[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 "onak.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/ripemd160.h>
35 #include <nettle/sha.h>
36 #else
37 #include "md5.h"
38 #include "sha1.h"
39 #endif
40
41
42 /**
43  *      get_keyid - Given a public key returns the keyid.
44  *      @publickey: The key to calculate the id for.
45  */
46 onak_status_t get_keyid(struct openpgp_publickey *publickey, uint64_t *keyid)
47 {
48         return (get_packetid(publickey->publickey, keyid));
49 }
50
51 /**
52  *      get_fingerprint - Given a public key returns the fingerprint.
53  *      @publickey: The key to calculate the id for.
54  *      @fingerprint: The fingerprint (must be at least 20 bytes of space).
55  *      @len: The length of the returned fingerprint.
56  *
57  *      This function returns the fingerprint for a given public key. As Type 3
58  *      fingerprints are 16 bytes and Type 4 are 20 the len field indicates
59  *      which we've returned.
60  */
61 onak_status_t get_fingerprint(struct openpgp_packet *packet,
62         unsigned char *fingerprint,
63         size_t *len)
64 {
65         struct sha1_ctx sha_ctx;
66         struct md5_ctx md5_context;
67         unsigned char c;
68         size_t         modlen, explen;
69
70         if (fingerprint == NULL)
71                 return ONAK_E_INVALID_PARAM;
72         if (len == NULL)
73                 return ONAK_E_INVALID_PARAM;
74
75         *len = 0;
76
77         switch (packet->data[0]) {
78         case 2:
79         case 3:
80                 md5_init(&md5_context);
81
82                 /*
83                  * MD5 the modulus and exponent.
84                  */
85                 modlen = ((packet->data[8] << 8) +
86                          packet->data[9] + 7) >> 3;
87                 md5_update(&md5_context, modlen, &packet->data[10]);
88
89                 explen = ((packet->data[10+modlen] << 8) +
90                          packet->data[11+modlen] + 7) >> 3;
91                 md5_update(&md5_context, explen, &packet->data[12 + modlen]);
92
93                 *len = 16;
94                 md5_digest(&md5_context, *len, fingerprint);
95
96                 break;
97
98         case 4:
99                 sha1_init(&sha_ctx);
100                 /*
101                  * TODO: Can this be 0x99? Are all public key packets old
102                  * format with 2 bytes of length data?
103                  */
104                 c = 0x99;
105                 sha1_update(&sha_ctx, sizeof(c), &c);
106                 c = packet->length >> 8;
107                 sha1_update(&sha_ctx, sizeof(c), &c);
108                 c = packet->length & 0xFF;
109                 sha1_update(&sha_ctx, sizeof(c), &c);
110                 sha1_update(&sha_ctx, packet->length,
111                         packet->data);
112                 *len = 20;
113                 sha1_digest(&sha_ctx, *len, fingerprint);
114
115                 break;
116         default:
117                 return ONAK_E_UNKNOWN_VER;
118         }
119
120         return ONAK_E_OK;
121 }
122
123
124 /**
125  *      get_packetid - Given a PGP packet returns the keyid.
126  *      @packet: The packet to calculate the id for.
127  */
128 onak_status_t get_packetid(struct openpgp_packet *packet, uint64_t *keyid)
129 {
130         int             offset = 0;
131         int             i = 0;
132         size_t          length = 0;
133         unsigned char   buff[20];
134 #ifdef NETTLE_WITH_RIPEMD160
135         struct ripemd160_ctx ripemd160_context;
136         uint8_t         data;
137 #endif
138
139         if (packet == NULL)
140                 return ONAK_E_INVALID_PARAM;
141
142         switch (packet->data[0]) {
143         case 2:
144         case 3:
145                 /*
146                  * Old versions of GnuPG would put Elgamal keys inside
147                  * a V3 key structure, then generate the keyid using
148                  * RIPED160.
149                  */
150 #ifdef NETTLE_WITH_RIPEMD160
151                 if (packet->data[7] == 16) {
152                         ripemd160_init(&ripemd160_context);
153                         data = 0x99;
154                         ripemd160_update(&ripemd160_context, 1, &data);
155                         data = packet->length >> 8;
156                         ripemd160_update(&ripemd160_context, 1, &data);
157                         data = packet->length & 0xFF;
158                         ripemd160_update(&ripemd160_context, 1, &data);
159                         ripemd160_update(&ripemd160_context,
160                                 packet->length,
161                                 packet->data);
162
163                         ripemd160_digest(&ripemd160_context,
164                                 RIPEMD160_DIGEST_SIZE,
165                                 buff);
166
167                         for (*keyid = 0, i = 12; i < 20; i++) {
168                                 *keyid <<= 8;
169                                 *keyid += buff[i];
170                         }
171
172                         return ONAK_E_OK;
173                 }
174 #endif
175                 /*
176                  * Check for an RSA key; if not return an error.
177                  * 1 == RSA
178                  * 2 == RSA Encrypt-Only
179                  * 3 == RSA Sign-Only
180                  */
181                 if (packet->data[7] < 1 || packet->data[7] > 3) {
182                         return ONAK_E_INVALID_PKT;
183                 }
184
185                 /*
186                  * For a type 2 or 3 key the keyid is the last 64 bits of the
187                  * public modulus n, which is stored as an MPI from offset 8
188                  * onwards.
189                  */
190                 offset = (packet->data[8] << 8) +
191                         packet->data[9];
192                 offset = ((offset + 7) / 8) + 2;
193
194                 for (*keyid = 0, i = 0; i < 8; i++) {
195                         *keyid <<= 8;
196                         *keyid += packet->data[offset++];
197                 }
198                 break;
199         case 4:
200                 get_fingerprint(packet, buff, &length);
201                 
202                 for (*keyid = 0, i = 12; i < 20; i++) {
203                         *keyid <<= 8;
204                         *keyid += buff[i];
205                 }
206
207                 break;
208         default:
209                 return ONAK_E_UNKNOWN_VER;
210         }
211
212         return ONAK_E_OK;
213 }
214
215 static struct openpgp_packet_list *sortpackets(struct openpgp_packet_list
216                                                         *packets)
217 {
218         struct openpgp_packet_list *sorted, **cur, *next;
219
220         sorted = NULL;
221         while (packets != NULL) {
222                 cur = &sorted;
223                 while (*cur != NULL && compare_packets((*cur)->packet,
224                                 packets->packet) < 0) {
225                         cur = &((*cur)->next);
226                 }
227                 next = *cur;
228                 *cur = packets;
229                 packets = packets->next;
230                 (*cur)->next = next;
231         }
232
233         return sorted;
234 }
235
236 onak_status_t get_skshash(struct openpgp_publickey *key, struct skshash *hash)
237 {
238         struct openpgp_packet_list *packets = NULL, *list_end = NULL;
239         struct openpgp_packet_list *curpacket;
240         struct md5_ctx md5_context;
241         struct openpgp_publickey *next;
242         uint32_t tmp;
243
244         /*
245          * We only want a single key, so clear any link to the next
246          * one for the period during the flatten.
247          */
248         next = key->next;
249         key->next = NULL;
250         flatten_publickey(key, &packets, &list_end);
251         key->next = next;
252         packets = sortpackets(packets);
253
254         md5_init(&md5_context);
255
256         for (curpacket = packets; curpacket != NULL;
257                         curpacket = curpacket->next) {
258                 tmp = htonl(curpacket->packet->tag);
259                 md5_update(&md5_context, sizeof(tmp), (void *) &tmp);
260                 tmp = htonl(curpacket->packet->length);
261                 md5_update(&md5_context, sizeof(tmp), (void *) &tmp);
262                 md5_update(&md5_context,
263                                 curpacket->packet->length,
264                                 curpacket->packet->data);
265         }
266
267         md5_digest(&md5_context, 16, (uint8_t *) &hash->hash);
268         free_packet_list(packets);
269
270         return ONAK_E_OK;
271 }
272
273 uint8_t hexdigit(char c)
274 {
275         if (c >= '0' && c <= '9')
276                 return c - '0';
277         else if (c >= 'a' && c <= 'f')
278                 return c - 'a' + 10;
279         else if (c >= 'A' && c <= 'F')
280                 return c - 'A' + 10;
281         else
282                 return 0;
283 }
284
285 int parse_skshash(char *search, struct skshash *hash)
286 {
287         int i, len;
288
289         len = strlen(search);
290         if (len > 32) {
291                 return 0;
292         }
293
294         for (i = 0; i < len; i += 2) {
295                 hash->hash[i >> 1] = (hexdigit(search[i]) << 4) +
296                                 hexdigit(search[i + 1]);
297         }
298
299         return 1;
300 }