PEM encoding for GMP RSA public and private keys
[strongswan.git] / src / libstrongswan / plugins / gmp / gmp_rsa_public_key.c
1 /*
2 * Copyright (C) 2005-2009 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
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 <gmp.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 #include <stdio.h>
21 #include <string.h>
22
23 #include "gmp_rsa_public_key.h"
24
25 #include <debug.h>
26 #include <asn1/oid.h>
27 #include <asn1/asn1.h>
28 #include <asn1/asn1_parser.h>
29 #include <crypto/hashers/hasher.h>
30
31 #ifdef HAVE_MPZ_POWM_SEC
32 # undef mpz_powm
33 # define mpz_powm mpz_powm_sec
34 #endif
35
36 typedef struct private_gmp_rsa_public_key_t private_gmp_rsa_public_key_t;
37
38 /**
39 * Private data structure with signing context.
40 */
41 struct private_gmp_rsa_public_key_t {
42 /**
43 * Public interface for this signer.
44 */
45 gmp_rsa_public_key_t public;
46
47 /**
48 * Public modulus.
49 */
50 mpz_t n;
51
52 /**
53 * Public exponent.
54 */
55 mpz_t e;
56
57 /**
58 * Keysize in bytes.
59 */
60 size_t k;
61
62 /**
63 * reference counter
64 */
65 refcount_t ref;
66 };
67
68 /**
69 * Shared functions defined in gmp_rsa_private_key.c
70 */
71 extern chunk_t gmp_mpz_to_chunk(const mpz_t value);
72
73 /**
74 * RSAEP algorithm specified in PKCS#1.
75 */
76 static chunk_t rsaep(private_gmp_rsa_public_key_t *this, chunk_t data)
77 {
78 mpz_t m, c;
79 chunk_t encrypted;
80
81 mpz_init(c);
82 mpz_init(m);
83
84 mpz_import(m, data.len, 1, 1, 1, 0, data.ptr);
85
86 mpz_powm(c, m, this->e, this->n);
87
88 encrypted.len = this->k;
89 encrypted.ptr = mpz_export(NULL, NULL, 1, encrypted.len, 1, 0, c);
90 if (encrypted.ptr == NULL)
91 {
92 encrypted.len = 0;
93 }
94
95 mpz_clear(c);
96 mpz_clear(m);
97
98 return encrypted;
99 }
100
101 /**
102 * RSAVP1 algorithm specified in PKCS#1.
103 */
104 static chunk_t rsavp1(private_gmp_rsa_public_key_t *this, chunk_t data)
105 {
106 return rsaep(this, data);
107 }
108
109 /**
110 * ASN.1 definition of digestInfo
111 */
112 static const asn1Object_t digestInfoObjects[] = {
113 { 0, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
114 { 1, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
115 { 1, "digest", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */
116 { 0, "exit", ASN1_EOC, ASN1_EXIT }
117 };
118 #define DIGEST_INFO 0
119 #define DIGEST_INFO_ALGORITHM 1
120 #define DIGEST_INFO_DIGEST 2
121
122 /**
123 * Verification of an EMPSA PKCS1 signature described in PKCS#1
124 */
125 static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
126 hash_algorithm_t algorithm,
127 chunk_t data, chunk_t signature)
128 {
129 chunk_t em_ori, em;
130 bool success = FALSE;
131
132 /* remove any preceding 0-bytes from signature */
133 while (signature.len && *(signature.ptr) == 0x00)
134 {
135 signature = chunk_skip(signature, 1);
136 }
137
138 if (signature.len == 0 || signature.len > this->k)
139 {
140 return INVALID_ARG;
141 }
142
143 /* unpack signature */
144 em_ori = em = rsavp1(this, signature);
145
146 /* result should look like this:
147 * EM = 0x00 || 0x01 || PS || 0x00 || T.
148 * PS = 0xFF padding, with length to fill em
149 * T = oid || hash
150 */
151
152 /* check magic bytes */
153 if (*(em.ptr) != 0x00 || *(em.ptr+1) != 0x01)
154 {
155 goto end;
156 }
157 em = chunk_skip(em, 2);
158
159 /* find magic 0x00 */
160 while (em.len > 0)
161 {
162 if (*em.ptr == 0x00)
163 {
164 /* found magic byte, stop */
165 em = chunk_skip(em, 1);
166 break;
167 }
168 else if (*em.ptr != 0xFF)
169 {
170 /* bad padding, decryption failed ?!*/
171 goto end;
172 }
173 em = chunk_skip(em, 1);
174 }
175
176 if (em.len == 0)
177 {
178 /* no digestInfo found */
179 goto end;
180 }
181
182 if (algorithm == HASH_UNKNOWN)
183 { /* IKEv1 signatures without digestInfo */
184 if (em.len != data.len)
185 {
186 DBG1("hash size in signature is %u bytes instead of %u bytes",
187 em.len, data.len);
188 goto end;
189 }
190 success = memeq(em.ptr, data.ptr, data.len);
191 }
192 else
193 { /* IKEv2 and X.509 certificate signatures */
194 asn1_parser_t *parser;
195 chunk_t object;
196 int objectID;
197 hash_algorithm_t hash_algorithm = HASH_UNKNOWN;
198
199 DBG2("signature verification:");
200 parser = asn1_parser_create(digestInfoObjects, em);
201
202 while (parser->iterate(parser, &objectID, &object))
203 {
204 switch (objectID)
205 {
206 case DIGEST_INFO:
207 {
208 if (em.len > object.len)
209 {
210 DBG1("digestInfo field in signature is followed by %u surplus bytes",
211 em.len - object.len);
212 goto end_parser;
213 }
214 break;
215 }
216 case DIGEST_INFO_ALGORITHM:
217 {
218 int hash_oid = asn1_parse_algorithmIdentifier(object,
219 parser->get_level(parser)+1, NULL);
220
221 hash_algorithm = hasher_algorithm_from_oid(hash_oid);
222 if (hash_algorithm == HASH_UNKNOWN || hash_algorithm != algorithm)
223 {
224 DBG1("expected hash algorithm %N, but found %N (OID: %#B)",
225 hash_algorithm_names, algorithm,
226 hash_algorithm_names, hash_algorithm, &object);
227 goto end_parser;
228 }
229 break;
230 }
231 case DIGEST_INFO_DIGEST:
232 {
233 chunk_t hash;
234 hasher_t *hasher;
235
236 hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
237 if (hasher == NULL)
238 {
239 DBG1("hash algorithm %N not supported",
240 hash_algorithm_names, hash_algorithm);
241 goto end_parser;
242 }
243
244 if (object.len != hasher->get_hash_size(hasher))
245 {
246 DBG1("hash size in signature is %u bytes instead of %u "
247 "bytes", object.len, hasher->get_hash_size(hasher));
248 hasher->destroy(hasher);
249 goto end_parser;
250 }
251
252 /* build our own hash and compare */
253 hasher->allocate_hash(hasher, data, &hash);
254 hasher->destroy(hasher);
255 success = memeq(object.ptr, hash.ptr, hash.len);
256 free(hash.ptr);
257 break;
258 }
259 default:
260 break;
261 }
262 }
263
264 end_parser:
265 success &= parser->success(parser);
266 parser->destroy(parser);
267 }
268
269 end:
270 free(em_ori.ptr);
271 return success;
272 }
273
274 /**
275 * Implementation of public_key_t.get_type.
276 */
277 static key_type_t get_type(private_gmp_rsa_public_key_t *this)
278 {
279 return KEY_RSA;
280 }
281
282 /**
283 * Implementation of public_key_t.verify.
284 */
285 static bool verify(private_gmp_rsa_public_key_t *this, signature_scheme_t scheme,
286 chunk_t data, chunk_t signature)
287 {
288 switch (scheme)
289 {
290 case SIGN_RSA_EMSA_PKCS1_NULL:
291 return verify_emsa_pkcs1_signature(this, HASH_UNKNOWN, data, signature);
292 case SIGN_RSA_EMSA_PKCS1_MD5:
293 return verify_emsa_pkcs1_signature(this, HASH_MD5, data, signature);
294 case SIGN_RSA_EMSA_PKCS1_SHA1:
295 return verify_emsa_pkcs1_signature(this, HASH_SHA1, data, signature);
296 case SIGN_RSA_EMSA_PKCS1_SHA224:
297 return verify_emsa_pkcs1_signature(this, HASH_SHA224, data, signature);
298 case SIGN_RSA_EMSA_PKCS1_SHA256:
299 return verify_emsa_pkcs1_signature(this, HASH_SHA256, data, signature);
300 case SIGN_RSA_EMSA_PKCS1_SHA384:
301 return verify_emsa_pkcs1_signature(this, HASH_SHA384, data, signature);
302 case SIGN_RSA_EMSA_PKCS1_SHA512:
303 return verify_emsa_pkcs1_signature(this, HASH_SHA512, data, signature);
304 default:
305 DBG1("signature scheme %N not supported in RSA",
306 signature_scheme_names, scheme);
307 return FALSE;
308 }
309 }
310
311 #define MIN_PS_PADDING 8
312
313 /**
314 * Implementation of public_key_t.encrypt.
315 */
316 static bool encrypt_(private_gmp_rsa_public_key_t *this, chunk_t plain,
317 chunk_t *crypto)
318 {
319 chunk_t em;
320 u_char *pos;
321 int padding, i;
322 rng_t *rng;
323
324 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
325 if (rng == NULL)
326 {
327 DBG1("no random generator available");
328 return FALSE;
329 }
330
331 /* number of pseudo-random padding octets */
332 padding = this->k - plain.len - 3;
333 if (padding < MIN_PS_PADDING)
334 {
335 DBG1("pseudo-random padding must be at least %d octets", MIN_PS_PADDING);
336 return FALSE;
337 }
338
339 /* padding according to PKCS#1 7.2.1 (RSAES-PKCS1-v1.5-ENCRYPT) */
340 DBG2("padding %u bytes of data to the rsa modulus size of %u bytes",
341 plain.len, this->k);
342 em.len = this->k;
343 em.ptr = malloc(em.len);
344 pos = em.ptr;
345 *pos++ = 0x00;
346 *pos++ = 0x02;
347
348 /* fill with pseudo random octets */
349 rng->get_bytes(rng, padding, pos);
350
351 /* replace zero-valued random octets */
352 for (i = 0; i < padding; i++)
353 {
354 while (*pos == 0)
355 {
356 rng->get_bytes(rng, 1, pos);
357 }
358 pos++;
359 }
360 rng->destroy(rng);
361
362 /* append the padding terminator */
363 *pos++ = 0x00;
364
365 /* now add the data */
366 memcpy(pos, plain.ptr, plain.len);
367 DBG3("padded data before rsa encryption: %B", &em);
368
369 /* rsa encryption using PKCS#1 RSAEP */
370 *crypto = rsaep(this, em);
371 DBG3("rsa encrypted data: %B", crypto);
372 chunk_clear(&em);
373 return TRUE;
374 }
375
376 /**
377 * Implementation of gmp_rsa_public_key.equals.
378 */
379 static bool equals(private_gmp_rsa_public_key_t *this, public_key_t *other)
380 {
381 return public_key_equals(&this->public.interface, other);
382 }
383
384 /**
385 * Implementation of public_key_t.get_keysize.
386 */
387 static size_t get_keysize(private_gmp_rsa_public_key_t *this)
388 {
389 return this->k;
390 }
391
392 /**
393 * Implementation of public_key_t.get_encoding
394 */
395 static bool get_encoding(private_gmp_rsa_public_key_t *this,
396 key_encoding_type_t type, chunk_t *encoding)
397 {
398 chunk_t n, e;
399 bool success, pem = FALSE;
400
401 if (type == KEY_PUB_PEM)
402 {
403 pem = TRUE;
404 type = KEY_PUB_SPKI_ASN1_DER;
405 }
406
407 n = gmp_mpz_to_chunk(this->n);
408 e = gmp_mpz_to_chunk(this->e);
409
410 success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
411 KEY_PART_RSA_MODULUS, n, KEY_PART_RSA_PUB_EXP, e, KEY_PART_END);
412 chunk_free(&n);
413 chunk_free(&e);
414
415 if (pem && success)
416 {
417 chunk_t asn1_encoding = *encoding;
418
419 success = lib->encoding->encode(lib->encoding, KEY_PUB_PEM, NULL,
420 encoding, KEY_PART_RSA_PUB_ASN1_DER,
421 asn1_encoding, KEY_PART_END);
422 chunk_clear(&asn1_encoding);
423 }
424 return success;
425 }
426
427 /**
428 * Implementation of public_key_t.get_fingerprint
429 */
430 static bool get_fingerprint(private_gmp_rsa_public_key_t *this,
431 key_encoding_type_t type, chunk_t *fp)
432 {
433 chunk_t n, e;
434 bool success;
435
436 if (lib->encoding->get_cache(lib->encoding, type, this, fp))
437 {
438 return TRUE;
439 }
440 n = gmp_mpz_to_chunk(this->n);
441 e = gmp_mpz_to_chunk(this->e);
442
443 success = lib->encoding->encode(lib->encoding, type, this, fp,
444 KEY_PART_RSA_MODULUS, n, KEY_PART_RSA_PUB_EXP, e, KEY_PART_END);
445 chunk_free(&n);
446 chunk_free(&e);
447
448 return success;
449 }
450
451 /**
452 * Implementation of public_key_t.get_ref.
453 */
454 static private_gmp_rsa_public_key_t* get_ref(private_gmp_rsa_public_key_t *this)
455 {
456 ref_get(&this->ref);
457 return this;
458 }
459
460 /**
461 * Implementation of gmp_rsa_public_key.destroy.
462 */
463 static void destroy(private_gmp_rsa_public_key_t *this)
464 {
465 if (ref_put(&this->ref))
466 {
467 mpz_clear(this->n);
468 mpz_clear(this->e);
469 lib->encoding->clear_cache(lib->encoding, this);
470 free(this);
471 }
472 }
473
474 /**
475 * See header.
476 */
477 gmp_rsa_public_key_t *gmp_rsa_public_key_load(key_type_t type, va_list args)
478 {
479 private_gmp_rsa_public_key_t *this;
480 chunk_t n, e;
481
482 n = e = chunk_empty;
483 while (TRUE)
484 {
485 switch (va_arg(args, builder_part_t))
486 {
487 case BUILD_RSA_MODULUS:
488 n = va_arg(args, chunk_t);
489 continue;
490 case BUILD_RSA_PUB_EXP:
491 e = va_arg(args, chunk_t);
492 continue;
493 case BUILD_END:
494 break;
495 default:
496 return NULL;
497 }
498 break;
499 }
500 if (!e.ptr || !n.ptr)
501 {
502 return NULL;
503 }
504
505 this = malloc_thing(private_gmp_rsa_public_key_t);
506
507 this->public.interface.get_type = (key_type_t (*) (public_key_t*))get_type;
508 this->public.interface.verify = (bool (*) (public_key_t*, signature_scheme_t, chunk_t, chunk_t))verify;
509 this->public.interface.encrypt = (bool (*) (public_key_t*, chunk_t, chunk_t*))encrypt_;
510 this->public.interface.equals = (bool (*) (public_key_t*, public_key_t*))equals;
511 this->public.interface.get_keysize = (size_t (*) (public_key_t*))get_keysize;
512 this->public.interface.get_fingerprint = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
513 this->public.interface.has_fingerprint = (bool(*)(public_key_t*, chunk_t fp))public_key_has_fingerprint;
514 this->public.interface.get_encoding = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
515 this->public.interface.get_ref = (public_key_t* (*) (public_key_t *this))get_ref;
516 this->public.interface.destroy = (void (*) (public_key_t *this))destroy;
517
518 this->ref = 1;
519
520 mpz_init(this->n);
521 mpz_init(this->e);
522
523 mpz_import(this->n, n.len, 1, 1, 1, 0, n.ptr);
524 mpz_import(this->e, e.len, 1, 1, 1, 0, e.ptr);
525
526 this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
527
528 return &this->public;
529 }
530