diff options
Diffstat (limited to 'src/lib/libcrypto/bn/bn_gf2m.c')
-rw-r--r-- | src/lib/libcrypto/bn/bn_gf2m.c | 1150 |
1 files changed, 678 insertions, 472 deletions
diff --git a/src/lib/libcrypto/bn/bn_gf2m.c b/src/lib/libcrypto/bn/bn_gf2m.c index a75c98ac0e..669f8c403e 100644 --- a/src/lib/libcrypto/bn/bn_gf2m.c +++ b/src/lib/libcrypto/bn/bn_gf2m.c | |||
@@ -42,7 +42,7 @@ | |||
42 | * are met: | 42 | * are met: |
43 | * | 43 | * |
44 | * 1. Redistributions of source code must retain the above copyright | 44 | * 1. Redistributions of source code must retain the above copyright |
45 | * notice, this list of conditions and the following disclaimer. | 45 | * notice, this list of conditions and the following disclaimer. |
46 | * | 46 | * |
47 | * 2. Redistributions in binary form must reproduce the above copyright | 47 | * 2. Redistributions in binary form must reproduce the above copyright |
48 | * notice, this list of conditions and the following disclaimer in | 48 | * notice, this list of conditions and the following disclaimer in |
@@ -100,8 +100,8 @@ | |||
100 | #define MAX_ITERATIONS 50 | 100 | #define MAX_ITERATIONS 50 |
101 | 101 | ||
102 | static const BN_ULONG SQR_tb[16] = | 102 | static const BN_ULONG SQR_tb[16] = |
103 | { 0, 1, 4, 5, 16, 17, 20, 21, | 103 | { 0, 1, 4, 5, 16, 17, 20, 21, |
104 | 64, 65, 68, 69, 80, 81, 84, 85 }; | 104 | 64, 65, 68, 69, 80, 81, 84, 85 }; |
105 | /* Platform-specific macros to accelerate squaring. */ | 105 | /* Platform-specific macros to accelerate squaring. */ |
106 | #ifdef _LP64 | 106 | #ifdef _LP64 |
107 | #define SQR1(w) \ | 107 | #define SQR1(w) \ |
@@ -129,126 +129,225 @@ static const BN_ULONG SQR_tb[16] = | |||
129 | * The caller MUST ensure that the variables have the right amount | 129 | * The caller MUST ensure that the variables have the right amount |
130 | * of space allocated. | 130 | * of space allocated. |
131 | */ | 131 | */ |
132 | static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, const BN_ULONG b) | 132 | static void |
133 | { | 133 | bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, const BN_ULONG b) |
134 | { | ||
134 | #ifndef _LP64 | 135 | #ifndef _LP64 |
135 | register BN_ULONG h, l, s; | 136 | register BN_ULONG h, l, s; |
136 | BN_ULONG tab[8], top2b = a >> 30; | 137 | BN_ULONG tab[8], top2b = a >> 30; |
137 | register BN_ULONG a1, a2, a4; | 138 | register BN_ULONG a1, a2, a4; |
138 | 139 | ||
139 | a1 = a & (0x3FFFFFFF); a2 = a1 << 1; a4 = a2 << 1; | 140 | a1 = a & (0x3FFFFFFF); |
140 | 141 | a2 = a1 << 1; | |
141 | tab[0] = 0; tab[1] = a1; tab[2] = a2; tab[3] = a1^a2; | 142 | a4 = a2 << 1; |
142 | tab[4] = a4; tab[5] = a1^a4; tab[6] = a2^a4; tab[7] = a1^a2^a4; | 143 | |
143 | 144 | tab[0] = 0; | |
144 | s = tab[b & 0x7]; l = s; | 145 | tab[1] = a1; |
145 | s = tab[b >> 3 & 0x7]; l ^= s << 3; h = s >> 29; | 146 | tab[2] = a2; |
146 | s = tab[b >> 6 & 0x7]; l ^= s << 6; h ^= s >> 26; | 147 | tab[3] = a1 ^ a2; |
147 | s = tab[b >> 9 & 0x7]; l ^= s << 9; h ^= s >> 23; | 148 | tab[4] = a4; |
148 | s = tab[b >> 12 & 0x7]; l ^= s << 12; h ^= s >> 20; | 149 | tab[5] = a1 ^ a4; |
149 | s = tab[b >> 15 & 0x7]; l ^= s << 15; h ^= s >> 17; | 150 | tab[6] = a2 ^ a4; |
150 | s = tab[b >> 18 & 0x7]; l ^= s << 18; h ^= s >> 14; | 151 | tab[7] = a1 ^ a2 ^ a4; |
151 | s = tab[b >> 21 & 0x7]; l ^= s << 21; h ^= s >> 11; | 152 | |
152 | s = tab[b >> 24 & 0x7]; l ^= s << 24; h ^= s >> 8; | 153 | s = tab[b & 0x7]; |
153 | s = tab[b >> 27 & 0x7]; l ^= s << 27; h ^= s >> 5; | 154 | l = s; |
154 | s = tab[b >> 30 ]; l ^= s << 30; h ^= s >> 2; | 155 | s = tab[b >> 3 & 0x7]; |
156 | l ^= s << 3; | ||
157 | h = s >> 29; | ||
158 | s = tab[b >> 6 & 0x7]; | ||
159 | l ^= s << 6; | ||
160 | h ^= s >> 26; | ||
161 | s = tab[b >> 9 & 0x7]; | ||
162 | l ^= s << 9; | ||
163 | h ^= s >> 23; | ||
164 | s = tab[b >> 12 & 0x7]; | ||
165 | l ^= s << 12; | ||
166 | h ^= s >> 20; | ||
167 | s = tab[b >> 15 & 0x7]; | ||
168 | l ^= s << 15; | ||
169 | h ^= s >> 17; | ||
170 | s = tab[b >> 18 & 0x7]; | ||
171 | l ^= s << 18; | ||
172 | h ^= s >> 14; | ||
173 | s = tab[b >> 21 & 0x7]; | ||
174 | l ^= s << 21; | ||
175 | h ^= s >> 11; | ||
176 | s = tab[b >> 24 & 0x7]; | ||
177 | l ^= s << 24; | ||
178 | h ^= s >> 8; | ||
179 | s = tab[b >> 27 & 0x7]; | ||
180 | l ^= s << 27; | ||
181 | h ^= s >> 5; | ||
182 | s = tab[b >> 30]; | ||
183 | l ^= s << 30; | ||
184 | h ^= s >> 2; | ||
155 | 185 | ||
156 | /* compensate for the top two bits of a */ | 186 | /* compensate for the top two bits of a */ |
187 | if (top2b & 01) { | ||
188 | l ^= b << 30; | ||
189 | h ^= b >> 2; | ||
190 | } | ||
191 | if (top2b & 02) { | ||
192 | l ^= b << 31; | ||
193 | h ^= b >> 1; | ||
194 | } | ||
157 | 195 | ||
158 | if (top2b & 01) { l ^= b << 30; h ^= b >> 2; } | 196 | *r1 = h; |
159 | if (top2b & 02) { l ^= b << 31; h ^= b >> 1; } | 197 | *r0 = l; |
160 | |||
161 | *r1 = h; *r0 = l; | ||
162 | #else | 198 | #else |
163 | register BN_ULONG h, l, s; | 199 | register BN_ULONG h, l, s; |
164 | BN_ULONG tab[16], top3b = a >> 61; | 200 | BN_ULONG tab[16], top3b = a >> 61; |
165 | register BN_ULONG a1, a2, a4, a8; | 201 | register BN_ULONG a1, a2, a4, a8; |
166 | 202 | ||
167 | a1 = a & (0x1FFFFFFFFFFFFFFFULL); a2 = a1 << 1; a4 = a2 << 1; a8 = a4 << 1; | 203 | a1 = a & (0x1FFFFFFFFFFFFFFFULL); |
168 | 204 | a2 = a1 << 1; | |
169 | tab[ 0] = 0; tab[ 1] = a1; tab[ 2] = a2; tab[ 3] = a1^a2; | 205 | a4 = a2 << 1; |
170 | tab[ 4] = a4; tab[ 5] = a1^a4; tab[ 6] = a2^a4; tab[ 7] = a1^a2^a4; | 206 | a8 = a4 << 1; |
171 | tab[ 8] = a8; tab[ 9] = a1^a8; tab[10] = a2^a8; tab[11] = a1^a2^a8; | 207 | |
172 | tab[12] = a4^a8; tab[13] = a1^a4^a8; tab[14] = a2^a4^a8; tab[15] = a1^a2^a4^a8; | 208 | tab[0] = 0; |
173 | 209 | tab[1] = a1; | |
174 | s = tab[b & 0xF]; l = s; | 210 | tab[2] = a2; |
175 | s = tab[b >> 4 & 0xF]; l ^= s << 4; h = s >> 60; | 211 | tab[3] = a1 ^ a2; |
176 | s = tab[b >> 8 & 0xF]; l ^= s << 8; h ^= s >> 56; | 212 | tab[4] = a4; |
177 | s = tab[b >> 12 & 0xF]; l ^= s << 12; h ^= s >> 52; | 213 | tab[5] = a1 ^ a4; |
178 | s = tab[b >> 16 & 0xF]; l ^= s << 16; h ^= s >> 48; | 214 | tab[6] = a2 ^ a4; |
179 | s = tab[b >> 20 & 0xF]; l ^= s << 20; h ^= s >> 44; | 215 | tab[7] = a1 ^ a2 ^ a4; |
180 | s = tab[b >> 24 & 0xF]; l ^= s << 24; h ^= s >> 40; | 216 | tab[8] = a8; |
181 | s = tab[b >> 28 & 0xF]; l ^= s << 28; h ^= s >> 36; | 217 | tab[9] = a1 ^ a8; |
182 | s = tab[b >> 32 & 0xF]; l ^= s << 32; h ^= s >> 32; | 218 | tab[10] = a2 ^ a8; |
183 | s = tab[b >> 36 & 0xF]; l ^= s << 36; h ^= s >> 28; | 219 | tab[11] = a1 ^ a2 ^ a8; |
184 | s = tab[b >> 40 & 0xF]; l ^= s << 40; h ^= s >> 24; | 220 | tab[12] = a4 ^ a8; |
185 | s = tab[b >> 44 & 0xF]; l ^= s << 44; h ^= s >> 20; | 221 | tab[13] = a1 ^ a4 ^ a8; |
186 | s = tab[b >> 48 & 0xF]; l ^= s << 48; h ^= s >> 16; | 222 | tab[14] = a2 ^ a4 ^ a8; |
187 | s = tab[b >> 52 & 0xF]; l ^= s << 52; h ^= s >> 12; | 223 | tab[15] = a1 ^ a2 ^ a4 ^ a8; |
188 | s = tab[b >> 56 & 0xF]; l ^= s << 56; h ^= s >> 8; | 224 | |
189 | s = tab[b >> 60 ]; l ^= s << 60; h ^= s >> 4; | 225 | s = tab[b & 0xF]; |
226 | l = s; | ||
227 | s = tab[b >> 4 & 0xF]; | ||
228 | l ^= s << 4; | ||
229 | h = s >> 60; | ||
230 | s = tab[b >> 8 & 0xF]; | ||
231 | l ^= s << 8; | ||
232 | h ^= s >> 56; | ||
233 | s = tab[b >> 12 & 0xF]; | ||
234 | l ^= s << 12; | ||
235 | h ^= s >> 52; | ||
236 | s = tab[b >> 16 & 0xF]; | ||
237 | l ^= s << 16; | ||
238 | h ^= s >> 48; | ||
239 | s = tab[b >> 20 & 0xF]; | ||
240 | l ^= s << 20; | ||
241 | h ^= s >> 44; | ||
242 | s = tab[b >> 24 & 0xF]; | ||
243 | l ^= s << 24; | ||
244 | h ^= s >> 40; | ||
245 | s = tab[b >> 28 & 0xF]; | ||
246 | l ^= s << 28; | ||
247 | h ^= s >> 36; | ||
248 | s = tab[b >> 32 & 0xF]; | ||
249 | l ^= s << 32; | ||
250 | h ^= s >> 32; | ||
251 | s = tab[b >> 36 & 0xF]; | ||
252 | l ^= s << 36; | ||
253 | h ^= s >> 28; | ||
254 | s = tab[b >> 40 & 0xF]; | ||
255 | l ^= s << 40; | ||
256 | h ^= s >> 24; | ||
257 | s = tab[b >> 44 & 0xF]; | ||
258 | l ^= s << 44; | ||
259 | h ^= s >> 20; | ||
260 | s = tab[b >> 48 & 0xF]; | ||
261 | l ^= s << 48; | ||
262 | h ^= s >> 16; | ||
263 | s = tab[b >> 52 & 0xF]; | ||
264 | l ^= s << 52; | ||
265 | h ^= s >> 12; | ||
266 | s = tab[b >> 56 & 0xF]; | ||
267 | l ^= s << 56; | ||
268 | h ^= s >> 8; | ||
269 | s = tab[b >> 60]; | ||
270 | l ^= s << 60; | ||
271 | h ^= s >> 4; | ||
190 | 272 | ||
191 | /* compensate for the top three bits of a */ | 273 | /* compensate for the top three bits of a */ |
274 | if (top3b & 01) { | ||
275 | l ^= b << 61; | ||
276 | h ^= b >> 3; | ||
277 | } | ||
278 | if (top3b & 02) { | ||
279 | l ^= b << 62; | ||
280 | h ^= b >> 2; | ||
281 | } | ||
282 | if (top3b & 04) { | ||
283 | l ^= b << 63; | ||
284 | h ^= b >> 1; | ||
285 | } | ||
192 | 286 | ||
193 | if (top3b & 01) { l ^= b << 61; h ^= b >> 3; } | 287 | *r1 = h; |
194 | if (top3b & 02) { l ^= b << 62; h ^= b >> 2; } | 288 | *r0 = l; |
195 | if (top3b & 04) { l ^= b << 63; h ^= b >> 1; } | ||
196 | |||
197 | *r1 = h; *r0 = l; | ||
198 | #endif | 289 | #endif |
199 | } | 290 | } |
200 | 291 | ||
201 | /* Product of two polynomials a, b each with degree < 2 * BN_BITS2 - 1, | 292 | /* Product of two polynomials a, b each with degree < 2 * BN_BITS2 - 1, |
202 | * result is a polynomial r with degree < 4 * BN_BITS2 - 1 | 293 | * result is a polynomial r with degree < 4 * BN_BITS2 - 1 |
203 | * The caller MUST ensure that the variables have the right amount | 294 | * The caller MUST ensure that the variables have the right amount |
204 | * of space allocated. | 295 | * of space allocated. |
205 | */ | 296 | */ |
206 | static void bn_GF2m_mul_2x2(BN_ULONG *r, const BN_ULONG a1, const BN_ULONG a0, const BN_ULONG b1, const BN_ULONG b0) | 297 | static void |
207 | { | 298 | bn_GF2m_mul_2x2(BN_ULONG *r, const BN_ULONG a1, const BN_ULONG a0, |
299 | const BN_ULONG b1, const BN_ULONG b0) | ||
300 | { | ||
208 | BN_ULONG m1, m0; | 301 | BN_ULONG m1, m0; |
302 | |||
209 | /* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */ | 303 | /* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */ |
210 | bn_GF2m_mul_1x1(r+3, r+2, a1, b1); | 304 | bn_GF2m_mul_1x1(r + 3, r + 2, a1, b1); |
211 | bn_GF2m_mul_1x1(r+1, r, a0, b0); | 305 | bn_GF2m_mul_1x1(r + 1, r, a0, b0); |
212 | bn_GF2m_mul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1); | 306 | bn_GF2m_mul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1); |
213 | /* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */ | 307 | /* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */ |
214 | r[2] ^= m1 ^ r[1] ^ r[3]; /* h0 ^= m1 ^ l1 ^ h1; */ | 308 | r[2] ^= m1 ^ r[1] ^ r[3]; /* h0 ^= m1 ^ l1 ^ h1; */ |
215 | r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0; /* l1 ^= l0 ^ h0 ^ m0; */ | 309 | r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0; /* l1 ^= l0 ^ h0 ^ m0; */ |
216 | } | 310 | } |
217 | #else | 311 | #else |
218 | void bn_GF2m_mul_2x2(BN_ULONG *r, BN_ULONG a1, BN_ULONG a0, BN_ULONG b1, BN_ULONG b0); | 312 | void bn_GF2m_mul_2x2(BN_ULONG *r, BN_ULONG a1, BN_ULONG a0, BN_ULONG b1, |
219 | #endif | 313 | BN_ULONG b0); |
314 | #endif | ||
220 | 315 | ||
221 | /* Add polynomials a and b and store result in r; r could be a or b, a and b | 316 | /* Add polynomials a and b and store result in r; r could be a or b, a and b |
222 | * could be equal; r is the bitwise XOR of a and b. | 317 | * could be equal; r is the bitwise XOR of a and b. |
223 | */ | 318 | */ |
224 | int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) | 319 | int |
225 | { | 320 | BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) |
321 | { | ||
226 | int i; | 322 | int i; |
227 | const BIGNUM *at, *bt; | 323 | const BIGNUM *at, *bt; |
228 | 324 | ||
229 | bn_check_top(a); | 325 | bn_check_top(a); |
230 | bn_check_top(b); | 326 | bn_check_top(b); |
231 | 327 | ||
232 | if (a->top < b->top) { at = b; bt = a; } | 328 | if (a->top < b->top) { |
233 | else { at = a; bt = b; } | 329 | at = b; |
330 | bt = a; | ||
331 | } else { | ||
332 | at = a; | ||
333 | bt = b; | ||
334 | } | ||
234 | 335 | ||
235 | if(bn_wexpand(r, at->top) == NULL) | 336 | if (bn_wexpand(r, at->top) == NULL) |
236 | return 0; | 337 | return 0; |
237 | 338 | ||
238 | for (i = 0; i < bt->top; i++) | 339 | for (i = 0; i < bt->top; i++) { |
239 | { | ||
240 | r->d[i] = at->d[i] ^ bt->d[i]; | 340 | r->d[i] = at->d[i] ^ bt->d[i]; |
241 | } | 341 | } |
242 | for (; i < at->top; i++) | 342 | for (; i < at->top; i++) { |
243 | { | ||
244 | r->d[i] = at->d[i]; | 343 | r->d[i] = at->d[i]; |
245 | } | 344 | } |
246 | 345 | ||
247 | r->top = at->top; | 346 | r->top = at->top; |
248 | bn_correct_top(r); | 347 | bn_correct_top(r); |
249 | 348 | ||
250 | return 1; | 349 | return 1; |
251 | } | 350 | } |
252 | 351 | ||
253 | 352 | ||
254 | /* Some functions allow for representation of the irreducible polynomials | 353 | /* Some functions allow for representation of the irreducible polynomials |
@@ -259,70 +358,73 @@ int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) | |||
259 | 358 | ||
260 | 359 | ||
261 | /* Performs modular reduction of a and store result in r. r could be a. */ | 360 | /* Performs modular reduction of a and store result in r. r could be a. */ |
262 | int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[]) | 361 | int |
263 | { | 362 | BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[]) |
363 | { | ||
264 | int j, k; | 364 | int j, k; |
265 | int n, dN, d0, d1; | 365 | int n, dN, d0, d1; |
266 | BN_ULONG zz, *z; | 366 | BN_ULONG zz, *z; |
267 | 367 | ||
268 | bn_check_top(a); | 368 | bn_check_top(a); |
269 | 369 | ||
270 | if (!p[0]) | 370 | if (!p[0]) { |
271 | { | ||
272 | /* reduction mod 1 => return 0 */ | 371 | /* reduction mod 1 => return 0 */ |
273 | BN_zero(r); | 372 | BN_zero(r); |
274 | return 1; | 373 | return 1; |
275 | } | 374 | } |
276 | 375 | ||
277 | /* Since the algorithm does reduction in the r value, if a != r, copy | 376 | /* Since the algorithm does reduction in the r value, if a != r, copy |
278 | * the contents of a into r so we can do reduction in r. | 377 | * the contents of a into r so we can do reduction in r. |
279 | */ | 378 | */ |
280 | if (a != r) | 379 | if (a != r) { |
281 | { | 380 | if (!bn_wexpand(r, a->top)) |
282 | if (!bn_wexpand(r, a->top)) return 0; | 381 | return 0; |
283 | for (j = 0; j < a->top; j++) | 382 | for (j = 0; j < a->top; j++) { |
284 | { | ||
285 | r->d[j] = a->d[j]; | 383 | r->d[j] = a->d[j]; |
286 | } | ||
287 | r->top = a->top; | ||
288 | } | 384 | } |
385 | r->top = a->top; | ||
386 | } | ||
289 | z = r->d; | 387 | z = r->d; |
290 | 388 | ||
291 | /* start reduction */ | 389 | /* start reduction */ |
292 | dN = p[0] / BN_BITS2; | 390 | dN = p[0] / BN_BITS2; |
293 | for (j = r->top - 1; j > dN;) | 391 | for (j = r->top - 1; j > dN; ) { |
294 | { | ||
295 | zz = z[j]; | 392 | zz = z[j]; |
296 | if (z[j] == 0) { j--; continue; } | 393 | if (z[j] == 0) { |
394 | j--; | ||
395 | continue; | ||
396 | } | ||
297 | z[j] = 0; | 397 | z[j] = 0; |
298 | 398 | ||
299 | for (k = 1; p[k] != 0; k++) | 399 | for (k = 1; p[k] != 0; k++) { |
300 | { | ||
301 | /* reducing component t^p[k] */ | 400 | /* reducing component t^p[k] */ |
302 | n = p[0] - p[k]; | 401 | n = p[0] - p[k]; |
303 | d0 = n % BN_BITS2; d1 = BN_BITS2 - d0; | 402 | d0 = n % BN_BITS2; |
304 | n /= BN_BITS2; | 403 | d1 = BN_BITS2 - d0; |
305 | z[j-n] ^= (zz>>d0); | 404 | n /= BN_BITS2; |
306 | if (d0) z[j-n-1] ^= (zz<<d1); | 405 | z[j - n] ^= (zz >> d0); |
307 | } | 406 | if (d0) |
407 | z[j - n - 1] ^= (zz << d1); | ||
408 | } | ||
308 | 409 | ||
309 | /* reducing component t^0 */ | 410 | /* reducing component t^0 */ |
310 | n = dN; | 411 | n = dN; |
311 | d0 = p[0] % BN_BITS2; | 412 | d0 = p[0] % BN_BITS2; |
312 | d1 = BN_BITS2 - d0; | 413 | d1 = BN_BITS2 - d0; |
313 | z[j-n] ^= (zz >> d0); | 414 | z[j - n] ^= (zz >> d0); |
314 | if (d0) z[j-n-1] ^= (zz << d1); | 415 | if (d0) |
315 | } | 416 | z[j - n - 1] ^= (zz << d1); |
417 | } | ||
316 | 418 | ||
317 | /* final round of reduction */ | 419 | /* final round of reduction */ |
318 | while (j == dN) | 420 | while (j == dN) { |
319 | { | ||
320 | 421 | ||
321 | d0 = p[0] % BN_BITS2; | 422 | d0 = p[0] % BN_BITS2; |
322 | zz = z[dN] >> d0; | 423 | zz = z[dN] >> d0; |
323 | if (zz == 0) break; | 424 | if (zz == 0) |
425 | break; | ||
324 | d1 = BN_BITS2 - d0; | 426 | d1 = BN_BITS2 - d0; |
325 | 427 | ||
326 | /* clear up the top d1 bits */ | 428 | /* clear up the top d1 bits */ |
327 | if (d0) | 429 | if (d0) |
328 | z[dN] = (z[dN] << d1) >> d1; | 430 | z[dN] = (z[dN] << d1) >> d1; |
@@ -330,56 +432,58 @@ int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[]) | |||
330 | z[dN] = 0; | 432 | z[dN] = 0; |
331 | z[0] ^= zz; /* reduction t^0 component */ | 433 | z[0] ^= zz; /* reduction t^0 component */ |
332 | 434 | ||
333 | for (k = 1; p[k] != 0; k++) | 435 | for (k = 1; p[k] != 0; k++) { |
334 | { | ||
335 | BN_ULONG tmp_ulong; | 436 | BN_ULONG tmp_ulong; |
336 | 437 | ||
337 | /* reducing component t^p[k]*/ | 438 | /* reducing component t^p[k]*/ |
338 | n = p[k] / BN_BITS2; | 439 | n = p[k] / BN_BITS2; |
339 | d0 = p[k] % BN_BITS2; | 440 | d0 = p[k] % BN_BITS2; |
340 | d1 = BN_BITS2 - d0; | 441 | d1 = BN_BITS2 - d0; |
341 | z[n] ^= (zz << d0); | 442 | z[n] ^= (zz << d0); |
342 | tmp_ulong = zz >> d1; | 443 | tmp_ulong = zz >> d1; |
343 | if (d0 && tmp_ulong) | 444 | if (d0 && tmp_ulong) |
344 | z[n+1] ^= tmp_ulong; | 445 | z[n + 1] ^= tmp_ulong; |
345 | } | ||
346 | |||
347 | |||
348 | } | 446 | } |
349 | 447 | ||
448 | |||
449 | } | ||
450 | |||
350 | bn_correct_top(r); | 451 | bn_correct_top(r); |
351 | return 1; | 452 | return 1; |
352 | } | 453 | } |
353 | 454 | ||
354 | /* Performs modular reduction of a by p and store result in r. r could be a. | 455 | /* Performs modular reduction of a by p and store result in r. r could be a. |
355 | * | 456 | * |
356 | * This function calls down to the BN_GF2m_mod_arr implementation; this wrapper | 457 | * This function calls down to the BN_GF2m_mod_arr implementation; this wrapper |
357 | * function is only provided for convenience; for best performance, use the | 458 | * function is only provided for convenience; for best performance, use the |
358 | * BN_GF2m_mod_arr function. | 459 | * BN_GF2m_mod_arr function. |
359 | */ | 460 | */ |
360 | int BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p) | 461 | int |
361 | { | 462 | BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p) |
463 | { | ||
362 | int ret = 0; | 464 | int ret = 0; |
363 | int arr[6]; | 465 | int arr[6]; |
466 | |||
364 | bn_check_top(a); | 467 | bn_check_top(a); |
365 | bn_check_top(p); | 468 | bn_check_top(p); |
366 | ret = BN_GF2m_poly2arr(p, arr, sizeof(arr)/sizeof(arr[0])); | 469 | ret = BN_GF2m_poly2arr(p, arr, sizeof(arr) / sizeof(arr[0])); |
367 | if (!ret || ret > (int)(sizeof(arr)/sizeof(arr[0]))) | 470 | if (!ret || ret > (int)(sizeof(arr) / sizeof(arr[0]))) { |
368 | { | 471 | BNerr(BN_F_BN_GF2M_MOD, BN_R_INVALID_LENGTH); |
369 | BNerr(BN_F_BN_GF2M_MOD,BN_R_INVALID_LENGTH); | ||
370 | return 0; | 472 | return 0; |
371 | } | 473 | } |
372 | ret = BN_GF2m_mod_arr(r, a, arr); | 474 | ret = BN_GF2m_mod_arr(r, a, arr); |
373 | bn_check_top(r); | 475 | bn_check_top(r); |
374 | return ret; | 476 | return ret; |
375 | } | 477 | } |
376 | 478 | ||
377 | 479 | ||
378 | /* Compute the product of two polynomials a and b, reduce modulo p, and store | 480 | /* Compute the product of two polynomials a and b, reduce modulo p, and store |
379 | * the result in r. r could be a or b; a could be b. | 481 | * the result in r. r could be a or b; a could be b. |
380 | */ | 482 | */ |
381 | int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p[], BN_CTX *ctx) | 483 | int |
382 | { | 484 | BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p[], |
485 | BN_CTX *ctx) | ||
486 | { | ||
383 | int zlen, i, j, k, ret = 0; | 487 | int zlen, i, j, k, ret = 0; |
384 | BIGNUM *s; | 488 | BIGNUM *s; |
385 | BN_ULONG x1, x0, y1, y0, zz[4]; | 489 | BN_ULONG x1, x0, y1, y0, zz[4]; |
@@ -387,32 +491,33 @@ int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p | |||
387 | bn_check_top(a); | 491 | bn_check_top(a); |
388 | bn_check_top(b); | 492 | bn_check_top(b); |
389 | 493 | ||
390 | if (a == b) | 494 | if (a == b) { |
391 | { | ||
392 | return BN_GF2m_mod_sqr_arr(r, a, p, ctx); | 495 | return BN_GF2m_mod_sqr_arr(r, a, p, ctx); |
393 | } | 496 | } |
394 | 497 | ||
395 | BN_CTX_start(ctx); | 498 | BN_CTX_start(ctx); |
396 | if ((s = BN_CTX_get(ctx)) == NULL) goto err; | 499 | if ((s = BN_CTX_get(ctx)) == NULL) |
397 | 500 | goto err; | |
501 | |||
398 | zlen = a->top + b->top + 4; | 502 | zlen = a->top + b->top + 4; |
399 | if (!bn_wexpand(s, zlen)) goto err; | 503 | if (!bn_wexpand(s, zlen)) |
504 | goto err; | ||
400 | s->top = zlen; | 505 | s->top = zlen; |
401 | 506 | ||
402 | for (i = 0; i < zlen; i++) s->d[i] = 0; | 507 | for (i = 0; i < zlen; i++) |
508 | s->d[i] = 0; | ||
403 | 509 | ||
404 | for (j = 0; j < b->top; j += 2) | 510 | for (j = 0; j < b->top; j += 2) { |
405 | { | ||
406 | y0 = b->d[j]; | 511 | y0 = b->d[j]; |
407 | y1 = ((j+1) == b->top) ? 0 : b->d[j+1]; | 512 | y1 = ((j + 1) == b->top) ? 0 : b->d[j + 1]; |
408 | for (i = 0; i < a->top; i += 2) | 513 | for (i = 0; i < a->top; i += 2) { |
409 | { | ||
410 | x0 = a->d[i]; | 514 | x0 = a->d[i]; |
411 | x1 = ((i+1) == a->top) ? 0 : a->d[i+1]; | 515 | x1 = ((i + 1) == a->top) ? 0 : a->d[i + 1]; |
412 | bn_GF2m_mul_2x2(zz, x1, x0, y1, y0); | 516 | bn_GF2m_mul_2x2(zz, x1, x0, y1, y0); |
413 | for (k = 0; k < 4; k++) s->d[i+j+k] ^= zz[k]; | 517 | for (k = 0; k < 4; k++) |
414 | } | 518 | s->d[i + j + k] ^= zz[k]; |
415 | } | 519 | } |
520 | } | ||
416 | 521 | ||
417 | bn_correct_top(s); | 522 | bn_correct_top(s); |
418 | if (BN_GF2m_mod_arr(r, s, p)) | 523 | if (BN_GF2m_mod_arr(r, s, p)) |
@@ -422,101 +527,114 @@ int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p | |||
422 | err: | 527 | err: |
423 | BN_CTX_end(ctx); | 528 | BN_CTX_end(ctx); |
424 | return ret; | 529 | return ret; |
425 | } | 530 | } |
426 | 531 | ||
427 | /* Compute the product of two polynomials a and b, reduce modulo p, and store | 532 | /* Compute the product of two polynomials a and b, reduce modulo p, and store |
428 | * the result in r. r could be a or b; a could equal b. | 533 | * the result in r. r could be a or b; a could equal b. |
429 | * | 534 | * |
430 | * This function calls down to the BN_GF2m_mod_mul_arr implementation; this wrapper | 535 | * This function calls down to the BN_GF2m_mod_mul_arr implementation; this wrapper |
431 | * function is only provided for convenience; for best performance, use the | 536 | * function is only provided for convenience; for best performance, use the |
432 | * BN_GF2m_mod_mul_arr function. | 537 | * BN_GF2m_mod_mul_arr function. |
433 | */ | 538 | */ |
434 | int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx) | 539 | int |
435 | { | 540 | BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, |
541 | BN_CTX *ctx) | ||
542 | { | ||
436 | int ret = 0; | 543 | int ret = 0; |
437 | const int max = BN_num_bits(p) + 1; | 544 | const int max = BN_num_bits(p) + 1; |
438 | int *arr=NULL; | 545 | int *arr = NULL; |
546 | |||
439 | bn_check_top(a); | 547 | bn_check_top(a); |
440 | bn_check_top(b); | 548 | bn_check_top(b); |
441 | bn_check_top(p); | 549 | bn_check_top(p); |
442 | if ((arr = (int *)malloc(sizeof(int) * max)) == NULL) goto err; | 550 | if ((arr = (int *)malloc(sizeof(int) * max)) == NULL) |
551 | goto err; | ||
443 | ret = BN_GF2m_poly2arr(p, arr, max); | 552 | ret = BN_GF2m_poly2arr(p, arr, max); |
444 | if (!ret || ret > max) | 553 | if (!ret || ret > max) { |
445 | { | 554 | BNerr(BN_F_BN_GF2M_MOD_MUL, BN_R_INVALID_LENGTH); |
446 | BNerr(BN_F_BN_GF2M_MOD_MUL,BN_R_INVALID_LENGTH); | ||
447 | goto err; | 555 | goto err; |
448 | } | 556 | } |
449 | ret = BN_GF2m_mod_mul_arr(r, a, b, arr, ctx); | 557 | ret = BN_GF2m_mod_mul_arr(r, a, b, arr, ctx); |
450 | bn_check_top(r); | 558 | bn_check_top(r); |
559 | |||
451 | err: | 560 | err: |
452 | if (arr) free(arr); | 561 | if (arr) |
562 | free(arr); | ||
453 | return ret; | 563 | return ret; |
454 | } | 564 | } |
455 | 565 | ||
456 | 566 | ||
457 | /* Square a, reduce the result mod p, and store it in a. r could be a. */ | 567 | /* Square a, reduce the result mod p, and store it in a. r could be a. */ |
458 | int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[], BN_CTX *ctx) | 568 | int |
459 | { | 569 | BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[], BN_CTX *ctx) |
570 | { | ||
460 | int i, ret = 0; | 571 | int i, ret = 0; |
461 | BIGNUM *s; | 572 | BIGNUM *s; |
462 | 573 | ||
463 | bn_check_top(a); | 574 | bn_check_top(a); |
464 | BN_CTX_start(ctx); | 575 | BN_CTX_start(ctx); |
465 | if ((s = BN_CTX_get(ctx)) == NULL) return 0; | 576 | if ((s = BN_CTX_get(ctx)) == NULL) |
466 | if (!bn_wexpand(s, 2 * a->top)) goto err; | 577 | return 0; |
578 | if (!bn_wexpand(s, 2 * a->top)) | ||
579 | goto err; | ||
467 | 580 | ||
468 | for (i = a->top - 1; i >= 0; i--) | 581 | for (i = a->top - 1; i >= 0; i--) { |
469 | { | 582 | s->d[2 * i + 1] = SQR1(a->d[i]); |
470 | s->d[2*i+1] = SQR1(a->d[i]); | 583 | s->d[2 * i] = SQR0(a->d[i]); |
471 | s->d[2*i ] = SQR0(a->d[i]); | 584 | } |
472 | } | ||
473 | 585 | ||
474 | s->top = 2 * a->top; | 586 | s->top = 2 * a->top; |
475 | bn_correct_top(s); | 587 | bn_correct_top(s); |
476 | if (!BN_GF2m_mod_arr(r, s, p)) goto err; | 588 | if (!BN_GF2m_mod_arr(r, s, p)) |
589 | goto err; | ||
477 | bn_check_top(r); | 590 | bn_check_top(r); |
478 | ret = 1; | 591 | ret = 1; |
592 | |||
479 | err: | 593 | err: |
480 | BN_CTX_end(ctx); | 594 | BN_CTX_end(ctx); |
481 | return ret; | 595 | return ret; |
482 | } | 596 | } |
483 | 597 | ||
484 | /* Square a, reduce the result mod p, and store it in a. r could be a. | 598 | /* Square a, reduce the result mod p, and store it in a. r could be a. |
485 | * | 599 | * |
486 | * This function calls down to the BN_GF2m_mod_sqr_arr implementation; this wrapper | 600 | * This function calls down to the BN_GF2m_mod_sqr_arr implementation; this wrapper |
487 | * function is only provided for convenience; for best performance, use the | 601 | * function is only provided for convenience; for best performance, use the |
488 | * BN_GF2m_mod_sqr_arr function. | 602 | * BN_GF2m_mod_sqr_arr function. |
489 | */ | 603 | */ |
490 | int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) | 604 | int |
491 | { | 605 | BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) |
606 | { | ||
492 | int ret = 0; | 607 | int ret = 0; |
493 | const int max = BN_num_bits(p) + 1; | 608 | const int max = BN_num_bits(p) + 1; |
494 | int *arr=NULL; | 609 | int *arr = NULL; |
495 | 610 | ||
496 | bn_check_top(a); | 611 | bn_check_top(a); |
497 | bn_check_top(p); | 612 | bn_check_top(p); |
498 | if ((arr = (int *)malloc(sizeof(int) * max)) == NULL) goto err; | 613 | if ((arr = (int *)malloc(sizeof(int) * max)) == NULL) |
614 | goto err; | ||
499 | ret = BN_GF2m_poly2arr(p, arr, max); | 615 | ret = BN_GF2m_poly2arr(p, arr, max); |
500 | if (!ret || ret > max) | 616 | if (!ret || ret > max) { |
501 | { | 617 | BNerr(BN_F_BN_GF2M_MOD_SQR, BN_R_INVALID_LENGTH); |
502 | BNerr(BN_F_BN_GF2M_MOD_SQR,BN_R_INVALID_LENGTH); | ||
503 | goto err; | 618 | goto err; |
504 | } | 619 | } |
505 | ret = BN_GF2m_mod_sqr_arr(r, a, arr, ctx); | 620 | ret = BN_GF2m_mod_sqr_arr(r, a, arr, ctx); |
506 | bn_check_top(r); | 621 | bn_check_top(r); |
622 | |||
507 | err: | 623 | err: |
508 | if (arr) free(arr); | 624 | if (arr) |
625 | free(arr); | ||
509 | return ret; | 626 | return ret; |
510 | } | 627 | } |
511 | 628 | ||
512 | 629 | ||
513 | /* Invert a, reduce modulo p, and store the result in r. r could be a. | 630 | /* Invert a, reduce modulo p, and store the result in r. r could be a. |
514 | * Uses Modified Almost Inverse Algorithm (Algorithm 10) from | 631 | * Uses Modified Almost Inverse Algorithm (Algorithm 10) from |
515 | * Hankerson, D., Hernandez, J.L., and Menezes, A. "Software Implementation | 632 | * Hankerson, D., Hernandez, J.L., and Menezes, A. "Software Implementation |
516 | * of Elliptic Curve Cryptography Over Binary Fields". | 633 | * of Elliptic Curve Cryptography Over Binary Fields". |
517 | */ | 634 | */ |
518 | int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) | 635 | int |
519 | { | 636 | BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) |
637 | { | ||
520 | BIGNUM *b, *c = NULL, *u = NULL, *v = NULL, *tmp; | 638 | BIGNUM *b, *c = NULL, *u = NULL, *v = NULL, *tmp; |
521 | int ret = 0; | 639 | int ret = 0; |
522 | 640 | ||
@@ -524,161 +642,194 @@ int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) | |||
524 | bn_check_top(p); | 642 | bn_check_top(p); |
525 | 643 | ||
526 | BN_CTX_start(ctx); | 644 | BN_CTX_start(ctx); |
527 | |||
528 | if ((b = BN_CTX_get(ctx))==NULL) goto err; | ||
529 | if ((c = BN_CTX_get(ctx))==NULL) goto err; | ||
530 | if ((u = BN_CTX_get(ctx))==NULL) goto err; | ||
531 | if ((v = BN_CTX_get(ctx))==NULL) goto err; | ||
532 | 645 | ||
533 | if (!BN_GF2m_mod(u, a, p)) goto err; | 646 | if ((b = BN_CTX_get(ctx)) == NULL) |
534 | if (BN_is_zero(u)) goto err; | 647 | goto err; |
648 | if ((c = BN_CTX_get(ctx)) == NULL) | ||
649 | goto err; | ||
650 | if ((u = BN_CTX_get(ctx)) == NULL) | ||
651 | goto err; | ||
652 | if ((v = BN_CTX_get(ctx)) == NULL) | ||
653 | goto err; | ||
535 | 654 | ||
536 | if (!BN_copy(v, p)) goto err; | 655 | if (!BN_GF2m_mod(u, a, p)) |
656 | goto err; | ||
657 | if (BN_is_zero(u)) | ||
658 | goto err; | ||
659 | |||
660 | if (!BN_copy(v, p)) | ||
661 | goto err; | ||
537 | #if 0 | 662 | #if 0 |
538 | if (!BN_one(b)) goto err; | 663 | if (!BN_one(b)) |
539 | 664 | goto err; | |
540 | while (1) | 665 | |
541 | { | 666 | while (1) { |
542 | while (!BN_is_odd(u)) | 667 | while (!BN_is_odd(u)) { |
543 | { | 668 | if (BN_is_zero(u)) |
544 | if (BN_is_zero(u)) goto err; | 669 | goto err; |
545 | if (!BN_rshift1(u, u)) goto err; | 670 | if (!BN_rshift1(u, u)) |
546 | if (BN_is_odd(b)) | 671 | goto err; |
547 | { | 672 | if (BN_is_odd(b)) { |
548 | if (!BN_GF2m_add(b, b, p)) goto err; | 673 | if (!BN_GF2m_add(b, b, p)) |
549 | } | 674 | goto err; |
550 | if (!BN_rshift1(b, b)) goto err; | ||
551 | } | 675 | } |
676 | if (!BN_rshift1(b, b)) | ||
677 | goto err; | ||
678 | } | ||
552 | 679 | ||
553 | if (BN_abs_is_word(u, 1)) break; | 680 | if (BN_abs_is_word(u, 1)) |
681 | break; | ||
554 | 682 | ||
555 | if (BN_num_bits(u) < BN_num_bits(v)) | 683 | if (BN_num_bits(u) < BN_num_bits(v)) { |
556 | { | 684 | tmp = u; |
557 | tmp = u; u = v; v = tmp; | 685 | u = v; |
558 | tmp = b; b = c; c = tmp; | 686 | v = tmp; |
559 | } | 687 | tmp = b; |
560 | 688 | b = c; | |
561 | if (!BN_GF2m_add(u, u, v)) goto err; | 689 | c = tmp; |
562 | if (!BN_GF2m_add(b, b, c)) goto err; | ||
563 | } | 690 | } |
691 | |||
692 | if (!BN_GF2m_add(u, u, v)) | ||
693 | goto err; | ||
694 | if (!BN_GF2m_add(b, b, c)) | ||
695 | goto err; | ||
696 | } | ||
564 | #else | 697 | #else |
565 | { | 698 | { |
566 | int i, ubits = BN_num_bits(u), | 699 | int i, ubits = BN_num_bits(u), |
567 | vbits = BN_num_bits(v), /* v is copy of p */ | 700 | vbits = BN_num_bits(v), /* v is copy of p */ |
568 | top = p->top; | 701 | top = p->top; |
569 | BN_ULONG *udp,*bdp,*vdp,*cdp; | 702 | BN_ULONG *udp, *bdp, *vdp, *cdp; |
570 | 703 | ||
571 | bn_wexpand(u,top); udp = u->d; | 704 | bn_wexpand(u, top); |
572 | for (i=u->top;i<top;i++) udp[i] = 0; | 705 | udp = u->d; |
573 | u->top = top; | 706 | for (i = u->top; i < top; i++) |
574 | bn_wexpand(b,top); bdp = b->d; | 707 | udp[i] = 0; |
575 | bdp[0] = 1; | 708 | u->top = top; |
576 | for (i=1;i<top;i++) bdp[i] = 0; | 709 | bn_wexpand(b, top); |
577 | b->top = top; | 710 | bdp = b->d; |
578 | bn_wexpand(c,top); cdp = c->d; | 711 | bdp[0] = 1; |
579 | for (i=0;i<top;i++) cdp[i] = 0; | 712 | for (i = 1; i < top; i++) |
580 | c->top = top; | 713 | bdp[i] = 0; |
581 | vdp = v->d; /* It pays off to "cache" *->d pointers, because | 714 | b->top = top; |
582 | * it allows optimizer to be more aggressive. | 715 | bn_wexpand(c, top); |
583 | * But we don't have to "cache" p->d, because *p | 716 | cdp = c->d; |
584 | * is declared 'const'... */ | 717 | for (i = 0; i < top; i++) |
585 | while (1) | 718 | cdp[i] = 0; |
586 | { | 719 | c->top = top; |
587 | while (ubits && !(udp[0]&1)) | 720 | vdp = v->d; /* It pays off to "cache" *->d pointers, because |
588 | { | 721 | * it allows optimizer to be more aggressive. |
589 | BN_ULONG u0,u1,b0,b1,mask; | 722 | * But we don't have to "cache" p->d, because *p |
590 | 723 | * is declared 'const'... */ | |
591 | u0 = udp[0]; | 724 | while (1) { |
592 | b0 = bdp[0]; | 725 | while (ubits && !(udp[0]&1)) { |
593 | mask = (BN_ULONG)0-(b0&1); | 726 | BN_ULONG u0, u1, b0, b1, mask; |
594 | b0 ^= p->d[0]&mask; | 727 | |
595 | for (i=0;i<top-1;i++) | 728 | u0 = udp[0]; |
596 | { | 729 | b0 = bdp[0]; |
597 | u1 = udp[i+1]; | 730 | mask = (BN_ULONG)0 - (b0 & 1); |
598 | udp[i] = ((u0>>1)|(u1<<(BN_BITS2-1)))&BN_MASK2; | 731 | b0 ^= p->d[0] & mask; |
599 | u0 = u1; | 732 | for (i = 0; i < top - 1; i++) { |
600 | b1 = bdp[i+1]^(p->d[i+1]&mask); | 733 | u1 = udp[i + 1]; |
601 | bdp[i] = ((b0>>1)|(b1<<(BN_BITS2-1)))&BN_MASK2; | 734 | udp[i] = ((u0 >> 1) | |
602 | b0 = b1; | 735 | (u1 << (BN_BITS2 - 1))) & BN_MASK2; |
736 | u0 = u1; | ||
737 | b1 = bdp[i + 1] ^ (p->d[i + 1] & mask); | ||
738 | bdp[i] = ((b0 >> 1) | | ||
739 | (b1 << (BN_BITS2 - 1))) & BN_MASK2; | ||
740 | b0 = b1; | ||
603 | } | 741 | } |
604 | udp[i] = u0>>1; | 742 | udp[i] = u0 >> 1; |
605 | bdp[i] = b0>>1; | 743 | bdp[i] = b0 >> 1; |
606 | ubits--; | 744 | ubits--; |
607 | } | 745 | } |
608 | 746 | ||
609 | if (ubits<=BN_BITS2 && udp[0]==1) break; | 747 | if (ubits <= BN_BITS2 && udp[0] == 1) |
610 | 748 | break; | |
611 | if (ubits<vbits) | 749 | |
612 | { | 750 | if (ubits < vbits) { |
613 | i = ubits; ubits = vbits; vbits = i; | 751 | i = ubits; |
614 | tmp = u; u = v; v = tmp; | 752 | ubits = vbits; |
615 | tmp = b; b = c; c = tmp; | 753 | vbits = i; |
616 | udp = vdp; vdp = v->d; | 754 | tmp = u; |
617 | bdp = cdp; cdp = c->d; | 755 | u = v; |
756 | v = tmp; | ||
757 | tmp = b; | ||
758 | b = c; | ||
759 | c = tmp; | ||
760 | udp = vdp; | ||
761 | vdp = v->d; | ||
762 | bdp = cdp; | ||
763 | cdp = c->d; | ||
618 | } | 764 | } |
619 | for(i=0;i<top;i++) | 765 | for (i = 0; i < top; i++) { |
620 | { | 766 | udp[i] ^= vdp[i]; |
621 | udp[i] ^= vdp[i]; | 767 | bdp[i] ^= cdp[i]; |
622 | bdp[i] ^= cdp[i]; | ||
623 | } | 768 | } |
624 | if (ubits==vbits) | 769 | if (ubits == vbits) { |
625 | { | 770 | BN_ULONG ul; |
626 | BN_ULONG ul; | 771 | int utop = (ubits - 1) / BN_BITS2; |
627 | int utop = (ubits-1)/BN_BITS2; | ||
628 | 772 | ||
629 | while ((ul=udp[utop])==0 && utop) utop--; | 773 | while ((ul = udp[utop]) == 0 && utop) |
630 | ubits = utop*BN_BITS2 + BN_num_bits_word(ul); | 774 | utop--; |
775 | ubits = utop*BN_BITS2 + BN_num_bits_word(ul); | ||
631 | } | 776 | } |
632 | } | 777 | } |
633 | bn_correct_top(b); | 778 | bn_correct_top(b); |
634 | } | 779 | } |
635 | #endif | 780 | #endif |
636 | 781 | ||
637 | if (!BN_copy(r, b)) goto err; | 782 | if (!BN_copy(r, b)) |
783 | goto err; | ||
638 | bn_check_top(r); | 784 | bn_check_top(r); |
639 | ret = 1; | 785 | ret = 1; |
640 | 786 | ||
641 | err: | 787 | err: |
642 | #ifdef BN_DEBUG /* BN_CTX_end would complain about the expanded form */ | 788 | #ifdef BN_DEBUG /* BN_CTX_end would complain about the expanded form */ |
643 | bn_correct_top(c); | 789 | bn_correct_top(c); |
644 | bn_correct_top(u); | 790 | bn_correct_top(u); |
645 | bn_correct_top(v); | 791 | bn_correct_top(v); |
646 | #endif | 792 | #endif |
647 | BN_CTX_end(ctx); | 793 | BN_CTX_end(ctx); |
648 | return ret; | 794 | return ret; |
649 | } | 795 | } |
650 | 796 | ||
651 | /* Invert xx, reduce modulo p, and store the result in r. r could be xx. | 797 | /* Invert xx, reduce modulo p, and store the result in r. r could be xx. |
652 | * | 798 | * |
653 | * This function calls down to the BN_GF2m_mod_inv implementation; this wrapper | 799 | * This function calls down to the BN_GF2m_mod_inv implementation; this wrapper |
654 | * function is only provided for convenience; for best performance, use the | 800 | * function is only provided for convenience; for best performance, use the |
655 | * BN_GF2m_mod_inv function. | 801 | * BN_GF2m_mod_inv function. |
656 | */ | 802 | */ |
657 | int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *xx, const int p[], BN_CTX *ctx) | 803 | int |
658 | { | 804 | BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *xx, const int p[], BN_CTX *ctx) |
805 | { | ||
659 | BIGNUM *field; | 806 | BIGNUM *field; |
660 | int ret = 0; | 807 | int ret = 0; |
661 | 808 | ||
662 | bn_check_top(xx); | 809 | bn_check_top(xx); |
663 | BN_CTX_start(ctx); | 810 | BN_CTX_start(ctx); |
664 | if ((field = BN_CTX_get(ctx)) == NULL) goto err; | 811 | if ((field = BN_CTX_get(ctx)) == NULL) |
665 | if (!BN_GF2m_arr2poly(p, field)) goto err; | 812 | goto err; |
666 | 813 | if (!BN_GF2m_arr2poly(p, field)) | |
814 | goto err; | ||
815 | |||
667 | ret = BN_GF2m_mod_inv(r, xx, field, ctx); | 816 | ret = BN_GF2m_mod_inv(r, xx, field, ctx); |
668 | bn_check_top(r); | 817 | bn_check_top(r); |
669 | 818 | ||
670 | err: | 819 | err: |
671 | BN_CTX_end(ctx); | 820 | BN_CTX_end(ctx); |
672 | return ret; | 821 | return ret; |
673 | } | 822 | } |
674 | 823 | ||
675 | 824 | ||
676 | #ifndef OPENSSL_SUN_GF2M_DIV | 825 | #ifndef OPENSSL_SUN_GF2M_DIV |
677 | /* Divide y by x, reduce modulo p, and store the result in r. r could be x | 826 | /* Divide y by x, reduce modulo p, and store the result in r. r could be x |
678 | * or y, x could equal y. | 827 | * or y, x could equal y. |
679 | */ | 828 | */ |
680 | int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p, BN_CTX *ctx) | 829 | int |
681 | { | 830 | BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p, |
831 | BN_CTX *ctx) | ||
832 | { | ||
682 | BIGNUM *xinv = NULL; | 833 | BIGNUM *xinv = NULL; |
683 | int ret = 0; | 834 | int ret = 0; |
684 | 835 | ||
@@ -688,26 +839,31 @@ int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p | |||
688 | 839 | ||
689 | BN_CTX_start(ctx); | 840 | BN_CTX_start(ctx); |
690 | xinv = BN_CTX_get(ctx); | 841 | xinv = BN_CTX_get(ctx); |
691 | if (xinv == NULL) goto err; | 842 | if (xinv == NULL) |
692 | 843 | goto err; | |
693 | if (!BN_GF2m_mod_inv(xinv, x, p, ctx)) goto err; | 844 | |
694 | if (!BN_GF2m_mod_mul(r, y, xinv, p, ctx)) goto err; | 845 | if (!BN_GF2m_mod_inv(xinv, x, p, ctx)) |
846 | goto err; | ||
847 | if (!BN_GF2m_mod_mul(r, y, xinv, p, ctx)) | ||
848 | goto err; | ||
695 | bn_check_top(r); | 849 | bn_check_top(r); |
696 | ret = 1; | 850 | ret = 1; |
697 | 851 | ||
698 | err: | 852 | err: |
699 | BN_CTX_end(ctx); | 853 | BN_CTX_end(ctx); |
700 | return ret; | 854 | return ret; |
701 | } | 855 | } |
702 | #else | 856 | #else |
703 | /* Divide y by x, reduce modulo p, and store the result in r. r could be x | 857 | /* Divide y by x, reduce modulo p, and store the result in r. r could be x |
704 | * or y, x could equal y. | 858 | * or y, x could equal y. |
705 | * Uses algorithm Modular_Division_GF(2^m) from | 859 | * Uses algorithm Modular_Division_GF(2^m) from |
706 | * Chang-Shantz, S. "From Euclid's GCD to Montgomery Multiplication to | 860 | * Chang-Shantz, S. "From Euclid's GCD to Montgomery Multiplication to |
707 | * the Great Divide". | 861 | * the Great Divide". |
708 | */ | 862 | */ |
709 | int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p, BN_CTX *ctx) | 863 | int |
710 | { | 864 | BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p, |
865 | BN_CTX *ctx) | ||
866 | { | ||
711 | BIGNUM *a, *b, *u, *v; | 867 | BIGNUM *a, *b, *u, *v; |
712 | int ret = 0; | 868 | int ret = 0; |
713 | 869 | ||
@@ -716,72 +872,88 @@ int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p | |||
716 | bn_check_top(p); | 872 | bn_check_top(p); |
717 | 873 | ||
718 | BN_CTX_start(ctx); | 874 | BN_CTX_start(ctx); |
719 | 875 | ||
720 | a = BN_CTX_get(ctx); | 876 | a = BN_CTX_get(ctx); |
721 | b = BN_CTX_get(ctx); | 877 | b = BN_CTX_get(ctx); |
722 | u = BN_CTX_get(ctx); | 878 | u = BN_CTX_get(ctx); |
723 | v = BN_CTX_get(ctx); | 879 | v = BN_CTX_get(ctx); |
724 | if (v == NULL) goto err; | 880 | if (v == NULL) |
881 | goto err; | ||
725 | 882 | ||
726 | /* reduce x and y mod p */ | 883 | /* reduce x and y mod p */ |
727 | if (!BN_GF2m_mod(u, y, p)) goto err; | 884 | if (!BN_GF2m_mod(u, y, p)) |
728 | if (!BN_GF2m_mod(a, x, p)) goto err; | 885 | goto err; |
729 | if (!BN_copy(b, p)) goto err; | 886 | if (!BN_GF2m_mod(a, x, p)) |
730 | 887 | goto err; | |
731 | while (!BN_is_odd(a)) | 888 | if (!BN_copy(b, p)) |
732 | { | 889 | goto err; |
733 | if (!BN_rshift1(a, a)) goto err; | ||
734 | if (BN_is_odd(u)) if (!BN_GF2m_add(u, u, p)) goto err; | ||
735 | if (!BN_rshift1(u, u)) goto err; | ||
736 | } | ||
737 | 890 | ||
738 | do | 891 | while (!BN_is_odd(a)) { |
739 | { | 892 | if (!BN_rshift1(a, a)) |
740 | if (BN_GF2m_cmp(b, a) > 0) | 893 | goto err; |
741 | { | 894 | if (BN_is_odd(u)) |
742 | if (!BN_GF2m_add(b, b, a)) goto err; | 895 | if (!BN_GF2m_add(u, u, p)) |
743 | if (!BN_GF2m_add(v, v, u)) goto err; | 896 | goto err; |
744 | do | 897 | if (!BN_rshift1(u, u)) |
745 | { | 898 | goto err; |
746 | if (!BN_rshift1(b, b)) goto err; | 899 | } |
747 | if (BN_is_odd(v)) if (!BN_GF2m_add(v, v, p)) goto err; | 900 | |
748 | if (!BN_rshift1(v, v)) goto err; | 901 | do { |
749 | } while (!BN_is_odd(b)); | 902 | if (BN_GF2m_cmp(b, a) > 0) { |
750 | } | 903 | if (!BN_GF2m_add(b, b, a)) |
751 | else if (BN_abs_is_word(a, 1)) | 904 | goto err; |
905 | if (!BN_GF2m_add(v, v, u)) | ||
906 | goto err; | ||
907 | do { | ||
908 | if (!BN_rshift1(b, b)) | ||
909 | goto err; | ||
910 | if (BN_is_odd(v)) | ||
911 | if (!BN_GF2m_add(v, v, p)) | ||
912 | goto err; | ||
913 | if (!BN_rshift1(v, v)) | ||
914 | goto err; | ||
915 | } while (!BN_is_odd(b)); | ||
916 | } else if (BN_abs_is_word(a, 1)) | ||
752 | break; | 917 | break; |
753 | else | 918 | else { |
754 | { | 919 | if (!BN_GF2m_add(a, a, b)) |
755 | if (!BN_GF2m_add(a, a, b)) goto err; | 920 | goto err; |
756 | if (!BN_GF2m_add(u, u, v)) goto err; | 921 | if (!BN_GF2m_add(u, u, v)) |
757 | do | 922 | goto err; |
758 | { | 923 | do { |
759 | if (!BN_rshift1(a, a)) goto err; | 924 | if (!BN_rshift1(a, a)) |
760 | if (BN_is_odd(u)) if (!BN_GF2m_add(u, u, p)) goto err; | 925 | goto err; |
761 | if (!BN_rshift1(u, u)) goto err; | 926 | if (BN_is_odd(u)) |
762 | } while (!BN_is_odd(a)); | 927 | if (!BN_GF2m_add(u, u, p)) |
763 | } | 928 | goto err; |
764 | } while (1); | 929 | if (!BN_rshift1(u, u)) |
930 | goto err; | ||
931 | } while (!BN_is_odd(a)); | ||
932 | } | ||
933 | } while (1); | ||
765 | 934 | ||
766 | if (!BN_copy(r, u)) goto err; | 935 | if (!BN_copy(r, u)) |
936 | goto err; | ||
767 | bn_check_top(r); | 937 | bn_check_top(r); |
768 | ret = 1; | 938 | ret = 1; |
769 | 939 | ||
770 | err: | 940 | err: |
771 | BN_CTX_end(ctx); | 941 | BN_CTX_end(ctx); |
772 | return ret; | 942 | return ret; |
773 | } | 943 | } |
774 | #endif | 944 | #endif |
775 | 945 | ||
776 | /* Divide yy by xx, reduce modulo p, and store the result in r. r could be xx | 946 | /* Divide yy by xx, reduce modulo p, and store the result in r. r could be xx |
777 | * or yy, xx could equal yy. | 947 | * or yy, xx could equal yy. |
778 | * | 948 | * |
779 | * This function calls down to the BN_GF2m_mod_div implementation; this wrapper | 949 | * This function calls down to the BN_GF2m_mod_div implementation; this wrapper |
780 | * function is only provided for convenience; for best performance, use the | 950 | * function is only provided for convenience; for best performance, use the |
781 | * BN_GF2m_mod_div function. | 951 | * BN_GF2m_mod_div function. |
782 | */ | 952 | */ |
783 | int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *yy, const BIGNUM *xx, const int p[], BN_CTX *ctx) | 953 | int |
784 | { | 954 | BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *yy, const BIGNUM *xx, |
955 | const int p[], BN_CTX *ctx) | ||
956 | { | ||
785 | BIGNUM *field; | 957 | BIGNUM *field; |
786 | int ret = 0; | 958 | int ret = 0; |
787 | 959 | ||
@@ -789,24 +961,28 @@ int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *yy, const BIGNUM *xx, const int | |||
789 | bn_check_top(xx); | 961 | bn_check_top(xx); |
790 | 962 | ||
791 | BN_CTX_start(ctx); | 963 | BN_CTX_start(ctx); |
792 | if ((field = BN_CTX_get(ctx)) == NULL) goto err; | 964 | if ((field = BN_CTX_get(ctx)) == NULL) |
793 | if (!BN_GF2m_arr2poly(p, field)) goto err; | 965 | goto err; |
794 | 966 | if (!BN_GF2m_arr2poly(p, field)) | |
967 | goto err; | ||
968 | |||
795 | ret = BN_GF2m_mod_div(r, yy, xx, field, ctx); | 969 | ret = BN_GF2m_mod_div(r, yy, xx, field, ctx); |
796 | bn_check_top(r); | 970 | bn_check_top(r); |
797 | 971 | ||
798 | err: | 972 | err: |
799 | BN_CTX_end(ctx); | 973 | BN_CTX_end(ctx); |
800 | return ret; | 974 | return ret; |
801 | } | 975 | } |
802 | 976 | ||
803 | 977 | ||
804 | /* Compute the bth power of a, reduce modulo p, and store | 978 | /* Compute the bth power of a, reduce modulo p, and store |
805 | * the result in r. r could be a. | 979 | * the result in r. r could be a. |
806 | * Uses simple square-and-multiply algorithm A.5.1 from IEEE P1363. | 980 | * Uses simple square-and-multiply algorithm A.5.1 from IEEE P1363. |
807 | */ | 981 | */ |
808 | int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p[], BN_CTX *ctx) | 982 | int |
809 | { | 983 | BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p[], |
984 | BN_CTX *ctx) | ||
985 | { | ||
810 | int ret = 0, i, n; | 986 | int ret = 0, i, n; |
811 | BIGNUM *u; | 987 | BIGNUM *u; |
812 | 988 | ||
@@ -814,202 +990,230 @@ int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p | |||
814 | bn_check_top(b); | 990 | bn_check_top(b); |
815 | 991 | ||
816 | if (BN_is_zero(b)) | 992 | if (BN_is_zero(b)) |
817 | return(BN_one(r)); | 993 | return (BN_one(r)); |
818 | 994 | ||
819 | if (BN_abs_is_word(b, 1)) | 995 | if (BN_abs_is_word(b, 1)) |
820 | return (BN_copy(r, a) != NULL); | 996 | return (BN_copy(r, a) != NULL); |
821 | 997 | ||
822 | BN_CTX_start(ctx); | 998 | BN_CTX_start(ctx); |
823 | if ((u = BN_CTX_get(ctx)) == NULL) goto err; | 999 | if ((u = BN_CTX_get(ctx)) == NULL) |
824 | 1000 | goto err; | |
825 | if (!BN_GF2m_mod_arr(u, a, p)) goto err; | 1001 | |
826 | 1002 | if (!BN_GF2m_mod_arr(u, a, p)) | |
1003 | goto err; | ||
1004 | |||
827 | n = BN_num_bits(b) - 1; | 1005 | n = BN_num_bits(b) - 1; |
828 | for (i = n - 1; i >= 0; i--) | 1006 | for (i = n - 1; i >= 0; i--) { |
829 | { | 1007 | if (!BN_GF2m_mod_sqr_arr(u, u, p, ctx)) |
830 | if (!BN_GF2m_mod_sqr_arr(u, u, p, ctx)) goto err; | 1008 | goto err; |
831 | if (BN_is_bit_set(b, i)) | 1009 | if (BN_is_bit_set(b, i)) { |
832 | { | 1010 | if (!BN_GF2m_mod_mul_arr(u, u, a, p, ctx)) |
833 | if (!BN_GF2m_mod_mul_arr(u, u, a, p, ctx)) goto err; | 1011 | goto err; |
834 | } | ||
835 | } | 1012 | } |
836 | if (!BN_copy(r, u)) goto err; | 1013 | } |
1014 | if (!BN_copy(r, u)) | ||
1015 | goto err; | ||
837 | bn_check_top(r); | 1016 | bn_check_top(r); |
838 | ret = 1; | 1017 | ret = 1; |
1018 | |||
839 | err: | 1019 | err: |
840 | BN_CTX_end(ctx); | 1020 | BN_CTX_end(ctx); |
841 | return ret; | 1021 | return ret; |
842 | } | 1022 | } |
843 | 1023 | ||
844 | /* Compute the bth power of a, reduce modulo p, and store | 1024 | /* Compute the bth power of a, reduce modulo p, and store |
845 | * the result in r. r could be a. | 1025 | * the result in r. r could be a. |
846 | * | 1026 | * |
847 | * This function calls down to the BN_GF2m_mod_exp_arr implementation; this wrapper | 1027 | * This function calls down to the BN_GF2m_mod_exp_arr implementation; this wrapper |
848 | * function is only provided for convenience; for best performance, use the | 1028 | * function is only provided for convenience; for best performance, use the |
849 | * BN_GF2m_mod_exp_arr function. | 1029 | * BN_GF2m_mod_exp_arr function. |
850 | */ | 1030 | */ |
851 | int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx) | 1031 | int |
852 | { | 1032 | BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, |
1033 | BN_CTX *ctx) | ||
1034 | { | ||
853 | int ret = 0; | 1035 | int ret = 0; |
854 | const int max = BN_num_bits(p) + 1; | 1036 | const int max = BN_num_bits(p) + 1; |
855 | int *arr=NULL; | 1037 | int *arr = NULL; |
1038 | |||
856 | bn_check_top(a); | 1039 | bn_check_top(a); |
857 | bn_check_top(b); | 1040 | bn_check_top(b); |
858 | bn_check_top(p); | 1041 | bn_check_top(p); |
859 | if ((arr = (int *)malloc(sizeof(int) * max)) == NULL) goto err; | 1042 | if ((arr = (int *)malloc(sizeof(int) * max)) == NULL) |
1043 | goto err; | ||
860 | ret = BN_GF2m_poly2arr(p, arr, max); | 1044 | ret = BN_GF2m_poly2arr(p, arr, max); |
861 | if (!ret || ret > max) | 1045 | if (!ret || ret > max) { |
862 | { | 1046 | BNerr(BN_F_BN_GF2M_MOD_EXP, BN_R_INVALID_LENGTH); |
863 | BNerr(BN_F_BN_GF2M_MOD_EXP,BN_R_INVALID_LENGTH); | ||
864 | goto err; | 1047 | goto err; |
865 | } | 1048 | } |
866 | ret = BN_GF2m_mod_exp_arr(r, a, b, arr, ctx); | 1049 | ret = BN_GF2m_mod_exp_arr(r, a, b, arr, ctx); |
867 | bn_check_top(r); | 1050 | bn_check_top(r); |
1051 | |||
868 | err: | 1052 | err: |
869 | if (arr) free(arr); | 1053 | if (arr) |
1054 | free(arr); | ||
870 | return ret; | 1055 | return ret; |
871 | } | 1056 | } |
872 | 1057 | ||
873 | /* Compute the square root of a, reduce modulo p, and store | 1058 | /* Compute the square root of a, reduce modulo p, and store |
874 | * the result in r. r could be a. | 1059 | * the result in r. r could be a. |
875 | * Uses exponentiation as in algorithm A.4.1 from IEEE P1363. | 1060 | * Uses exponentiation as in algorithm A.4.1 from IEEE P1363. |
876 | */ | 1061 | */ |
877 | int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, const int p[], BN_CTX *ctx) | 1062 | int |
878 | { | 1063 | BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, const int p[], BN_CTX *ctx) |
1064 | { | ||
879 | int ret = 0; | 1065 | int ret = 0; |
880 | BIGNUM *u; | 1066 | BIGNUM *u; |
881 | 1067 | ||
882 | bn_check_top(a); | 1068 | bn_check_top(a); |
883 | 1069 | ||
884 | if (!p[0]) | 1070 | if (!p[0]) { |
885 | { | ||
886 | /* reduction mod 1 => return 0 */ | 1071 | /* reduction mod 1 => return 0 */ |
887 | BN_zero(r); | 1072 | BN_zero(r); |
888 | return 1; | 1073 | return 1; |
889 | } | 1074 | } |
890 | 1075 | ||
891 | BN_CTX_start(ctx); | 1076 | BN_CTX_start(ctx); |
892 | if ((u = BN_CTX_get(ctx)) == NULL) goto err; | 1077 | if ((u = BN_CTX_get(ctx)) == NULL) |
893 | 1078 | goto err; | |
894 | if (!BN_set_bit(u, p[0] - 1)) goto err; | 1079 | |
1080 | if (!BN_set_bit(u, p[0] - 1)) | ||
1081 | goto err; | ||
895 | ret = BN_GF2m_mod_exp_arr(r, a, u, p, ctx); | 1082 | ret = BN_GF2m_mod_exp_arr(r, a, u, p, ctx); |
896 | bn_check_top(r); | 1083 | bn_check_top(r); |
897 | 1084 | ||
898 | err: | 1085 | err: |
899 | BN_CTX_end(ctx); | 1086 | BN_CTX_end(ctx); |
900 | return ret; | 1087 | return ret; |
901 | } | 1088 | } |
902 | 1089 | ||
903 | /* Compute the square root of a, reduce modulo p, and store | 1090 | /* Compute the square root of a, reduce modulo p, and store |
904 | * the result in r. r could be a. | 1091 | * the result in r. r could be a. |
905 | * | 1092 | * |
906 | * This function calls down to the BN_GF2m_mod_sqrt_arr implementation; this wrapper | 1093 | * This function calls down to the BN_GF2m_mod_sqrt_arr implementation; this wrapper |
907 | * function is only provided for convenience; for best performance, use the | 1094 | * function is only provided for convenience; for best performance, use the |
908 | * BN_GF2m_mod_sqrt_arr function. | 1095 | * BN_GF2m_mod_sqrt_arr function. |
909 | */ | 1096 | */ |
910 | int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) | 1097 | int |
911 | { | 1098 | BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) |
1099 | { | ||
912 | int ret = 0; | 1100 | int ret = 0; |
913 | const int max = BN_num_bits(p) + 1; | 1101 | const int max = BN_num_bits(p) + 1; |
914 | int *arr=NULL; | 1102 | int *arr = NULL; |
915 | bn_check_top(a); | 1103 | bn_check_top(a); |
916 | bn_check_top(p); | 1104 | bn_check_top(p); |
917 | if ((arr = (int *)malloc(sizeof(int) * max)) == NULL) goto err; | 1105 | if ((arr = (int *)malloc(sizeof(int) * max)) == NULL) |
1106 | goto err; | ||
918 | ret = BN_GF2m_poly2arr(p, arr, max); | 1107 | ret = BN_GF2m_poly2arr(p, arr, max); |
919 | if (!ret || ret > max) | 1108 | if (!ret || ret > max) { |
920 | { | 1109 | BNerr(BN_F_BN_GF2M_MOD_SQRT, BN_R_INVALID_LENGTH); |
921 | BNerr(BN_F_BN_GF2M_MOD_SQRT,BN_R_INVALID_LENGTH); | ||
922 | goto err; | 1110 | goto err; |
923 | } | 1111 | } |
924 | ret = BN_GF2m_mod_sqrt_arr(r, a, arr, ctx); | 1112 | ret = BN_GF2m_mod_sqrt_arr(r, a, arr, ctx); |
925 | bn_check_top(r); | 1113 | bn_check_top(r); |
1114 | |||
926 | err: | 1115 | err: |
927 | if (arr) free(arr); | 1116 | if (arr) |
1117 | free(arr); | ||
928 | return ret; | 1118 | return ret; |
929 | } | 1119 | } |
930 | 1120 | ||
931 | /* Find r such that r^2 + r = a mod p. r could be a. If no r exists returns 0. | 1121 | /* Find r such that r^2 + r = a mod p. r could be a. If no r exists returns 0. |
932 | * Uses algorithms A.4.7 and A.4.6 from IEEE P1363. | 1122 | * Uses algorithms A.4.7 and A.4.6 from IEEE P1363. |
933 | */ | 1123 | */ |
934 | int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[], BN_CTX *ctx) | 1124 | int |
935 | { | 1125 | BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[], |
1126 | BN_CTX *ctx) | ||
1127 | { | ||
936 | int ret = 0, count = 0, j; | 1128 | int ret = 0, count = 0, j; |
937 | BIGNUM *a, *z, *rho, *w, *w2, *tmp; | 1129 | BIGNUM *a, *z, *rho, *w, *w2, *tmp; |
938 | 1130 | ||
939 | bn_check_top(a_); | 1131 | bn_check_top(a_); |
940 | 1132 | ||
941 | if (!p[0]) | 1133 | if (!p[0]) { |
942 | { | ||
943 | /* reduction mod 1 => return 0 */ | 1134 | /* reduction mod 1 => return 0 */ |
944 | BN_zero(r); | 1135 | BN_zero(r); |
945 | return 1; | 1136 | return 1; |
946 | } | 1137 | } |
947 | 1138 | ||
948 | BN_CTX_start(ctx); | 1139 | BN_CTX_start(ctx); |
949 | a = BN_CTX_get(ctx); | 1140 | a = BN_CTX_get(ctx); |
950 | z = BN_CTX_get(ctx); | 1141 | z = BN_CTX_get(ctx); |
951 | w = BN_CTX_get(ctx); | 1142 | w = BN_CTX_get(ctx); |
952 | if (w == NULL) goto err; | 1143 | if (w == NULL) |
1144 | goto err; | ||
953 | 1145 | ||
954 | if (!BN_GF2m_mod_arr(a, a_, p)) goto err; | 1146 | if (!BN_GF2m_mod_arr(a, a_, p)) |
955 | 1147 | goto err; | |
956 | if (BN_is_zero(a)) | 1148 | |
957 | { | 1149 | if (BN_is_zero(a)) { |
958 | BN_zero(r); | 1150 | BN_zero(r); |
959 | ret = 1; | 1151 | ret = 1; |
960 | goto err; | 1152 | goto err; |
961 | } | 1153 | } |
962 | 1154 | ||
963 | if (p[0] & 0x1) /* m is odd */ | 1155 | if (p[0] & 0x1) /* m is odd */ |
964 | { | 1156 | { |
965 | /* compute half-trace of a */ | 1157 | /* compute half-trace of a */ |
966 | if (!BN_copy(z, a)) goto err; | 1158 | if (!BN_copy(z, a)) |
967 | for (j = 1; j <= (p[0] - 1) / 2; j++) | 1159 | goto err; |
968 | { | 1160 | for (j = 1; j <= (p[0] - 1) / 2; j++) { |
969 | if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err; | 1161 | if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) |
970 | if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err; | 1162 | goto err; |
971 | if (!BN_GF2m_add(z, z, a)) goto err; | 1163 | if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) |
972 | } | 1164 | goto err; |
973 | 1165 | if (!BN_GF2m_add(z, z, a)) | |
1166 | goto err; | ||
974 | } | 1167 | } |
1168 | |||
1169 | } | ||
975 | else /* m is even */ | 1170 | else /* m is even */ |
976 | { | 1171 | { |
977 | rho = BN_CTX_get(ctx); | 1172 | rho = BN_CTX_get(ctx); |
978 | w2 = BN_CTX_get(ctx); | 1173 | w2 = BN_CTX_get(ctx); |
979 | tmp = BN_CTX_get(ctx); | 1174 | tmp = BN_CTX_get(ctx); |
980 | if (tmp == NULL) goto err; | 1175 | if (tmp == NULL) |
981 | do | 1176 | goto err; |
982 | { | 1177 | do { |
983 | if (!BN_rand(rho, p[0], 0, 0)) goto err; | 1178 | if (!BN_rand(rho, p[0], 0, 0)) |
984 | if (!BN_GF2m_mod_arr(rho, rho, p)) goto err; | 1179 | goto err; |
1180 | if (!BN_GF2m_mod_arr(rho, rho, p)) | ||
1181 | goto err; | ||
985 | BN_zero(z); | 1182 | BN_zero(z); |
986 | if (!BN_copy(w, rho)) goto err; | 1183 | if (!BN_copy(w, rho)) |
987 | for (j = 1; j <= p[0] - 1; j++) | 1184 | goto err; |
988 | { | 1185 | for (j = 1; j <= p[0] - 1; j++) { |
989 | if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err; | 1186 | if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) |
990 | if (!BN_GF2m_mod_sqr_arr(w2, w, p, ctx)) goto err; | 1187 | goto err; |
991 | if (!BN_GF2m_mod_mul_arr(tmp, w2, a, p, ctx)) goto err; | 1188 | if (!BN_GF2m_mod_sqr_arr(w2, w, p, ctx)) |
992 | if (!BN_GF2m_add(z, z, tmp)) goto err; | 1189 | goto err; |
993 | if (!BN_GF2m_add(w, w2, rho)) goto err; | 1190 | if (!BN_GF2m_mod_mul_arr(tmp, w2, a, p, ctx)) |
994 | } | 1191 | goto err; |
1192 | if (!BN_GF2m_add(z, z, tmp)) | ||
1193 | goto err; | ||
1194 | if (!BN_GF2m_add(w, w2, rho)) | ||
1195 | goto err; | ||
1196 | } | ||
995 | count++; | 1197 | count++; |
996 | } while (BN_is_zero(w) && (count < MAX_ITERATIONS)); | 1198 | } while (BN_is_zero(w) && (count < MAX_ITERATIONS)); |
997 | if (BN_is_zero(w)) | 1199 | if (BN_is_zero(w)) { |
998 | { | 1200 | BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, |
999 | BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR,BN_R_TOO_MANY_ITERATIONS); | 1201 | BN_R_TOO_MANY_ITERATIONS); |
1000 | goto err; | 1202 | goto err; |
1001 | } | ||
1002 | } | 1203 | } |
1003 | 1204 | } | |
1004 | if (!BN_GF2m_mod_sqr_arr(w, z, p, ctx)) goto err; | 1205 | |
1005 | if (!BN_GF2m_add(w, z, w)) goto err; | 1206 | if (!BN_GF2m_mod_sqr_arr(w, z, p, ctx)) |
1006 | if (BN_GF2m_cmp(w, a)) | 1207 | goto err; |
1007 | { | 1208 | if (!BN_GF2m_add(w, z, w)) |
1209 | goto err; | ||
1210 | if (BN_GF2m_cmp(w, a)) { | ||
1008 | BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_NO_SOLUTION); | 1211 | BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_NO_SOLUTION); |
1009 | goto err; | 1212 | goto err; |
1010 | } | 1213 | } |
1011 | 1214 | ||
1012 | if (!BN_copy(r, z)) goto err; | 1215 | if (!BN_copy(r, z)) |
1216 | goto err; | ||
1013 | bn_check_top(r); | 1217 | bn_check_top(r); |
1014 | 1218 | ||
1015 | ret = 1; | 1219 | ret = 1; |
@@ -1017,66 +1221,68 @@ int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[], BN_CT | |||
1017 | err: | 1221 | err: |
1018 | BN_CTX_end(ctx); | 1222 | BN_CTX_end(ctx); |
1019 | return ret; | 1223 | return ret; |
1020 | } | 1224 | } |
1021 | 1225 | ||
1022 | /* Find r such that r^2 + r = a mod p. r could be a. If no r exists returns 0. | 1226 | /* Find r such that r^2 + r = a mod p. r could be a. If no r exists returns 0. |
1023 | * | 1227 | * |
1024 | * This function calls down to the BN_GF2m_mod_solve_quad_arr implementation; this wrapper | 1228 | * This function calls down to the BN_GF2m_mod_solve_quad_arr implementation; this wrapper |
1025 | * function is only provided for convenience; for best performance, use the | 1229 | * function is only provided for convenience; for best performance, use the |
1026 | * BN_GF2m_mod_solve_quad_arr function. | 1230 | * BN_GF2m_mod_solve_quad_arr function. |
1027 | */ | 1231 | */ |
1028 | int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) | 1232 | int |
1029 | { | 1233 | BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) |
1234 | { | ||
1030 | int ret = 0; | 1235 | int ret = 0; |
1031 | const int max = BN_num_bits(p) + 1; | 1236 | const int max = BN_num_bits(p) + 1; |
1032 | int *arr=NULL; | 1237 | int *arr = NULL; |
1238 | |||
1033 | bn_check_top(a); | 1239 | bn_check_top(a); |
1034 | bn_check_top(p); | 1240 | bn_check_top(p); |
1035 | if ((arr = (int *)malloc(sizeof(int) * | 1241 | if ((arr = (int *)malloc(sizeof(int) * max)) == NULL) |
1036 | max)) == NULL) goto err; | 1242 | goto err; |
1037 | ret = BN_GF2m_poly2arr(p, arr, max); | 1243 | ret = BN_GF2m_poly2arr(p, arr, max); |
1038 | if (!ret || ret > max) | 1244 | if (!ret || ret > max) { |
1039 | { | 1245 | BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD, BN_R_INVALID_LENGTH); |
1040 | BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD,BN_R_INVALID_LENGTH); | ||
1041 | goto err; | 1246 | goto err; |
1042 | } | 1247 | } |
1043 | ret = BN_GF2m_mod_solve_quad_arr(r, a, arr, ctx); | 1248 | ret = BN_GF2m_mod_solve_quad_arr(r, a, arr, ctx); |
1044 | bn_check_top(r); | 1249 | bn_check_top(r); |
1250 | |||
1045 | err: | 1251 | err: |
1046 | if (arr) free(arr); | 1252 | if (arr) |
1253 | free(arr); | ||
1047 | return ret; | 1254 | return ret; |
1048 | } | 1255 | } |
1049 | 1256 | ||
1050 | /* Convert the bit-string representation of a polynomial | 1257 | /* Convert the bit-string representation of a polynomial |
1051 | * ( \sum_{i=0}^n a_i * x^i) into an array of integers corresponding | 1258 | * ( \sum_{i=0}^n a_i * x^i) into an array of integers corresponding |
1052 | * to the bits with non-zero coefficient. Array is terminated with -1. | 1259 | * to the bits with non-zero coefficient. Array is terminated with -1. |
1053 | * Up to max elements of the array will be filled. Return value is total | 1260 | * Up to max elements of the array will be filled. Return value is total |
1054 | * number of array elements that would be filled if array was large enough. | 1261 | * number of array elements that would be filled if array was large enough. |
1055 | */ | 1262 | */ |
1056 | int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max) | 1263 | int |
1057 | { | 1264 | BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max) |
1265 | { | ||
1058 | int i, j, k = 0; | 1266 | int i, j, k = 0; |
1059 | BN_ULONG mask; | 1267 | BN_ULONG mask; |
1060 | 1268 | ||
1061 | if (BN_is_zero(a)) | 1269 | if (BN_is_zero(a)) |
1062 | return 0; | 1270 | return 0; |
1063 | 1271 | ||
1064 | for (i = a->top - 1; i >= 0; i--) | 1272 | for (i = a->top - 1; i >= 0; i--) { |
1065 | { | ||
1066 | if (!a->d[i]) | 1273 | if (!a->d[i]) |
1067 | /* skip word if a->d[i] == 0 */ | 1274 | /* skip word if a->d[i] == 0 */ |
1068 | continue; | 1275 | continue; |
1069 | mask = BN_TBIT; | 1276 | mask = BN_TBIT; |
1070 | for (j = BN_BITS2 - 1; j >= 0; j--) | 1277 | for (j = BN_BITS2 - 1; j >= 0; j--) { |
1071 | { | 1278 | if (a->d[i] & mask) { |
1072 | if (a->d[i] & mask) | 1279 | if (k < max) |
1073 | { | 1280 | p[k] = BN_BITS2 * i + j; |
1074 | if (k < max) p[k] = BN_BITS2 * i + j; | ||
1075 | k++; | 1281 | k++; |
1076 | } | ||
1077 | mask >>= 1; | ||
1078 | } | 1282 | } |
1283 | mask >>= 1; | ||
1079 | } | 1284 | } |
1285 | } | ||
1080 | 1286 | ||
1081 | if (k < max) { | 1287 | if (k < max) { |
1082 | p[k] = -1; | 1288 | p[k] = -1; |
@@ -1084,25 +1290,25 @@ int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max) | |||
1084 | } | 1290 | } |
1085 | 1291 | ||
1086 | return k; | 1292 | return k; |
1087 | } | 1293 | } |
1088 | 1294 | ||
1089 | /* Convert the coefficient array representation of a polynomial to a | 1295 | /* Convert the coefficient array representation of a polynomial to a |
1090 | * bit-string. The array must be terminated by -1. | 1296 | * bit-string. The array must be terminated by -1. |
1091 | */ | 1297 | */ |
1092 | int BN_GF2m_arr2poly(const int p[], BIGNUM *a) | 1298 | int |
1093 | { | 1299 | BN_GF2m_arr2poly(const int p[], BIGNUM *a) |
1300 | { | ||
1094 | int i; | 1301 | int i; |
1095 | 1302 | ||
1096 | bn_check_top(a); | 1303 | bn_check_top(a); |
1097 | BN_zero(a); | 1304 | BN_zero(a); |
1098 | for (i = 0; p[i] != -1; i++) | 1305 | for (i = 0; p[i] != -1; i++) { |
1099 | { | ||
1100 | if (BN_set_bit(a, p[i]) == 0) | 1306 | if (BN_set_bit(a, p[i]) == 0) |
1101 | return 0; | 1307 | return 0; |
1102 | } | 1308 | } |
1103 | bn_check_top(a); | 1309 | bn_check_top(a); |
1104 | 1310 | ||
1105 | return 1; | 1311 | return 1; |
1106 | } | 1312 | } |
1107 | 1313 | ||
1108 | #endif | 1314 | #endif |