acb44a11014f025d008a76998f54276380cd42dd
[strongswan.git] / src / libstrongswan / plugins / gmp / gmp_rsa_public_key.c
1 /*
2 * Copyright (C) 2005-2008 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 <asn1/pem.h>
30 #include <crypto/hashers/hasher.h>
31
32 /**
33 * defined in gmp_rsa_private_key.c
34 */
35 extern chunk_t gmp_mpz_to_asn1(const mpz_t value);
36
37 typedef struct private_gmp_rsa_public_key_t private_gmp_rsa_public_key_t;
38
39 /**
40 * Private data structure with signing context.
41 */
42 struct private_gmp_rsa_public_key_t {
43 /**
44 * Public interface for this signer.
45 */
46 gmp_rsa_public_key_t public;
47
48 /**
49 * Public modulus.
50 */
51 mpz_t n;
52
53 /**
54 * Public exponent.
55 */
56 mpz_t e;
57
58 /**
59 * Keysize in bytes.
60 */
61 size_t k;
62
63 /**
64 * Keyid formed as a SHA-1 hash of a publicKeyInfo object
65 */
66 identification_t *keyid_info;
67
68 /**
69 * Keyid formed as a SHA-1 hash of a publicKey object
70 */
71 identification_t *keyid;
72
73 /**
74 * reference counter
75 */
76 refcount_t ref;
77 };
78
79 /**
80 * RSAEP algorithm specified in PKCS#1.
81 */
82 static chunk_t rsaep(private_gmp_rsa_public_key_t *this, chunk_t data)
83 {
84 mpz_t m, c;
85 chunk_t encrypted;
86
87 mpz_init(c);
88 mpz_init(m);
89
90 mpz_import(m, data.len, 1, 1, 1, 0, data.ptr);
91
92 mpz_powm(c, m, this->e, this->n);
93
94 encrypted.len = this->k;
95 encrypted.ptr = mpz_export(NULL, NULL, 1, encrypted.len, 1, 0, c);
96 if (encrypted.ptr == NULL)
97 {
98 encrypted.len = 0;
99 }
100
101 mpz_clear(c);
102 mpz_clear(m);
103
104 return encrypted;
105 }
106
107 /**
108 * RSAVP1 algorithm specified in PKCS#1.
109 */
110 static chunk_t rsavp1(private_gmp_rsa_public_key_t *this, chunk_t data)
111 {
112 return rsaep(this, data);
113 }
114
115 /**
116 * ASN.1 definition of digestInfo
117 */
118 static const asn1Object_t digestInfoObjects[] = {
119 { 0, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
120 { 1, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
121 { 1, "digest", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */
122 { 0, "exit", ASN1_EOC, ASN1_EXIT }
123 };
124 #define DIGEST_INFO 0
125 #define DIGEST_INFO_ALGORITHM 1
126 #define DIGEST_INFO_DIGEST 2
127
128 /**
129 * Verification of an EMPSA PKCS1 signature described in PKCS#1
130 */
131 static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
132 hash_algorithm_t algorithm,
133 chunk_t data, chunk_t signature)
134 {
135 chunk_t em_ori, em;
136 bool success = FALSE;
137
138 /* remove any preceding 0-bytes from signature */
139 while (signature.len && *(signature.ptr) == 0x00)
140 {
141 signature.len -= 1;
142 signature.ptr++;
143 }
144
145 if (signature.len > this->k)
146 {
147 return INVALID_ARG;
148 }
149
150 /* unpack signature */
151 em_ori = em = rsavp1(this, signature);
152
153 /* result should look like this:
154 * EM = 0x00 || 0x01 || PS || 0x00 || T.
155 * PS = 0xFF padding, with length to fill em
156 * T = oid || hash
157 */
158
159 /* check magic bytes */
160 if (*(em.ptr) != 0x00 || *(em.ptr+1) != 0x01)
161 {
162 goto end;
163 }
164 em.ptr += 2;
165 em.len -= 2;
166
167 /* find magic 0x00 */
168 while (em.len > 0)
169 {
170 if (*em.ptr == 0x00)
171 {
172 /* found magic byte, stop */
173 em.ptr++;
174 em.len--;
175 break;
176 }
177 else if (*em.ptr != 0xFF)
178 {
179 /* bad padding, decryption failed ?!*/
180 goto end;
181 }
182 em.ptr++;
183 em.len--;
184 }
185
186 if (em.len == 0)
187 {
188 /* no digestInfo found */
189 goto end;
190 }
191
192 /* parse ASN.1-based digestInfo */
193 {
194 asn1_parser_t *parser;
195 chunk_t object;
196 int objectID;
197 hash_algorithm_t hash_algorithm = HASH_UNKNOWN;
198
199 parser = asn1_parser_create(digestInfoObjects, em);
200
201 while (parser->iterate(parser, &objectID, &object))
202 {
203 switch (objectID)
204 {
205 case DIGEST_INFO:
206 {
207 if (em.len > object.len)
208 {
209 DBG1("digestInfo field in signature is followed by %u surplus bytes",
210 em.len - object.len);
211 goto end_parser;
212 }
213 break;
214 }
215 case DIGEST_INFO_ALGORITHM:
216 {
217 int hash_oid = asn1_parse_algorithmIdentifier(object,
218 parser->get_level(parser)+1, NULL);
219
220 hash_algorithm = hasher_algorithm_from_oid(hash_oid);
221 if (hash_algorithm == HASH_UNKNOWN ||
222 (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_DEFAULT: /* default is EMSA-PKCS1 using included OID */
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_SHA256:
297 return verify_emsa_pkcs1_signature(this, HASH_SHA256, data, signature);
298 case SIGN_RSA_EMSA_PKCS1_SHA384:
299 return verify_emsa_pkcs1_signature(this, HASH_SHA384, data, signature);
300 case SIGN_RSA_EMSA_PKCS1_SHA512:
301 return verify_emsa_pkcs1_signature(this, HASH_SHA512, data, signature);
302 default:
303 DBG1("signature scheme %N not supported in RSA",
304 signature_scheme_names, scheme);
305 return FALSE;
306 }
307 }
308
309 /**
310 * Implementation of public_key_t.get_keysize.
311 */
312 static bool encrypt_(private_gmp_rsa_public_key_t *this, chunk_t crypto, chunk_t *plain)
313 {
314 DBG1("RSA public key encryption not implemented");
315 return FALSE;
316 }
317
318 /**
319 * Implementation of public_key_t.get_keysize.
320 */
321 static size_t get_keysize(private_gmp_rsa_public_key_t *this)
322 {
323 return this->k;
324 }
325
326 /**
327 * Implementation of public_key_t.get_id.
328 */
329 static identification_t *get_id(private_gmp_rsa_public_key_t *this,
330 id_type_t type)
331 {
332 switch (type)
333 {
334 case ID_PUBKEY_INFO_SHA1:
335 return this->keyid_info;
336 case ID_PUBKEY_SHA1:
337 return this->keyid;
338 default:
339 return NULL;
340 }
341 }
342
343 /*
344 * Implementation of public_key_t.get_encoding.
345 */
346 static chunk_t get_encoding(private_gmp_rsa_public_key_t *this)
347 {
348 return asn1_wrap(ASN1_SEQUENCE, "mm",
349 gmp_mpz_to_asn1(this->n),
350 gmp_mpz_to_asn1(this->e));
351 }
352
353 /**
354 * Implementation of public_key_t.get_ref.
355 */
356 static private_gmp_rsa_public_key_t* get_ref(private_gmp_rsa_public_key_t *this)
357 {
358 ref_get(&this->ref);
359 return this;
360 }
361
362 /**
363 * Implementation of gmp_rsa_public_key.destroy.
364 */
365 static void destroy(private_gmp_rsa_public_key_t *this)
366 {
367 if (ref_put(&this->ref))
368 {
369 mpz_clear(this->n);
370 mpz_clear(this->e);
371 DESTROY_IF(this->keyid);
372 DESTROY_IF(this->keyid_info);
373 free(this);
374 }
375 }
376
377 /**
378 * Generic private constructor
379 */
380 static private_gmp_rsa_public_key_t *gmp_rsa_public_key_create_empty()
381 {
382 private_gmp_rsa_public_key_t *this = malloc_thing(private_gmp_rsa_public_key_t);
383
384 this->public.interface.get_type = (key_type_t (*)(public_key_t *this))get_type;
385 this->public.interface.verify = (bool (*)(public_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t signature))verify;
386 this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_;
387 this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
388 this->public.interface.get_id = (identification_t* (*) (public_key_t *this,id_type_t))get_id;
389 this->public.interface.get_encoding = (chunk_t(*)(public_key_t*))get_encoding;
390 this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref;
391 this->public.interface.destroy = (void (*)(public_key_t *this))destroy;
392
393 this->keyid = NULL;
394 this->keyid_info = NULL;
395 this->ref = 1;
396
397 return this;
398 }
399
400 /**
401 * Build the RSA key identifier from n and e using SHA1 hashed publicKey(Info).
402 * Also used in rsa_private_key.c.
403 */
404 bool gmp_rsa_public_key_build_id(mpz_t n, mpz_t e, identification_t **keyid,
405 identification_t **keyid_info)
406 {
407 chunk_t publicKeyInfo, publicKey, hash;
408 hasher_t *hasher;
409
410 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
411 if (hasher == NULL)
412 {
413 DBG1("SHA1 hash algorithm not supported, unable to use RSA");
414 return FALSE;
415 }
416 publicKey = asn1_wrap(ASN1_SEQUENCE, "mm",
417 gmp_mpz_to_asn1(n),
418 gmp_mpz_to_asn1(e));
419 hasher->allocate_hash(hasher, publicKey, &hash);
420 *keyid = identification_create_from_encoding(ID_PUBKEY_SHA1, hash);
421 chunk_free(&hash);
422
423 publicKeyInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
424 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
425 asn1_bitstring("m", publicKey));
426 hasher->allocate_hash(hasher, publicKeyInfo, &hash);
427 *keyid_info = identification_create_from_encoding(ID_PUBKEY_INFO_SHA1, hash);
428 chunk_free(&hash);
429
430 hasher->destroy(hasher);
431 chunk_free(&publicKeyInfo);
432
433 return TRUE;
434 }
435
436 /**
437 * Create a public key from mpz values, used in gmp_rsa_private_key
438 */
439 gmp_rsa_public_key_t *gmp_rsa_public_key_create_from_n_e(mpz_t n, mpz_t e)
440 {
441 private_gmp_rsa_public_key_t *this = gmp_rsa_public_key_create_empty();
442
443 mpz_init_set(this->n, n);
444 mpz_init_set(this->e, e);
445
446 this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
447 if (!gmp_rsa_public_key_build_id(this->n, this->e,
448 &this->keyid, &this->keyid_info))
449 {
450 destroy(this);
451 return NULL;
452 }
453 return &this->public;
454 }
455
456 /**
457 * ASN.1 definition of RSApublicKey
458 */
459 static const asn1Object_t pubkeyObjects[] = {
460 { 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
461 { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */
462 { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */
463 { 0, "exit", ASN1_EOC, ASN1_EXIT }
464 };
465 #define PUB_KEY_RSA_PUBLIC_KEY 0
466 #define PUB_KEY_MODULUS 1
467 #define PUB_KEY_EXPONENT 2
468
469 /**
470 * Load a public key from an ASN1 encoded blob
471 */
472 static gmp_rsa_public_key_t *load(chunk_t blob)
473 {
474 asn1_parser_t *parser;
475 chunk_t object;
476 int objectID;
477 bool success = FALSE;
478
479 private_gmp_rsa_public_key_t *this = gmp_rsa_public_key_create_empty();
480
481 mpz_init(this->n);
482 mpz_init(this->e);
483
484 parser = asn1_parser_create(pubkeyObjects, blob);
485
486 while (parser->iterate(parser, &objectID, &object))
487 {
488 switch (objectID)
489 {
490 case PUB_KEY_MODULUS:
491 mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
492 break;
493 case PUB_KEY_EXPONENT:
494 mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
495 break;
496 }
497 }
498 success = parser->success(parser);
499 free(blob.ptr);
500 parser->destroy(parser);
501
502 if (!success)
503 {
504 destroy(this);
505 return NULL;
506 }
507
508 this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
509
510 if (!gmp_rsa_public_key_build_id(this->n, this->e,
511 &this->keyid, &this->keyid_info))
512 {
513 destroy(this);
514 return NULL;
515 }
516 return &this->public;
517 }
518
519 typedef struct private_builder_t private_builder_t;
520 /**
521 * Builder implementation for key loading
522 */
523 struct private_builder_t {
524 /** implements the builder interface */
525 builder_t public;
526 /** loaded public key */
527 gmp_rsa_public_key_t *key;
528 };
529
530 /**
531 * Implementation of builder_t.build
532 */
533 static gmp_rsa_public_key_t *build(private_builder_t *this)
534 {
535 gmp_rsa_public_key_t *key = this->key;
536
537 free(this);
538 return key;
539 }
540
541 /**
542 * Implementation of builder_t.add
543 */
544 static void add(private_builder_t *this, builder_part_t part, ...)
545 {
546 if (!this->key)
547 {
548 va_list args;
549 chunk_t chunk;
550
551 switch (part)
552 {
553 case BUILD_BLOB_ASN1_DER:
554 {
555 va_start(args, part);
556 chunk = va_arg(args, chunk_t);
557 this->key = load(chunk_clone(chunk));
558 va_end(args);
559 return;
560 }
561 default:
562 break;
563 }
564 }
565 if (this->key)
566 {
567 destroy((private_gmp_rsa_public_key_t*)this->key);
568 }
569 builder_cancel(&this->public);
570 }
571
572 /**
573 * Builder construction function
574 */
575 builder_t *gmp_rsa_public_key_builder(key_type_t type)
576 {
577 private_builder_t *this;
578
579 if (type != KEY_RSA)
580 {
581 return NULL;
582 }
583
584 this = malloc_thing(private_builder_t);
585
586 this->key = NULL;
587 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
588 this->public.build = (void*(*)(builder_t *this))build;
589
590 return &this->public;
591 }
592