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