comparison tomsfastmath/src/exptmod/fp_exptmod.c @ 643:a362b62d38b2 dropbear-tfm

Add tomsfastmath from git rev bfa4582842bc3bab42e4be4aed5703437049502a with Makefile.in renamed
author Matt Johnston <matt@ucc.asn.au>
date Wed, 23 Nov 2011 18:10:20 +0700
parents
children
comparison
equal deleted inserted replaced
642:33fd2f3499d2 643:a362b62d38b2
1 /* TomsFastMath, a fast ISO C bignum library.
2 *
3 * This project is meant to fill in where LibTomMath
4 * falls short. That is speed ;-)
5 *
6 * This project is public domain and free for all purposes.
7 *
8 * Tom St Denis, [email protected]
9 */
10 #include <tfm.h>
11
12 #ifdef TFM_TIMING_RESISTANT
13
14 /* timing resistant montgomery ladder based exptmod
15
16 Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder", Cryptographic Hardware and Embedded Systems, CHES 2002
17 */
18 static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
19 {
20 fp_int R[2];
21 fp_digit buf, mp;
22 int err, bitcnt, digidx, y;
23
24 /* now setup montgomery */
25 if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) {
26 return err;
27 }
28
29 fp_init(&R[0]);
30 fp_init(&R[1]);
31
32 /* now we need R mod m */
33 fp_montgomery_calc_normalization (&R[0], P);
34
35 /* now set R[0][1] to G * R mod m */
36 if (fp_cmp_mag(P, G) != FP_GT) {
37 /* G > P so we reduce it first */
38 fp_mod(G, P, &R[1]);
39 } else {
40 fp_copy(G, &R[1]);
41 }
42 fp_mulmod (&R[1], &R[0], P, &R[1]);
43
44 /* for j = t-1 downto 0 do
45 r_!k = R0*R1; r_k = r_k^2
46 */
47
48 /* set initial mode and bit cnt */
49 bitcnt = 1;
50 buf = 0;
51 digidx = X->used - 1;
52
53 for (;;) {
54 /* grab next digit as required */
55 if (--bitcnt == 0) {
56 /* if digidx == -1 we are out of digits so break */
57 if (digidx == -1) {
58 break;
59 }
60 /* read next digit and reset bitcnt */
61 buf = X->dp[digidx--];
62 bitcnt = (int)DIGIT_BIT;
63 }
64
65 /* grab the next msb from the exponent */
66 y = (fp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
67 buf <<= (fp_digit)1;
68
69 /* do ops */
70 fp_mul(&R[0], &R[1], &R[y^1]); fp_montgomery_reduce(&R[y^1], P, mp);
71 fp_sqr(&R[y], &R[y]); fp_montgomery_reduce(&R[y], P, mp);
72 }
73
74 fp_montgomery_reduce(&R[0], P, mp);
75 fp_copy(&R[0], Y);
76 return FP_OKAY;
77 }
78
79 #else
80
81 /* y = g**x (mod b)
82 * Some restrictions... x must be positive and < b
83 */
84 static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
85 {
86 fp_int M[64], res;
87 fp_digit buf, mp;
88 int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
89
90 /* find window size */
91 x = fp_count_bits (X);
92 if (x <= 21) {
93 winsize = 1;
94 } else if (x <= 36) {
95 winsize = 3;
96 } else if (x <= 140) {
97 winsize = 4;
98 } else if (x <= 450) {
99 winsize = 5;
100 } else {
101 winsize = 6;
102 }
103
104 /* init M array */
105 memset(M, 0, sizeof(M));
106
107 /* now setup montgomery */
108 if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) {
109 return err;
110 }
111
112 /* setup result */
113 fp_init(&res);
114
115 /* create M table
116 *
117 * The M table contains powers of the input base, e.g. M[x] = G^x mod P
118 *
119 * The first half of the table is not computed though accept for M[0] and M[1]
120 */
121
122 /* now we need R mod m */
123 fp_montgomery_calc_normalization (&res, P);
124
125 /* now set M[1] to G * R mod m */
126 if (fp_cmp_mag(P, G) != FP_GT) {
127 /* G > P so we reduce it first */
128 fp_mod(G, P, &M[1]);
129 } else {
130 fp_copy(G, &M[1]);
131 }
132 fp_mulmod (&M[1], &res, P, &M[1]);
133
134 /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
135 fp_copy (&M[1], &M[1 << (winsize - 1)]);
136 for (x = 0; x < (winsize - 1); x++) {
137 fp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)]);
138 fp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp);
139 }
140
141 /* create upper table */
142 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
143 fp_mul(&M[x - 1], &M[1], &M[x]);
144 fp_montgomery_reduce(&M[x], P, mp);
145 }
146
147 /* set initial mode and bit cnt */
148 mode = 0;
149 bitcnt = 1;
150 buf = 0;
151 digidx = X->used - 1;
152 bitcpy = 0;
153 bitbuf = 0;
154
155 for (;;) {
156 /* grab next digit as required */
157 if (--bitcnt == 0) {
158 /* if digidx == -1 we are out of digits so break */
159 if (digidx == -1) {
160 break;
161 }
162 /* read next digit and reset bitcnt */
163 buf = X->dp[digidx--];
164 bitcnt = (int)DIGIT_BIT;
165 }
166
167 /* grab the next msb from the exponent */
168 y = (fp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
169 buf <<= (fp_digit)1;
170
171 /* if the bit is zero and mode == 0 then we ignore it
172 * These represent the leading zero bits before the first 1 bit
173 * in the exponent. Technically this opt is not required but it
174 * does lower the # of trivial squaring/reductions used
175 */
176 if (mode == 0 && y == 0) {
177 continue;
178 }
179
180 /* if the bit is zero and mode == 1 then we square */
181 if (mode == 1 && y == 0) {
182 fp_sqr(&res, &res);
183 fp_montgomery_reduce(&res, P, mp);
184 continue;
185 }
186
187 /* else we add it to the window */
188 bitbuf |= (y << (winsize - ++bitcpy));
189 mode = 2;
190
191 if (bitcpy == winsize) {
192 /* ok window is filled so square as required and multiply */
193 /* square first */
194 for (x = 0; x < winsize; x++) {
195 fp_sqr(&res, &res);
196 fp_montgomery_reduce(&res, P, mp);
197 }
198
199 /* then multiply */
200 fp_mul(&res, &M[bitbuf], &res);
201 fp_montgomery_reduce(&res, P, mp);
202
203 /* empty window and reset */
204 bitcpy = 0;
205 bitbuf = 0;
206 mode = 1;
207 }
208 }
209
210 /* if bits remain then square/multiply */
211 if (mode == 2 && bitcpy > 0) {
212 /* square then multiply if the bit is set */
213 for (x = 0; x < bitcpy; x++) {
214 fp_sqr(&res, &res);
215 fp_montgomery_reduce(&res, P, mp);
216
217 /* get next bit of the window */
218 bitbuf <<= 1;
219 if ((bitbuf & (1 << winsize)) != 0) {
220 /* then multiply */
221 fp_mul(&res, &M[1], &res);
222 fp_montgomery_reduce(&res, P, mp);
223 }
224 }
225 }
226
227 /* fixup result if Montgomery reduction is used
228 * recall that any value in a Montgomery system is
229 * actually multiplied by R mod n. So we have
230 * to reduce one more time to cancel out the factor
231 * of R.
232 */
233 fp_montgomery_reduce(&res, P, mp);
234
235 /* swap res with Y */
236 fp_copy (&res, Y);
237 return FP_OKAY;
238 }
239
240 #endif
241
242
243 int fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
244 {
245 fp_int tmp;
246 int err;
247
248 #ifdef TFM_CHECK
249 /* prevent overflows */
250 if (P->used > (FP_SIZE/2)) {
251 return FP_VAL;
252 }
253 #endif
254
255 /* is X negative? */
256 if (X->sign == FP_NEG) {
257 /* yes, copy G and invmod it */
258 fp_copy(G, &tmp);
259 if ((err = fp_invmod(&tmp, P, &tmp)) != FP_OKAY) {
260 return err;
261 }
262 X->sign = FP_ZPOS;
263 err = _fp_exptmod(&tmp, X, P, Y);
264 if (X != Y) {
265 X->sign = FP_NEG;
266 }
267 return err;
268 } else {
269 /* Positive exponent so just exptmod */
270 return _fp_exptmod(G, X, P, Y);
271 }
272 }
273
274 /* $Source$ */
275 /* $Revision$ */
276 /* $Date$ */