2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010 Free
3 * Software Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 /* Here lie everything that has to do with large numbers, libgcrypt and
27 * other stuff that didn't fit anywhere else.
30 #include <gnutls_int.h>
31 #include <gnutls_errors.h>
32 #include <gnutls_num.h>
33 #include <gnutls_mpi.h>
36 /* Functions that refer to the libgcrypt library.
40 _format_conv (gnutls_bigint_format_t format)
42 if (format == GNUTLS_MPI_FORMAT_USG)
43 return GCRYMPI_FMT_USG;
44 else if (format == GNUTLS_MPI_FORMAT_STD)
45 return GCRYMPI_FMT_STD;
47 return GCRYMPI_FMT_PGP;
50 /* returns zero on success
53 wrap_gcry_mpi_scan (const void *buffer, size_t nbytes,
54 gnutls_bigint_format_t format)
56 gcry_mpi_t ret_mpi = NULL;
59 ret = gcry_mpi_scan (&ret_mpi, _format_conv (format), buffer, nbytes, NULL);
67 wrap_gcry_mpi_print (const bigint_t a, void *buffer, size_t * nbytes,
68 gnutls_bigint_format_t format)
71 size_t init_bytes = *nbytes;
73 format = _format_conv (format);
75 if (nbytes == NULL || a == NULL)
76 return GNUTLS_E_INVALID_REQUEST;
78 ret = gcry_mpi_print (format, buffer, *nbytes, nbytes, a);
81 if (buffer == NULL || init_bytes < *nbytes)
84 /* in STD format we may want to include
85 * an extra byte for zero. Sometimes the gcry_
86 * function doesn't add it.
88 if (format == GNUTLS_MPI_FORMAT_STD)
90 return GNUTLS_E_SHORT_MEMORY_BUFFER;
95 return GNUTLS_E_MPI_PRINT_FAILED;
99 wrap_gcry_mpi_new (int nbits)
101 return gcry_mpi_new (nbits);
105 wrap_gcry_mpi_cmp (const bigint_t u, const bigint_t v)
107 return gcry_mpi_cmp (u, v);
111 wrap_gcry_mpi_cmp_ui (const bigint_t u, unsigned long v)
113 return gcry_mpi_cmp_ui (u, v);
117 wrap_gcry_mpi_set (bigint_t w, const bigint_t u)
119 return gcry_mpi_set (w, u);
123 wrap_gcry_mpi_set_ui (bigint_t w, unsigned long u)
125 return gcry_mpi_set_ui (w, u);
129 wrap_gcry_mpi_get_nbits (bigint_t a)
131 return gcry_mpi_get_nbits (a);
135 wrap_gcry_mpi_release (bigint_t a)
137 gcry_mpi_release (a);
140 #undef _gnutls_mpi_alloc_like
141 #define _gnutls_mpi_alloc_like(x) gcry_mpi_new(gcry_mpi_get_nbits(x))
144 wrap_gcry_mpi_mod (const bigint_t a, const bigint_t b)
146 bigint_t r = _gnutls_mpi_alloc_like (b);
151 gcry_mpi_mod (r, a, b);
157 wrap_gcry_mpi_powm (bigint_t w, const bigint_t b, const bigint_t e,
161 w = _gnutls_mpi_alloc_like (m);
166 gcry_mpi_powm (w, b, e, m);
172 wrap_gcry_mpi_addm (bigint_t w, const bigint_t a, const bigint_t b,
176 w = _gnutls_mpi_alloc_like (m);
181 gcry_mpi_addm (w, a, b, m);
187 wrap_gcry_mpi_subm (bigint_t w, const bigint_t a, const bigint_t b,
191 w = _gnutls_mpi_alloc_like (m);
196 gcry_mpi_subm (w, a, b, m);
202 wrap_gcry_mpi_mulm (bigint_t w, const bigint_t a, const bigint_t b,
206 w = _gnutls_mpi_alloc_like (m);
211 gcry_mpi_mulm (w, a, b, m);
217 wrap_gcry_mpi_add (bigint_t w, const bigint_t a, const bigint_t b)
220 w = _gnutls_mpi_alloc_like (b);
225 gcry_mpi_add (w, a, b);
231 wrap_gcry_mpi_sub (bigint_t w, const bigint_t a, const bigint_t b)
234 w = _gnutls_mpi_alloc_like (b);
239 gcry_mpi_sub (w, a, b);
245 wrap_gcry_mpi_mul (bigint_t w, const bigint_t a, const bigint_t b)
248 w = _gnutls_mpi_alloc_like (b);
253 gcry_mpi_mul (w, a, b);
260 wrap_gcry_mpi_div (bigint_t q, const bigint_t a, const bigint_t b)
263 q = _gnutls_mpi_alloc_like (a);
268 gcry_mpi_div (q, NULL, a, b, 0);
274 wrap_gcry_mpi_add_ui (bigint_t w, const bigint_t a, unsigned long b)
277 w = _gnutls_mpi_alloc_like (a);
282 gcry_mpi_add_ui (w, a, b);
288 wrap_gcry_mpi_sub_ui (bigint_t w, const bigint_t a, unsigned long b)
291 w = _gnutls_mpi_alloc_like (a);
296 gcry_mpi_sub_ui (w, a, b);
302 wrap_gcry_mpi_mul_ui (bigint_t w, const bigint_t a, unsigned long b)
305 w = _gnutls_mpi_alloc_like (a);
310 gcry_mpi_mul_ui (w, a, b);
316 wrap_gcry_prime_check (bigint_t pp)
318 return gcry_prime_check (pp, 0);
322 wrap_gcry_generate_group (gnutls_group_st * group, unsigned int bits)
324 gcry_mpi_t g = NULL, prime = NULL;
326 int times = 0, qbits;
327 gcry_mpi_t *factors = NULL;
329 /* Calculate the size of a prime factor of (prime-1)/2.
330 * This is an emulation of the values in "Selecting Cryptographic Key Sizes" paper.
336 qbits = (bits / 40) + 105;
339 if (qbits & 1) /* better have an even number */
342 /* find a prime number of size bits.
348 gcry_mpi_release (prime);
349 gcry_prime_release_factors (factors);
352 err = gcry_prime_generate (&prime, bits, qbits, &factors,
353 NULL, NULL, GCRY_STRONG_RANDOM,
354 GCRY_PRIME_FLAG_SPECIAL_FACTOR);
358 return GNUTLS_E_INTERNAL_ERROR;
361 err = gcry_prime_check (prime, 0);
365 while (err != 0 && times < 10);
370 gcry_mpi_release (prime);
371 gcry_prime_release_factors (factors);
372 return GNUTLS_E_INTERNAL_ERROR;
375 /* generate the group generator.
377 err = gcry_prime_group_generator (&g, prime, factors, NULL);
378 gcry_prime_release_factors (factors);
382 gcry_mpi_release (prime);
383 return GNUTLS_E_INTERNAL_ERROR;
392 int crypto_bigint_prio = INT_MAX;
394 gnutls_crypto_bigint_st _gnutls_mpi_ops = {
395 .bigint_new = wrap_gcry_mpi_new,
396 .bigint_cmp = wrap_gcry_mpi_cmp,
397 .bigint_cmp_ui = wrap_gcry_mpi_cmp_ui,
398 .bigint_mod = wrap_gcry_mpi_mod,
399 .bigint_set = wrap_gcry_mpi_set,
400 .bigint_set_ui = wrap_gcry_mpi_set_ui,
401 .bigint_get_nbits = wrap_gcry_mpi_get_nbits,
402 .bigint_powm = wrap_gcry_mpi_powm,
403 .bigint_addm = wrap_gcry_mpi_addm,
404 .bigint_subm = wrap_gcry_mpi_subm,
405 .bigint_add = wrap_gcry_mpi_add,
406 .bigint_sub = wrap_gcry_mpi_sub,
407 .bigint_add_ui = wrap_gcry_mpi_add_ui,
408 .bigint_sub_ui = wrap_gcry_mpi_sub_ui,
409 .bigint_mul = wrap_gcry_mpi_mul,
410 .bigint_mulm = wrap_gcry_mpi_mulm,
411 .bigint_mul_ui = wrap_gcry_mpi_mul_ui,
412 .bigint_div = wrap_gcry_mpi_div,
413 .bigint_prime_check = wrap_gcry_prime_check,
414 .bigint_release = wrap_gcry_mpi_release,
415 .bigint_print = wrap_gcry_mpi_print,
416 .bigint_scan = wrap_gcry_mpi_scan,
417 .bigint_generate_group = wrap_gcry_generate_group