0fb3d12b65f58f093fbb7d5a5ec5ee8df8f61393
[strongswan.git] / src / libstrongswan / crypto / rsa / rsa_private_key.c
1 /**
2 * @file rsa_private_key.c
3 *
4 * @brief Implementation of rsa_private_key_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 *
23 * RCSID $Id$
24 */
25
26 #include <gmp.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <string.h>
30
31 #include "rsa_public_key.h"
32 #include "rsa_private_key.h"
33
34 #include <debug.h>
35 #include <asn1/asn1.h>
36 #include <asn1/pem.h>
37 #include <utils/randomizer.h>
38
39 /**
40 * defined in rsa_public_key.c
41 */
42 extern chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e);
43
44 /**
45 * Public exponent to use for key generation.
46 */
47 #define PUBLIC_EXPONENT 0x10001
48
49 typedef struct private_rsa_private_key_t private_rsa_private_key_t;
50
51 /**
52 * Private data of a rsa_private_key_t object.
53 */
54 struct private_rsa_private_key_t {
55 /**
56 * Public interface for this signer.
57 */
58 rsa_private_key_t public;
59
60 /**
61 * Version of key, as encoded in PKCS#1
62 */
63 u_int version;
64
65 /**
66 * Public modulus.
67 */
68 mpz_t n;
69
70 /**
71 * Public exponent.
72 */
73 mpz_t e;
74
75 /**
76 * Private prime 1.
77 */
78 mpz_t p;
79
80 /**
81 * Private Prime 2.
82 */
83 mpz_t q;
84
85 /**
86 * Private exponent.
87 */
88 mpz_t d;
89
90 /**
91 * Private exponent 1.
92 */
93 mpz_t exp1;
94
95 /**
96 * Private exponent 2.
97 */
98 mpz_t exp2;
99
100 /**
101 * Private coefficient.
102 */
103 mpz_t coeff;
104
105 /**
106 * Keysize in bytes.
107 */
108 size_t k;
109
110 /**
111 * Keyid formed as a SHA-1 hash of a publicKeyInfo object
112 */
113 chunk_t keyid;
114
115
116 /**
117 * @brief Implements the RSADP algorithm specified in PKCS#1.
118 *
119 * @param this calling object
120 * @param data data to process
121 * @return processed data
122 */
123 chunk_t (*rsadp) (private_rsa_private_key_t *this, chunk_t data);
124
125 /**
126 * @brief Implements the RSASP1 algorithm specified in PKCS#1.
127 * @param this calling object
128 * @param data data to process
129 * @return processed data
130 */
131 chunk_t (*rsasp1) (private_rsa_private_key_t *this, chunk_t data);
132
133 /**
134 * @brief Generate a prime value.
135 *
136 * @param this calling object
137 * @param prime_size size of the prime, in bytes
138 * @param[out] prime uninitialized mpz
139 */
140 status_t (*compute_prime) (private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime);
141
142 };
143
144 /* ASN.1 definition of a PKCS#1 RSA private key */
145 static const asn1Object_t privkey_objects[] = {
146 { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
147 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
148 { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
149 { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */
150 { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */
151 { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */
152 { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */
153 { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */
154 { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */
155 { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */
156 { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT |
157 ASN1_LOOP }, /* 10 */
158 { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
159 { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */
160 { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */
161 { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */
162 { 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */
163 };
164
165 #define PRIV_KEY_VERSION 1
166 #define PRIV_KEY_MODULUS 2
167 #define PRIV_KEY_PUB_EXP 3
168 #define PRIV_KEY_PRIV_EXP 4
169 #define PRIV_KEY_PRIME1 5
170 #define PRIV_KEY_PRIME2 6
171 #define PRIV_KEY_EXP1 7
172 #define PRIV_KEY_EXP2 8
173 #define PRIV_KEY_COEFF 9
174 #define PRIV_KEY_ROOF 16
175
176 static private_rsa_private_key_t *rsa_private_key_create_empty(void);
177
178 /**
179 * Auxiliary function overwriting private key material with
180 * pseudo-random bytes before releasing it
181 */
182 static void mpz_clear_randomized(mpz_t z)
183 {
184 size_t len = mpz_size(z) * GMP_LIMB_BITS / BITS_PER_BYTE;
185 u_int8_t *random_bytes = alloca(len);
186
187 randomizer_t *randomizer = randomizer_create();
188
189 randomizer->get_pseudo_random_bytes(randomizer, len, random_bytes);
190
191 /* overwrite mpz_t with pseudo-random bytes before clearing it */
192 mpz_import(z, len, 1, 1, 1, 0, random_bytes);
193 mpz_clear(z);
194
195 randomizer->destroy(randomizer);
196 }
197
198 /**
199 * Implementation of private_rsa_private_key_t.compute_prime.
200 */
201 static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime)
202 {
203 randomizer_t *randomizer;
204 chunk_t random_bytes;
205 status_t status;
206
207 randomizer = randomizer_create();
208 mpz_init(*prime);
209
210 do
211 {
212 status = randomizer->allocate_random_bytes(randomizer, prime_size, &random_bytes);
213 if (status != SUCCESS)
214 {
215 randomizer->destroy(randomizer);
216 mpz_clear(*prime);
217 return FAILED;
218 }
219
220 /* make sure most significant bit is set */
221 random_bytes.ptr[0] = random_bytes.ptr[0] | 0x80;
222
223 /* convert chunk to mpz value */
224 mpz_import(*prime, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
225
226 /* get next prime */
227 mpz_nextprime (*prime, *prime);
228
229 /* free the random_bytes after overwriting them with a pseudo-random sequence */
230 chunk_free_randomized(&random_bytes);
231 }
232 /* check if it isnt too large */
233 while (((mpz_sizeinbase(*prime, 2) + 7) / 8) > prime_size);
234
235 randomizer->destroy(randomizer);
236 return SUCCESS;
237 }
238
239 /**
240 * Implementation of private_rsa_private_key_t.rsadp and private_rsa_private_key_t.rsasp1.
241 */
242 static chunk_t rsadp(private_rsa_private_key_t *this, chunk_t data)
243 {
244 mpz_t t1, t2;
245 chunk_t decrypted;
246
247 mpz_init(t1);
248 mpz_init(t2);
249
250 mpz_import(t1, data.len, 1, 1, 1, 0, data.ptr);
251
252 mpz_powm(t2, t1, this->exp1, this->p); /* m1 = c^dP mod p */
253 mpz_powm(t1, t1, this->exp2, this->q); /* m2 = c^dQ mod Q */
254 mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */
255 mpz_mod(t2, t2, this->p);
256 mpz_mul(t2, t2, this->coeff);
257 mpz_mod(t2, t2, this->p);
258
259 mpz_mul(t2, t2, this->q); /* m = m2 + h q */
260 mpz_add(t1, t1, t2);
261
262 decrypted.len = this->k;
263 decrypted.ptr = mpz_export(NULL, NULL, 1, decrypted.len, 1, 0, t1);
264
265 mpz_clear_randomized(t1);
266 mpz_clear_randomized(t2);
267
268 return decrypted;
269 }
270
271 /**
272 * Implementation of rsa_private_key_t.eme_pkcs1_decrypt.
273 */
274 static status_t eme_pkcs1_decrypt(private_rsa_private_key_t *this,
275 chunk_t in, chunk_t *out)
276 {
277 status_t status = FAILED;
278 chunk_t em, em_ori;
279
280 /* decrypt the input data */
281 em = em_ori = this->rsadp(this, in);
282
283 /* PKCS#1 v1.5 EME encryption formatting
284 * EM = 00 || 02 || PS || 00 || M
285 * PS = pseudo-random nonzero octets
286 */
287
288 /* check for magic bytes */
289 if (*(em.ptr) != 0x00 || *(em.ptr+1) != 0x02)
290 {
291 DBG1("incorrect padding - probably wrong RSA key");
292 goto end;
293 }
294 em.ptr += 2;
295 em.len -= 2;
296
297 /* the plaintext data starts after first 0x00 byte */
298 while (em.len-- > 0 && *em.ptr++ != 0x00);
299
300 if (em.len == 0)
301 {
302 DBG1("no plaintext data found");
303 goto end;
304 }
305
306 *out = chunk_clone(em);
307 status = SUCCESS;
308
309 end:
310 free(em_ori.ptr);
311 return status;
312 }
313
314 /**
315 * Implementation of rsa_private_key_t.build_emsa_pkcs1_signature.
316 */
317 static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this,
318 hash_algorithm_t hash_algorithm,
319 chunk_t data, chunk_t *signature)
320 {
321 hasher_t *hasher;
322 chunk_t em, digestInfo, hash_id, hash;
323
324 /* get oid string prepended to hash */
325 switch (hash_algorithm)
326 {
327 case HASH_MD2:
328 {
329 hash_id =ASN1_md2_id;
330 break;
331 }
332 case HASH_MD5:
333 {
334 hash_id = ASN1_md5_id;
335 break;
336 }
337 case HASH_SHA1:
338 {
339 hash_id = ASN1_sha1_id;
340 break;
341 }
342 case HASH_SHA256:
343 {
344 hash_id = ASN1_sha256_id;
345 break;
346 }
347 case HASH_SHA384:
348 {
349 hash_id = ASN1_sha384_id;
350 break;
351 }
352 case HASH_SHA512:
353 {
354 hash_id = ASN1_sha512_id;
355 break;
356 }
357 default:
358 {
359 return NOT_SUPPORTED;
360 }
361 }
362
363 /* get hasher */
364 hasher = hasher_create(hash_algorithm);
365 if (hasher == NULL)
366 {
367 return NOT_SUPPORTED;
368 }
369
370 /* build hash */
371 hasher->allocate_hash(hasher, data, &hash);
372 hasher->destroy(hasher);
373
374 /* build DER-encoded digestInfo */
375 digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
376 hash_id,
377 asn1_simple_object(ASN1_OCTET_STRING, hash)
378 );
379 chunk_free(&hash);
380
381 /* build chunk to rsa-decrypt:
382 * EM = 0x00 || 0x01 || PS || 0x00 || T.
383 * PS = 0xFF padding, with length to fill em
384 * T = encoded_hash
385 */
386 em.len = this->k;
387 em.ptr = malloc(em.len);
388
389 /* fill em with padding */
390 memset(em.ptr, 0xFF, em.len);
391 /* set magic bytes */
392 *(em.ptr) = 0x00;
393 *(em.ptr+1) = 0x01;
394 *(em.ptr + em.len - digestInfo.len - 1) = 0x00;
395 /* set DER-encoded hash */
396 memcpy(em.ptr + em.len - digestInfo.len, digestInfo.ptr, digestInfo.len);
397
398 /* build signature */
399 *signature = this->rsasp1(this, em);
400
401 free(digestInfo.ptr);
402 free(em.ptr);
403
404 return SUCCESS;
405 }
406
407 /**
408 * Implementation of rsa_private_key.save_key.
409 */
410 static status_t save_key(private_rsa_private_key_t *this, char *file)
411 {
412 return NOT_SUPPORTED;
413 }
414
415 /**
416 * Implementation of rsa_private_key.get_public_key.
417 */
418 rsa_public_key_t *get_public_key(private_rsa_private_key_t *this)
419 {
420 return NULL;
421 }
422
423 /**
424 * Implementation of rsa_private_key.belongs_to.
425 */
426 static bool belongs_to(private_rsa_private_key_t *this, rsa_public_key_t *public)
427 {
428 return chunk_equals(this->keyid, public->get_keyid(public));
429 }
430
431 /**
432 * Check the loaded key if it is valid and usable
433 * TODO: Log errors
434 */
435 static status_t check(private_rsa_private_key_t *this)
436 {
437 mpz_t t, u, q1;
438 status_t status = SUCCESS;
439
440 /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets.
441 * We actually require more (for security).
442 */
443 if (this->k < 512/8)
444 {
445 return FAILED;
446 }
447
448 /* we picked a max modulus size to simplify buffer allocation */
449 if (this->k > 8192/8)
450 {
451 return FAILED;
452 }
453
454 mpz_init(t);
455 mpz_init(u);
456 mpz_init(q1);
457
458 /* check that n == p * q */
459 mpz_mul(u, this->p, this->q);
460 if (mpz_cmp(u, this->n) != 0)
461 {
462 status = FAILED;
463 }
464
465 /* check that e divides neither p-1 nor q-1 */
466 mpz_sub_ui(t, this->p, 1);
467 mpz_mod(t, t, this->e);
468 if (mpz_cmp_ui(t, 0) == 0)
469 {
470 status = FAILED;
471 }
472
473 mpz_sub_ui(t, this->q, 1);
474 mpz_mod(t, t, this->e);
475 if (mpz_cmp_ui(t, 0) == 0)
476 {
477 status = FAILED;
478 }
479
480 /* check that d is e^-1 (mod lcm(p-1, q-1)) */
481 /* see PKCS#1v2, aka RFC 2437, for the "lcm" */
482 mpz_sub_ui(q1, this->q, 1);
483 mpz_sub_ui(u, this->p, 1);
484 mpz_gcd(t, u, q1); /* t := gcd(p-1, q-1) */
485 mpz_mul(u, u, q1); /* u := (p-1) * (q-1) */
486 mpz_divexact(u, u, t); /* u := lcm(p-1, q-1) */
487
488 mpz_mul(t, this->d, this->e);
489 mpz_mod(t, t, u);
490 if (mpz_cmp_ui(t, 1) != 0)
491 {
492 status = FAILED;
493 }
494
495 /* check that exp1 is d mod (p-1) */
496 mpz_sub_ui(u, this->p, 1);
497 mpz_mod(t, this->d, u);
498 if (mpz_cmp(t, this->exp1) != 0)
499 {
500 status = FAILED;
501 }
502
503 /* check that exp2 is d mod (q-1) */
504 mpz_sub_ui(u, this->q, 1);
505 mpz_mod(t, this->d, u);
506 if (mpz_cmp(t, this->exp2) != 0)
507 {
508 status = FAILED;
509 }
510
511 /* check that coeff is (q^-1) mod p */
512 mpz_mul(t, this->coeff, this->q);
513 mpz_mod(t, t, this->p);
514 if (mpz_cmp_ui(t, 1) != 0)
515 {
516 status = FAILED;
517 }
518
519 mpz_clear_randomized(t);
520 mpz_clear_randomized(u);
521 mpz_clear_randomized(q1);
522 return status;
523 }
524
525 /**
526 * Implementation of rsa_private_key.destroy.
527 */
528 static void destroy(private_rsa_private_key_t *this)
529 {
530 mpz_clear_randomized(this->n);
531 mpz_clear_randomized(this->e);
532 mpz_clear_randomized(this->p);
533 mpz_clear_randomized(this->q);
534 mpz_clear_randomized(this->d);
535 mpz_clear_randomized(this->exp1);
536 mpz_clear_randomized(this->exp2);
537 mpz_clear_randomized(this->coeff);
538 chunk_free_randomized(&this->keyid);
539 free(this);
540 }
541
542 /**
543 * Internal generic constructor
544 */
545 static private_rsa_private_key_t *rsa_private_key_create_empty(void)
546 {
547 private_rsa_private_key_t *this = malloc_thing(private_rsa_private_key_t);
548
549 /* public functions */
550 this->public.eme_pkcs1_decrypt = (status_t (*) (rsa_private_key_t*,chunk_t,chunk_t*))eme_pkcs1_decrypt;
551 this->public.build_emsa_pkcs1_signature = (status_t (*) (rsa_private_key_t*,hash_algorithm_t,chunk_t,chunk_t*))build_emsa_pkcs1_signature;
552 this->public.save_key = (status_t (*) (rsa_private_key_t*,char*))save_key;
553 this->public.get_public_key = (rsa_public_key_t *(*) (rsa_private_key_t*))get_public_key;
554 this->public.belongs_to = (bool (*) (rsa_private_key_t*,rsa_public_key_t*))belongs_to;
555 this->public.destroy = (void (*) (rsa_private_key_t*))destroy;
556
557 /* private functions */
558 this->rsadp = rsadp;
559 this->rsasp1 = rsadp; /* same algorithm */
560 this->compute_prime = compute_prime;
561
562 this->keyid = chunk_empty;
563
564 return this;
565 }
566
567 /*
568 * See header
569 */
570 rsa_private_key_t *rsa_private_key_create(size_t key_size)
571 {
572 mpz_t p, q, n, e, d, exp1, exp2, coeff;
573 mpz_t m, q1, t;
574 private_rsa_private_key_t *this;
575
576 this = rsa_private_key_create_empty();
577 key_size = key_size / 8;
578
579 /* Get values of primes p and q */
580 if (this->compute_prime(this, key_size/2, &p) != SUCCESS)
581 {
582 free(this);
583 return NULL;
584 }
585 if (this->compute_prime(this, key_size/2, &q) != SUCCESS)
586 {
587 mpz_clear(p);
588 free(this);
589 return NULL;
590 }
591
592 mpz_init(t);
593 mpz_init(n);
594 mpz_init(d);
595 mpz_init(exp1);
596 mpz_init(exp2);
597 mpz_init(coeff);
598
599 /* Swapping Primes so p is larger then q */
600 if (mpz_cmp(p, q) < 0)
601 {
602 mpz_swap(p, q);
603 }
604
605 mpz_mul(n, p, q); /* n = p*q */
606 mpz_init_set_ui(e, PUBLIC_EXPONENT); /* assign public exponent */
607 mpz_init_set(m, p); /* m = p */
608 mpz_sub_ui(m, m, 1); /* m = m -1 */
609 mpz_init_set(q1, q); /* q1 = q */
610 mpz_sub_ui(q1, q1, 1); /* q1 = q1 -1 */
611 mpz_gcd(t, m, q1); /* t = gcd(p-1, q-1) */
612 mpz_mul(m, m, q1); /* m = (p-1)*(q-1) */
613 mpz_divexact(m, m, t); /* m = m / t */
614 mpz_gcd(t, m, e); /* t = gcd(m, e) (greatest common divisor) */
615
616 mpz_invert(d, e, m); /* e has an inverse mod m */
617 if (mpz_cmp_ui(d, 0) < 0) /* make sure d is positive */
618 {
619 mpz_add(d, d, m);
620 }
621 mpz_sub_ui(t, p, 1); /* t = p-1 */
622 mpz_mod(exp1, d, t); /* exp1 = d mod p-1 */
623 mpz_sub_ui(t, q, 1); /* t = q-1 */
624 mpz_mod(exp2, d, t); /* exp2 = d mod q-1 */
625
626 mpz_invert(coeff, q, p); /* coeff = q^-1 mod p */
627 if (mpz_cmp_ui(coeff, 0) < 0) /* make coeff d is positive */
628 {
629 mpz_add(coeff, coeff, p);
630 }
631
632 mpz_clear_randomized(q1);
633 mpz_clear_randomized(m);
634 mpz_clear_randomized(t);
635
636 /* apply values */
637 *(this->p) = *p;
638 *(this->q) = *q;
639 *(this->n) = *n;
640 *(this->e) = *e;
641 *(this->d) = *d;
642 *(this->exp1) = *exp1;
643 *(this->exp2) = *exp2;
644 *(this->coeff) = *coeff;
645
646 /* set key size in bytes */
647 this->k = key_size;
648
649 return &this->public;
650 }
651
652 /*
653 * see header
654 */
655 rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob)
656 {
657 asn1_ctx_t ctx;
658 chunk_t object;
659 u_int level;
660 int objectID = 0;
661 private_rsa_private_key_t *this;
662
663 this = rsa_private_key_create_empty();
664
665 mpz_init(this->n);
666 mpz_init(this->e);
667 mpz_init(this->p);
668 mpz_init(this->q);
669 mpz_init(this->d);
670 mpz_init(this->exp1);
671 mpz_init(this->exp2);
672 mpz_init(this->coeff);
673
674 asn1_init(&ctx, blob, 0, FALSE, TRUE);
675
676 while (objectID < PRIV_KEY_ROOF)
677 {
678 if (!extract_object(privkey_objects, &objectID, &object, &level, &ctx))
679 {
680 destroy(this);
681 return FALSE;
682 }
683 switch (objectID)
684 {
685 case PRIV_KEY_VERSION:
686 if (object.len > 0 && *object.ptr != 0)
687 {
688 destroy(this);
689 return NULL;
690 }
691 break;
692 case PRIV_KEY_MODULUS:
693 mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
694 break;
695 case PRIV_KEY_PUB_EXP:
696 mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
697 break;
698 case PRIV_KEY_PRIV_EXP:
699 mpz_import(this->d, object.len, 1, 1, 1, 0, object.ptr);
700 break;
701 case PRIV_KEY_PRIME1:
702 mpz_import(this->p, object.len, 1, 1, 1, 0, object.ptr);
703 break;
704 case PRIV_KEY_PRIME2:
705 mpz_import(this->q, object.len, 1, 1, 1, 0, object.ptr);
706 break;
707 case PRIV_KEY_EXP1:
708 mpz_import(this->exp1, object.len, 1, 1, 1, 0, object.ptr);
709 break;
710 case PRIV_KEY_EXP2:
711 mpz_import(this->exp2, object.len, 1, 1, 1, 0, object.ptr);
712 break;
713 case PRIV_KEY_COEFF:
714 mpz_import(this->coeff, object.len, 1, 1, 1, 0, object.ptr);
715 break;
716 }
717 objectID++;
718 }
719
720 this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
721
722 /* form the keyid as a SHA-1 hash of a publicKeyInfo object */
723 {
724 chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(this->n, this->e);
725 hasher_t *hasher = hasher_create(HASH_SHA1);
726
727 hasher->allocate_hash(hasher, publicKeyInfo, &this->keyid);
728 hasher->destroy(hasher);
729 free(publicKeyInfo.ptr);
730 }
731
732 if (check(this) != SUCCESS)
733 {
734 destroy(this);
735 return NULL;
736 }
737 else
738 {
739 return &this->public;
740 }
741 }
742
743 /*
744 * see header
745 */
746 rsa_private_key_t *rsa_private_key_create_from_file(char *filename, chunk_t *passphrase)
747 {
748 bool pgp = FALSE;
749 chunk_t chunk = chunk_empty;
750 rsa_private_key_t *key = NULL;
751
752 if (!pem_asn1_load_file(filename, passphrase, "private key", &chunk, &pgp))
753 return NULL;
754
755 key = rsa_private_key_create_from_chunk(chunk);
756 chunk_free_randomized(&chunk);
757 return key;
758 }