2 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <krb5-types.h>
46 BN2mpz(mpz_t s, const BIGNUM *bn)
51 len = BN_num_bytes(bn);
55 mpz_import(s, len, 1, 1, 1, 0, p);
68 mpz_export(NULL, &size, 1, 1, 1, 0, s);
70 if (p == NULL && size != 0)
72 mpz_export(p, &size, 1, 1, 1, 0, s);
73 bn = BN_bin2bn(p, size, NULL);
79 rsa_private_calculate(mpz_t in, mpz_t p, mpz_t q,
80 mpz_t dmp1, mpz_t dmq1, mpz_t iqmp,
84 mpz_init(vp); mpz_init(vq); mpz_init(u);
86 /* vq = c ^ (d mod (q - 1)) mod q */
87 /* vp = c ^ (d mod (p - 1)) mod p */
88 mpz_fdiv_r(vp, in, p);
89 mpz_powm(vp, vp, dmp1, p);
90 mpz_fdiv_r(vq, in, q);
91 mpz_powm(vq, vq, dmq1, q);
93 /* C2 = 1/q mod p (iqmp) */
94 /* u = (vp - vq)C2 mod p. */
97 if (mp_int_compare_zero(&u) < 0)
98 mp_int_add(&u, p, &u);
103 /* c ^ d mod n = vq + u q */
119 gmp_rsa_public_encrypt(int flen, const unsigned char* from,
120 unsigned char* to, RSA* rsa, int padding)
122 unsigned char *p, *p0;
124 mpz_t enc, dec, n, e;
126 if (padding != RSA_PKCS1_PADDING)
129 size = RSA_size(rsa);
131 if (size < RSA_PKCS1_PADDING_SIZE || size - RSA_PKCS1_PADDING_SIZE < flen)
137 p = p0 = malloc(size - 1);
144 padlen = size - flen - 3;
148 if (RAND_bytes(p, padlen) != 1) {
161 memcpy(p, from, flen);
163 assert((p - p0) == size - 1);
167 mpz_import(dec, size - 1, 1, 1, 1, 0, p0);
170 mpz_powm(enc, dec, e, n);
177 mpz_export(to, &ssize, 1, 1, 1, 0, enc);
178 assert(size >= ssize);
187 gmp_rsa_public_decrypt(int flen, const unsigned char* from,
188 unsigned char* to, RSA* rsa, int padding)
194 if (padding != RSA_PKCS1_PADDING)
197 if (flen > RSA_size(rsa))
204 /* Check that the exponent is larger then 3 */
205 if (mp_int_compare_value(&e, 3) <= 0) {
214 mpz_import(s, flen, 1, 1, 1, 0, rk_UNCONST(from));
216 if (mpz_cmp(s, n) >= 0) {
222 mpz_powm(us, s, e, n);
230 mpz_export(p, &size, 1, 1, 1, 0, us);
231 assert(size <= RSA_size(rsa));
235 /* head zero was skipped by mp_int_to_unsigned */
241 while (size && *p == 0xff) {
244 if (size == 0 || *p != 0)
248 memmove(to, p, size);
254 gmp_rsa_private_encrypt(int flen, const unsigned char* from,
255 unsigned char* to, RSA* rsa, int padding)
257 unsigned char *p, *p0;
261 if (padding != RSA_PKCS1_PADDING)
264 size = RSA_size(rsa);
266 if (size < RSA_PKCS1_PADDING_SIZE || size - RSA_PKCS1_PADDING_SIZE < flen)
269 p0 = p = malloc(size);
272 memset(p, 0xff, size - flen - 3);
273 p += size - flen - 3;
275 memcpy(p, from, flen);
277 assert((p - p0) == size);
284 mpz_import(in, size, 1, 1, 1, 0, p0);
288 if(mp_int_compare_zero(&in) < 0 ||
289 mp_int_compare(&in, &n) >= 0) {
295 if (rsa->p && rsa->q && rsa->dmp1 && rsa->dmq1 && rsa->iqmp) {
296 mpz_t p, q, dmp1, dmq1, iqmp;
300 BN2mpz(dmp1, rsa->dmp1);
301 BN2mpz(dmq1, rsa->dmq1);
302 BN2mpz(iqmp, rsa->iqmp);
304 rsa_private_calculate(in, p, q, dmp1, dmq1, iqmp, out);
315 mpz_powm(out, in, d, n);
321 mpz_export(to, &ssize, 1, 1, 1, 0, out);
322 assert(size >= ssize);
335 gmp_rsa_private_decrypt(int flen, const unsigned char* from,
336 unsigned char* to, RSA* rsa, int padding)
342 if (padding != RSA_PKCS1_PADDING)
345 size = RSA_size(rsa);
355 mpz_import(in, flen, 1, 1, 1, 0, from);
357 if(mpz_cmp_ui(in, 0) < 0 ||
358 mpz_cmp(in, n) >= 0) {
363 if (rsa->p && rsa->q && rsa->dmp1 && rsa->dmq1 && rsa->iqmp) {
364 mpz_t p, q, dmp1, dmq1, iqmp;
368 BN2mpz(dmp1, rsa->dmp1);
369 BN2mpz(dmq1, rsa->dmq1);
370 BN2mpz(iqmp, rsa->iqmp);
372 rsa_private_calculate(in, p, q, dmp1, dmq1, iqmp, out);
383 if(mp_int_compare_zero(&in) < 0 ||
384 mp_int_compare(&in, &n) >= 0)
389 mpz_powm(out, in, d, n);
396 mpz_export(ptr, &ssize, 1, 1, 1, 0, out);
397 assert(size >= ssize);
401 /* head zero was skipped by mp_int_to_unsigned */
405 while (size && *ptr != 0) {
412 memmove(to, ptr, size);
424 random_num(mpz_t num, size_t len)
432 if (RAND_bytes(p, len) != 1) {
436 mpz_import(num, len, 1, 1, 1, 0, p);
443 gmp_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
445 mpz_t el, p, q, n, d, dmp1, dmq1, iqmp, t1, t2, t3;
467 /* generate p and q so that p != q and bits(pq) ~ bits */
471 BN_GENCB_call(cb, 2, counter++);
472 random_num(p, bits / 2 + 1);
475 mpz_sub_ui(t1, p, 1);
477 } while(mpz_cmp_ui(t2, 1) != 0);
479 BN_GENCB_call(cb, 3, 0);
483 BN_GENCB_call(cb, 2, counter++);
484 random_num(q, bits / 2 + 1);
487 mpz_sub_ui(t1, q, 1);
489 } while(mpz_cmp_ui(t2, 1) != 0);
492 if (mpz_cmp(p, q) < 0)
495 BN_GENCB_call(cb, 3, 1);
497 /* calculate n, n = p * q */
500 /* calculate d, d = 1/e mod (p - 1)(q - 1) */
501 mpz_sub_ui(t1, p, 1);
502 mpz_sub_ui(t2, q, 1);
504 mpz_invert(d, el, t3);
506 /* calculate dmp1 dmp1 = d mod (p-1) */
507 mpz_mod(dmp1, d, t1);
508 /* calculate dmq1 dmq1 = d mod (q-1) */
509 mpz_mod(dmq1, d, t2);
510 /* calculate iqmp iqmp = 1/q mod p */
511 mpz_invert(iqmp, q, p);
513 /* fill in RSA key */
520 rsa->dmp1 = mpz2BN(dmp1);
521 rsa->dmq1 = mpz2BN(dmq1);
522 rsa->iqmp = mpz2BN(iqmp);
542 gmp_rsa_init(RSA *rsa)
548 gmp_rsa_finish(RSA *rsa)
553 const RSA_METHOD hc_rsa_gmp_method = {
555 gmp_rsa_public_encrypt,
556 gmp_rsa_public_decrypt,
557 gmp_rsa_private_encrypt,
558 gmp_rsa_private_decrypt,
570 #endif /* HAVE_GMP */
573 * RSA implementation using Gnu Multipresistion Library.
580 return &hc_rsa_gmp_method;