2 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /* Here lie everything that has to do with large numbers, gmp.
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28 #include <algorithms.h>
29 #include <gnutls_num.h>
30 #include <gnutls_mpi.h>
32 #include <nettle/bignum.h>
36 #define TOMPZ(x) (*((mpz_t*)(x)))
39 wrap_nettle_mpi_print (const bigint_t a
, void *buffer
, size_t * nbytes
,
40 gnutls_bigint_format_t format
)
43 mpz_t
*p
= (void *) a
;
45 if (format
== GNUTLS_MPI_FORMAT_USG
)
47 size
= nettle_mpz_sizeinbase_256_u (*p
);
49 else if (format
== GNUTLS_MPI_FORMAT_STD
)
51 size
= nettle_mpz_sizeinbase_256_s (*p
);
53 else if (format
== GNUTLS_MPI_FORMAT_PGP
)
55 size
= nettle_mpz_sizeinbase_256_u (*p
) + 2;
60 return GNUTLS_E_INVALID_REQUEST
;
63 if (buffer
== NULL
|| size
> *nbytes
)
66 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
69 if (format
== GNUTLS_MPI_FORMAT_PGP
)
71 uint8_t *buf
= buffer
;
72 unsigned int nbits
= _gnutls_mpi_get_nbits (a
);
73 buf
[0] = (nbits
>> 8) & 0xff;
74 buf
[1] = (nbits
) & 0xff;
75 nettle_mpz_get_str_256 (size
- 2, buf
+ 2, *p
);
79 nettle_mpz_get_str_256 (size
, buffer
, *p
);
87 wrap_nettle_mpi_new (int nbits
)
91 p
= gnutls_malloc (sizeof (*p
));
97 mpz_init2 (*p
, nbits
);
103 wrap_nettle_mpi_scan (const void *buffer
, size_t nbytes
,
104 gnutls_bigint_format_t format
)
106 bigint_t r
= wrap_nettle_mpi_new (nbytes
* 8);
114 if (format
== GNUTLS_MPI_FORMAT_USG
)
116 nettle_mpz_set_str_256_u (TOMPZ (r
), nbytes
, buffer
);
118 else if (format
== GNUTLS_MPI_FORMAT_STD
)
120 nettle_mpz_set_str_256_s (TOMPZ (r
), nbytes
, buffer
);
122 else if (format
== GNUTLS_MPI_FORMAT_PGP
)
124 const uint8_t *buf
= buffer
;
133 size
= (buf
[0] << 8) | buf
[1];
134 size
= (size
+ 7) / 8;
136 if (size
> nbytes
- 2)
141 nettle_mpz_set_str_256_u (TOMPZ (r
), size
, buf
+ 2);
151 _gnutls_mpi_release (&r
);
157 wrap_nettle_mpi_cmp (const bigint_t u
, const bigint_t v
)
159 mpz_t
*i1
= u
, *i2
= v
;
161 return mpz_cmp (*i1
, *i2
);
165 wrap_nettle_mpi_cmp_ui (const bigint_t u
, unsigned long v
)
169 return mpz_cmp_ui (*i1
, v
);
173 wrap_nettle_mpi_set (bigint_t w
, const bigint_t u
)
178 w
= _gnutls_mpi_alloc_like (u
);
187 wrap_nettle_mpi_set_ui (bigint_t w
, unsigned long u
)
192 w
= wrap_nettle_mpi_new (32);
202 wrap_nettle_mpi_get_nbits (bigint_t a
)
204 return mpz_sizeinbase (*((mpz_t
*) a
), 2);
208 wrap_nettle_mpi_release (bigint_t a
)
210 mpz_clear (*((mpz_t
*) a
));
215 wrap_nettle_mpi_mod (const bigint_t a
, const bigint_t b
)
217 bigint_t r
= wrap_nettle_mpi_new (wrap_nettle_mpi_get_nbits (b
));
222 mpz_mod (*((mpz_t
*) r
), *((mpz_t
*) a
), *((mpz_t
*) b
));
228 wrap_nettle_mpi_powm (bigint_t w
, const bigint_t b
, const bigint_t e
,
232 w
= wrap_nettle_mpi_new (wrap_nettle_mpi_get_nbits (m
));
237 mpz_powm (*((mpz_t
*) w
), *((mpz_t
*) b
), *((mpz_t
*) e
), *((mpz_t
*) m
));
243 wrap_nettle_mpi_addm (bigint_t w
, const bigint_t a
, const bigint_t b
,
247 w
= wrap_nettle_mpi_new (wrap_nettle_mpi_get_nbits (a
));
252 mpz_add (*((mpz_t
*) w
), *((mpz_t
*) b
), *((mpz_t
*) a
));
253 mpz_fdiv_r (*((mpz_t
*) w
), *((mpz_t
*) w
), *((mpz_t
*) m
));
259 wrap_nettle_mpi_subm (bigint_t w
, const bigint_t a
, const bigint_t b
,
263 w
= wrap_nettle_mpi_new (wrap_nettle_mpi_get_nbits (a
));
268 mpz_sub (*((mpz_t
*) w
), *((mpz_t
*) a
), *((mpz_t
*) b
));
269 mpz_fdiv_r (*((mpz_t
*) w
), *((mpz_t
*) w
), *((mpz_t
*) m
));
275 wrap_nettle_mpi_mulm (bigint_t w
, const bigint_t a
, const bigint_t b
,
279 w
= wrap_nettle_mpi_new (wrap_nettle_mpi_get_nbits (m
));
284 mpz_mul (*((mpz_t
*) w
), *((mpz_t
*) a
), *((mpz_t
*) b
));
285 mpz_fdiv_r (*((mpz_t
*) w
), *((mpz_t
*) w
), *((mpz_t
*) m
));
291 wrap_nettle_mpi_add (bigint_t w
, const bigint_t a
, const bigint_t b
)
294 w
= wrap_nettle_mpi_new (wrap_nettle_mpi_get_nbits (b
));
299 mpz_add (*((mpz_t
*) w
), *((mpz_t
*) a
), *((mpz_t
*) b
));
305 wrap_nettle_mpi_sub (bigint_t w
, const bigint_t a
, const bigint_t b
)
308 w
= wrap_nettle_mpi_new (wrap_nettle_mpi_get_nbits (a
));
313 mpz_sub (*((mpz_t
*) w
), *((mpz_t
*) a
), *((mpz_t
*) b
));
319 wrap_nettle_mpi_mul (bigint_t w
, const bigint_t a
, const bigint_t b
)
322 w
= wrap_nettle_mpi_new (wrap_nettle_mpi_get_nbits (a
));
327 mpz_mul (*((mpz_t
*) w
), *((mpz_t
*) a
), *((mpz_t
*) b
));
334 wrap_nettle_mpi_div (bigint_t q
, const bigint_t a
, const bigint_t b
)
337 q
= wrap_nettle_mpi_new (wrap_nettle_mpi_get_nbits (a
));
342 mpz_cdiv_q (*((mpz_t
*) q
), *((mpz_t
*) a
), *((mpz_t
*) b
));
348 wrap_nettle_mpi_add_ui (bigint_t w
, const bigint_t a
, unsigned long b
)
351 w
= wrap_nettle_mpi_new (wrap_nettle_mpi_get_nbits (a
));
356 mpz_add_ui (*((mpz_t
*) w
), *((mpz_t
*) a
), b
);
362 wrap_nettle_mpi_sub_ui (bigint_t w
, const bigint_t a
, unsigned long b
)
365 w
= wrap_nettle_mpi_new (wrap_nettle_mpi_get_nbits (a
));
370 mpz_sub_ui (*((mpz_t
*) w
), *((mpz_t
*) a
), b
);
377 wrap_nettle_mpi_mul_ui (bigint_t w
, const bigint_t a
, unsigned long b
)
380 w
= wrap_nettle_mpi_new (wrap_nettle_mpi_get_nbits (a
));
385 mpz_mul_ui (*((mpz_t
*) w
), *((mpz_t
*) a
), b
);
392 wrap_nettle_prime_check (bigint_t pp
)
395 ret
= mpz_probab_prime_p (*((mpz_t
*) pp
), PRIME_CHECK_PARAM
);
402 return GNUTLS_E_INTERNAL_ERROR
; /* ignored */
406 /* generate a prime of the form p=2qw+1
407 * The algorithm is simple but probably it has to be modified to gcrypt's
408 * since it is slow. Nature did not want 2qw+1 to be prime.
409 * The generator will be the generator of a subgroup of order q-1.
411 * Algorithm based on the algorithm in "A Computational Introduction to Number
412 * Theory and Algebra" by V. Shoup, sec 11.1 Finding a generator for Z^{*}_p
416 gen_group (mpz_t
* prime
, mpz_t
* generator
, unsigned int nbits
, unsigned int *q_bits
)
419 unsigned int p_bytes
= nbits
/ 8;
420 uint8_t *buffer
= NULL
;
421 unsigned int q_bytes
, w_bytes
, r_bytes
, w_bits
;
424 /* security level enforcement.
425 * Values for q are selected according to ECRYPT II recommendations.
427 q_bytes
= _gnutls_pk_bits_to_subgroup_bits (nbits
);
430 if (q_bytes
== 0 || q_bytes
>= p_bytes
)
433 return GNUTLS_E_INVALID_REQUEST
;
439 w_bits
= nbits
- q_bytes
* 8;
440 w_bytes
= w_bits
/ 8;
445 ("Generating group of prime of %u bits and format of 2wq+1. q_size=%u bits\n",
447 buffer
= gnutls_malloc (p_bytes
); /* p_bytes > q_bytes */
451 return GNUTLS_E_MEMORY_ERROR
;
458 /* search for a prime. We are not that unlucky so search
463 ret
= _gnutls_rnd (GNUTLS_RND_RANDOM
, buffer
, w_bytes
);
470 nettle_mpz_set_str_256_u (w
, w_bytes
, buffer
);
474 ret
= mpz_probab_prime_p (w
, PRIME_CHECK_PARAM
);
481 /* now generate q of size p_bytes - w_bytes */
484 ("Found prime w of %u bits. Will look for q of %u bits...\n",
485 wrap_nettle_mpi_get_nbits (&w
), q_bytes
*8);
489 ret
= _gnutls_rnd (GNUTLS_RND_RANDOM
, buffer
, q_bytes
);
496 nettle_mpz_set_str_256_u (q
, q_bytes
, buffer
);
500 ret
= mpz_probab_prime_p (q
, PRIME_CHECK_PARAM
);
506 /* check if 2wq+1 is prime */
507 mpz_mul_ui (*prime
, w
, 2);
508 mpz_mul (*prime
, *prime
, q
);
509 mpz_add_ui (*prime
, *prime
, 1);
511 ret
= mpz_probab_prime_p (*prime
, PRIME_CHECK_PARAM
);
518 *q_bits
= wrap_nettle_mpi_get_nbits (&q
);
519 _gnutls_debug_log ("Found prime q of %u bits. Looking for generator...\n",
522 /* finally a prime! Let's calculate generator
525 /* c = r^((p-1)/q), r == random
527 * if c!=1 c is the generator for the subgroup of order q-1
532 mpz_mul_ui (w
, w
, 2); /* w = w*2 */
533 mpz_fdiv_r (w
, w
, *prime
);
537 ret
= _gnutls_rnd (GNUTLS_RND_NONCE
, buffer
, r_bytes
);
544 nettle_mpz_set_str_256_u (r
, r_bytes
, buffer
);
545 mpz_fdiv_r (r
, r
, *prime
);
547 /* check if r^w mod n != 1 mod n */
548 mpz_powm (*generator
, r
, w
, *prime
);
550 if (mpz_cmp_ui (*generator
, 1) == 0)
556 _gnutls_debug_log ("Found generator g of %u bits\n",
557 wrap_nettle_mpi_get_nbits (generator
));
558 _gnutls_debug_log ("Prime n is %u bits\n",
559 wrap_nettle_mpi_get_nbits (prime
));
566 mpz_clear (*generator
);
572 gnutls_free (buffer
);
578 wrap_nettle_generate_group (gnutls_group_st
* group
, unsigned int bits
)
581 bigint_t p
= wrap_nettle_mpi_new (bits
);
588 return GNUTLS_E_MEMORY_ERROR
;
591 g
= wrap_nettle_mpi_new (bits
);
595 _gnutls_mpi_release (&p
);
596 return GNUTLS_E_MEMORY_ERROR
;
599 ret
= gen_group (p
, g
, bits
, &q_bits
);
602 _gnutls_mpi_release (&g
);
603 _gnutls_mpi_release (&p
);
610 group
->q_bits
= q_bits
;
616 int crypto_bigint_prio
= INT_MAX
;
618 gnutls_crypto_bigint_st _gnutls_mpi_ops
= {
619 .bigint_new
= wrap_nettle_mpi_new
,
620 .bigint_cmp
= wrap_nettle_mpi_cmp
,
621 .bigint_cmp_ui
= wrap_nettle_mpi_cmp_ui
,
622 .bigint_mod
= wrap_nettle_mpi_mod
,
623 .bigint_set
= wrap_nettle_mpi_set
,
624 .bigint_set_ui
= wrap_nettle_mpi_set_ui
,
625 .bigint_get_nbits
= wrap_nettle_mpi_get_nbits
,
626 .bigint_powm
= wrap_nettle_mpi_powm
,
627 .bigint_addm
= wrap_nettle_mpi_addm
,
628 .bigint_subm
= wrap_nettle_mpi_subm
,
629 .bigint_add
= wrap_nettle_mpi_add
,
630 .bigint_sub
= wrap_nettle_mpi_sub
,
631 .bigint_add_ui
= wrap_nettle_mpi_add_ui
,
632 .bigint_sub_ui
= wrap_nettle_mpi_sub_ui
,
633 .bigint_mul
= wrap_nettle_mpi_mul
,
634 .bigint_mulm
= wrap_nettle_mpi_mulm
,
635 .bigint_mul_ui
= wrap_nettle_mpi_mul_ui
,
636 .bigint_div
= wrap_nettle_mpi_div
,
637 .bigint_prime_check
= wrap_nettle_prime_check
,
638 .bigint_release
= wrap_nettle_mpi_release
,
639 .bigint_print
= wrap_nettle_mpi_print
,
640 .bigint_scan
= wrap_nettle_mpi_scan
,
641 .bigint_generate_group
= wrap_nettle_generate_group