Mercurial > dropbear
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$ */ |