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