bn_s_mp_exptmod.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #include "tommath_private.h"
  2. #ifdef BN_S_MP_EXPTMOD_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis */
  4. /* SPDX-License-Identifier: Unlicense */
  5. #ifdef MP_LOW_MEM
  6. # define TAB_SIZE 32
  7. # define MAX_WINSIZE 5
  8. #else
  9. # define TAB_SIZE 256
  10. # define MAX_WINSIZE 0
  11. #endif
  12. mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode)
  13. {
  14. mp_int M[TAB_SIZE], res, mu;
  15. mp_digit buf;
  16. mp_err err;
  17. int bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
  18. mp_err(*redux)(mp_int *x, const mp_int *m, const mp_int *mu);
  19. /* find window size */
  20. x = mp_count_bits(X);
  21. if (x <= 7) {
  22. winsize = 2;
  23. } else if (x <= 36) {
  24. winsize = 3;
  25. } else if (x <= 140) {
  26. winsize = 4;
  27. } else if (x <= 450) {
  28. winsize = 5;
  29. } else if (x <= 1303) {
  30. winsize = 6;
  31. } else if (x <= 3529) {
  32. winsize = 7;
  33. } else {
  34. winsize = 8;
  35. }
  36. winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize;
  37. /* init M array */
  38. /* init first cell */
  39. if ((err = mp_init(&M[1])) != MP_OKAY) {
  40. return err;
  41. }
  42. /* now init the second half of the array */
  43. for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
  44. if ((err = mp_init(&M[x])) != MP_OKAY) {
  45. for (y = 1<<(winsize-1); y < x; y++) {
  46. mp_clear(&M[y]);
  47. }
  48. mp_clear(&M[1]);
  49. return err;
  50. }
  51. }
  52. /* create mu, used for Barrett reduction */
  53. if ((err = mp_init(&mu)) != MP_OKAY) goto LBL_M;
  54. if (redmode == 0) {
  55. if ((err = mp_reduce_setup(&mu, P)) != MP_OKAY) goto LBL_MU;
  56. redux = mp_reduce;
  57. } else {
  58. if ((err = mp_reduce_2k_setup_l(P, &mu)) != MP_OKAY) goto LBL_MU;
  59. redux = mp_reduce_2k_l;
  60. }
  61. /* create M table
  62. *
  63. * The M table contains powers of the base,
  64. * e.g. M[x] = G**x mod P
  65. *
  66. * The first half of the table is not
  67. * computed though accept for M[0] and M[1]
  68. */
  69. if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) goto LBL_MU;
  70. /* compute the value at M[1<<(winsize-1)] by squaring
  71. * M[1] (winsize-1) times
  72. */
  73. if ((err = mp_copy(&M[1], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU;
  74. for (x = 0; x < (winsize - 1); x++) {
  75. /* square it */
  76. if ((err = mp_sqr(&M[(size_t)1 << (winsize - 1)],
  77. &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU;
  78. /* reduce modulo P */
  79. if ((err = redux(&M[(size_t)1 << (winsize - 1)], P, &mu)) != MP_OKAY) goto LBL_MU;
  80. }
  81. /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
  82. * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
  83. */
  84. for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
  85. if ((err = mp_mul(&M[x - 1], &M[1], &M[x])) != MP_OKAY) goto LBL_MU;
  86. if ((err = redux(&M[x], P, &mu)) != MP_OKAY) goto LBL_MU;
  87. }
  88. /* setup result */
  89. if ((err = mp_init(&res)) != MP_OKAY) goto LBL_MU;
  90. mp_set(&res, 1uL);
  91. /* set initial mode and bit cnt */
  92. mode = 0;
  93. bitcnt = 1;
  94. buf = 0;
  95. digidx = X->used - 1;
  96. bitcpy = 0;
  97. bitbuf = 0;
  98. for (;;) {
  99. /* grab next digit as required */
  100. if (--bitcnt == 0) {
  101. /* if digidx == -1 we are out of digits */
  102. if (digidx == -1) {
  103. break;
  104. }
  105. /* read next digit and reset the bitcnt */
  106. buf = X->dp[digidx--];
  107. bitcnt = (int)MP_DIGIT_BIT;
  108. }
  109. /* grab the next msb from the exponent */
  110. y = (buf >> (mp_digit)(MP_DIGIT_BIT - 1)) & 1uL;
  111. buf <<= (mp_digit)1;
  112. /* if the bit is zero and mode == 0 then we ignore it
  113. * These represent the leading zero bits before the first 1 bit
  114. * in the exponent. Technically this opt is not required but it
  115. * does lower the # of trivial squaring/reductions used
  116. */
  117. if ((mode == 0) && (y == 0)) {
  118. continue;
  119. }
  120. /* if the bit is zero and mode == 1 then we square */
  121. if ((mode == 1) && (y == 0)) {
  122. if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES;
  123. if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES;
  124. continue;
  125. }
  126. /* else we add it to the window */
  127. bitbuf |= (y << (winsize - ++bitcpy));
  128. mode = 2;
  129. if (bitcpy == winsize) {
  130. /* ok window is filled so square as required and multiply */
  131. /* square first */
  132. for (x = 0; x < winsize; x++) {
  133. if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES;
  134. if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES;
  135. }
  136. /* then multiply */
  137. if ((err = mp_mul(&res, &M[bitbuf], &res)) != MP_OKAY) goto LBL_RES;
  138. if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES;
  139. /* empty window and reset */
  140. bitcpy = 0;
  141. bitbuf = 0;
  142. mode = 1;
  143. }
  144. }
  145. /* if bits remain then square/multiply */
  146. if ((mode == 2) && (bitcpy > 0)) {
  147. /* square then multiply if the bit is set */
  148. for (x = 0; x < bitcpy; x++) {
  149. if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES;
  150. if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES;
  151. bitbuf <<= 1;
  152. if ((bitbuf & (1 << winsize)) != 0) {
  153. /* then multiply */
  154. if ((err = mp_mul(&res, &M[1], &res)) != MP_OKAY) goto LBL_RES;
  155. if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES;
  156. }
  157. }
  158. }
  159. mp_exch(&res, Y);
  160. err = MP_OKAY;
  161. LBL_RES:
  162. mp_clear(&res);
  163. LBL_MU:
  164. mp_clear(&mu);
  165. LBL_M:
  166. mp_clear(&M[1]);
  167. for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
  168. mp_clear(&M[x]);
  169. }
  170. return err;
  171. }
  172. #endif