5b21b46d446cc5785ac92da5292e278e8ea0b018
[strongswan.git] / src / libstrongswan / plugins / pgp / pgp_cert.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "pgp_cert.h"
17 #include "pgp_utils.h"
18
19 #include <time.h>
20
21 #include <debug.h>
22
23 typedef struct private_pgp_cert_t private_pgp_cert_t;
24
25 /**
26 * Private data of an pgp_cert_t object.
27 */
28 struct private_pgp_cert_t {
29
30 /**
31 * Implements pgp_cert_t interface.
32 */
33 pgp_cert_t public;
34
35 /**
36 * Public key of the certificate
37 */
38 public_key_t *key;
39
40 /**
41 * version of the public key
42 */
43 u_int32_t version;
44
45 /**
46 * creation time
47 */
48 u_int32_t created;
49
50 /**
51 * days the certificate is valid
52 */
53 u_int32_t valid;
54
55 /**
56 * userid of the certificate
57 */
58 identification_t *user_id;
59
60 /**
61 * v3 or v4 fingerprint of the PGP public key
62 */
63 chunk_t fingerprint;
64
65 /**
66 * full PGP encoding
67 */
68 chunk_t encoding;
69
70 /**
71 * reference counter
72 */
73 refcount_t ref;
74 };
75
76
77 /**
78 * Implementation of certificate_t.get_type
79 */
80 static certificate_type_t get_type(private_pgp_cert_t *this)
81 {
82 return CERT_GPG;
83 }
84
85 /**
86 * Implementation of certificate_t.get_subject
87 */
88 static identification_t* get_subject(private_pgp_cert_t *this)
89 {
90 return this->user_id;
91 }
92
93 /**
94 * Implementation of certificate_t.get_issuer
95 */
96 static identification_t* get_issuer(private_pgp_cert_t *this)
97 {
98 return this->user_id;
99 }
100
101 /**
102 * Implementation of certificate_t.has_subject.
103 */
104 static id_match_t has_subject(private_pgp_cert_t *this,
105 identification_t *subject)
106 {
107 id_match_t match_user_id;
108
109 match_user_id = this->user_id->matches(this->user_id, subject);
110 if (match_user_id == ID_MATCH_NONE &&
111 subject->get_type(subject) == ID_KEY_ID &&
112 chunk_equals(this->fingerprint, subject->get_encoding(subject)))
113 {
114 return ID_MATCH_PERFECT;
115 }
116 return match_user_id;
117 }
118
119 /**
120 * Implementation of certificate_t.has_subject.
121 */
122 static id_match_t has_issuer(private_pgp_cert_t *this, identification_t *issuer)
123 {
124 return ID_MATCH_NONE;
125 }
126
127 /**
128 * Implementation of certificate_t.issued_by
129 */
130 static bool issued_by(private_pgp_cert_t *this, certificate_t *issuer)
131 {
132 /* TODO: check signature blobs for a valid signature */
133 return FALSE;
134 }
135
136 /**
137 * Implementation of certificate_t.get_public_key
138 */
139 static public_key_t* get_public_key(private_pgp_cert_t *this)
140 {
141 this->key->get_ref(this->key);
142 return this->key;
143 }
144
145 /**
146 * Implementation of certificate_t.get_ref
147 */
148 static private_pgp_cert_t* get_ref(private_pgp_cert_t *this)
149 {
150 ref_get(&this->ref);
151 return this;
152 }
153
154 /**
155 * Implementation of certificate_t.get_validity.
156 */
157 static bool get_validity(private_pgp_cert_t *this, time_t *when,
158 time_t *not_before, time_t *not_after)
159 {
160 time_t t, until;
161
162 if (when)
163 {
164 t = *when;
165 }
166 else
167 {
168 t = time(NULL);
169 }
170 if (not_before)
171 {
172 *not_before = this->created;
173 }
174 if (this->valid)
175 {
176 until = this->valid + this->created * 24 * 60 * 60;
177 }
178 else
179 {
180 /* Jan 19 03:14:07 UTC 2038 */
181 until = TIME_32_BIT_SIGNED_MAX;
182 }
183 if (not_after)
184 {
185 *not_after = until;
186 }
187 return (t >= this->valid && t <= until);
188 }
189
190 /**
191 * Implementation of certificate_t.get_encoding.
192 */
193 static bool get_encoding(private_pgp_cert_t *this, cred_encoding_type_t type,
194 chunk_t *encoding)
195 {
196 if (type == CERT_PGP_PKT)
197 {
198 *encoding = chunk_clone(this->encoding);
199 return TRUE;
200 }
201 return lib->encoding->encode(lib->encoding, type, NULL, encoding,
202 CRED_PART_PGP_CERT, this->encoding, CRED_PART_END);
203 }
204
205 /**
206 * Implementation of certificate_t.equals.
207 */
208 static bool equals(private_pgp_cert_t *this, certificate_t *other)
209 {
210 chunk_t encoding;
211 bool equal;
212
213 if (this == (private_pgp_cert_t*)other)
214 {
215 return TRUE;
216 }
217 if (other->get_type(other) != CERT_X509)
218 {
219 return FALSE;
220 }
221 if (other->equals == (void*)equals)
222 { /* skip allocation if we have the same implementation */
223 return chunk_equals(this->encoding, ((private_pgp_cert_t*)other)->encoding);
224 }
225 if (!other->get_encoding(other, CERT_PGP_PKT, &encoding))
226 {
227 return FALSE;
228 }
229 equal = chunk_equals(this->encoding, encoding);
230 free(encoding.ptr);
231 return equal;
232 }
233
234 /**
235 * Implementation of pgp_cert_t.destroy.
236 */
237 static void destroy(private_pgp_cert_t *this)
238 {
239 if (ref_put(&this->ref))
240 {
241 DESTROY_IF(this->key);
242 DESTROY_IF(this->user_id);
243 free(this->fingerprint.ptr);
244 free(this->encoding.ptr);
245 free(this);
246 }
247 }
248
249 /**
250 * Implementation of pgp_certificate_t.get_fingerprint.
251 */
252 static chunk_t get_fingerprint(private_pgp_cert_t *this)
253 {
254 return this->fingerprint;
255 }
256
257 /**
258 * See header
259 */
260 private_pgp_cert_t *create_empty()
261 {
262 private_pgp_cert_t *this = malloc_thing(private_pgp_cert_t);
263
264 this->public.interface.interface.get_type = (certificate_type_t (*) (certificate_t*))get_type;
265 this->public.interface.interface.get_subject = (identification_t* (*) (certificate_t*))get_subject;
266 this->public.interface.interface.get_issuer = (identification_t* (*) (certificate_t*))get_issuer;
267 this->public.interface.interface.has_subject = (id_match_t (*) (certificate_t*, identification_t*))has_subject;
268 this->public.interface.interface.has_issuer = (id_match_t (*) (certificate_t*, identification_t*))has_issuer;
269 this->public.interface.interface.issued_by = (bool (*) (certificate_t*, certificate_t*))issued_by;
270 this->public.interface.interface.get_public_key = (public_key_t* (*) (certificate_t*))get_public_key;
271 this->public.interface.interface.get_validity = (bool (*) (certificate_t*, time_t*, time_t*, time_t*))get_validity;
272 this->public.interface.interface.get_encoding = (bool (*) (certificate_t*,cred_encoding_type_t,chunk_t*))get_encoding;
273 this->public.interface.interface.equals = (bool (*)(certificate_t*, certificate_t*))equals;
274 this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t*))get_ref;
275 this->public.interface.interface.destroy = (void (*)(certificate_t*))destroy;
276 this->public.interface.get_fingerprint = (chunk_t (*)(pgp_certificate_t*))get_fingerprint;
277
278 this->key = NULL;
279 this->version = 0;
280 this->created = 0;
281 this->valid = 0;
282 this->user_id = NULL;
283 this->fingerprint = chunk_empty;
284 this->encoding = chunk_empty;
285 this->ref = 1;
286
287 return this;
288 }
289
290 /**
291 * Parse the public key packet of a PGP certificate
292 */
293 static bool parse_public_key(private_pgp_cert_t *this, chunk_t packet)
294 {
295 chunk_t pubkey_packet = packet;
296
297 if (!pgp_read_scalar(&packet, 1, &this->version))
298 {
299 return FALSE;
300 }
301 switch (this->version)
302 {
303 case 3:
304 if (!pgp_read_scalar(&packet, 4, &this->created) ||
305 !pgp_read_scalar(&packet, 2, &this->valid))
306 {
307 return FALSE;
308 }
309 break;
310 case 4:
311 if (!pgp_read_scalar(&packet, 4, &this->created))
312 {
313 return FALSE;
314 }
315 break;
316 default:
317 DBG1(DBG_LIB, "PGP packet version V%d not supported",
318 this->version);
319 return FALSE;
320 }
321 if (this->valid)
322 {
323 DBG2(DBG_LIB, "L2 - created %T, valid %d days", &this->created, FALSE,
324 this->valid);
325 }
326 else
327 {
328 DBG2(DBG_LIB, "L2 - created %T, never expires", &this->created, FALSE);
329 }
330 DESTROY_IF(this->key);
331 this->key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
332 BUILD_BLOB_PGP, packet, BUILD_END);
333 if (this->key == NULL)
334 {
335 return FALSE;
336 }
337
338 /* compute V4 or V3 fingerprint according to section 12.2 of RFC 4880 */
339 if (this->version == 4)
340 {
341 chunk_t pubkey_packet_header = chunk_from_chars(
342 0x99, pubkey_packet.len / 256, pubkey_packet.len % 256
343 );
344 hasher_t *hasher;
345
346 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
347 if (hasher == NULL)
348 {
349 DBG1(DBG_LIB, "no SHA-1 hasher available");
350 return FALSE;
351 }
352 hasher->allocate_hash(hasher, pubkey_packet_header, NULL);
353 hasher->allocate_hash(hasher, pubkey_packet, &this->fingerprint);
354 hasher->destroy(hasher);
355 DBG2(DBG_LIB, "L2 - v4 fingerprint %#B", &this->fingerprint);
356 }
357 else
358 {
359 /* V3 fingerprint is computed by public_key_t class */
360 if (!this->key->get_fingerprint(this->key, KEYID_PGPV3,
361 &this->fingerprint))
362 {
363 return FALSE;
364 }
365 this->fingerprint = chunk_clone(this->fingerprint);
366 DBG2(DBG_LIB, "L2 - v3 fingerprint %#B", &this->fingerprint);
367 }
368 return TRUE;
369 }
370
371 /**
372 * Parse the signature packet of a PGP certificate
373 */
374 static bool parse_signature(private_pgp_cert_t *this, chunk_t packet)
375 {
376 u_int32_t version, len, type, created;
377
378 if (!pgp_read_scalar(&packet, 1, &version))
379 {
380 return FALSE;
381 }
382
383 /* we parse only v3 or v4 signature packets */
384 if (version != 3 && version != 4)
385 {
386 DBG2(DBG_LIB, "L2 - v%d signature ignored", version);
387 return TRUE;
388 }
389 if (version == 4)
390 {
391 if (!pgp_read_scalar(&packet, 1, &type))
392 {
393 return FALSE;
394 }
395 DBG2(DBG_LIB, "L2 - v%d signature of type 0x%02x", version, type);
396 }
397 else
398 {
399 if (!pgp_read_scalar(&packet, 1, &len) || len != 5)
400 {
401 return FALSE;
402 }
403 if (!pgp_read_scalar(&packet, 1, &type) ||
404 !pgp_read_scalar(&packet, 4, &created))
405 {
406 return FALSE;
407 }
408 DBG2(DBG_LIB, "L2 - v3 signature of type 0x%02x, created %T", type,
409 &created, FALSE);
410 }
411 /* TODO: parse and save signature to a list */
412 return TRUE;
413 }
414
415 /**
416 * Parse the userid packet of a PGP certificate
417 */
418 static bool parse_user_id(private_pgp_cert_t *this, chunk_t packet)
419 {
420 DESTROY_IF(this->user_id);
421 this->user_id = identification_create_from_encoding(ID_KEY_ID, packet);
422 DBG2(DBG_LIB, "L2 - '%Y'", this->user_id);
423 return TRUE;
424 }
425
426 /**
427 * See header.
428 */
429 pgp_cert_t *pgp_cert_load(certificate_type_t type, va_list args)
430 {
431 chunk_t packet, blob = chunk_empty;
432 pgp_packet_tag_t tag;
433 private_pgp_cert_t *this;
434
435 while (TRUE)
436 {
437 switch (va_arg(args, builder_part_t))
438 {
439 case BUILD_BLOB_PGP:
440 blob = va_arg(args, chunk_t);
441 continue;
442 case BUILD_END:
443 break;
444 default:
445 return NULL;
446 }
447 break;
448 }
449
450 this = create_empty();
451 this->encoding = chunk_clone(blob);
452 while (blob.len)
453 {
454 if (!pgp_read_packet(&blob, &packet, &tag))
455 {
456 destroy(this);
457 return NULL;
458 }
459 switch (tag)
460 {
461 case PGP_PKT_PUBLIC_KEY:
462 if (!parse_public_key(this, packet))
463 {
464 destroy(this);
465 return NULL;
466 }
467 break;
468 case PGP_PKT_SIGNATURE:
469 if (!parse_signature(this, packet))
470 {
471 destroy(this);
472 return FALSE;
473 }
474 break;
475 case PGP_PKT_USER_ID:
476 if (!parse_user_id(this, packet))
477 {
478 destroy(this);
479 return FALSE;
480 }
481 break;
482 default:
483 DBG1(DBG_LIB, "ignoring %N packet in PGP certificate",
484 pgp_packet_tag_names, tag);
485 break;
486 }
487 }
488 if (this->key)
489 {
490 return &this->public;
491 }
492 destroy(this);
493 return NULL;
494 }
495