mpint_i.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /*
  2. * mpint_i.h: definitions used internally by the bignum code, and
  3. * also a few other vaguely-bignum-like places.
  4. */
  5. /* ----------------------------------------------------------------------
  6. * The assorted conditional definitions of BignumInt and multiply
  7. * macros used throughout the bignum code to treat numbers as arrays
  8. * of the most conveniently sized word for the target machine.
  9. * Exported so that other code (e.g. poly1305) can use it too.
  10. *
  11. * This code must export, in whatever ifdef branch it ends up in:
  12. *
  13. * - two types: 'BignumInt' and 'BignumCarry'. BignumInt is an
  14. * unsigned integer type which will be used as the base word size
  15. * for all bignum operations. BignumCarry is an unsigned integer
  16. * type used to hold the carry flag taken as input and output by
  17. * the BignumADC macro (see below).
  18. *
  19. * - four constant macros: BIGNUM_INT_BITS, BIGNUM_INT_BYTES,
  20. * BIGNUM_TOP_BIT, BIGNUM_INT_MASK. These should be more or less
  21. * self-explanatory, but just in case, they give the number of bits
  22. * in BignumInt, the number of bytes that works out to, the
  23. * BignumInt value consisting of only the top bit, and the
  24. * BignumInt value with all bits set.
  25. *
  26. * - four statement macros: BignumADC, BignumMUL, BignumMULADD,
  27. * BignumMULADD2. These do various kinds of multi-word arithmetic,
  28. * and all produce two output values.
  29. * * BignumADC(ret,retc,a,b,c) takes input BignumInt values a,b
  30. * and a BignumCarry c, and outputs a BignumInt ret = a+b+c and
  31. * a BignumCarry retc which is the carry off the top of that
  32. * addition.
  33. * * BignumMUL(rh,rl,a,b) returns the two halves of the
  34. * double-width product a*b.
  35. * * BignumMULADD(rh,rl,a,b,addend) returns the two halves of the
  36. * double-width value a*b + addend.
  37. * * BignumMULADD2(rh,rl,a,b,addend1,addend2) returns the two
  38. * halves of the double-width value a*b + addend1 + addend2.
  39. *
  40. * Every branch of the main ifdef below defines the type BignumInt and
  41. * the value BIGNUM_INT_BITS. The other three constant macros are
  42. * filled in by common code further down.
  43. *
  44. * Most branches also define a macro DEFINE_BIGNUMDBLINT containing a
  45. * typedef statement which declares a type _twice_ the length of a
  46. * BignumInt. This causes the common code further down to produce a
  47. * default implementation of the four statement macros in terms of
  48. * that double-width type, and also to defined BignumCarry to be
  49. * BignumInt.
  50. *
  51. * However, if a particular compile target does not have a type twice
  52. * the length of the BignumInt you want to use but it does provide
  53. * some alternative means of doing add-with-carry and double-word
  54. * multiply, then the ifdef branch in question can just define
  55. * BignumCarry and the four statement macros itself, and that's fine
  56. * too.
  57. */
  58. #if defined __SIZEOF_INT128__
  59. /*
  60. * 64-bit BignumInt using gcc/clang style 128-bit BignumDblInt.
  61. *
  62. * gcc and clang both provide a __uint128_t type on 64-bit targets
  63. * (and, when they do, indicate its presence by the above macro),
  64. * using the same 'two machine registers' kind of code generation
  65. * that 32-bit targets use for 64-bit ints.
  66. */
  67. typedef unsigned long long BignumInt;
  68. #define BIGNUM_INT_BITS_BITS 6
  69. #define DEFINE_BIGNUMDBLINT typedef __uint128_t BignumDblInt
  70. #elif defined _MSC_VER && defined _M_AMD64
  71. /*
  72. * 64-bit BignumInt, using Visual Studio x86-64 compiler intrinsics.
  73. *
  74. * 64-bit Visual Studio doesn't provide very much in the way of help
  75. * here: there's no int128 type, and also no inline assembler giving
  76. * us direct access to the x86-64 MUL or ADC instructions. However,
  77. * there are compiler intrinsics giving us that access, so we can
  78. * use those - though it turns out we have to be a little careful,
  79. * since they seem to generate wrong code if their pointer-typed
  80. * output parameters alias their inputs. Hence all the internal temp
  81. * variables inside the macros.
  82. */
  83. #include <intrin.h>
  84. typedef unsigned char BignumCarry; /* the type _addcarry_u64 likes to use */
  85. typedef unsigned __int64 BignumInt;
  86. #define BIGNUM_INT_BITS_BITS 6
  87. #define BignumADC(ret, retc, a, b, c) do \
  88. { \
  89. BignumInt ADC_tmp; \
  90. (retc) = _addcarry_u64(c, a, b, &ADC_tmp); \
  91. (ret) = ADC_tmp; \
  92. } while (0)
  93. #define BignumMUL(rh, rl, a, b) do \
  94. { \
  95. BignumInt MULADD_hi; \
  96. (rl) = _umul128(a, b, &MULADD_hi); \
  97. (rh) = MULADD_hi; \
  98. } while (0)
  99. #define BignumMULADD(rh, rl, a, b, addend) do \
  100. { \
  101. BignumInt MULADD_lo, MULADD_hi; \
  102. MULADD_lo = _umul128(a, b, &MULADD_hi); \
  103. MULADD_hi += _addcarry_u64(0, MULADD_lo, (addend), &(rl)); \
  104. (rh) = MULADD_hi; \
  105. } while (0)
  106. #define BignumMULADD2(rh, rl, a, b, addend1, addend2) do \
  107. { \
  108. BignumInt MULADD_lo1, MULADD_lo2, MULADD_hi; \
  109. MULADD_lo1 = _umul128(a, b, &MULADD_hi); \
  110. MULADD_hi += _addcarry_u64(0, MULADD_lo1, (addend1), &MULADD_lo2); \
  111. MULADD_hi += _addcarry_u64(0, MULADD_lo2, (addend2), &(rl)); \
  112. (rh) = MULADD_hi; \
  113. } while (0)
  114. #elif defined __GNUC__ || defined _LLP64 || __STDC__ >= 199901L
  115. /* 32-bit BignumInt, using C99 unsigned long long as BignumDblInt */
  116. typedef unsigned int BignumInt;
  117. #define BIGNUM_INT_BITS_BITS 5
  118. #define DEFINE_BIGNUMDBLINT typedef unsigned long long BignumDblInt
  119. #elif (defined _MSC_VER && defined _M_IX86) || defined(MPEXT)
  120. /* 32-bit BignumInt, using Visual Studio __int64 as BignumDblInt */
  121. typedef unsigned int BignumInt;
  122. #define BIGNUM_INT_BITS_BITS 5
  123. #define DEFINE_BIGNUMDBLINT typedef unsigned __int64 BignumDblInt
  124. #ifdef MPEXT
  125. // BCC requires semicolons
  126. #define DIVMOD_WORD(q, r, hi, lo, w) do { \
  127. __asm mov edx, hi; \
  128. __asm mov eax, lo; \
  129. __asm div w; \
  130. __asm mov r, edx; \
  131. __asm mov q, eax; \
  132. } while(0)
  133. #else
  134. #endif
  135. #elif defined _LP64
  136. /*
  137. * 32-bit BignumInt, using unsigned long itself as BignumDblInt.
  138. *
  139. * Only for platforms where long is 64 bits, of course.
  140. */
  141. typedef unsigned int BignumInt;
  142. #define BIGNUM_INT_BITS_BITS 5
  143. #define DEFINE_BIGNUMDBLINT typedef unsigned long BignumDblInt
  144. #else
  145. /*
  146. * 16-bit BignumInt, using unsigned long as BignumDblInt.
  147. *
  148. * This is the final fallback for real emergencies: C89 guarantees
  149. * unsigned short/long to be at least the required sizes, so this
  150. * should work on any C implementation at all. But it'll be
  151. * noticeably slow, so if you find yourself in this case you
  152. * probably want to move heaven and earth to find an alternative!
  153. */
  154. typedef unsigned short BignumInt;
  155. #define BIGNUM_INT_BITS_BITS 4
  156. #define DEFINE_BIGNUMDBLINT typedef unsigned long BignumDblInt
  157. #endif
  158. /*
  159. * Common code across all branches of that ifdef: define all the
  160. * easy constant macros in terms of BIGNUM_INT_BITS_BITS.
  161. */
  162. #define BIGNUM_INT_BITS (1 << BIGNUM_INT_BITS_BITS)
  163. #define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)
  164. #define BIGNUM_TOP_BIT (((BignumInt)1) << (BIGNUM_INT_BITS-1))
  165. #define BIGNUM_INT_MASK (BIGNUM_TOP_BIT | (BIGNUM_TOP_BIT-1))
  166. /*
  167. * Common code across _most_ branches of the ifdef: define a set of
  168. * statement macros in terms of the BignumDblInt type provided. In
  169. * this case, we also define BignumCarry to be the same thing as
  170. * BignumInt, for simplicity.
  171. */
  172. #ifdef DEFINE_BIGNUMDBLINT
  173. typedef BignumInt BignumCarry;
  174. #define BignumADC(ret, retc, a, b, c) do \
  175. { \
  176. DEFINE_BIGNUMDBLINT; \
  177. BignumDblInt ADC_temp = (BignumInt)(a); \
  178. ADC_temp += (BignumInt)(b); \
  179. ADC_temp += (c); \
  180. (ret) = (BignumInt)ADC_temp; \
  181. (retc) = (BignumCarry)(ADC_temp >> BIGNUM_INT_BITS); \
  182. } while (0)
  183. #define BignumMUL(rh, rl, a, b) do \
  184. { \
  185. DEFINE_BIGNUMDBLINT; \
  186. BignumDblInt MUL_temp = (BignumInt)(a); \
  187. MUL_temp *= (BignumInt)(b); \
  188. (rh) = (BignumInt)(MUL_temp >> BIGNUM_INT_BITS); \
  189. (rl) = (BignumInt)(MUL_temp); \
  190. } while (0)
  191. #define BignumMULADD(rh, rl, a, b, addend) do \
  192. { \
  193. DEFINE_BIGNUMDBLINT; \
  194. BignumDblInt MUL_temp = (BignumInt)(a); \
  195. MUL_temp *= (BignumInt)(b); \
  196. MUL_temp += (BignumInt)(addend); \
  197. (rh) = (BignumInt)(MUL_temp >> BIGNUM_INT_BITS); \
  198. (rl) = (BignumInt)(MUL_temp); \
  199. } while (0)
  200. #define BignumMULADD2(rh, rl, a, b, addend1, addend2) do \
  201. { \
  202. DEFINE_BIGNUMDBLINT; \
  203. BignumDblInt MUL_temp = (BignumInt)(a); \
  204. MUL_temp *= (BignumInt)(b); \
  205. MUL_temp += (BignumInt)(addend1); \
  206. MUL_temp += (BignumInt)(addend2); \
  207. (rh) = (BignumInt)(MUL_temp >> BIGNUM_INT_BITS); \
  208. (rl) = (BignumInt)(MUL_temp); \
  209. } while (0)
  210. #endif /* DEFINE_BIGNUMDBLINT */
  211. /* ----------------------------------------------------------------------
  212. * Data structures used inside bignum.c.
  213. */
  214. struct mp_int {
  215. size_t nw;
  216. BignumInt *w;
  217. };
  218. struct MontyContext {
  219. /*
  220. * The actual modulus.
  221. */
  222. mp_int *m;
  223. /*
  224. * Montgomery multiplication works by selecting a value r > m,
  225. * coprime to m, which is really easy to divide by. In binary
  226. * arithmetic, that means making it a power of 2; in fact we make
  227. * it a whole number of BignumInt.
  228. *
  229. * We don't store r directly as an mp_int (there's no need). But
  230. * its value is 2^rbits; we also store rw = rbits/BIGNUM_INT_BITS
  231. * (the corresponding word offset within an mp_int).
  232. *
  233. * pw is the number of words needed to store an mp_int you're
  234. * doing reduction on: it has to be big enough to hold the sum of
  235. * an input value up to m^2 plus an extra addend up to m*r.
  236. */
  237. size_t rbits, rw, pw;
  238. /*
  239. * The key step in Montgomery reduction requires the inverse of -m
  240. * mod r.
  241. */
  242. mp_int *minus_minv_mod_r;
  243. /*
  244. * r^1, r^2 and r^3 mod m, which are used for various purposes.
  245. *
  246. * (Annoyingly, this is one of the rare cases where it would have
  247. * been nicer to have a Pascal-style 1-indexed array. I couldn't
  248. * _quite_ bring myself to put a gratuitous zero element in here.
  249. * So you just have to live with getting r^k by taking the [k-1]th
  250. * element of this array.)
  251. */
  252. mp_int *powers_of_r_mod_m[3];
  253. /*
  254. * Persistent scratch space from which monty_* functions can
  255. * allocate storage for intermediate values.
  256. */
  257. mp_int *scratch;
  258. };