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