implemented pkcs1_encrypt()
[strongswan.git] / src / libstrongswan / crypto / rsa / rsa_public_key.c
1 /**
2 * @file rsa_public_key.c
3 *
4 * @brief Implementation of rsa_public_key_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter
10 * Copyright (C) 2005-2006 Martin Willi
11 * Copyright (C) 2007-2008 Andreas Steffen
12 *
13 * Hochschule fuer Technik Rapperswil
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 2 of the License, or (at your
18 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * for more details.
24 *
25 * RCSID $Id$
26 */
27
28 #include <gmp.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <string.h>
33
34 #include "rsa_public_key.h"
35
36 #include <debug.h>
37 #include <utils/randomizer.h>
38 #include <crypto/hashers/hasher.h>
39 #include <asn1/asn1.h>
40 #include <asn1/pem.h>
41
42 /* ASN.1 definition of RSApublicKey */
43 static const asn1Object_t pubkeyObjects[] = {
44 { 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
45 { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */
46 { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */
47 };
48
49 #define PUB_KEY_RSA_PUBLIC_KEY 0
50 #define PUB_KEY_MODULUS 1
51 #define PUB_KEY_EXPONENT 2
52 #define PUB_KEY_ROOF 3
53
54 /* ASN.1 definition of digestInfo */
55 static const asn1Object_t digestInfoObjects[] = {
56 { 0, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
57 { 1, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
58 { 1, "digest", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */
59 };
60
61 #define DIGEST_INFO 0
62 #define DIGEST_INFO_ALGORITHM 1
63 #define DIGEST_INFO_DIGEST 2
64 #define DIGEST_INFO_ROOF 3
65
66 typedef struct private_rsa_public_key_t private_rsa_public_key_t;
67
68 /**
69 * Private data structure with signing context.
70 */
71 struct private_rsa_public_key_t {
72 /**
73 * Public interface for this signer.
74 */
75 rsa_public_key_t public;
76
77 /**
78 * Public modulus.
79 */
80 mpz_t n;
81
82 /**
83 * Public exponent.
84 */
85 mpz_t e;
86
87 /**
88 * Keysize in bytes.
89 */
90 size_t k;
91
92 /**
93 * Keyid formed as a SHA-1 hash of a publicKeyInfo object
94 */
95 chunk_t keyid;
96
97 /**
98 * @brief Implements the RSAEP algorithm specified in PKCS#1.
99 *
100 * @param this calling object
101 * @param data data to process
102 * @return processed data
103 */
104 chunk_t (*rsaep) (const private_rsa_public_key_t *this, chunk_t data);
105
106 /**
107 * @brief Implements the RSASVP1 algorithm specified in PKCS#1.
108 *
109 * @param this calling object
110 * @param data data to process
111 * @return processed data
112 */
113 chunk_t (*rsavp1) (const private_rsa_public_key_t *this, chunk_t data);
114 };
115
116 /**
117 * Implementation of private_rsa_public_key_t.rsaep and private_rsa_public_key_t.rsavp1
118 */
119 static chunk_t rsaep(const private_rsa_public_key_t *this, chunk_t data)
120 {
121 mpz_t m, c;
122 chunk_t encrypted;
123
124 mpz_init(c);
125 mpz_init(m);
126
127 mpz_import(m, data.len, 1, 1, 1, 0, data.ptr);
128
129 mpz_powm(c, m, this->e, this->n);
130
131 encrypted.len = this->k;
132 encrypted.ptr = mpz_export(NULL, NULL, 1, encrypted.len, 1, 0, c);
133
134 mpz_clear(c);
135 mpz_clear(m);
136
137 return encrypted;
138 }
139
140 /**
141 * Implementation of rsa_public_key_t.eme_pkcs1_encrypt.
142 */
143 static status_t pkcs1_encrypt(private_rsa_public_key_t *this,
144 chunk_t in, chunk_t *out)
145 {
146 chunk_t em;
147 u_char *pos;
148 int padding = this->k - in.len - 3;
149
150 if (padding < 8)
151 {
152 DBG1("rsa padding of %d bytes is too small", padding);
153 return FAILED;
154 }
155 em.len = this->k;
156 em.ptr = pos = malloc(em.len);
157
158 /* add padding according to PKCS#1 7.2.1 1.+2. */
159 *pos++ = 0x00;
160 *pos++ = 0x02;
161
162 /* pad with pseudo random bytes unequal to zero */
163 {
164 randomizer_t *randomizer = randomizer_create();
165
166 /* pad with pseudo random bytes unequal to zero */
167 while (padding--)
168 {
169 randomizer->get_pseudo_random_bytes(randomizer, 1, pos);
170 while (!*pos)
171 {
172 randomizer->get_pseudo_random_bytes(randomizer, 1, pos);
173 }
174 pos++;
175 }
176 randomizer->destroy(randomizer);
177 }
178
179 /* append the padding terminator */
180 *pos++ = 0x00;
181
182 /* now add the data */
183 memcpy(pos, in.ptr, in.len);
184 *out = this->rsaep(this, em);
185 free(em.ptr);
186 return SUCCESS;
187 }
188
189 /**
190 * Implementation of rsa_public_key.verify_emsa_pkcs1_signature.
191 */
192 static status_t verify_emsa_pkcs1_signature(const private_rsa_public_key_t *this,
193 hash_algorithm_t algorithm,
194 chunk_t data, chunk_t signature)
195 {
196 chunk_t em_ori, em;
197 status_t res = FAILED;
198
199 /* remove any preceding 0-bytes from signature */
200 while (signature.len && *(signature.ptr) == 0x00)
201 {
202 signature.len -= 1;
203 signature.ptr++;
204 }
205
206 if (signature.len > this->k)
207 {
208 return INVALID_ARG;
209 }
210
211 /* unpack signature */
212 em_ori = em = this->rsavp1(this, signature);
213
214 /* result should look like this:
215 * EM = 0x00 || 0x01 || PS || 0x00 || T.
216 * PS = 0xFF padding, with length to fill em
217 * T = oid || hash
218 */
219
220 /* check magic bytes */
221 if (*(em.ptr) != 0x00 || *(em.ptr+1) != 0x01)
222 {
223 DBG2("incorrect padding - probably wrong RSA key");
224 goto end;
225 }
226 em.ptr += 2;
227 em.len -= 2;
228
229 /* find magic 0x00 */
230 while (em.len > 0)
231 {
232 if (*em.ptr == 0x00)
233 {
234 /* found magic byte, stop */
235 em.ptr++;
236 em.len--;
237 break;
238 }
239 else if (*em.ptr != 0xFF)
240 {
241 /* bad padding, decryption failed ?!*/
242 goto end;
243 }
244 em.ptr++;
245 em.len--;
246 }
247
248 if (em.len == 0)
249 {
250 /* no digestInfo found */
251 goto end;
252 }
253
254 /* parse ASN.1-based digestInfo */
255 {
256 asn1_ctx_t ctx;
257 chunk_t object;
258 u_int level;
259 int objectID = 0;
260 hash_algorithm_t hash_algorithm = HASH_UNKNOWN;
261
262 asn1_init(&ctx, em, 0, FALSE, FALSE);
263
264 while (objectID < DIGEST_INFO_ROOF)
265 {
266 if (!extract_object(digestInfoObjects, &objectID, &object, &level, &ctx))
267 {
268 goto end;
269 }
270 switch (objectID)
271 {
272 case DIGEST_INFO:
273 if (em.len > object.len)
274 {
275 DBG1("digestInfo field in signature is followed by %u surplus bytes",
276 em.len - object.len);
277 goto end;
278 }
279 break;
280 case DIGEST_INFO_ALGORITHM:
281 {
282 int hash_oid = parse_algorithmIdentifier(object, level+1, NULL);
283
284 hash_algorithm = hasher_algorithm_from_oid(hash_oid);
285 if (hash_algorithm == HASH_UNKNOWN
286 || (algorithm != HASH_UNKNOWN && hash_algorithm != algorithm))
287 {
288 DBG1("wrong hash algorithm used in signature");
289 goto end;
290 }
291 }
292 break;
293 case DIGEST_INFO_DIGEST:
294 {
295 chunk_t hash;
296 hasher_t *hasher = hasher_create(hash_algorithm);
297
298 if (object.len != hasher->get_hash_size(hasher))
299 {
300 DBG1("hash size in signature is %u bytes instead of %u bytes",
301 object.len, hasher->get_hash_size(hasher));
302 hasher->destroy(hasher);
303 goto end;
304 }
305
306 /* build our own hash */
307 hasher->allocate_hash(hasher, data, &hash);
308 hasher->destroy(hasher);
309
310 /* compare the hashes */
311 res = memeq(object.ptr, hash.ptr, hash.len) ? SUCCESS : FAILED;
312 free(hash.ptr);
313 }
314 break;
315 default:
316 break;
317 }
318 objectID++;
319 }
320 }
321
322 end:
323 free(em_ori.ptr);
324 return res;
325 }
326
327
328 /**
329 * Implementation of rsa_public_key_t.get_modulus.
330 */
331 static mpz_t *get_modulus(const private_rsa_public_key_t *this)
332 {
333 return (mpz_t*)&this->n;
334 }
335
336 /**
337 * Implementation of rsa_public_key_t.get_keysize.
338 */
339 static size_t get_keysize(const private_rsa_public_key_t *this)
340 {
341 return this->k;
342 }
343
344 /**
345 * Build a DER-encoded publicKeyInfo object from an RSA public key.
346 * Also used in rsa_private_key.c.
347 */
348 chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e)
349 {
350 chunk_t publicKey = asn1_wrap(ASN1_SEQUENCE, "mm",
351 asn1_integer_from_mpz(n),
352 asn1_integer_from_mpz(e));
353
354 return asn1_wrap(ASN1_SEQUENCE, "cm",
355 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
356 asn1_bitstring("m", publicKey));
357 }
358
359 /**
360 * Form the RSA keyid as a SHA-1 hash of a publicKeyInfo object
361 * Also used in rsa_private_key.c.
362 */
363 chunk_t rsa_public_key_id_create(mpz_t n, mpz_t e)
364 {
365 chunk_t keyid;
366 chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(n, e);
367 hasher_t *hasher = hasher_create(HASH_SHA1);
368
369 hasher->allocate_hash(hasher, publicKeyInfo, &keyid);
370 hasher->destroy(hasher);
371 free(publicKeyInfo.ptr);
372
373 return keyid;
374 }
375
376 /**
377 * Implementation of rsa_public_key_t.get_publicKeyInfo.
378 */
379 static chunk_t get_publicKeyInfo(const private_rsa_public_key_t *this)
380 {
381 return rsa_public_key_info_to_asn1(this->n, this->e);
382 }
383
384 /**
385 * Implementation of rsa_public_key_t.get_keyid.
386 */
387 static chunk_t get_keyid(const private_rsa_public_key_t *this)
388 {
389 return this->keyid;
390 }
391
392 /* forward declaration used by rsa_public_key_t.clone */
393 private_rsa_public_key_t *rsa_public_key_create_empty(void);
394
395 /**
396 * Implementation of rsa_public_key_t.clone.
397 */
398 static rsa_public_key_t* _clone(const private_rsa_public_key_t *this)
399 {
400 private_rsa_public_key_t *clone = rsa_public_key_create_empty();
401
402 mpz_init_set(clone->n, this->n);
403 mpz_init_set(clone->e, this->e);
404 clone->keyid = chunk_clone(this->keyid);
405 clone->k = this->k;
406
407 return &clone->public;
408 }
409
410 /**
411 * Implementation of rsa_public_key_t.destroy.
412 */
413 static void destroy(private_rsa_public_key_t *this)
414 {
415 mpz_clear(this->n);
416 mpz_clear(this->e);
417 free(this->keyid.ptr);
418 free(this);
419 }
420
421 /**
422 * Generic private constructor
423 */
424 private_rsa_public_key_t *rsa_public_key_create_empty(void)
425 {
426 private_rsa_public_key_t *this = malloc_thing(private_rsa_public_key_t);
427
428 /* public functions */
429 this->public.pkcs1_encrypt = (status_t (*) (rsa_public_key_t*,chunk_t,chunk_t*))pkcs1_encrypt;
430 this->public.verify_emsa_pkcs1_signature = (status_t (*) (const rsa_public_key_t*,hash_algorithm_t,chunk_t,chunk_t))verify_emsa_pkcs1_signature;
431 this->public.get_modulus = (mpz_t *(*) (const rsa_public_key_t*))get_modulus;
432 this->public.get_keysize = (size_t (*) (const rsa_public_key_t*))get_keysize;
433 this->public.get_publicKeyInfo = (chunk_t (*) (const rsa_public_key_t*))get_publicKeyInfo;
434 this->public.get_keyid = (chunk_t (*) (const rsa_public_key_t*))get_keyid;
435 this->public.clone = (rsa_public_key_t* (*) (const rsa_public_key_t*))_clone;
436 this->public.destroy = (void (*) (rsa_public_key_t*))destroy;
437
438 /* private functions */
439 this->rsaep = rsaep;
440 this->rsavp1 = rsaep; /* same algorithm */
441
442 return this;
443 }
444
445 /*
446 * See header
447 */
448 rsa_public_key_t *rsa_public_key_create(mpz_t n, mpz_t e)
449 {
450 private_rsa_public_key_t *this = rsa_public_key_create_empty();
451
452 mpz_init_set(this->n, n);
453 mpz_init_set(this->e, e);
454
455 this->k = (mpz_sizeinbase(n, 2) + 7) / BITS_PER_BYTE;
456 this->keyid = rsa_public_key_id_create(n, e);
457 return &this->public;
458 }
459 /*
460 * See header
461 */
462 rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob)
463 {
464 asn1_ctx_t ctx;
465 chunk_t object;
466 u_int level;
467 int objectID = 0;
468
469 private_rsa_public_key_t *this = rsa_public_key_create_empty();
470
471 mpz_init(this->n);
472 mpz_init(this->e);
473
474 asn1_init(&ctx, blob, 0, FALSE, FALSE);
475
476 while (objectID < PUB_KEY_ROOF)
477 {
478 if (!extract_object(pubkeyObjects, &objectID, &object, &level, &ctx))
479 {
480 destroy(this);
481 return FALSE;
482 }
483 switch (objectID)
484 {
485 case PUB_KEY_MODULUS:
486 mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
487 break;
488 case PUB_KEY_EXPONENT:
489 mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
490 break;
491 }
492 objectID++;
493 }
494
495 this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
496 this->keyid = rsa_public_key_id_create(this->n, this->e);
497 return &this->public;
498 }
499
500 /*
501 * See header
502 */
503 rsa_public_key_t *rsa_public_key_create_from_file(char *filename)
504 {
505 bool pgp = FALSE;
506 chunk_t chunk = chunk_empty;
507 rsa_public_key_t *pubkey = NULL;
508
509 if (!pem_asn1_load_file(filename, NULL, "public key", &chunk, &pgp))
510 {
511 return NULL;
512 }
513 pubkey = rsa_public_key_create_from_chunk(chunk);
514 free(chunk.ptr);
515 return pubkey;
516 }