diff options
Diffstat (limited to 'lib/nettle/mpi.c')
-rw-r--r-- | lib/nettle/mpi.c | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/lib/nettle/mpi.c b/lib/nettle/mpi.c new file mode 100644 index 0000000..55086de --- /dev/null +++ b/lib/nettle/mpi.c @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2010-2012 Free Software Foundation, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GNUTLS. + * + * The GNUTLS library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* Here lie everything that has to do with large numbers, gmp. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include <algorithms.h> +#include <num.h> +#include <mpi.h> +#include <nettle/bignum.h> /* includes gmp.h */ +#if ENABLE_GOST +#include "gost/bignum-le.h" +#endif +#include <gnettle.h> +#include <random.h> + +static int +wrap_nettle_mpi_print(const bigint_t a, void *buffer, size_t * nbytes, + gnutls_bigint_format_t format) +{ + unsigned int size; + mpz_t *p = (void *) a; + + if (format == GNUTLS_MPI_FORMAT_USG) { + size = nettle_mpz_sizeinbase_256_u(*p); + } else if (format == GNUTLS_MPI_FORMAT_STD) { + size = nettle_mpz_sizeinbase_256_s(*p); +#if ENABLE_GOST + } else if (format == GNUTLS_MPI_FORMAT_ULE) { + size = nettle_mpz_sizeinbase_256_u_le(*p); +#endif + } else { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + if (buffer == NULL || size > *nbytes) { + *nbytes = size; + gnutls_assert(); + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + +#if ENABLE_GOST + if (format == GNUTLS_MPI_FORMAT_ULE) + nettle_mpz_get_str_256_u_le(size, buffer, *p); + else +#endif + nettle_mpz_get_str_256(size, buffer, *p); + *nbytes = size; + + return 0; +} + +static int wrap_nettle_mpi_init(bigint_t *w) +{ +bigint_t r; + + r = gnutls_malloc(SIZEOF_MPZT); + if (r == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + mpz_init(TOMPZ(r)); + *w = r; + + return 0; +} + +static int wrap_nettle_mpi_init_multi(bigint_t *w, ...) +{ + va_list args; + bigint_t *next; + int ret; + bigint_t* last_failed = NULL; + + ret = wrap_nettle_mpi_init(w); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + va_start(args, w); + + do { + next = va_arg(args, bigint_t*); + if (next != NULL) { + ret = wrap_nettle_mpi_init(next); + if (ret < 0) { + gnutls_assert(); + va_end(args); + last_failed = next; + goto fail; + } + } + } while(next != 0); + + va_end(args); + + return 0; +fail: + mpz_clear(TOMPZ(*w)); + gnutls_free(*w); + + va_start(args, w); + + do { + next = va_arg(args, bigint_t*); + if (next != last_failed) { + mpz_clear(TOMPZ(*next)); + gnutls_free(*next); + } + } while(next != last_failed); + + va_end(args); + + return GNUTLS_E_MEMORY_ERROR; +} + +static int +wrap_nettle_mpi_scan(bigint_t r, const void *buffer, size_t nbytes, + gnutls_bigint_format_t format) +{ + if (format == GNUTLS_MPI_FORMAT_USG) { + nettle_mpz_set_str_256_u(TOMPZ(r), nbytes, buffer); + } else if (format == GNUTLS_MPI_FORMAT_STD) { + nettle_mpz_set_str_256_s(TOMPZ(r), nbytes, buffer); +#if ENABLE_GOST + } else if (format == GNUTLS_MPI_FORMAT_ULE) { + nettle_mpz_set_str_256_u_le(TOMPZ(r), nbytes, buffer); +#endif + } else { + gnutls_assert(); + goto fail; + } + + return 0; + fail: + return GNUTLS_E_MPI_SCAN_FAILED; +} + +static int wrap_nettle_mpi_cmp(const bigint_t u, const bigint_t v) +{ + mpz_t *i1 = u, *i2 = v; + + return mpz_cmp(*i1, *i2); +} + +static int wrap_nettle_mpi_cmp_ui(const bigint_t u, unsigned long v) +{ + mpz_t *i1 = u; + + return mpz_cmp_ui(*i1, v); +} + +static int wrap_nettle_mpi_set(bigint_t w, const bigint_t u) +{ + mpz_set(TOMPZ(w), TOMPZ(u)); + + return 0; +} + +static bigint_t wrap_nettle_mpi_copy(const bigint_t u) +{ + int ret; + bigint_t w; + + ret = wrap_nettle_mpi_init(&w); + if (ret < 0) + return NULL; + + mpz_set(TOMPZ(w), u); + + return w; +} + +static int wrap_nettle_mpi_set_ui(bigint_t w, unsigned long u) +{ + mpz_set_ui(TOMPZ(w), u); + + return 0; +} + +static unsigned int wrap_nettle_mpi_get_nbits(bigint_t a) +{ + return mpz_sizeinbase(TOMPZ(a), 2); +} + +static void wrap_nettle_mpi_release(bigint_t a) +{ + mpz_clear(TOMPZ(a)); + gnutls_free(a); +} + +static void wrap_nettle_mpi_clear(bigint_t a) +{ + zeroize_key(TOMPZ(a)[0]._mp_d, + TOMPZ(a)[0]._mp_alloc * sizeof(mp_limb_t)); +} + +static int wrap_nettle_mpi_modm(bigint_t r, const bigint_t a, const bigint_t b) +{ + if (mpz_cmp_ui(TOMPZ(b), 0) == 0) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + mpz_mod(TOMPZ(r), TOMPZ(a), TOMPZ(b)); + + return 0; +} + +static int +wrap_nettle_mpi_powm(bigint_t w, const bigint_t b, const bigint_t e, + const bigint_t m) +{ + mpz_powm(TOMPZ(w), TOMPZ(b), TOMPZ(e), TOMPZ(m)); + + return 0; +} + +static int +wrap_nettle_mpi_addm(bigint_t w, const bigint_t a, const bigint_t b, + const bigint_t m) +{ + mpz_add(TOMPZ(w), TOMPZ(b), TOMPZ(a)); + mpz_fdiv_r(TOMPZ(w), TOMPZ(w), TOMPZ(m)); + + return 0; +} + +static int +wrap_nettle_mpi_subm(bigint_t w, const bigint_t a, const bigint_t b, + const bigint_t m) +{ + mpz_sub(TOMPZ(w), TOMPZ(a), TOMPZ(b)); + mpz_fdiv_r(TOMPZ(w), TOMPZ(w), TOMPZ(m)); + + return 0; +} + +static int +wrap_nettle_mpi_mulm(bigint_t w, const bigint_t a, const bigint_t b, + const bigint_t m) +{ + mpz_mul(TOMPZ(w), TOMPZ(a), TOMPZ(b)); + mpz_fdiv_r(TOMPZ(w), TOMPZ(w), TOMPZ(m)); + + return 0; +} + +static int +wrap_nettle_mpi_add(bigint_t w, const bigint_t a, const bigint_t b) +{ + mpz_add(TOMPZ(w), TOMPZ(a), TOMPZ(b)); + + return 0; +} + +static int +wrap_nettle_mpi_sub(bigint_t w, const bigint_t a, const bigint_t b) +{ + mpz_sub(TOMPZ(w), TOMPZ(a), TOMPZ(b)); + + return 0; +} + +static int +wrap_nettle_mpi_mul(bigint_t w, const bigint_t a, const bigint_t b) +{ + mpz_mul(TOMPZ(w), TOMPZ(a), TOMPZ(b)); + + return 0; +} + +/* q = a / b */ +static int +wrap_nettle_mpi_div(bigint_t q, const bigint_t a, const bigint_t b) +{ + mpz_cdiv_q(TOMPZ(q), TOMPZ(a), TOMPZ(b)); + + return 0; +} + +static int +wrap_nettle_mpi_add_ui(bigint_t w, const bigint_t a, unsigned long b) +{ + mpz_add_ui(TOMPZ(w), TOMPZ(a), b); + + return 0; +} + +static int +wrap_nettle_mpi_sub_ui(bigint_t w, const bigint_t a, unsigned long b) +{ + mpz_sub_ui(TOMPZ(w), TOMPZ(a), b); + + return 0; +} + +static int +wrap_nettle_mpi_mul_ui(bigint_t w, const bigint_t a, unsigned long b) +{ + mpz_mul_ui(TOMPZ(w), TOMPZ(a), b); + + return 0; +} + +static int wrap_nettle_prime_check(bigint_t pp) +{ + int ret; + + ret = mpz_probab_prime_p(TOMPZ(pp), PRIME_CHECK_PARAM); + if (ret > 0) { + return 0; + } + + return GNUTLS_E_INTERNAL_ERROR; /* ignored */ +} + + + +int crypto_bigint_prio = INT_MAX; + +gnutls_crypto_bigint_st _gnutls_mpi_ops = { + .bigint_init = wrap_nettle_mpi_init, + .bigint_init_multi = wrap_nettle_mpi_init_multi, + .bigint_cmp = wrap_nettle_mpi_cmp, + .bigint_cmp_ui = wrap_nettle_mpi_cmp_ui, + .bigint_modm = wrap_nettle_mpi_modm, + .bigint_copy = wrap_nettle_mpi_copy, + .bigint_set = wrap_nettle_mpi_set, + .bigint_set_ui = wrap_nettle_mpi_set_ui, + .bigint_get_nbits = wrap_nettle_mpi_get_nbits, + .bigint_powm = wrap_nettle_mpi_powm, + .bigint_addm = wrap_nettle_mpi_addm, + .bigint_subm = wrap_nettle_mpi_subm, + .bigint_add = wrap_nettle_mpi_add, + .bigint_sub = wrap_nettle_mpi_sub, + .bigint_add_ui = wrap_nettle_mpi_add_ui, + .bigint_sub_ui = wrap_nettle_mpi_sub_ui, + .bigint_mul = wrap_nettle_mpi_mul, + .bigint_mulm = wrap_nettle_mpi_mulm, + .bigint_mul_ui = wrap_nettle_mpi_mul_ui, + .bigint_div = wrap_nettle_mpi_div, + .bigint_prime_check = wrap_nettle_prime_check, + .bigint_release = wrap_nettle_mpi_release, + .bigint_clear = wrap_nettle_mpi_clear, + .bigint_print = wrap_nettle_mpi_print, + .bigint_scan = wrap_nettle_mpi_scan, +}; |