2 #ifdef BN_S_MP_EXPTMOD_C
3 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5 * LibTomMath is a library that provides multiple-precision
6 * integer arithmetic as well as number theoretic functionality.
8 * The library was designed directly after the MPI library by
9 * Michael Fromberger but has been written from scratch with
10 * additional optimizations in place.
12 * The library is free for all purposes without any express
15 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
23 int s_mp_exptmod (mp_int
* G
, mp_int
* X
, mp_int
* P
, mp_int
* Y
, int redmode
)
25 mp_int M
[TAB_SIZE
], res
, mu
;
27 int err
, bitbuf
, bitcpy
, bitcnt
, mode
, digidx
, x
, y
, winsize
;
28 int (*redux
)(mp_int
*,mp_int
*,mp_int
*);
30 /* find window size */
31 x
= mp_count_bits (X
);
36 } else if (x
<= 140) {
38 } else if (x
<= 450) {
40 } else if (x
<= 1303) {
42 } else if (x
<= 3529) {
56 if ((err
= mp_init(&M
[1])) != MP_OKAY
) {
60 /* now init the second half of the array */
61 for (x
= 1<<(winsize
-1); x
< (1 << winsize
); x
++) {
62 if ((err
= mp_init(&M
[x
])) != MP_OKAY
) {
63 for (y
= 1<<(winsize
-1); y
< x
; y
++) {
71 /* create mu, used for Barrett reduction */
72 if ((err
= mp_init (&mu
)) != MP_OKAY
) {
77 if ((err
= mp_reduce_setup (&mu
, P
)) != MP_OKAY
) {
82 if ((err
= mp_reduce_2k_setup_l (P
, &mu
)) != MP_OKAY
) {
85 redux
= mp_reduce_2k_l
;
90 * The M table contains powers of the base,
91 * e.g. M[x] = G**x mod P
93 * The first half of the table is not
94 * computed though accept for M[0] and M[1]
96 if ((err
= mp_mod (G
, P
, &M
[1])) != MP_OKAY
) {
100 /* compute the value at M[1<<(winsize-1)] by squaring
101 * M[1] (winsize-1) times
103 if ((err
= mp_copy (&M
[1], &M
[1 << (winsize
- 1)])) != MP_OKAY
) {
107 for (x
= 0; x
< (winsize
- 1); x
++) {
109 if ((err
= mp_sqr (&M
[1 << (winsize
- 1)],
110 &M
[1 << (winsize
- 1)])) != MP_OKAY
) {
114 /* reduce modulo P */
115 if ((err
= redux (&M
[1 << (winsize
- 1)], P
, &mu
)) != MP_OKAY
) {
120 /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
121 * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
123 for (x
= (1 << (winsize
- 1)) + 1; x
< (1 << winsize
); x
++) {
124 if ((err
= mp_mul (&M
[x
- 1], &M
[1], &M
[x
])) != MP_OKAY
) {
127 if ((err
= redux (&M
[x
], P
, &mu
)) != MP_OKAY
) {
133 if ((err
= mp_init (&res
)) != MP_OKAY
) {
138 /* set initial mode and bit cnt */
142 digidx
= X
->used
- 1;
147 /* grab next digit as required */
149 /* if digidx == -1 we are out of digits */
153 /* read next digit and reset the bitcnt */
154 buf
= X
->dp
[digidx
--];
155 bitcnt
= (int) DIGIT_BIT
;
158 /* grab the next msb from the exponent */
159 y
= (buf
>> (mp_digit
)(DIGIT_BIT
- 1)) & 1;
162 /* if the bit is zero and mode == 0 then we ignore it
163 * These represent the leading zero bits before the first 1 bit
164 * in the exponent. Technically this opt is not required but it
165 * does lower the # of trivial squaring/reductions used
167 if (mode
== 0 && y
== 0) {
171 /* if the bit is zero and mode == 1 then we square */
172 if (mode
== 1 && y
== 0) {
173 if ((err
= mp_sqr (&res
, &res
)) != MP_OKAY
) {
176 if ((err
= redux (&res
, P
, &mu
)) != MP_OKAY
) {
182 /* else we add it to the window */
183 bitbuf
|= (y
<< (winsize
- ++bitcpy
));
186 if (bitcpy
== winsize
) {
187 /* ok window is filled so square as required and multiply */
189 for (x
= 0; x
< winsize
; x
++) {
190 if ((err
= mp_sqr (&res
, &res
)) != MP_OKAY
) {
193 if ((err
= redux (&res
, P
, &mu
)) != MP_OKAY
) {
199 if ((err
= mp_mul (&res
, &M
[bitbuf
], &res
)) != MP_OKAY
) {
202 if ((err
= redux (&res
, P
, &mu
)) != MP_OKAY
) {
206 /* empty window and reset */
213 /* if bits remain then square/multiply */
214 if (mode
== 2 && bitcpy
> 0) {
215 /* square then multiply if the bit is set */
216 for (x
= 0; x
< bitcpy
; x
++) {
217 if ((err
= mp_sqr (&res
, &res
)) != MP_OKAY
) {
220 if ((err
= redux (&res
, P
, &mu
)) != MP_OKAY
) {
225 if ((bitbuf
& (1 << winsize
)) != 0) {
227 if ((err
= mp_mul (&res
, &M
[1], &res
)) != MP_OKAY
) {
230 if ((err
= redux (&res
, P
, &mu
)) != MP_OKAY
) {
239 LBL_RES
:mp_clear (&res
);
240 LBL_MU
:mp_clear (&mu
);
243 for (x
= 1<<(winsize
-1); x
< (1 << winsize
); x
++) {
250 /* $Source: /cvs/libtom/libtommath/bn_s_mp_exptmod.c,v $ */
251 /* $Revision: 1.4 $ */
252 /* $Date: 2006/03/31 14:18:44 $ */