1 /* LibTomPoly, Polynomial Basis Math -- Tom St Denis
3 * LibTomPoly is a public domain library that provides
4 * polynomial basis arithmetic support. It relies on
5 * LibTomMath for large integer support.
7 * This library is free for all purposes without any
8 * express guarantee that it works.
10 * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org
20 int pb_exptmod (pb_poly
* G
, mp_int
* X
, pb_poly
* P
, pb_poly
* Y
)
22 pb_poly M
[TAB_SIZE
], res
;
24 int err
, bitbuf
, bitcpy
, bitcnt
, mode
, digidx
, x
, y
, winsize
;
26 /* find window size */
27 x
= mp_count_bits (X
);
32 } else if (x
<= 140) {
34 } else if (x
<= 450) {
36 } else if (x
<= 1303) {
38 } else if (x
<= 3529) {
52 if ((err
= pb_init(&M
[1], &(Y
->characteristic
))) != MP_OKAY
) {
56 /* now init the second half of the array */
57 for (x
= 1<<(winsize
-1); x
< (1 << winsize
); x
++) {
58 if ((err
= pb_init(&M
[x
], &(Y
->characteristic
))) != MP_OKAY
) {
59 for (y
= 1<<(winsize
-1); y
< x
; y
++) {
69 * The M table contains powers of the base,
70 * e.g. M[x] = G**x mod P
72 * The first half of the table is not
73 * computed though accept for M[0] and M[1]
76 if (X
->sign
== MP_ZPOS
) {
77 if ((err
= pb_mod (G
, P
, &M
[1])) != MP_OKAY
) { goto __M
; }
79 if ((err
= pb_invmod(G
, P
, &M
[1])) != MP_OKAY
) { goto __M
; }
82 /* compute the value at M[1<<(winsize-1)] by squaring
83 * M[1] (winsize-1) times
85 if ((err
= pb_copy (&M
[1], &M
[1 << (winsize
- 1)])) != MP_OKAY
) { goto __M
; }
87 for (x
= 0; x
< (winsize
- 1); x
++) {
88 if ((err
= pb_mulmod (&M
[1 << (winsize
- 1)], &M
[1 << (winsize
- 1)],
89 P
, &M
[1 << (winsize
- 1)])) != MP_OKAY
) { goto __M
; }
92 /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
93 * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
95 for (x
= (1 << (winsize
- 1)) + 1; x
< (1 << winsize
); x
++) {
96 if ((err
= pb_mulmod (&M
[x
- 1], &M
[1], P
, &M
[x
])) != MP_OKAY
) { goto __M
; }
100 if ((err
= pb_init (&res
, &(Y
->characteristic
))) != MP_OKAY
) { goto __M
; }
101 mp_set (&(res
.terms
[0]), 1); res
.used
= 1;
103 /* set initial mode and bit cnt */
107 digidx
= X
->used
- 1;
112 /* grab next digit as required */
114 /* if digidx == -1 we are out of digits */
118 /* read next digit and reset the bitcnt */
119 buf
= X
->dp
[digidx
--];
120 bitcnt
= (int) DIGIT_BIT
;
123 /* grab the next msb from the exponent */
124 y
= (buf
>> (mp_digit
)(DIGIT_BIT
- 1)) & 1;
127 /* if the bit is zero and mode == 0 then we ignore it
128 * These represent the leading zero bits before the first 1 bit
129 * in the exponent. Technically this opt is not required but it
130 * does lower the # of trivial squaring/reductions used
132 if (mode
== 0 && y
== 0) {
136 /* if the bit is zero and mode == 1 then we square */
137 if (mode
== 1 && y
== 0) {
138 if ((err
= pb_mulmod (&res
, &res
, P
, &res
)) != MP_OKAY
) { goto __RES
; }
142 /* else we add it to the window */
143 bitbuf
|= (y
<< (winsize
- ++bitcpy
));
146 if (bitcpy
== winsize
) {
147 /* ok window is filled so square as required and multiply */
149 for (x
= 0; x
< winsize
; x
++) {
150 if ((err
= pb_mulmod (&res
, &res
, P
, &res
)) != MP_OKAY
) { goto __RES
; }
154 if ((err
= pb_mulmod (&res
, &M
[bitbuf
], P
, &res
)) != MP_OKAY
) { goto __RES
; }
156 /* empty window and reset */
163 /* if bits remain then square/multiply */
164 if (mode
== 2 && bitcpy
> 0) {
165 /* square then multiply if the bit is set */
166 for (x
= 0; x
< bitcpy
; x
++) {
167 if ((err
= pb_mulmod (&res
, &res
, P
, &res
)) != MP_OKAY
) { goto __RES
; }
170 if ((bitbuf
& (1 << winsize
)) != 0) {
172 if ((err
= pb_mulmod (&res
, &M
[1], P
, &res
)) != MP_OKAY
) { goto __RES
; }
179 __RES
:pb_clear (&res
);
182 for (x
= 1<<(winsize
-1); x
< (1 << winsize
); x
++) {