2 * @file rsa_private_key.c
4 * @brief Implementation of rsa_private_key_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 #include "rsa_private_key.h"
28 #include <utils/allocator.h>
31 /* oids for hash algorithms are defined in
34 extern u_int8_t md2_oid
[18];
35 extern u_int8_t md5_oid
[18];
36 extern u_int8_t sha1_oid
[15];
37 extern u_int8_t sha256_oid
[19];
38 extern u_int8_t sha384_oid
[19];
39 extern u_int8_t sha512_oid
[19];
42 * Public exponent to use for key generation
44 #define PUBLIC_EXPONENT 0x10001
47 typedef struct private_rsa_private_key_t private_rsa_private_key_t
;
50 * private data structure for rsa_private_key.
52 struct private_rsa_private_key_t
{
54 * Public interface for this signer.
56 rsa_private_key_t
public;
59 * is the key already set ?
109 * @brief Implements the RSADP algorithm specified in PKCS#1.
111 chunk_t (*rsadp
) (private_rsa_private_key_t
*this, chunk_t data
);
114 * @brief Implements the RSASP1 algorithm specified in PKCS#1.
116 chunk_t (*rsasp1
) (private_rsa_private_key_t
*this, chunk_t data
);
121 * Implements private_rsa_private_key_t.rsadp
122 * Implements private_rsa_private_key_t.rsasp1
124 static chunk_t
rsadp(private_rsa_private_key_t
*this, chunk_t data
)
132 mpz_import(t1
, data
.len
, 1, 1, 1, 0, data
.ptr
);
134 mpz_powm(t2
, t1
, this->exp1
, this->p
); /* m1 = c^dP mod p */
135 mpz_powm(t1
, t1
, this->exp2
, this->q
); /* m2 = c^dQ mod Q */
136 mpz_sub(t2
, t2
, t1
); /* h = qInv (m1 - m2) mod p */
137 mpz_mod(t2
, t2
, this->p
);
138 mpz_mul(t2
, t2
, this->coeff
);
139 mpz_mod(t2
, t2
, this->p
);
141 mpz_mul(t2
, t2
, this->q
); /* m = m2 + h q */
144 decrypted
.len
= this->k
;
145 decrypted
.ptr
= mpz_export(NULL
, NULL
, 1, decrypted
.len
, 1, 0, t1
);
154 * implementation of rsa_private_key.build_emsa_signature.
156 static status_t
build_emsa_pkcs1_signature(private_rsa_private_key_t
*this, hash_algorithm_t hash_algorithm
, chunk_t data
, chunk_t
*signature
)
163 /* get oid string prepended to hash */
164 switch (hash_algorithm
)
169 oid
.len
= sizeof(md2_oid
);
175 oid
.len
= sizeof(md5_oid
);
181 oid
.len
= sizeof(sha1_oid
);
186 oid
.ptr
= sha256_oid
;
187 oid
.len
= sizeof(sha256_oid
);
192 oid
.ptr
= sha384_oid
;
193 oid
.len
= sizeof(sha384_oid
);
198 oid
.ptr
= sha512_oid
;
199 oid
.len
= sizeof(sha512_oid
);
204 return NOT_SUPPORTED
;
209 hasher
= hasher_create(hash_algorithm
);
212 return NOT_SUPPORTED
;
216 hasher
->allocate_hash(hasher
, data
, &hash
);
217 hasher
->destroy(hasher
);
219 /* build chunk to rsa-decrypt:
220 * EM = 0x00 || 0x01 || PS || 0x00 || T.
221 * PS = 0xFF padding, with length to fill em
225 em
.ptr
= allocator_alloc(em
.len
);
227 /* fill em with padding */
228 memset(em
.ptr
, 0xFF, em
.len
);
229 /* set magic bytes */
232 *(em
.ptr
+ em
.len
- hash
.len
- oid
.len
- 1) = 0x00;
234 memcpy(em
.ptr
+ em
.len
- hash
.len
, hash
.ptr
, hash
.len
);
236 memcpy(em
.ptr
+ em
.len
- hash
.len
- oid
.len
, oid
.ptr
, oid
.len
);
239 /* build signature */
240 *signature
= this->rsasp1(this, em
);
242 allocator_free(hash
.ptr
);
243 allocator_free(em
.ptr
);
250 * implementation of rsa_private_key.set_key.
252 static status_t
set_key(private_rsa_private_key_t
*this, chunk_t key
)
254 chunk_t n
, e
, p
, q
, d
, exp1
, exp2
, coeff
;
255 this->k
= key
.len
/ 8;
266 n
.ptr
= key
.ptr
+ this->k
* 0;
267 e
.ptr
= key
.ptr
+ this->k
* 1;
268 p
.ptr
= key
.ptr
+ this->k
* 2;
269 q
.ptr
= key
.ptr
+ this->k
* 3;
270 d
.ptr
= key
.ptr
+ this->k
* 4;
271 exp1
.ptr
= key
.ptr
+ this->k
* 5;
272 exp2
.ptr
= key
.ptr
+ this->k
* 6;
273 coeff
.ptr
= key
.ptr
+ this->k
* 7;
275 mpz_import(this->n
, this->k
, 1, 1, 1, 0, n
.ptr
);
276 mpz_import(this->e
, this->k
, 1, 1, 1, 0, e
.ptr
);
277 mpz_import(this->p
, this->k
, 1, 1, 1, 0, p
.ptr
);
278 mpz_import(this->q
, this->k
, 1, 1, 1, 0, q
.ptr
);
279 mpz_import(this->d
, this->k
, 1, 1, 1, 0, d
.ptr
);
280 mpz_import(this->exp1
, this->k
, 1, 1, 1, 0, exp1
.ptr
);
281 mpz_import(this->exp2
, this->k
, 1, 1, 1, 0, exp2
.ptr
);
282 mpz_import(this->coeff
, this->k
, 1, 1, 1, 0, coeff
.ptr
);
284 this->is_key_set
= TRUE
;
291 * implementation of rsa_private_key.get_key.
293 static status_t
get_key(private_rsa_private_key_t
*this, chunk_t
*key
)
295 if (!this->is_key_set
)
297 return INVALID_STATE
;
300 chunk_t n
, e
, p
, q
, d
, exp1
, exp2
, coeff
;
303 n
.ptr
= mpz_export(NULL
, NULL
, 1, n
.len
, 1, 0, this->n
);
305 e
.ptr
= mpz_export(NULL
, NULL
, 1, e
.len
, 1, 0, this->e
);
307 p
.ptr
= mpz_export(NULL
, NULL
, 1, p
.len
, 1, 0, this->p
);
309 q
.ptr
= mpz_export(NULL
, NULL
, 1, q
.len
, 1, 0, this->q
);
311 d
.ptr
= mpz_export(NULL
, NULL
, 1, d
.len
, 1, 0, this->d
);
313 exp1
.ptr
= mpz_export(NULL
, NULL
, 1, exp1
.len
, 1, 0, this->exp1
);
315 exp2
.ptr
= mpz_export(NULL
, NULL
, 1, exp2
.len
, 1, 0, this->exp2
);
317 coeff
.ptr
= mpz_export(NULL
, NULL
, 1, coeff
.len
, 1, 0, this->coeff
);
319 key
->len
= this->k
* 8;
320 key
->ptr
= allocator_alloc(key
->len
);
321 memcpy(key
->ptr
+ this->k
* 0, n
.ptr
, n
.len
);
322 memcpy(key
->ptr
+ this->k
* 1, e
.ptr
, e
.len
);
323 memcpy(key
->ptr
+ this->k
* 2, p
.ptr
, p
.len
);
324 memcpy(key
->ptr
+ this->k
* 3, q
.ptr
, q
.len
);
325 memcpy(key
->ptr
+ this->k
* 4, d
.ptr
, d
.len
);
326 memcpy(key
->ptr
+ this->k
* 5, exp1
.ptr
, exp1
.len
);
327 memcpy(key
->ptr
+ this->k
* 6, exp2
.ptr
, exp2
.len
);
328 memcpy(key
->ptr
+ this->k
* 7, coeff
.ptr
, coeff
.len
);
330 allocator_free(n
.ptr
);
331 allocator_free(e
.ptr
);
332 allocator_free(p
.ptr
);
333 allocator_free(q
.ptr
);
334 allocator_free(d
.ptr
);
335 allocator_free(exp1
.ptr
);
336 allocator_free(exp2
.ptr
);
337 allocator_free(coeff
.ptr
);
343 * implementation of rsa_private_key.load_key.
345 static status_t
load_key(private_rsa_private_key_t
*this, char *file
)
347 return NOT_SUPPORTED
;
351 * implementation of rsa_private_key.save_key.
353 static status_t
save_key(private_rsa_private_key_t
*this, char *file
)
355 return NOT_SUPPORTED
;
359 * implementation of rsa_private_key.generate_key.
361 static status_t
generate_key(private_rsa_private_key_t
*this, size_t key_size
)
363 mpz_t p
, q
, n
, e
, d
, exp1
, exp2
, coeff
;
371 if (this->is_key_set
)
378 mpz_clear(this->exp1
);
379 mpz_clear(this->exp2
);
380 mpz_clear(this->coeff
);
383 key_size
= key_size
/ 8;
392 /* Get values of primes p and q */
393 charon
->prime_pool
->get_prime(charon
->prime_pool
, key_size
/2, &p
);
394 charon
->prime_pool
->get_prime(charon
->prime_pool
, key_size
/2, &q
);
396 /* Swapping Primes so p is larger then q */
397 if (mpz_cmp(p
, q
) < 0)
404 mpz_mul(n
, p
, q
); /* n = p*q */
405 mpz_init_set_ui(e
, PUBLIC_EXPONENT
); /* assign public exponent */
406 mpz_init_set(m
, p
); /* m = p */
407 mpz_sub_ui(m
, m
, 1); /* m = m -1 */
408 mpz_init_set(q1
, q
); /* q1 = q */
409 mpz_sub_ui(q1
, q1
, 1); /* q1 = q1 -1 */
410 mpz_gcd(t
, m
, q1
); /* t = gcd(p-1, q-1) */
411 mpz_mul(m
, m
, q1
); /* m = (p-1)*(q-1) */
412 mpz_divexact(m
, m
, t
); /* m = m / t */
413 mpz_gcd(t
, m
, e
); /* t = gcd(m, e) (greatest common divisor) */
415 mpz_invert(d
, e
, m
); /* e has an inverse mod m */
416 if (mpz_cmp_ui(d
, 0) < 0) /* make sure d is positive */
420 mpz_sub_ui(t
, p
, 1); /* t = p-1 */
421 mpz_mod(exp1
, d
, t
); /* exp1 = d mod p-1 */
422 mpz_sub_ui(t
, q
, 1); /* t = q-1 */
423 mpz_mod(exp2
, d
, t
); /* exp2 = d mod q-1 */
425 mpz_invert(coeff
, q
, p
); /* coeff = q^-1 mod p */
426 if (mpz_cmp_ui(coeff
, 0) < 0) /* make coeff d is positive */
428 mpz_add(coeff
, coeff
, p
);
441 *(this->exp1
) = *exp1
;
442 *(this->exp2
) = *exp2
;
443 *(this->coeff
) = *coeff
;
445 /* set key size in bytes */
447 this->is_key_set
= TRUE
;
454 rsa_public_key_t
*get_public_key(private_rsa_private_key_t
*this)
456 rsa_public_key_t
*public_key
;
459 public_key
= rsa_public_key_create();
461 if (this->is_key_set
)
467 n
.ptr
= mpz_export(NULL
, NULL
, 1, n
.len
, 1, 0, this->n
);
469 e
.ptr
= mpz_export(NULL
, NULL
, 1, e
.len
, 1, 0, this->e
);
471 key
.len
= this->k
* 2;
472 key
.ptr
= allocator_alloc(key
.len
);
473 memcpy(key
.ptr
, n
.ptr
, n
.len
);
474 memcpy(key
.ptr
+ n
.len
, e
.ptr
, e
.len
);
475 allocator_free(n
.ptr
);
476 allocator_free(e
.ptr
);
478 public_key
->set_key(public_key
, key
);
479 allocator_free(key
.ptr
);
488 * implementation of rsa_private_key.destroy.
490 static void destroy(private_rsa_private_key_t
*this)
492 if (this->is_key_set
)
499 mpz_clear(this->exp1
);
500 mpz_clear(this->exp2
);
501 mpz_clear(this->coeff
);
503 allocator_free(this);
507 * Described in header
509 rsa_private_key_t
*rsa_private_key_create(hash_algorithm_t hash_algoritm
)
511 private_rsa_private_key_t
*this = allocator_alloc_thing(private_rsa_private_key_t
);
513 /* public functions */
514 this->public.build_emsa_pkcs1_signature
= (status_t (*) (rsa_private_key_t
*,hash_algorithm_t
,chunk_t
,chunk_t
*))build_emsa_pkcs1_signature
;
515 this->public.set_key
= (status_t (*) (rsa_private_key_t
*,chunk_t
))set_key
;
516 this->public.get_key
= (status_t (*) (rsa_private_key_t
*,chunk_t
*))get_key
;
517 this->public.load_key
= (status_t (*) (rsa_private_key_t
*,char*))load_key
;
518 this->public.save_key
= (status_t (*) (rsa_private_key_t
*,char*))save_key
;
519 this->public.generate_key
= (status_t (*) (rsa_private_key_t
*,size_t))generate_key
;
520 this->public.get_public_key
= (rsa_public_key_t
*(*) (rsa_private_key_t
*))get_public_key
;
521 this->public.destroy
= (void (*) (rsa_private_key_t
*))destroy
;
523 /* private functions */
525 this->rsasp1
= rsadp
; /* same algorithm */
527 this->is_key_set
= FALSE
;
529 return &(this->public);