Implemented support for preinstalled PGP certificates in charon
[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 * full PGP encoding
62 */
63 chunk_t encoding;
64
65 /**
66 * reference counter
67 */
68 refcount_t ref;
69 };
70
71
72 /**
73 * Implementation of certificate_t.get_type
74 */
75 static certificate_type_t get_type(private_pgp_cert_t *this)
76 {
77 return CERT_GPG;
78 }
79
80 /**
81 * Implementation of certificate_t.get_subject
82 */
83 static identification_t* get_subject(private_pgp_cert_t *this)
84 {
85 return this->user_id;
86 }
87
88 /**
89 * Implementation of certificate_t.get_issuer
90 */
91 static identification_t* get_issuer(private_pgp_cert_t *this)
92 {
93 return this->user_id;
94 }
95
96 /**
97 * Implementation of certificate_t.has_subject.
98 */
99 static id_match_t has_subject(private_pgp_cert_t *this,
100 identification_t *subject)
101 {
102 return this->user_id->matches(this->user_id, subject);
103 }
104
105 /**
106 * Implementation of certificate_t.has_subject.
107 */
108 static id_match_t has_issuer(private_pgp_cert_t *this, identification_t *issuer)
109 {
110 return ID_MATCH_NONE;
111 }
112
113 /**
114 * Implementation of certificate_t.issued_by
115 */
116 static bool issued_by(private_pgp_cert_t *this, certificate_t *issuer)
117 {
118 /* TODO: check signature blobs for a valid signature */
119 return FALSE;
120 }
121
122 /**
123 * Implementation of certificate_t.get_public_key
124 */
125 static public_key_t* get_public_key(private_pgp_cert_t *this)
126 {
127 this->key->get_ref(this->key);
128 return this->key;
129 }
130
131 /**
132 * Implementation of certificate_t.get_ref
133 */
134 static private_pgp_cert_t* get_ref(private_pgp_cert_t *this)
135 {
136 ref_get(&this->ref);
137 return this;
138 }
139
140 /**
141 * Implementation of x509_cert_t.get_validity.
142 */
143 static bool get_validity(private_pgp_cert_t *this, time_t *when,
144 time_t *not_before, time_t *not_after)
145 {
146 time_t t, until;
147
148 if (when)
149 {
150 t = *when;
151 }
152 else
153 {
154 t = time(NULL);
155 }
156 if (not_before)
157 {
158 *not_before = this->created;
159 }
160 if (this->valid)
161 {
162 until = this->valid + this->created * 24 * 60 * 60;
163 }
164 else
165 {
166 /* year 2038 */
167 until = 2147483647;
168 }
169 if (not_after)
170 {
171 *not_after = until;
172 }
173 return (t >= this->valid && t <= until);
174 }
175
176 /**
177 * Implementation of certificate_t.is_newer.
178 */
179 static bool is_newer(certificate_t *this, certificate_t *that)
180 {
181 time_t this_update, that_update, now = time(NULL);
182 bool new;
183
184 this->get_validity(this, &now, &this_update, NULL);
185 that->get_validity(that, &now, &that_update, NULL);
186 new = this_update > that_update;
187 DBG1(" certificate from %T is %s - existing certificate from %T %s",
188 &this_update, FALSE, new ? "newer":"not newer",
189 &that_update, FALSE, new ? "replaced":"retained");
190 return new;
191 }
192
193 /**
194 * Implementation of certificate_t.get_encoding.
195 */
196 static chunk_t get_encoding(private_pgp_cert_t *this)
197 {
198 return chunk_clone(this->encoding);
199 }
200
201 /**
202 * Implementation of certificate_t.equals.
203 */
204 static bool equals(private_pgp_cert_t *this, certificate_t *other)
205 {
206 chunk_t encoding;
207 bool equal;
208
209 if (this == (private_pgp_cert_t*)other)
210 {
211 return TRUE;
212 }
213 if (other->get_type(other) != CERT_X509)
214 {
215 return FALSE;
216 }
217 if (other->equals == (void*)equals)
218 { /* skip allocation if we have the same implementation */
219 return chunk_equals(this->encoding, ((private_pgp_cert_t*)other)->encoding);
220 }
221 encoding = other->get_encoding(other);
222 equal = chunk_equals(this->encoding, encoding);
223 free(encoding.ptr);
224 return equal;
225 }
226
227 /**
228 * Implementation of pgp_cert_t.destroy.
229 */
230 static void destroy(private_pgp_cert_t *this)
231 {
232 if (ref_put(&this->ref))
233 {
234 DESTROY_IF(this->key);
235 DESTROY_IF(this->user_id);
236 free(this->encoding.ptr);
237 free(this);
238 }
239 }
240
241 /**
242 * See header
243 */
244 private_pgp_cert_t *create_empty()
245 {
246 private_pgp_cert_t *this = malloc_thing(private_pgp_cert_t);
247
248 this->public.interface.interface.get_type = (certificate_type_t (*) (certificate_t*))get_type;
249 this->public.interface.interface.get_subject = (identification_t* (*) (certificate_t*))get_subject;
250 this->public.interface.interface.get_issuer = (identification_t* (*) (certificate_t*))get_issuer;
251 this->public.interface.interface.has_subject = (id_match_t (*) (certificate_t*, identification_t*))has_subject;
252 this->public.interface.interface.has_issuer = (id_match_t (*) (certificate_t*, identification_t*))has_issuer;
253 this->public.interface.interface.issued_by = (bool (*) (certificate_t*, certificate_t*))issued_by;
254 this->public.interface.interface.get_public_key = (public_key_t* (*) (certificate_t*))get_public_key;
255 this->public.interface.interface.get_validity = (bool (*) (certificate_t*, time_t*, time_t*, time_t*))get_validity;
256 this->public.interface.interface.is_newer = (bool (*) (certificate_t*,certificate_t*))is_newer;
257 this->public.interface.interface.get_encoding = (chunk_t (*) (certificate_t*))get_encoding;
258 this->public.interface.interface.equals = (bool (*)(certificate_t*, certificate_t*))equals;
259 this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t*))get_ref;
260 this->public.interface.interface.destroy = (void (*)(certificate_t*))destroy;
261
262 this->key = NULL;
263 this->version = 0;
264 this->created = 0;
265 this->valid = 0;
266 this->user_id = NULL;
267 this->encoding = chunk_empty;
268 this->ref = 1;
269
270 return this;
271 }
272
273 /**
274 * Parse the public key packet of a PGP certificate
275 */
276 static bool parse_public_key(private_pgp_cert_t *this, chunk_t packet)
277 {
278 if (!pgp_read_scalar(&packet, 1, &this->version))
279 {
280 return FALSE;
281 }
282 switch (this->version)
283 {
284 case 3:
285 if (!pgp_read_scalar(&packet, 4, &this->created) ||
286 !pgp_read_scalar(&packet, 2, &this->valid))
287 {
288 return FALSE;
289 }
290 break;
291 case 4:
292 if (!pgp_read_scalar(&packet, 4, &this->created))
293 {
294 return FALSE;
295 }
296 break;
297 default:
298 DBG1("PGP packet version V%d not supported", this->version);
299 return FALSE;
300 }
301 DESTROY_IF(this->key);
302 this->key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
303 BUILD_BLOB_PGP, packet, BUILD_END);
304 return this->key != NULL;
305 }
306
307 /**
308 * Parse the signature packet of a PGP certificate
309 */
310 static bool parse_signature(private_pgp_cert_t *this, chunk_t packet)
311 {
312 u_int32_t version, len, type, created;
313
314 if (!pgp_read_scalar(&packet, 1, &version))
315 {
316 return FALSE;
317 }
318 /* we parse only V3 signature packets */
319 if (version != 3)
320 {
321 DBG1("skipped V%d PGP signature", version);
322 return TRUE;
323 }
324 if (!pgp_read_scalar(&packet, 1, &len) || len != 5)
325 {
326 return FALSE;
327 }
328 if (!pgp_read_scalar(&packet, 1, &type) ||
329 !pgp_read_scalar(&packet, 1, &created))
330 {
331 return FALSE;
332 }
333 /* TODO: parse and save signature to a list */
334 return TRUE;
335 }
336
337 /**
338 * Parse the userid packet of a PGP certificate
339 */
340 static bool parse_user_id(private_pgp_cert_t *this, chunk_t packet)
341 {
342 DESTROY_IF(this->user_id);
343 this->user_id = identification_create_from_encoding(ID_RFC822_ADDR, packet);
344 return TRUE;
345 }
346
347 /**
348 * See header.
349 */
350 pgp_cert_t *pgp_cert_load(certificate_type_t type, va_list args)
351 {
352 chunk_t packet, blob = chunk_empty;
353 pgp_packet_tag_t tag;
354 private_pgp_cert_t *this;
355
356 while (TRUE)
357 {
358 switch (va_arg(args, builder_part_t))
359 {
360 case BUILD_BLOB_PGP:
361 blob = va_arg(args, chunk_t);
362 continue;
363 case BUILD_END:
364 break;
365 default:
366 return NULL;
367 }
368 break;
369 }
370
371 this = create_empty();
372 this->encoding = chunk_clone(blob);
373 while (blob.len)
374 {
375 if (!pgp_read_packet(&blob, &packet, &tag))
376 {
377 destroy(this);
378 return NULL;
379 }
380 switch (tag)
381 {
382 case PGP_PKT_PUBLIC_KEY:
383 if (!parse_public_key(this, packet))
384 {
385 destroy(this);
386 return NULL;
387 }
388 break;
389 case PGP_PKT_SIGNATURE:
390 if (!parse_signature(this, packet))
391 {
392 destroy(this);
393 return FALSE;
394 }
395 break;
396 case PGP_PKT_USER_ID:
397 if (!parse_user_id(this, packet))
398 {
399 destroy(this);
400 return FALSE;
401 }
402 break;
403 default:
404 DBG1("ignoring %N packet in PGP certificate",
405 pgp_packet_tag_names, tag);
406 break;
407 }
408 }
409 if (this->key)
410 {
411 return &this->public;
412 }
413 destroy(this);
414 return NULL;
415 }
416