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