1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
/* LibTomMath, multiple-precision integer library -- Tom St Denis
*
* LibTomMath is library that provides for multiple-precision
* integer arithmetic as well as number theoretic functionality.
*
* The library is designed directly after the MPI library by
* Michael Fromberger but has been written from scratch with
* additional optimizations in place.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtommath.iahu.ca
*/
#ifndef BN_H_
#define BN_H_
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
/* some default configurations.
*
* A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
* A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
*
* At the very least a mp_digit must be able to hold 7 bits
* [any size beyond that is ok provided it overflow the data type]
*/
#ifdef MP_8BIT
typedef unsigned char mp_digit;
typedef unsigned short mp_word;
#elif defined(MP_16BIT)
typedef unsigned short mp_digit;
typedef unsigned long mp_word;
#else
typedef unsigned long mp_digit;
typedef unsigned long long mp_word;
#define DIGIT_BIT 28U
#endif
#ifndef DIGIT_BIT
#define DIGIT_BIT ((CHAR_BIT * sizeof(mp_digit) - 1)) /* bits per digit */
#endif
#define MP_DIGIT_BIT DIGIT_BIT
#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
#define MP_DIGIT_MAX MP_MASK
/* equalities */
#define MP_LT -1 /* less than */
#define MP_EQ 0 /* equal to */
#define MP_GT 1 /* greater than */
#define MP_ZPOS 0 /* positive integer */
#define MP_NEG 1 /* negative */
#define MP_OKAY 0 /* ok result */
#define MP_MEM -2 /* out of mem */
#define MP_VAL -3 /* invalid input */
#define MP_RANGE MP_VAL
#define KARATSUBA_MUL_CUTOFF 80 /* Min. number of digits before Karatsuba multiplication is used. */
#define KARATSUBA_SQR_CUTOFF 80 /* Min. number of digits before Karatsuba squaring is used. */
typedef struct {
int used, alloc, sign;
mp_digit *dp;
} mp_int;
#define USED(m) ((m)->used)
#define DIGIT(m,k) ((m)->dp[k])
#define SIGN(m) ((m)->sign)
/* ---> init and deinit bignum functions <--- */
/* init a bignum */
int mp_init(mp_int *a);
/* free a bignum */
void mp_clear(mp_int *a);
/* exchange two ints */
void mp_exch(mp_int *a, mp_int *b);
/* shrink ram required for a bignum */
int mp_shrink(mp_int *a);
/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? 1 : 0)
#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? 1 : 0)
#define mp_isodd(a) (((a)->used > 0 || (((a)->dp[0] & 1) == 1)) ? 1 : 0)
/* set to zero */
void mp_zero(mp_int *a);
/* set to a digit */
void mp_set(mp_int *a, mp_digit b);
/* set a 32-bit const */
int mp_set_int(mp_int *a, unsigned long b);
/* init to a given number of digits */
int mp_init_size(mp_int *a, int size);
/* copy, b = a */
int mp_copy(mp_int *a, mp_int *b);
/* inits and copies, a = b */
int mp_init_copy(mp_int *a, mp_int *b);
/* ---> digit manipulation <--- */
/* right shift by "b" digits */
void mp_rshd(mp_int *a, int b);
/* left shift by "b" digits */
int mp_lshd(mp_int *a, int b);
/* c = a / 2^b */
int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);
/* b = a/2 */
int mp_div_2(mp_int *a, mp_int *b);
/* c = a * 2^b */
int mp_mul_2d(mp_int *a, int b, mp_int *c);
/* b = a*2 */
int mp_mul_2(mp_int *a, mp_int *b);
/* c = a mod 2^d */
int mp_mod_2d(mp_int *a, int b, mp_int *c);
/* ---> Basic arithmetic <--- */
/* b = -a */
int mp_neg(mp_int *a, mp_int *b);
/* b = |a| */
int mp_abs(mp_int *a, mp_int *b);
/* compare a to b */
int mp_cmp(mp_int *a, mp_int *b);
/* compare |a| to |b| */
int mp_cmp_mag(mp_int *a, mp_int *b);
/* c = a + b */
int mp_add(mp_int *a, mp_int *b, mp_int *c);
/* c = a - b */
int mp_sub(mp_int *a, mp_int *b, mp_int *c);
/* c = a * b */
int mp_mul(mp_int *a, mp_int *b, mp_int *c);
/* b = a^2 */
int mp_sqr(mp_int *a, mp_int *b);
/* a/b => cb + d == a */
int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
/* c = a mod b, 0 <= c < b */
int mp_mod(mp_int *a, mp_int *b, mp_int *c);
/* ---> single digit functions <--- */
/* compare against a single digit */
int mp_cmp_d(mp_int *a, mp_digit b);
/* c = a + b */
int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
/* c = a - b */
int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
/* c = a * b */
int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
/* a/b => cb + d == a */
int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
/* c = a^b */
int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
/* c = a mod b, 0 <= c < b */
int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
/* ---> number theory <--- */
/* d = a + b (mod c) */
int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
/* d = a - b (mod c) */
int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
/* d = a * b (mod c) */
int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
/* c = a * a (mod b) */
int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);
/* c = 1/a (mod b) */
int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
/* c = (a, b) */
int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
/* c = [a, b] or (a*b)/(a, b) */
int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
/* used to setup the Barrett reduction for a given modulus b */
int mp_reduce_setup(mp_int *a, mp_int *b);
/* Barrett Reduction, computes a (mod b) with a precomputed value c
*
* Assumes that 0 < a <= b^2, note if 0 > a > -(b^2) then you can merely
* compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
*/
int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
/* d = a^b (mod c) */
int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
/* ---> radix conversion <--- */
int mp_count_bits(mp_int *a);
int mp_unsigned_bin_size(mp_int *a);
int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c);
int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
int mp_signed_bin_size(mp_int *a);
int mp_read_signed_bin(mp_int *a, unsigned char *b, int c);
int mp_to_signed_bin(mp_int *a, unsigned char *b);
int mp_read_radix(mp_int *a, unsigned char *str, int radix);
int mp_toradix(mp_int *a, unsigned char *str, int radix);
int mp_radix_size(mp_int *a, int radix);
#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
#define mp_raw_size(mp) mp_signed_bin_size(mp)
#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str))
#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
#define mp_mag_size(mp) mp_unsigned_bin_size(mp)
#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str))
#define mp_tobinary(M, S) mp_toradix((M), (S), 2)
#define mp_tooctal(M, S) mp_toradix((M), (S), 8)
#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
#define mp_tohex(M, S) mp_toradix((M), (S), 16)
#endif