fad8fe10f84745ab9e4a2a121e863fb3e6888dc6
[strongswan.git] / src / libstrongswan / plugins / pgp / pgp_builder.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * Copyright (C) 2002-2009 Andreas Steffen
4 * 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 "pgp_builder.h"
18
19 #include <enum.h>
20 #include <debug.h>
21 #include <credentials/keys/private_key.h>
22
23 typedef enum pgp_pubkey_alg_t pgp_pubkey_alg_t;
24 typedef enum pgp_sym_alg_t pgp_sym_alg_t;
25
26 /**
27 * OpenPGP public key algorithms as defined in section 9.1 of RFC 4880
28 */
29 enum pgp_pubkey_alg_t {
30 PGP_PUBKEY_ALG_RSA = 1,
31 PGP_PUBKEY_ALG_RSA_ENC_ONLY = 2,
32 PGP_PUBKEY_ALG_RSA_SIGN_ONLY = 3,
33 PGP_PUBKEY_ALG_ELGAMAL_ENC_ONLY = 16,
34 PGP_PUBKEY_ALG_DSA = 17,
35 PGP_PUBKEY_ALG_ECC = 18,
36 PGP_PUBKEY_ALG_ECDSA = 19,
37 PGP_PUBKEY_ALG_ELGAMAL = 20,
38 PGP_PUBKEY_ALG_DIFFIE_HELLMAN = 21,
39 };
40
41 /**
42 * OpenPGP symmetric key algorithms as defined in section 9.2 of RFC 4880
43 */
44 enum pgp_sym_alg_t {
45 PGP_SYM_ALG_PLAIN = 0,
46 PGP_SYM_ALG_IDEA = 1,
47 PGP_SYM_ALG_3DES = 2,
48 PGP_SYM_ALG_CAST5 = 3,
49 PGP_SYM_ALG_BLOWFISH = 4,
50 PGP_SYM_ALG_SAFER = 5,
51 PGP_SYM_ALG_DES = 6,
52 PGP_SYM_ALG_AES_128 = 7,
53 PGP_SYM_ALG_AES_192 = 8,
54 PGP_SYM_ALG_AES_256 = 9,
55 PGP_SYM_ALG_TWOFISH = 10
56 };
57
58 ENUM_BEGIN(pgp_pubkey_alg_names, PGP_PUBKEY_ALG_RSA, PGP_PUBKEY_ALG_RSA_SIGN_ONLY,
59 "RSA",
60 "RSA_ENC_ONLY",
61 "RSA_SIGN_ONLY"
62 );
63 ENUM_NEXT(pgp_pubkey_alg_names, PGP_PUBKEY_ALG_ELGAMAL_ENC_ONLY, PGP_PUBKEY_ALG_DIFFIE_HELLMAN, PGP_PUBKEY_ALG_RSA_SIGN_ONLY,
64 "ELGAMAL_ENC_ONLY",
65 "DSA",
66 "ECC",
67 "ECDSA",
68 "ELGAMAL",
69 "DIFFIE_HELLMAN"
70 );
71 ENUM_END(pgp_pubkey_alg_names, PGP_PUBKEY_ALG_DIFFIE_HELLMAN);
72
73 ENUM(pgp_sym_alg_names, PGP_SYM_ALG_PLAIN, PGP_SYM_ALG_TWOFISH,
74 "PLAINTEXT",
75 "IDEA",
76 "3DES",
77 "CAST5",
78 "BLOWFISH",
79 "SAFER",
80 "DES",
81 "AES_128",
82 "AES_192",
83 "AES_256",
84 "TWOFISH"
85 );
86
87 /**
88 * Read a PGP scalar of bytes length, advance blob
89 */
90 static bool read_scalar(chunk_t *blob, size_t bytes, u_int32_t *scalar)
91 {
92 u_int32_t res = 0;
93
94 if (bytes > blob->len)
95 {
96 DBG1("PGP data too short to read %d byte scalar", bytes);
97 return FALSE;
98 }
99 while (bytes-- > 0)
100 {
101 res = 256 * res + blob->ptr[0];
102 *blob = chunk_skip(*blob, 1);
103 }
104 *scalar = res;
105 return TRUE;
106 }
107
108 /**
109 * Read length of an PGP old packet length encoding
110 */
111 static bool old_packet_length(chunk_t *blob, u_int32_t *length)
112 {
113 /* bits 0 and 1 define the packet length type */
114 u_char type;
115
116 if (!blob->len)
117 {
118 return FALSE;
119 }
120 type = 0x03 & blob->ptr[0];
121 *blob = chunk_skip(*blob, 1);
122
123 if (type > 2)
124 {
125 return FALSE;
126 }
127 return read_scalar(blob, type == 0 ? 1 : type * 2, length);
128 }
129
130 /**
131 * Read a PGP MPI, advance blob
132 */
133 static bool read_mpi(chunk_t *blob, chunk_t *mpi)
134 {
135 u_int32_t bits, bytes;
136
137 if (!read_scalar(blob, 2, &bits))
138 {
139 DBG1("PGP data too short to read MPI length");
140 return FALSE;
141 }
142 bytes = (bits + 7) / 8;
143 if (bytes > blob->len)
144 {
145 DBG1("PGP data too short to read %d byte MPI", bytes);
146 return FALSE;
147 }
148 *mpi = chunk_create(blob->ptr, bytes);
149 *blob = chunk_skip(*blob, bytes);
150 return TRUE;
151 }
152
153 /**
154 * Load a generic public key from a PGP packet
155 */
156 static public_key_t *parse_public_key(chunk_t blob)
157 {
158 u_int32_t alg;
159 public_key_t *key;
160
161 if (!read_scalar(&blob, 1, &alg))
162 {
163 return NULL;
164 }
165 switch (alg)
166 {
167 case PGP_PUBKEY_ALG_RSA:
168 case PGP_PUBKEY_ALG_RSA_SIGN_ONLY:
169 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
170 BUILD_BLOB_PGP, blob, BUILD_END);
171 break;
172 default:
173 DBG1("PGP public key algorithm %N not supported",
174 pgp_pubkey_alg_names, alg);
175 return NULL;
176 }
177 return key;
178 }
179
180 /**
181 * Load a RSA public key from a PGP packet
182 */
183 static public_key_t *parse_rsa_public_key(chunk_t blob)
184 {
185 chunk_t mpi[2];
186 int i;
187
188 for (i = 0; i < 2; i++)
189 {
190 if (!read_mpi(&blob, &mpi[i]))
191 {
192 return NULL;
193 }
194 }
195 return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
196 BUILD_RSA_MODULUS, mpi[0], BUILD_RSA_PUB_EXP, mpi[1],
197 BUILD_END);
198 }
199
200 /**
201 * Load a RSA private key from a PGP packet
202 */
203 static private_key_t *parse_rsa_private_key(chunk_t blob)
204 {
205 chunk_t mpi[6];
206 u_int32_t s2k;
207 int i;
208
209 for (i = 0; i < 2; i++)
210 {
211 if (!read_mpi(&blob, &mpi[i]))
212 {
213 return NULL;
214 }
215 }
216 if (!read_scalar(&blob, 1, &s2k))
217 {
218 return NULL;
219 }
220 if (s2k == 255 || s2k == 254)
221 {
222 DBG1("string-to-key specifiers not supported");
223 return NULL;
224 }
225 if (s2k != PGP_SYM_ALG_PLAIN)
226 {
227 DBG1("%N private key encryption not supported", pgp_sym_alg_names, s2k);
228 return NULL;
229 }
230
231 for (i = 2; i < 6; i++)
232 {
233 if (!read_mpi(&blob, &mpi[i]))
234 {
235 return NULL;
236 }
237 }
238
239 /* PGP has uses p < q, but we use p > q */
240 return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
241 BUILD_RSA_MODULUS, mpi[0], BUILD_RSA_PUB_EXP, mpi[1],
242 BUILD_RSA_PRIV_EXP, mpi[2], BUILD_RSA_PRIME2, mpi[3],
243 BUILD_RSA_PRIME1, mpi[4], BUILD_RSA_COEFF, mpi[5],
244 BUILD_END);
245 }
246
247 /**
248 * Implementation of private_key_t.sign for encryption-only keys
249 */
250 static bool sign_not_allowed(private_key_t *this, signature_scheme_t scheme,
251 chunk_t data, chunk_t *signature)
252 {
253 DBG1("signing failed - decryption only key");
254 return FALSE;
255 }
256
257 /**
258 * Implementation of private_key_t.decrypt for signature-only keys
259 */
260 static bool decrypt_not_allowed(private_key_t *this,
261 chunk_t crypto, chunk_t *plain)
262 {
263 DBG1("decryption failed - signature only key");
264 return FALSE;
265 }
266
267 /**
268 * Load a generic private key from a PGP packet
269 */
270 static private_key_t *parse_private_key(chunk_t blob)
271 {
272 chunk_t packet;
273 u_char tag, type;
274 u_int32_t len, version, created, days, alg;
275 private_key_t *key;
276
277 tag = blob.ptr[0];
278
279 /* bit 7 must be set */
280 if (!(tag & 0x80))
281 {
282 DBG1("invalid packet tag");
283 return NULL;
284 }
285 /* bit 6 set defines new packet format */
286 if (tag & 0x40)
287 {
288 DBG1("new PGP packet format not supported");
289 return NULL;
290 }
291
292 type = (tag & 0x3C) >> 2;
293 if (!old_packet_length(&blob, &len) || len > blob.len)
294 {
295 DBG1("invalid packet length");
296 return NULL;
297 }
298 packet.len = len;
299 packet.ptr = blob.ptr;
300 blob = chunk_skip(blob, len);
301
302 if (!read_scalar(&packet, 1, &version))
303 {
304 return NULL;
305 }
306 if (version < 3 || version > 4)
307 {
308 DBG1("OpenPGP packet version V%d not supported", version);
309 return NULL;
310 }
311 if (!read_scalar(&packet, 4, &created))
312 {
313 return NULL;
314 }
315 if (version == 3)
316 {
317 if (!read_scalar(&packet, 2, &days))
318 {
319 return NULL;
320 }
321 }
322 if (!read_scalar(&packet, 1, &alg))
323 {
324 return NULL;
325 }
326 switch (alg)
327 {
328 case PGP_PUBKEY_ALG_RSA:
329 return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
330 BUILD_BLOB_PGP, packet, BUILD_END);
331 case PGP_PUBKEY_ALG_RSA_ENC_ONLY:
332 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
333 BUILD_BLOB_PGP, packet, BUILD_END);
334 if (key)
335 {
336 key->sign = sign_not_allowed;
337 }
338 return key;
339 case PGP_PUBKEY_ALG_RSA_SIGN_ONLY:
340 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
341 BUILD_BLOB_PGP, packet, BUILD_END);
342 if (key)
343 {
344 key->decrypt = decrypt_not_allowed;
345 }
346 return key;
347 case PGP_PUBKEY_ALG_ECDSA:
348 return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
349 BUILD_BLOB_PGP, packet, BUILD_END);
350 case PGP_PUBKEY_ALG_ELGAMAL_ENC_ONLY:
351 case PGP_PUBKEY_ALG_DSA:
352 case PGP_PUBKEY_ALG_ECC:
353 case PGP_PUBKEY_ALG_ELGAMAL:
354 case PGP_PUBKEY_ALG_DIFFIE_HELLMAN:
355 default:
356 return NULL;
357 }
358 }
359
360 typedef struct private_builder_t private_builder_t;
361
362 /**
363 * Builder implementation for private/public key loading
364 */
365 struct private_builder_t {
366 /** implements the builder interface */
367 builder_t public;
368 /** PGP packet data */
369 chunk_t blob;
370 /** type of key to build */
371 key_type_t type;
372 };
373
374 /**
375 * Implementation of builder_t.build for public keys
376 */
377 static public_key_t *build_public(private_builder_t *this)
378 {
379 public_key_t *key = NULL;
380
381 switch (this->type)
382 {
383 case KEY_ANY:
384 key = parse_public_key(this->blob);
385 break;
386 case KEY_RSA:
387 key = parse_rsa_public_key(this->blob);
388 break;
389 default:
390 break;
391 }
392 free(this);
393 return key;
394 }
395
396 /**
397 * Implementation of builder_t.add for public keys
398 */
399 static void add_public(private_builder_t *this, builder_part_t part, ...)
400 {
401 va_list args;
402
403 switch (part)
404 {
405 case BUILD_BLOB_PGP:
406 {
407 va_start(args, part);
408 this->blob = va_arg(args, chunk_t);
409 va_end(args);
410 break;
411 }
412 default:
413 builder_cancel(&this->public);
414 break;
415 }
416 }
417
418 /**
419 * Builder construction function for public keys
420 */
421 builder_t *pgp_public_key_builder(key_type_t type)
422 {
423 private_builder_t *this;
424
425 if (type != KEY_ANY && type != KEY_RSA)
426 {
427 return NULL;
428 }
429
430 this = malloc_thing(private_builder_t);
431
432 this->blob = chunk_empty;
433 this->type = type;
434 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add_public;
435 this->public.build = (void*(*)(builder_t *this))build_public;
436
437 return &this->public;
438 }
439
440 /**
441 * Implementation of builder_t.build for private keys
442 */
443 static private_key_t *build_private(private_builder_t *this)
444 {
445 private_key_t *key = NULL;
446
447 switch (this->type)
448 {
449 case KEY_ANY:
450 key = parse_private_key(this->blob);
451 break;
452 case KEY_RSA:
453 key = parse_rsa_private_key(this->blob);
454 break;
455 default:
456 break;
457 }
458 free(this);
459 return key;
460 }
461
462 /**
463 * Implementation of builder_t.add for private keys
464 */
465 static void add_private(private_builder_t *this, builder_part_t part, ...)
466 {
467 va_list args;
468
469 switch (part)
470 {
471 case BUILD_BLOB_PGP:
472 {
473 va_start(args, part);
474 this->blob = va_arg(args, chunk_t);
475 va_end(args);
476 break;
477 }
478 default:
479 builder_cancel(&this->public);
480 break;
481 }
482 }
483
484 /**
485 * Builder construction function for private keys
486 */
487 builder_t *pgp_private_key_builder(key_type_t type)
488 {
489 private_builder_t *this;
490
491 if (type != KEY_ANY && type != KEY_RSA)
492 {
493 return NULL;
494 }
495
496 this = malloc_thing(private_builder_t);
497
498 this->blob = chunk_empty;
499 this->type = type;
500 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add_private;
501 this->public.build = (void*(*)(builder_t *this))build_private;
502
503 return &this->public;
504 }
505