hooray, pluto and scepclient do not depend on libgmp anymore
[strongswan.git] / src / pluto / pgpcert.c
1 /* Support of OpenPGP certificates
2 * Copyright (C) 2002-2009 Andreas Steffen
3 *
4 * HSR - Hochschule fuer Technik Rapperswil
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
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <stdlib.h>
18 #include <string.h>
19 #include <time.h>
20
21 #include <freeswan.h>
22
23 #include <library.h>
24 #include <pgp/pgp.h>
25 #include <crypto/hashers/hasher.h>
26
27 #include "constants.h"
28 #include "defs.h"
29 #include "log.h"
30 #include "id.h"
31 #include "pgpcert.h"
32 #include "certs.h"
33 #include "whack.h"
34 #include "keys.h"
35
36 /**
37 * Chained list of OpenPGP end certificates
38 */
39 static pgpcert_t *pgpcerts = NULL;
40
41 /**
42 * Size of PGP Key ID
43 */
44 #define PGP_KEYID_SIZE 8
45
46 const pgpcert_t pgpcert_empty = {
47 NULL , /* next */
48 0 , /* version */
49 0 , /* installed */
50 0 , /* count */
51 { NULL, 0 }, /* certificate */
52 0 , /* created */
53 0 , /* until */
54 NULL , /* public key */
55 NULL /* fingerprint */
56 };
57
58
59 /**
60 * Extracts the length of a PGP packet
61 */
62 static size_t pgp_old_packet_length(chunk_t *blob)
63 {
64 /* bits 0 and 1 define the packet length type */
65 int len_type = 0x03 & *blob->ptr++;
66
67 blob->len--;
68
69 /* len_type: 0 -> 1 byte, 1 -> 2 bytes, 2 -> 4 bytes */
70 return pgp_length(blob, (len_type == 0)? 1: len_type << 1);
71 }
72
73 /**
74 * Extracts PGP packet version (V3 or V4)
75 */
76 static u_char pgp_version(chunk_t *blob)
77 {
78 u_char version = *blob->ptr++;
79 blob->len--;
80 DBG(DBG_PARSING,
81 DBG_log("L3 - version:");
82 DBG_log(" V%d", version)
83 )
84 return version;
85 }
86
87 /**
88 * Parse OpenPGP signature packet defined in section 5.2.2 of RFC 2440
89 */
90 static bool parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert)
91 {
92 time_t created;
93 chunk_t keyid;
94 u_char sig_type;
95 u_char version = pgp_version(packet);
96
97 /* we parse only V3 signature packets */
98 if (version != 3)
99 {
100 return TRUE;
101 }
102
103 /* size byte must have the value 5 */
104 if (pgp_length(packet, 1) != 5)
105 {
106 plog(" size must be 5");
107 return FALSE;
108 }
109
110 /* signature type - 1 byte */
111 sig_type = (u_char)pgp_length(packet, 1);
112 DBG(DBG_PARSING,
113 DBG_log("L3 - signature type: 0x%2x", sig_type)
114 )
115
116 /* creation date - 4 bytes */
117 created = (time_t)pgp_length(packet, 4);
118 DBG(DBG_PARSING,
119 DBG_log("L3 - created:");
120 DBG_log(" %T", &cert->created, TRUE)
121 )
122
123 /* key ID of signer - 8 bytes */
124 keyid.ptr = packet->ptr;
125 keyid.len = PGP_KEYID_SIZE;
126 DBG_cond_dump_chunk(DBG_PARSING, "L3 - key ID of signer", keyid);
127
128 return TRUE;
129 }
130
131 /**
132 * Parses the version and validity of an OpenPGP public key packet
133 */
134 static bool parse_pgp_pubkey_version_validity(chunk_t *packet, pgpcert_t *cert)
135 {
136 cert->version = pgp_version(packet);
137
138 if (cert->version < 3 || cert->version > 4)
139 {
140 plog("OpenPGP packet version V%d not supported", cert->version);
141 return FALSE;
142 }
143
144 /* creation date - 4 bytes */
145 cert->created = (time_t)pgp_length(packet, 4);
146 DBG(DBG_PARSING,
147 DBG_log("L3 - created:");
148 DBG_log(" %T", &cert->created, TRUE)
149 )
150
151 if (cert->version == 3)
152 {
153 /* validity in days - 2 bytes */
154 cert->until = (time_t)pgp_length(packet, 2);
155
156 /* validity of 0 days means that the key never expires */
157 if (cert->until > 0)
158 {
159 cert->until = cert->created + 24*3600*cert->until;
160 }
161 DBG(DBG_PARSING,
162 DBG_log("L3 - until:");
163 DBG_log(" %T", &cert->until, TRUE);
164 )
165 }
166 return TRUE;
167 }
168
169 /**
170 * Parse OpenPGP public key packet defined in section 5.5.2 of RFC 4880
171 */
172 static bool parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
173 {
174 pgp_pubkey_alg_t pubkey_alg;
175 public_key_t *key;
176
177 if (!parse_pgp_pubkey_version_validity(packet, cert))
178 {
179 return FALSE;
180 }
181
182 /* public key algorithm - 1 byte */
183 pubkey_alg = pgp_length(packet, 1);
184 DBG(DBG_PARSING,
185 DBG_log("L3 - public key algorithm:");
186 DBG_log(" %N", pgp_pubkey_alg_names, pubkey_alg)
187 )
188
189 switch (pubkey_alg)
190 {
191 case PGP_PUBKEY_ALG_RSA:
192 case PGP_PUBKEY_ALG_RSA_SIGN_ONLY:
193 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
194 BUILD_BLOB_PGP, *packet,
195 BUILD_END);
196 if (key == NULL)
197 {
198 return FALSE;
199 }
200 cert->public_key = key;
201
202 if (cert->version == 3)
203 {
204 cert->fingerprint = key->get_id(key, ID_KEY_ID);
205 if (cert->fingerprint == NULL)
206 {
207 return FALSE;
208 }
209 }
210 else
211 {
212 plog(" computation of V4 key ID not implemented yet");
213 return FALSE;
214 }
215 break;
216 default:
217 plog(" non RSA public keys not supported");
218 return FALSE;
219 }
220 return TRUE;
221 }
222
223 /*
224 * Parse OpenPGP secret key packet defined in section 5.5.3 of RFC 4880
225 */
226 static bool parse_pgp_secretkey_packet(chunk_t *packet, private_key_t **key)
227 {
228 pgp_pubkey_alg_t pubkey_alg;
229 pgpcert_t cert = pgpcert_empty;
230
231 if (!parse_pgp_pubkey_version_validity(packet, &cert))
232 {
233 return FALSE;
234 }
235
236 /* public key algorithm - 1 byte */
237 pubkey_alg = pgp_length(packet, 1);
238 DBG(DBG_PARSING,
239 DBG_log("L3 - public key algorithm:");
240 DBG_log(" %N", pgp_pubkey_alg_names, pubkey_alg)
241 )
242
243 switch (pubkey_alg)
244 {
245 case PGP_PUBKEY_ALG_RSA:
246 case PGP_PUBKEY_ALG_RSA_SIGN_ONLY:
247 *key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
248 BUILD_BLOB_PGP, *packet,
249 BUILD_END);
250 break;
251 default:
252 plog(" non RSA private keys not supported");
253 return FALSE;
254 }
255 return (*key != NULL);
256 }
257
258 bool parse_pgp(chunk_t blob, pgpcert_t *cert, private_key_t **key)
259 {
260 DBG(DBG_PARSING,
261 DBG_log("L0 - PGP file:")
262 )
263 DBG_cond_dump_chunk(DBG_RAW, "", blob);
264
265 if (cert != NULL)
266 {
267 /* parse a PGP certificate file */
268 cert->certificate = blob;
269 time(&cert->installed);
270 }
271 else if (key == NULL)
272 {
273 /* should not occur, nothing to parse */
274 return FALSE;
275 }
276
277 while (blob.len > 0)
278 {
279 chunk_t packet = chunk_empty;
280 u_char packet_tag = *blob.ptr;
281
282 DBG(DBG_PARSING,
283 DBG_log("L1 - PGP packet: tag= 0x%2x", packet_tag)
284 )
285
286 /* bit 7 must be set */
287 if (!(packet_tag & 0x80))
288 {
289 plog(" incorrect Packet Tag");
290 return FALSE;
291 }
292
293 /* bit 6 set defines new packet format */
294 if (packet_tag & 0x40)
295 {
296 plog(" new PGP packet format not supported");
297 return FALSE;
298 }
299 else
300 {
301 int packet_type = (packet_tag & 0x3C) >> 2;
302
303 packet.len = pgp_old_packet_length(&blob);
304 packet.ptr = blob.ptr;
305 blob.ptr += packet.len;
306 blob.len -= packet.len;
307 DBG(DBG_PARSING,
308 DBG_log(" %N (%d), old format, %u bytes",
309 pgp_packet_tag_names, packet_type,
310 packet_type, packet.len);
311 DBG_log("L2 - body:")
312 )
313 DBG_cond_dump_chunk(DBG_RAW, "", packet);
314
315 if (cert != NULL)
316 {
317 /* parse a PGP certificate */
318 switch (packet_type)
319 {
320 case PGP_PKT_PUBLIC_KEY:
321 if (!parse_pgp_pubkey_packet(&packet, cert))
322 {
323 return FALSE;
324 }
325 break;
326 case PGP_PKT_SIGNATURE:
327 if (!parse_pgp_signature_packet(&packet, cert))
328 {
329 return FALSE;
330 }
331 break;
332 case PGP_PKT_USER_ID:
333 DBG(DBG_PARSING,
334 DBG_log("L3 - user ID:");
335 DBG_log(" '%.*s'", (int)packet.len, packet.ptr)
336 )
337 break;
338 default:
339 break;
340 }
341 }
342 else
343 {
344 /* parse a PGP private key file */
345 switch (packet_type)
346 {
347 case PGP_PKT_SECRET_KEY:
348 if (!parse_pgp_secretkey_packet(&packet, key))
349 {
350 return FALSE;
351 }
352 break;
353 case PGP_PKT_USER_ID:
354 DBG(DBG_PARSING,
355 DBG_log("L3 - user ID:");
356 DBG_log(" '%.*s'", (int)packet.len, packet.ptr)
357 )
358 break;
359 default:
360 break;
361 }
362
363 }
364 }
365 }
366 return TRUE;
367 }
368
369 /**
370 * Compare two OpenPGP certificates
371 */
372 static bool same_pgpcert(pgpcert_t *a, pgpcert_t *b)
373 {
374 return a->certificate.len == b->certificate.len &&
375 memeq(a->certificate.ptr, b->certificate.ptr, b->certificate.len);
376 }
377
378 /**
379 * For each link pointing to the certificate increase the count by one
380 */
381 void share_pgpcert(pgpcert_t *cert)
382 {
383 if (cert != NULL)
384 {
385 cert->count++;
386 }
387 }
388
389 /**
390 * Select the OpenPGP keyid as ID
391 */
392 void select_pgpcert_id(pgpcert_t *cert, struct id *end_id)
393 {
394 end_id->kind = ID_KEY_ID;
395 end_id->name = cert->fingerprint->get_encoding(cert->fingerprint);
396 }
397
398 /**
399 * Add an OpenPGP user/host certificate to the chained list
400 */
401 pgpcert_t* add_pgpcert(pgpcert_t *cert)
402 {
403 pgpcert_t *c = pgpcerts;
404
405 while (c != NULL)
406 {
407 if (same_pgpcert(c, cert)) /* already in chain, free cert */
408 {
409 free_pgpcert(cert);
410 return c;
411 }
412 c = c->next;
413 }
414
415 /* insert new cert at the root of the chain */
416 cert->next = pgpcerts;
417 pgpcerts = cert;
418 DBG(DBG_CONTROL | DBG_PARSING,
419 DBG_log(" pgp cert inserted")
420 )
421 return cert;
422 }
423
424 /**
425 * Release of a certificate decreases the count by one.
426 * The certificate is freed when the counter reaches zero
427 */
428 void release_pgpcert(pgpcert_t *cert)
429 {
430 if (cert != NULL && --cert->count == 0)
431 {
432 pgpcert_t **pp = &pgpcerts;
433 while (*pp != cert)
434 {
435 pp = &(*pp)->next;
436 }
437 *pp = cert->next;
438 free_pgpcert(cert);
439 }
440 }
441
442 /**
443 * Free a PGP certificate
444 */
445 void free_pgpcert(pgpcert_t *cert)
446 {
447 if (cert != NULL)
448 {
449 DESTROY_IF(cert->public_key);
450 DESTROY_IF(cert->fingerprint);
451 free(cert->certificate.ptr);
452 free(cert);
453 }
454 }
455
456 /**
457 * List all PGP end certificates in a chained list
458 */
459 void list_pgp_end_certs(bool utc)
460 {
461 pgpcert_t *cert = pgpcerts;
462 time_t now;
463
464 /* determine the current time */
465 time(&now);
466
467 if (cert != NULL)
468 {
469 whack_log(RC_COMMENT, " ");
470 whack_log(RC_COMMENT, "List of PGP End certificates:");
471 whack_log(RC_COMMENT, " ");
472 }
473
474 while (cert != NULL)
475 {
476 public_key_t *key = cert->public_key;
477 cert_t c;
478
479 c.type = CERT_PGP;
480 c.u.pgp = cert;
481
482 whack_log(RC_COMMENT, "%T, count: %d", &cert->installed, utc, cert->count);
483 whack_log(RC_COMMENT, " digest: %Y", cert->fingerprint);
484 whack_log(RC_COMMENT, " created: %T", &cert->created, utc);
485 whack_log(RC_COMMENT, " until: %T %s", &cert->until, utc,
486 check_expiry(cert->until, CA_CERT_WARNING_INTERVAL, TRUE));
487 whack_log(RC_COMMENT, " pubkey: %N %4d bits%s",
488 key_type_names, key->get_type(key),
489 key->get_keysize(key) * BITS_PER_BYTE,
490 has_private_key(c)? ", has private key" : "");
491 whack_log(RC_COMMENT, " keyid: %Y",
492 key->get_id(key, ID_PUBKEY_INFO_SHA1));
493 cert = cert->next;
494 }
495 }
496