| /* |
| * Copyright (c) 1997-2007 The Stanford SRP Authentication Project |
| * All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining |
| * a copy of this software and associated documentation files (the |
| * "Software"), to deal in the Software without restriction, including |
| * without limitation the rights to use, copy, modify, merge, publish, |
| * distribute, sublicense, and/or sell copies of the Software, and to |
| * permit persons to whom the Software is furnished to do so, subject to |
| * the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY |
| * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. |
| * |
| * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL, |
| * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER |
| * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF |
| * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT |
| * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| * |
| * Redistributions in source or binary form must retain an intact copy |
| * of this copyright notice. |
| */ |
| |
| #include <stdio.h> |
| #include <sys/types.h> |
| |
| #include "config.h" |
| |
| #ifdef OPENSSL |
| # include "openssl/opensslv.h" |
| # include "openssl/bn.h" |
| typedef BIGNUM * BigInteger; |
| typedef BN_CTX * BigIntegerCtx; |
| typedef BN_MONT_CTX * BigIntegerModAccel; |
| #include <limits.h> |
| # ifndef OPENSSL_NO_ENGINE |
| # define OPENSSL_ENGINE |
| # include "openssl/engine.h" |
| static ENGINE * default_engine = NULL; |
| # endif /* OPENSSL_ENGINE */ |
| typedef int (*modexp_meth)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, |
| const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *mctx); |
| static modexp_meth default_modexp = NULL; |
| #elif defined(CRYPTOLIB) |
| # include "libcrypt.h" |
| typedef BigInt BigInteger; |
| typedef void * BigIntegerCtx; |
| typedef void * BigIntegerModAccel; |
| #elif defined(GNU_MP) |
| # include "gmp.h" |
| typedef MP_INT * BigInteger; |
| typedef void * BigIntegerCtx; |
| typedef void * BigIntegerModAccel; |
| # if __GNU_MP_VERSION >= 4 || (__GNU_MP_VERSION == 4 && __GNU_MP_VERSION_MINOR >= 1) |
| /* GMP 4.1 and up has fast import/export routines for integer conversion */ |
| # define GMP_IMPEXP 1 |
| # endif |
| #elif defined(TOMMATH) |
| # ifdef TOMCRYPT |
| /* as of v0.96 */ |
| # include "ltc_tommath.h" |
| # else |
| # include "tommath.h" |
| # endif |
| typedef mp_int * BigInteger; |
| typedef void * BigIntegerCtx; |
| typedef void * BigIntegerModAccel; |
| #elif defined(GCRYPT) |
| # include "gcrypt.h" |
| typedef gcry_mpi_t BigInteger; |
| typedef void * BigIntegerCtx; |
| typedef void * BigIntegerModAccel; |
| #elif defined(MPI) |
| # include "mpi.h" |
| typedef mp_int * BigInteger; |
| typedef void * BigIntegerCtx; |
| typedef void * BigIntegerModAccel; |
| #elif defined(MBEDTLS) |
| #include <mbedtls/bignum.h> |
| #include <mbedtls/error.h> |
| typedef mbedtls_mpi* BigInteger; |
| typedef void * BigIntegerCtx; |
| typedef void * BigIntegerModAccel; |
| #else |
| # error "no math library specified" |
| #endif |
| #define MATH_PRIV |
| |
| #include "t_defines.h" |
| #include "t_pwd.h" |
| #include "srp_aux.h" |
| |
| /* Math library interface stubs */ |
| |
| BigInteger |
| BigIntegerFromInt(n) |
| unsigned int n; |
| { |
| #ifdef OPENSSL |
| BIGNUM * a = BN_new(); |
| if(a) |
| BN_set_word(a, n); |
| return a; |
| #elif defined(CRYPTOLIB) |
| return bigInit(n); |
| #elif defined(GNU_MP) |
| BigInteger rv = (BigInteger) malloc(sizeof(MP_INT)); |
| if(rv) |
| mpz_init_set_ui(rv, n); |
| return rv; |
| #elif defined(GCRYPT) |
| BigInteger rv = gcry_mpi_new(32); |
| gcry_mpi_set_ui(rv, n); |
| return rv; |
| #elif defined(MPI) || defined(TOMMATH) |
| BigInteger rv = (BigInteger) malloc(sizeof(mp_int)); |
| if(rv) { |
| mp_init(rv); |
| mp_set_int(rv, n); |
| } |
| return rv; |
| #elif defined(MBEDTLS) |
| mbedtls_mpi* a = (mbedtls_mpi*)malloc(sizeof(mbedtls_mpi)); |
| if (a) { |
| mbedtls_mpi_init(a); |
| mbedtls_mpi_lset(a, n); |
| } |
| return a; |
| #endif |
| } |
| |
| BigInteger |
| BigIntegerFromBytes(bytes, length) |
| const unsigned char * bytes; |
| int length; |
| { |
| #ifdef OPENSSL |
| BIGNUM * a = BN_new(); |
| BN_bin2bn(bytes, length, a); |
| return a; |
| #elif defined(CRYPTOLIB) |
| BigInteger rv, t; |
| int i, n; |
| |
| rv = bigInit(0); |
| if(rv == NULL) |
| return rv; |
| if(length % 4 == 0) |
| RSA_bufToBig(bytes, length, rv); |
| else { /* Wouldn't need this if cryptolib behaved better */ |
| i = length & 0x3; |
| if(length > i) |
| RSA_bufToBig(bytes + i, length - i, rv); |
| for(n = 0; i > 0; --i) |
| n = (n << 8) | *bytes++; |
| t = bigInit(n); |
| bigLeftShift(t, (length & ~0x3) << 3, t); |
| bigAdd(rv, t, rv); |
| freeBignum(t); |
| } |
| return rv; |
| #elif defined(GNU_MP) |
| BigInteger rv = (BigInteger) malloc(sizeof(MP_INT)); |
| |
| # ifdef GMP_IMPEXP |
| if(rv) { |
| mpz_init(rv); |
| mpz_import(rv, length, 1, 1, 1, 0, bytes); |
| } |
| # else |
| cstr * hexbuf = cstr_new(); |
| |
| if(hexbuf) { |
| if(rv) |
| mpz_init_set_str(rv, t_tohexcstr(hexbuf, bytes, length), 16); |
| cstr_clear_free(hexbuf); |
| } |
| # endif /* GMP_IMPEXP */ |
| |
| return rv; |
| #elif defined(GCRYPT) |
| BigInteger rv; |
| gcry_mpi_scan(&rv, GCRYMPI_FMT_USG, bytes, length, NULL); |
| return rv; |
| #elif defined(MPI) || defined(TOMMATH) |
| BigInteger rv = (BigInteger) malloc(sizeof(mp_int)); |
| if(rv) { |
| mp_init(rv); |
| mp_read_unsigned_bin(rv, (unsigned char *)bytes, length); |
| } |
| return rv; |
| #elif defined(MBEDTLS) |
| mbedtls_mpi* a = (mbedtls_mpi*)malloc(sizeof(mbedtls_mpi)); |
| if (a) { |
| mbedtls_mpi_init(a); |
| mbedtls_mpi_read_binary(a, bytes, length); |
| } |
| return a; |
| #endif |
| } |
| |
| int |
| BigIntegerToBytes(src, dest, destlen) |
| BigInteger src; |
| unsigned char * dest; |
| int destlen; |
| { |
| #ifdef OPENSSL |
| return BN_bn2bin(src, dest); |
| #elif defined(CRYPTOLIB) |
| int i, j; |
| cstr * rawbuf; |
| |
| trim(src); |
| i = bigBytes(src); |
| j = (bigBits(src) + 7) / 8; |
| if(i == j) |
| RSA_bigToBuf(src, i, dest); |
| else { /* Wouldn't need this if cryptolib behaved better */ |
| rawbuf = cstr_new(); |
| cstr_set_length(rawbuf, i); |
| RSA_bigToBuf(src, i, rawbuf->data); |
| memcpy(dest, rawbuf->data + (i-j), j); |
| cstr_clear_free(rawbuf); |
| } |
| return j; |
| #elif defined(GNU_MP) |
| size_t r = 0; |
| # ifdef GMP_IMPEXP |
| mpz_export(dest, &r, 1, 1, 1, 0, src); |
| # else |
| cstr * hexbuf = cstr_new(); |
| |
| if(hexbuf) { |
| cstr_set_length(hexbuf, mpz_sizeinbase(src, 16) + 1); |
| mpz_get_str(hexbuf->data, 16, src); |
| r = t_fromhex(dest, hexbuf->data); |
| cstr_clear_free(hexbuf); |
| } |
| # endif |
| return r; |
| #elif defined(GCRYPT) |
| size_t r = 0; |
| gcry_mpi_print(GCRYMPI_FMT_USG, dest, destlen, &r, src); |
| return r; |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_to_unsigned_bin(src, dest); |
| return mp_unsigned_bin_size(src); |
| #elif defined(MBEDTLS) |
| size_t r = mbedtls_mpi_size(src); |
| mbedtls_mpi_write_binary(src, dest, r); |
| return r; |
| #endif |
| } |
| |
| BigIntegerResult |
| BigIntegerToCstr(BigInteger x, cstr * out) |
| { |
| int n = BigIntegerByteLen(x); |
| if(cstr_set_length(out, n) < 0) |
| return BIG_INTEGER_ERROR; |
| if(cstr_set_length(out, BigIntegerToBytes(x, (unsigned char*)out->data, n)) < 0) |
| return BIG_INTEGER_ERROR; |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerToCstrEx(BigInteger x, cstr * out, int len) |
| { |
| int n; |
| if(cstr_set_length(out, len) < 0) |
| return BIG_INTEGER_ERROR; |
| #if defined(MBEDTLS) |
| /* mbedtls will prefix the output with zeros if the buffer is larger */ |
| mbedtls_mpi_write_binary(x, (unsigned char*)out->data, len); |
| #else |
| n = BigIntegerToBytes(x, (unsigned char*)out->data, len); |
| if(n < len) { |
| memmove(out->data + (len - n), out->data, n); |
| memset(out->data, 0, len - n); |
| } |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerToHex(src, dest, destlen) |
| BigInteger src; |
| char * dest; |
| int destlen; |
| { |
| #ifdef OPENSSL |
| strncpy(dest, BN_bn2hex(src), destlen); |
| #elif defined(CRYPTOLIB) |
| trim(src); |
| bigsprint(src, dest); |
| #elif defined(GNU_MP) |
| mpz_get_str(dest, 16, src); |
| #elif defined(GCRYPT) |
| gcry_mpi_print(GCRYMPI_FMT_HEX, dest, destlen, NULL, src); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_toradix(src, dest, 16); |
| #elif defined(MBEDTLS) |
| size_t olen = 0; |
| mbedtls_mpi_write_string(src, 16, dest, destlen, &olen); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| static char b64table[] = |
| "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; |
| |
| BigIntegerResult |
| BigIntegerToString(src, dest, destlen, radix) |
| BigInteger src; |
| char * dest; |
| int destlen; |
| unsigned int radix; |
| { |
| BigInteger t = BigIntegerFromInt(0); |
| char * p = dest; |
| char c; |
| |
| *p++ = b64table[BigIntegerModInt(src, radix, NULL)]; |
| BigIntegerDivInt(t, src, radix, NULL); |
| while(BigIntegerCmpInt(t, 0) > 0) { |
| *p++ = b64table[BigIntegerModInt(t, radix, NULL)]; |
| BigIntegerDivInt(t, t, radix, NULL); |
| } |
| BigIntegerFree(t); |
| *p-- = '\0'; |
| /* reverse the string */ |
| while(p > dest) { |
| c = *p; |
| *p-- = *dest; |
| *dest++ = c; |
| } |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| int |
| BigIntegerBitLen(b) |
| BigInteger b; |
| { |
| #ifdef OPENSSL |
| return BN_num_bits(b); |
| #elif defined(CRYPTOLIB) |
| return bigBits(b); |
| #elif defined(GNU_MP) |
| return mpz_sizeinbase(b, 2); |
| #elif defined(GCRYPT) |
| return gcry_mpi_get_nbits(b); |
| #elif defined(MPI) || defined(TOMMATH) |
| return mp_count_bits(b); |
| #elif defined(MBEDTLS) |
| return (int)mbedtls_mpi_bitlen(b); |
| #endif |
| } |
| |
| int |
| BigIntegerCmp(c1, c2) |
| BigInteger c1, c2; |
| { |
| #ifdef OPENSSL |
| return BN_cmp(c1, c2); |
| #elif defined(CRYPTOLIB) |
| return bigCompare(c1, c2); |
| #elif defined(GNU_MP) |
| return mpz_cmp(c1, c2); |
| #elif defined(GCRYPT) |
| return gcry_mpi_cmp(c1, c2); |
| #elif defined(MPI) || defined(TOMMATH) |
| return mp_cmp(c1, c2); |
| #elif defined(MBEDTLS) |
| return mbedtls_mpi_cmp_mpi(c1, c2); |
| #endif |
| } |
| |
| int |
| BigIntegerCmpInt(c1, c2) |
| BigInteger c1; |
| unsigned int c2; |
| { |
| #ifdef OPENSSL |
| BigInteger bc2 = BigIntegerFromInt(c2); |
| int rv = BigIntegerCmp(c1, bc2); |
| BigIntegerFree(bc2); |
| return rv; |
| #elif defined(CRYPTOLIB) |
| BigInteger t; |
| int rv; |
| |
| t = bigInit(c2); |
| rv = bigCompare(c1, t); |
| freeBignum(t); |
| return rv; |
| #elif defined(GNU_MP) |
| return mpz_cmp_ui(c1, c2); |
| #elif defined(TOMMATH) |
| return mp_cmp_d(c1, c2); |
| #elif defined(GCRYPT) |
| return gcry_mpi_cmp_ui(c1, c2); |
| #elif defined(MPI) |
| return mp_cmp_int(c1, c2); |
| #elif defined(MBEDTLS) |
| return mbedtls_mpi_cmp_int(c1, c2); |
| #endif |
| } |
| |
| BigIntegerResult |
| BigIntegerLShift(result, x, bits) |
| BigInteger result, x; |
| unsigned int bits; |
| { |
| #ifdef OPENSSL |
| BN_lshift(result, x, bits); |
| #elif defined(CRYPTOLIB) |
| bigLeftShift(x, bits, result); |
| #elif defined(GNU_MP) |
| mpz_mul_2exp(result, x, bits); |
| #elif defined(GCRYPT) |
| gcry_mpi_mul_2exp(result, x, bits); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_mul_2d(x, bits, result); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_copy(result, x); |
| mbedtls_mpi_shift_l(result, bits); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerAdd(result, a1, a2) |
| BigInteger result, a1, a2; |
| { |
| #ifdef OPENSSL |
| BN_add(result, a1, a2); |
| #elif defined(CRYPTOLIB) |
| bigAdd(a1, a2, result); |
| #elif defined(GNU_MP) |
| mpz_add(result, a1, a2); |
| #elif defined(GCRYPT) |
| gcry_mpi_add(result, a1, a2); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_add(a1, a2, result); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_add_mpi(result, a1, a2); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerAddInt(result, a1, a2) |
| BigInteger result, a1; |
| unsigned int a2; |
| { |
| #ifdef OPENSSL |
| if(result != a1) |
| BN_copy(result, a1); |
| BN_add_word(result, a2); |
| #elif defined(CRYPTOLIB) |
| BigInteger t; |
| |
| t = bigInit(a2); |
| bigAdd(a1, t, result); |
| freeBignum(t); |
| #elif defined(GNU_MP) |
| mpz_add_ui(result, a1, a2); |
| #elif defined(GCRYPT) |
| gcry_mpi_add_ui(result, a1, a2); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_add_d(a1, a2, result); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_add_int(result, a1, a2); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerSub(result, s1, s2) |
| BigInteger result, s1, s2; |
| { |
| #ifdef OPENSSL |
| BN_sub(result, s1, s2); |
| #elif defined(CRYPTOLIB) |
| bigSubtract(s1, s2, result); |
| #elif defined(GNU_MP) |
| mpz_sub(result, s1, s2); |
| #elif defined(GCRYPT) |
| gcry_mpi_sub(result, s1, s2); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_sub(s1, s2, result); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_sub_mpi(result, s1, s2); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerSubInt(result, s1, s2) |
| BigInteger result, s1; |
| unsigned int s2; |
| { |
| #ifdef OPENSSL |
| if(result != s1) |
| BN_copy(result, s1); |
| BN_sub_word(result, s2); |
| #elif defined(CRYPTOLIB) |
| BigInteger t; |
| |
| t = bigInit(s2); |
| bigSubtract(s1, t, result); |
| freeBignum(t); |
| #elif defined(GNU_MP) |
| mpz_sub_ui(result, s1, s2); |
| #elif defined(GCRYPT) |
| gcry_mpi_sub_ui(result, s1, s2); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_sub_d(s1, s2, result); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_sub_int(result, s1, s2); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerMul(result, m1, m2, c) |
| BigInteger result, m1, m2; |
| BigIntegerCtx c; |
| { |
| #ifdef OPENSSL |
| BN_CTX * ctx = NULL; |
| if(c == NULL) |
| c = ctx = BN_CTX_new(); |
| BN_mul(result, m1, m2, c); |
| if(ctx) |
| BN_CTX_free(ctx); |
| #elif defined(CRYPTOLIB) |
| bigMultiply(m1, m2, result); |
| #elif defined(GNU_MP) |
| mpz_mul(result, m1, m2); |
| #elif defined(GCRYPT) |
| gcry_mpi_mul(result, m1, m2); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_mul(m1, m2, result); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_mul_mpi(result, m1, m2); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerMulInt(result, m1, m2, c) |
| BigInteger result, m1; |
| unsigned int m2; |
| BigIntegerCtx c; |
| { |
| #ifdef OPENSSL |
| if(result != m1) |
| BN_copy(result, m1); |
| BN_mul_word(result, m2); |
| #elif defined(CRYPTOLIB) |
| BigInteger t; |
| |
| t = bigInit(m2); |
| bigMultiply(m1, t, result); |
| freeBignum(t); |
| #elif defined(GNU_MP) |
| mpz_mul_ui(result, m1, m2); |
| #elif defined(GCRYPT) |
| gcry_mpi_mul_ui(result, m1, m2); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_mul_d(m1, m2, result); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_mul_int(result, m1, m2); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerDivInt(result, d, m, c) |
| BigInteger result, d; |
| unsigned int m; |
| BigIntegerCtx c; |
| { |
| #ifdef OPENSSL |
| if(result != d) |
| BN_copy(result, d); |
| BN_div_word(result, m); |
| #elif defined(CRYPTOLIB) |
| BigInteger t, u, q; |
| |
| t = bigInit(m); |
| u = bigInit(0); |
| /* We use a separate variable q because cryptolib breaks if result == d */ |
| q = bigInit(0); |
| bigDivide(d, t, q, u); |
| freeBignum(t); |
| freeBignum(u); |
| bigCopy(q, result); |
| freeBignum(q); |
| #elif defined(GNU_MP) |
| # ifdef GMP2 |
| mpz_fdiv_q_ui(result, d, m); |
| # else |
| mpz_div_ui(result, d, m); |
| # endif |
| #elif defined(GCRYPT) |
| BigInteger t = BigIntegerFromInt(m); |
| gcry_mpi_div(result, NULL, d, t, -1); |
| BigIntegerFree(t); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_div_d(d, m, result, NULL); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_div_int(result, NULL, d, m); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerMod(result, d, m, c) |
| BigInteger result, d, m; |
| BigIntegerCtx c; |
| { |
| #ifdef OPENSSL |
| BN_CTX * ctx = NULL; |
| if(c == NULL) |
| c = ctx = BN_CTX_new(); |
| BN_mod(result, d, m, c); |
| if(ctx) |
| BN_CTX_free(ctx); |
| #elif defined(CRYPTOLIB) |
| bigMod(d, m, result); |
| #elif defined(GNU_MP) |
| mpz_mod(result, d, m); |
| #elif defined(GCRYPT) |
| gcry_mpi_mod(result, d, m); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_mod(d, m, result); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_mod_mpi(result, d, m); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| unsigned int |
| BigIntegerModInt(d, m, c) |
| BigInteger d; |
| unsigned int m; |
| BigIntegerCtx c; |
| { |
| #ifdef OPENSSL |
| return BN_mod_word(d, m); |
| #elif defined(CRYPTOLIB) |
| BigInteger t, u; |
| unsigned char r[4]; |
| |
| t = bigInit(m); |
| u = bigInit(0); |
| bigMod(d, t, u); |
| bigToBuf(u, sizeof(r), r); |
| freeBignum(t); |
| freeBignum(u); |
| return r[0] | (r[1] << 8) | (r[2] << 16) | (r[3] << 24); |
| #elif defined(GNU_MP) |
| MP_INT result; |
| unsigned int i; |
| |
| mpz_init(&result); |
| |
| /* Define GMP2 if you're using an old gmp.h but want to link against a |
| * newer libgmp.a (e.g. 2.0 or later). */ |
| |
| # ifdef GMP2 |
| mpz_fdiv_r_ui(&result, d, m); |
| # else |
| mpz_mod_ui(&result, d, m); |
| # endif |
| i = mpz_get_ui(&result); |
| mpz_clear(&result); |
| return i; |
| #elif defined(GCRYPT) |
| /* TODO: any way to clean this up??? */ |
| unsigned char r[4]; |
| size_t len, i; |
| unsigned int ret = 0; |
| BigInteger t = BigIntegerFromInt(m); |
| BigInteger a = BigIntegerFromInt(0); |
| gcry_mpi_mod(a, d, t); |
| gcry_mpi_print(GCRYMPI_FMT_USG, r, 4, &len, a); |
| for(i = 0; i < len; ++i) |
| ret = (ret << 8) | r[i]; |
| BigIntegerFree(t); |
| BigIntegerFree(a); |
| return ret; |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_digit r; |
| mp_mod_d(d, m, &r); |
| return r; |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_uint r = 0; |
| mbedtls_mpi_mod_int(&r, d, m); |
| return r; |
| #endif |
| } |
| |
| BigIntegerResult |
| BigIntegerModMul(r, m1, m2, modulus, c) |
| BigInteger r, m1, m2, modulus; |
| BigIntegerCtx c; |
| { |
| #ifdef OPENSSL |
| BN_CTX * ctx = NULL; |
| if(c == NULL) |
| c = ctx = BN_CTX_new(); |
| BN_mod_mul(r, m1, m2, modulus, c); |
| if(ctx) |
| BN_CTX_free(ctx); |
| #elif defined(CRYPTOLIB) |
| bigMultiply(m1, m2, r); |
| bigMod(r, modulus, r); |
| #elif defined(GNU_MP) |
| mpz_mul(r, m1, m2); |
| mpz_mod(r, r, modulus); |
| #elif defined(GCRYPT) |
| gcry_mpi_mulm(r, m1, m2, modulus); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_mulmod(m1, m2, modulus, r); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi d; |
| mbedtls_mpi_init(&d); |
| mbedtls_mpi_mul_mpi(&d, m1, m2); |
| mbedtls_mpi_mod_mpi(r, &d, modulus); |
| mbedtls_mpi_free(&d); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerModExp(r, b, e, m, c, a) |
| BigInteger r, b, e, m; |
| BigIntegerCtx c; |
| BigIntegerModAccel a; |
| { |
| #ifdef OPENSSL |
| #if OPENSSL_VERSION_NUMBER >= 0x00906000 |
| BN_ULONG B = BN_get_word(b); |
| #endif |
| BN_CTX * ctx = NULL; |
| if(c == NULL) |
| c = ctx = BN_CTX_new(); |
| if(default_modexp) { |
| (*default_modexp)(r, b, e, m, c, a); |
| } |
| else if(a == NULL) { |
| BN_mod_exp(r, b, e, m, c); |
| } |
| #if OPENSSL_VERSION_NUMBER >= 0x00906000 |
| else if(B > 0 && B < ULONG_MAX) { /* 0.9.6 and above has mont_word optimization */ |
| BN_mod_exp_mont_word(r, B, e, m, c, a); |
| } |
| #endif |
| else |
| BN_mod_exp_mont(r, b, e, m, c, a); |
| if(ctx) |
| BN_CTX_free(ctx); |
| #elif defined(CRYPTOLIB) |
| bigPow(b, e, m, r); |
| #elif defined(GNU_MP) |
| mpz_powm(r, b, e, m); |
| #elif defined(GCRYPT) |
| gcry_mpi_powm(r, b, e, m); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_exptmod(b, e, m, r); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_exp_mod(r, b, e, m, NULL); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| #if defined(MBEDTLS) |
| int _mbedtls_f_rng(void* unused, unsigned char *buf, size_t size) |
| { |
| t_random(buf, size); |
| return 0; |
| } |
| #endif |
| |
| int |
| BigIntegerCheckPrime(n, c) |
| BigInteger n; |
| BigIntegerCtx c; |
| { |
| #ifdef OPENSSL |
| int rv; |
| BN_CTX * ctx = NULL; |
| if(c == NULL) |
| c = ctx = BN_CTX_new(); |
| #if OPENSSL_VERSION_NUMBER >= 0x00908000 |
| rv = BN_is_prime_ex(n, 25, c, NULL); |
| #else |
| rv = BN_is_prime(n, 25, NULL, c, NULL); |
| #endif |
| if(ctx) |
| BN_CTX_free(ctx); |
| return rv; |
| #elif defined(CRYPTOLIB) |
| #if 0 |
| /* |
| * Ugh. Not only is cryptolib's bigDivide sensitive to inputs |
| * and outputs being the same, but now the primeTest needs random |
| * numbers, which it gets by calling cryptolib's broken truerand |
| * implementation(!) We have to fake it out by doing our own |
| * seeding explicitly. |
| */ |
| static int seeded = 0; |
| static unsigned char seedbuf[64]; |
| if(!seeded) { |
| t_random(seedbuf, sizeof(seedbuf)); |
| seedDesRandom(seedbuf, sizeof(seedbuf)); |
| memset(seedbuf, 0, sizeof(seedbuf)); |
| seeded = 1; |
| } |
| #endif /* 0 */ |
| t_random(NULL, 0); |
| return primeTest(n); |
| #elif defined(GNU_MP) |
| return mpz_probab_prime_p(n, 25); |
| #elif defined(GCRYPT) |
| return (gcry_prime_check(n, 0) == GPG_ERR_NO_ERROR); |
| #elif defined(TOMMATH) |
| int rv; |
| mp_prime_is_prime(n, 25, &rv); |
| return rv; |
| #elif defined(MPI) |
| return (mpp_pprime(n, 25) == MP_YES); |
| #elif defined(MBEDTLS) |
| return mbedtls_mpi_is_prime_ext(n, 25, _mbedtls_f_rng, NULL); |
| #endif |
| } |
| |
| BigIntegerResult |
| BigIntegerFree(b) |
| BigInteger b; |
| { |
| #ifdef OPENSSL |
| BN_free(b); |
| #elif defined(CRYPTOLIB) |
| freeBignum(b); |
| #elif defined(GNU_MP) |
| mpz_clear(b); |
| free(b); |
| #elif defined(GCRYPT) |
| gcry_mpi_release(b); |
| #elif defined(MPI) || defined(TOMMATH) |
| mp_clear(b); |
| free(b); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_free(b); |
| free(b); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerClearFree(b) |
| BigInteger b; |
| { |
| #ifdef OPENSSL |
| BN_clear_free(b); |
| #elif defined(CRYPTOLIB) |
| /* TODO */ |
| freeBignum(b); |
| #elif defined(GNU_MP) |
| /* TODO */ |
| mpz_clear(b); |
| free(b); |
| #elif defined(GCRYPT) |
| /* TODO */ |
| gcry_mpi_release(b); |
| #elif defined(MPI) || defined(TOMMATH) |
| /* TODO */ |
| mp_clear(b); |
| free(b); |
| #elif defined(MBEDTLS) |
| mbedtls_mpi_free(b); |
| free(b); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerCtx |
| BigIntegerCtxNew() |
| { |
| #ifdef OPENSSL |
| return BN_CTX_new(); |
| #else |
| return NULL; |
| #endif |
| } |
| |
| BigIntegerResult |
| BigIntegerCtxFree(ctx) |
| BigIntegerCtx ctx; |
| { |
| #ifdef OPENSSL |
| if(ctx) |
| BN_CTX_free(ctx); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerModAccel |
| BigIntegerModAccelNew(m, c) |
| BigInteger m; |
| BigIntegerCtx c; |
| { |
| #ifdef OPENSSL |
| BN_CTX * ctx = NULL; |
| BN_MONT_CTX * mctx; |
| if(default_modexp) |
| return NULL; |
| if(c == NULL) |
| c = ctx = BN_CTX_new(); |
| mctx = BN_MONT_CTX_new(); |
| BN_MONT_CTX_set(mctx, m, c); |
| if(ctx) |
| BN_CTX_free(ctx); |
| return mctx; |
| #else |
| return NULL; |
| #endif |
| } |
| |
| BigIntegerResult |
| BigIntegerModAccelFree(accel) |
| BigIntegerModAccel accel; |
| { |
| #ifdef OPENSSL |
| if(accel) |
| BN_MONT_CTX_free(accel); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerInitialize() |
| { |
| #if OPENSSL_VERSION_NUMBER >= 0x00907000 && defined(OPENSSL_ENGINE) |
| ENGINE_load_builtin_engines(); |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |
| |
| BigIntegerResult |
| BigIntegerFinalize() |
| { |
| return BigIntegerReleaseEngine(); |
| } |
| |
| BigIntegerResult |
| BigIntegerUseEngine(const char * engine) |
| { |
| #if defined(OPENSSL) && defined(OPENSSL_ENGINE) |
| ENGINE * e = ENGINE_by_id(engine); |
| if(e) { |
| if(ENGINE_init(e) > 0) { |
| #if OPENSSL_VERSION_NUMBER >= 0x00907000 |
| /* 0.9.7 loses the BN_mod_exp method. Pity. */ |
| const RSA_METHOD * rsa = ENGINE_get_RSA(e); |
| if(rsa) |
| #if (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x3000000fL) || (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100005L) |
| default_modexp = (modexp_meth)RSA_meth_get_bn_mod_exp(rsa); |
| #else |
| default_modexp = (modexp_meth)rsa->bn_mod_exp; |
| #endif |
| #else |
| default_modexp = (modexp_meth)ENGINE_get_BN_mod_exp(e); |
| #endif |
| BigIntegerReleaseEngine(); |
| default_engine = e; |
| return BIG_INTEGER_SUCCESS; |
| } |
| else |
| ENGINE_free(e); |
| } |
| #endif |
| return BIG_INTEGER_ERROR; |
| } |
| |
| BigIntegerResult |
| BigIntegerReleaseEngine() |
| { |
| #if defined(OPENSSL) && defined(OPENSSL_ENGINE) |
| if(default_engine) { |
| ENGINE_finish(default_engine); |
| ENGINE_free(default_engine); |
| default_engine = NULL; |
| default_modexp = NULL; |
| } |
| #endif |
| return BIG_INTEGER_SUCCESS; |
| } |