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
27 #include "rsa_private_key.h"
30 #include <utils/allocator.h>
31 #include <asn1/der_decoder.h>
35 * Oids for hash algorithms are defined in
38 extern u_int8_t md2_oid
[18];
39 extern u_int8_t md5_oid
[18];
40 extern u_int8_t sha1_oid
[15];
41 extern u_int8_t sha256_oid
[19];
42 extern u_int8_t sha384_oid
[19];
43 extern u_int8_t sha512_oid
[19];
47 * Public exponent to use for key generation.
49 #define PUBLIC_EXPONENT 0x10001
52 typedef struct private_rsa_private_key_t private_rsa_private_key_t
;
55 * Private data of a rsa_private_key_t object.
57 struct private_rsa_private_key_t
{
59 * Public interface for this signer.
61 rsa_private_key_t
public;
64 * Version of key, as encoded in PKCS#1
104 * Private coefficient.
114 * @brief Implements the RSADP algorithm specified in PKCS#1.
116 * @param this calling object
117 * @param data data to process
118 * @return processed data
120 chunk_t (*rsadp
) (private_rsa_private_key_t
*this, chunk_t data
);
123 * @brief Implements the RSASP1 algorithm specified in PKCS#1.
124 * @param this calling object
125 * @param data data to process
126 * @return processed data
128 chunk_t (*rsasp1
) (private_rsa_private_key_t
*this, chunk_t data
);
131 * @brief Generate a prime value.
133 * @param this calling object
134 * @param prime_size size of the prime, in bytes
135 * @param[out] prime uninitialized mpz
137 void (*compute_prime
) (private_rsa_private_key_t
*this, size_t prime_size
, mpz_t
*prime
);
142 * Rules for de-/encoding of a private key from/in ASN1
144 static asn1_rule_t rsa_private_key_rules
[] = {
145 {ASN1_SEQUENCE
, 0, 0, 0},
146 { ASN1_INTEGER
, 0, offsetof(private_rsa_private_key_t
, version
), 0},
147 { ASN1_INTEGER
, ASN1_MPZ
, offsetof(private_rsa_private_key_t
, n
), 0},
148 { ASN1_INTEGER
, ASN1_MPZ
, offsetof(private_rsa_private_key_t
, e
), 0},
149 { ASN1_INTEGER
, ASN1_MPZ
, offsetof(private_rsa_private_key_t
, d
), 0},
150 { ASN1_INTEGER
, ASN1_MPZ
, offsetof(private_rsa_private_key_t
, p
), 0},
151 { ASN1_INTEGER
, ASN1_MPZ
, offsetof(private_rsa_private_key_t
, q
), 0},
152 { ASN1_INTEGER
, ASN1_MPZ
, offsetof(private_rsa_private_key_t
, exp1
), 0},
153 { ASN1_INTEGER
, ASN1_MPZ
, offsetof(private_rsa_private_key_t
, exp2
), 0},
154 { ASN1_INTEGER
, ASN1_MPZ
, offsetof(private_rsa_private_key_t
, coeff
), 0},
159 * Implementation of private_rsa_private_key_t.compute_prime.
161 static void compute_prime(private_rsa_private_key_t
*this, size_t prime_size
, mpz_t
*prime
)
163 randomizer_t
*randomizer
;
164 chunk_t random_bytes
;
166 randomizer
= randomizer_create();
171 randomizer
->allocate_random_bytes(randomizer
, prime_size
, &random_bytes
);
173 /* make sure most significant bit is set */
174 random_bytes
.ptr
[0] = random_bytes
.ptr
[0] | 0x80;
176 /* convert chunk to mpz value */
177 mpz_import(*prime
, random_bytes
.len
, 1, 1, 1, 0, random_bytes
.ptr
);
180 mpz_nextprime (*prime
, *prime
);
182 allocator_free(random_bytes
.ptr
);
184 /* check if it isnt too large */
185 while (((mpz_sizeinbase(*prime
, 2) + 7) / 8) > prime_size
);
187 randomizer
->destroy(randomizer
);
191 * Implementation of private_rsa_private_key_t.rsadp and private_rsa_private_key_t.rsasp1.
193 static chunk_t
rsadp(private_rsa_private_key_t
*this, chunk_t data
)
201 mpz_import(t1
, data
.len
, 1, 1, 1, 0, data
.ptr
);
203 mpz_powm(t2
, t1
, this->exp1
, this->p
); /* m1 = c^dP mod p */
204 mpz_powm(t1
, t1
, this->exp2
, this->q
); /* m2 = c^dQ mod Q */
205 mpz_sub(t2
, t2
, t1
); /* h = qInv (m1 - m2) mod p */
206 mpz_mod(t2
, t2
, this->p
);
207 mpz_mul(t2
, t2
, this->coeff
);
208 mpz_mod(t2
, t2
, this->p
);
210 mpz_mul(t2
, t2
, this->q
); /* m = m2 + h q */
213 decrypted
.len
= this->k
;
214 decrypted
.ptr
= mpz_export(NULL
, NULL
, 1, decrypted
.len
, 1, 0, t1
);
223 * Implementation of rsa_private_key.build_emsa_signature.
225 static status_t
build_emsa_pkcs1_signature(private_rsa_private_key_t
*this, hash_algorithm_t hash_algorithm
, chunk_t data
, chunk_t
*signature
)
232 /* get oid string prepended to hash */
233 switch (hash_algorithm
)
238 oid
.len
= sizeof(md2_oid
);
244 oid
.len
= sizeof(md5_oid
);
250 oid
.len
= sizeof(sha1_oid
);
255 oid
.ptr
= sha256_oid
;
256 oid
.len
= sizeof(sha256_oid
);
261 oid
.ptr
= sha384_oid
;
262 oid
.len
= sizeof(sha384_oid
);
267 oid
.ptr
= sha512_oid
;
268 oid
.len
= sizeof(sha512_oid
);
273 return NOT_SUPPORTED
;
278 hasher
= hasher_create(hash_algorithm
);
281 return NOT_SUPPORTED
;
285 hasher
->allocate_hash(hasher
, data
, &hash
);
286 hasher
->destroy(hasher
);
288 /* build chunk to rsa-decrypt:
289 * EM = 0x00 || 0x01 || PS || 0x00 || T.
290 * PS = 0xFF padding, with length to fill em
294 em
.ptr
= allocator_alloc(em
.len
);
296 /* fill em with padding */
297 memset(em
.ptr
, 0xFF, em
.len
);
298 /* set magic bytes */
301 *(em
.ptr
+ em
.len
- hash
.len
- oid
.len
- 1) = 0x00;
303 memcpy(em
.ptr
+ em
.len
- hash
.len
, hash
.ptr
, hash
.len
);
305 memcpy(em
.ptr
+ em
.len
- hash
.len
- oid
.len
, oid
.ptr
, oid
.len
);
308 /* build signature */
309 *signature
= this->rsasp1(this, em
);
311 allocator_free(hash
.ptr
);
312 allocator_free(em
.ptr
);
318 * Implementation of rsa_private_key.get_key.
320 static status_t
get_key(private_rsa_private_key_t
*this, chunk_t
*key
)
322 chunk_t n
, e
, p
, q
, d
, exp1
, exp2
, coeff
;
325 n
.ptr
= mpz_export(NULL
, NULL
, 1, n
.len
, 1, 0, this->n
);
327 e
.ptr
= mpz_export(NULL
, NULL
, 1, e
.len
, 1, 0, this->e
);
329 p
.ptr
= mpz_export(NULL
, NULL
, 1, p
.len
, 1, 0, this->p
);
331 q
.ptr
= mpz_export(NULL
, NULL
, 1, q
.len
, 1, 0, this->q
);
333 d
.ptr
= mpz_export(NULL
, NULL
, 1, d
.len
, 1, 0, this->d
);
335 exp1
.ptr
= mpz_export(NULL
, NULL
, 1, exp1
.len
, 1, 0, this->exp1
);
337 exp2
.ptr
= mpz_export(NULL
, NULL
, 1, exp2
.len
, 1, 0, this->exp2
);
339 coeff
.ptr
= mpz_export(NULL
, NULL
, 1, coeff
.len
, 1, 0, this->coeff
);
341 key
->len
= this->k
* 8;
342 key
->ptr
= allocator_alloc(key
->len
);
343 memcpy(key
->ptr
+ this->k
* 0, n
.ptr
, n
.len
);
344 memcpy(key
->ptr
+ this->k
* 1, e
.ptr
, e
.len
);
345 memcpy(key
->ptr
+ this->k
* 2, p
.ptr
, p
.len
);
346 memcpy(key
->ptr
+ this->k
* 3, q
.ptr
, q
.len
);
347 memcpy(key
->ptr
+ this->k
* 4, d
.ptr
, d
.len
);
348 memcpy(key
->ptr
+ this->k
* 5, exp1
.ptr
, exp1
.len
);
349 memcpy(key
->ptr
+ this->k
* 6, exp2
.ptr
, exp2
.len
);
350 memcpy(key
->ptr
+ this->k
* 7, coeff
.ptr
, coeff
.len
);
352 allocator_free(n
.ptr
);
353 allocator_free(e
.ptr
);
354 allocator_free(p
.ptr
);
355 allocator_free(q
.ptr
);
356 allocator_free(d
.ptr
);
357 allocator_free(exp1
.ptr
);
358 allocator_free(exp2
.ptr
);
359 allocator_free(coeff
.ptr
);
365 * Implementation of rsa_private_key.save_key.
367 static status_t
save_key(private_rsa_private_key_t
*this, char *file
)
369 return NOT_SUPPORTED
;
373 * Implementation of rsa_private_key.get_public_key.
375 rsa_public_key_t
*get_public_key(private_rsa_private_key_t
*this)
381 * Implementation of rsa_private_key.belongs_to.
383 bool belongs_to(private_rsa_private_key_t
*this, rsa_public_key_t
*public)
385 if (mpz_cmp(this->n
, *public->get_modulus(public)) == 0)
394 * Implementation of rsa_private_key.destroy.
396 static void destroy(private_rsa_private_key_t
*this)
403 mpz_clear(this->exp1
);
404 mpz_clear(this->exp2
);
405 mpz_clear(this->coeff
);
406 allocator_free(this);
410 * Internal generic constructor
412 static private_rsa_private_key_t
*rsa_private_key_create_empty()
414 private_rsa_private_key_t
*this = allocator_alloc_thing(private_rsa_private_key_t
);
416 /* public functions */
417 this->public.build_emsa_pkcs1_signature
= (status_t (*) (rsa_private_key_t
*,hash_algorithm_t
,chunk_t
,chunk_t
*))build_emsa_pkcs1_signature
;
418 this->public.get_key
= (status_t (*) (rsa_private_key_t
*,chunk_t
*))get_key
;
419 this->public.save_key
= (status_t (*) (rsa_private_key_t
*,char*))save_key
;
420 this->public.get_public_key
= (rsa_public_key_t
*(*) (rsa_private_key_t
*))get_public_key
;
421 this->public.belongs_to
= (bool (*) (rsa_private_key_t
*,rsa_public_key_t
*))belongs_to
;
422 this->public.destroy
= (void (*) (rsa_private_key_t
*))destroy
;
424 /* private functions */
426 this->rsasp1
= rsadp
; /* same algorithm */
427 this->compute_prime
= compute_prime
;
435 rsa_private_key_t
*rsa_private_key_create(size_t key_size
)
437 mpz_t p
, q
, n
, e
, d
, exp1
, exp2
, coeff
;
439 private_rsa_private_key_t
*this;
441 this = rsa_private_key_create_empty();
443 key_size
= key_size
/ 8;
452 /* Get values of primes p and q */
453 this->compute_prime(this, key_size
/2, &p
);
454 this->compute_prime(this, key_size
/2, &q
);
456 /* Swapping Primes so p is larger then q */
457 if (mpz_cmp(p
, q
) < 0)
464 mpz_mul(n
, p
, q
); /* n = p*q */
465 mpz_init_set_ui(e
, PUBLIC_EXPONENT
); /* assign public exponent */
466 mpz_init_set(m
, p
); /* m = p */
467 mpz_sub_ui(m
, m
, 1); /* m = m -1 */
468 mpz_init_set(q1
, q
); /* q1 = q */
469 mpz_sub_ui(q1
, q1
, 1); /* q1 = q1 -1 */
470 mpz_gcd(t
, m
, q1
); /* t = gcd(p-1, q-1) */
471 mpz_mul(m
, m
, q1
); /* m = (p-1)*(q-1) */
472 mpz_divexact(m
, m
, t
); /* m = m / t */
473 mpz_gcd(t
, m
, e
); /* t = gcd(m, e) (greatest common divisor) */
475 mpz_invert(d
, e
, m
); /* e has an inverse mod m */
476 if (mpz_cmp_ui(d
, 0) < 0) /* make sure d is positive */
480 mpz_sub_ui(t
, p
, 1); /* t = p-1 */
481 mpz_mod(exp1
, d
, t
); /* exp1 = d mod p-1 */
482 mpz_sub_ui(t
, q
, 1); /* t = q-1 */
483 mpz_mod(exp2
, d
, t
); /* exp2 = d mod q-1 */
485 mpz_invert(coeff
, q
, p
); /* coeff = q^-1 mod p */
486 if (mpz_cmp_ui(coeff
, 0) < 0) /* make coeff d is positive */
488 mpz_add(coeff
, coeff
, p
);
501 *(this->exp1
) = *exp1
;
502 *(this->exp2
) = *exp2
;
503 *(this->coeff
) = *coeff
;
505 /* set key size in bytes */
508 return &this->public;
514 rsa_private_key_t
*rsa_private_key_create_from_chunk(chunk_t chunk
)
516 private_rsa_private_key_t
*this;
520 this = rsa_private_key_create_empty();
527 mpz_init(this->exp1
);
528 mpz_init(this->exp2
);
529 mpz_init(this->coeff
);
531 dd
= der_decoder_create(rsa_private_key_rules
);
532 status
= dd
->decode(dd
, chunk
, this);
534 if (status
!= SUCCESS
)
539 this->k
= (mpz_sizeinbase(this->n
, 2) + 7) / 8;
540 return &this->public;
546 rsa_private_key_t
*rsa_private_key_create_from_file(char *filename
, char *passphrase
)
553 if (stat(filename
, &stb
) == -1)
558 buffer
= alloca(stb
.st_size
);
560 file
= fopen(filename
, "r");
566 if (fread(buffer
, stb
.st_size
, 1, file
) != 1)
572 chunk
.len
= stb
.st_size
;
574 return rsa_private_key_create_from_chunk(chunk
);