Branch data Line data Source code
1 : : /* crypto/bn/bn_gf2m.c */
2 : : /* ====================================================================
3 : : * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4 : : *
5 : : * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6 : : * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7 : : * to the OpenSSL project.
8 : : *
9 : : * The ECC Code is licensed pursuant to the OpenSSL open source
10 : : * license provided below.
11 : : *
12 : : * In addition, Sun covenants to all licensees who provide a reciprocal
13 : : * covenant with respect to their own patents if any, not to sue under
14 : : * current and future patent claims necessarily infringed by the making,
15 : : * using, practicing, selling, offering for sale and/or otherwise
16 : : * disposing of the ECC Code as delivered hereunder (or portions thereof),
17 : : * provided that such covenant shall not apply:
18 : : * 1) for code that a licensee deletes from the ECC Code;
19 : : * 2) separates from the ECC Code; or
20 : : * 3) for infringements caused by:
21 : : * i) the modification of the ECC Code or
22 : : * ii) the combination of the ECC Code with other software or
23 : : * devices where such combination causes the infringement.
24 : : *
25 : : * The software is originally written by Sheueling Chang Shantz and
26 : : * Douglas Stebila of Sun Microsystems Laboratories.
27 : : *
28 : : */
29 : :
30 : : /* NOTE: This file is licensed pursuant to the OpenSSL license below
31 : : * and may be modified; but after modifications, the above covenant
32 : : * may no longer apply! In such cases, the corresponding paragraph
33 : : * ["In addition, Sun covenants ... causes the infringement."] and
34 : : * this note can be edited out; but please keep the Sun copyright
35 : : * notice and attribution. */
36 : :
37 : : /* ====================================================================
38 : : * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
39 : : *
40 : : * Redistribution and use in source and binary forms, with or without
41 : : * modification, are permitted provided that the following conditions
42 : : * are met:
43 : : *
44 : : * 1. Redistributions of source code must retain the above copyright
45 : : * notice, this list of conditions and the following disclaimer.
46 : : *
47 : : * 2. Redistributions in binary form must reproduce the above copyright
48 : : * notice, this list of conditions and the following disclaimer in
49 : : * the documentation and/or other materials provided with the
50 : : * distribution.
51 : : *
52 : : * 3. All advertising materials mentioning features or use of this
53 : : * software must display the following acknowledgment:
54 : : * "This product includes software developed by the OpenSSL Project
55 : : * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
56 : : *
57 : : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
58 : : * endorse or promote products derived from this software without
59 : : * prior written permission. For written permission, please contact
60 : : * openssl-core@openssl.org.
61 : : *
62 : : * 5. Products derived from this software may not be called "OpenSSL"
63 : : * nor may "OpenSSL" appear in their names without prior written
64 : : * permission of the OpenSSL Project.
65 : : *
66 : : * 6. Redistributions of any form whatsoever must retain the following
67 : : * acknowledgment:
68 : : * "This product includes software developed by the OpenSSL Project
69 : : * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
70 : : *
71 : : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
72 : : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
74 : : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
75 : : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
76 : : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
77 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
78 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
79 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
80 : : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
81 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
82 : : * OF THE POSSIBILITY OF SUCH DAMAGE.
83 : : * ====================================================================
84 : : *
85 : : * This product includes cryptographic software written by Eric Young
86 : : * (eay@cryptsoft.com). This product includes software written by Tim
87 : : * Hudson (tjh@cryptsoft.com).
88 : : *
89 : : */
90 : :
91 : : #define OPENSSL_FIPSAPI
92 : :
93 : : #include <assert.h>
94 : : #include <limits.h>
95 : : #include <stdio.h>
96 : : #include "cryptlib.h"
97 : : #include "bn_lcl.h"
98 : :
99 : : #ifndef OPENSSL_NO_EC2M
100 : :
101 : : /* Maximum number of iterations before BN_GF2m_mod_solve_quad_arr should fail. */
102 : : #define MAX_ITERATIONS 50
103 : :
104 : : __fips_constseg
105 : : static const BN_ULONG SQR_tb[16] =
106 : : { 0, 1, 4, 5, 16, 17, 20, 21,
107 : : 64, 65, 68, 69, 80, 81, 84, 85 };
108 : : /* Platform-specific macros to accelerate squaring. */
109 : : #if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
110 : : #define SQR1(w) \
111 : : SQR_tb[(w) >> 60 & 0xF] << 56 | SQR_tb[(w) >> 56 & 0xF] << 48 | \
112 : : SQR_tb[(w) >> 52 & 0xF] << 40 | SQR_tb[(w) >> 48 & 0xF] << 32 | \
113 : : SQR_tb[(w) >> 44 & 0xF] << 24 | SQR_tb[(w) >> 40 & 0xF] << 16 | \
114 : : SQR_tb[(w) >> 36 & 0xF] << 8 | SQR_tb[(w) >> 32 & 0xF]
115 : : #define SQR0(w) \
116 : : SQR_tb[(w) >> 28 & 0xF] << 56 | SQR_tb[(w) >> 24 & 0xF] << 48 | \
117 : : SQR_tb[(w) >> 20 & 0xF] << 40 | SQR_tb[(w) >> 16 & 0xF] << 32 | \
118 : : SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >> 8 & 0xF] << 16 | \
119 : : SQR_tb[(w) >> 4 & 0xF] << 8 | SQR_tb[(w) & 0xF]
120 : : #endif
121 : : #ifdef THIRTY_TWO_BIT
122 : : #define SQR1(w) \
123 : : SQR_tb[(w) >> 28 & 0xF] << 24 | SQR_tb[(w) >> 24 & 0xF] << 16 | \
124 : : SQR_tb[(w) >> 20 & 0xF] << 8 | SQR_tb[(w) >> 16 & 0xF]
125 : : #define SQR0(w) \
126 : : SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >> 8 & 0xF] << 16 | \
127 : : SQR_tb[(w) >> 4 & 0xF] << 8 | SQR_tb[(w) & 0xF]
128 : : #endif
129 : :
130 : : #if !defined(OPENSSL_BN_ASM_GF2m)
131 : : /* Product of two polynomials a, b each with degree < BN_BITS2 - 1,
132 : : * result is a polynomial r with degree < 2 * BN_BITS - 1
133 : : * The caller MUST ensure that the variables have the right amount
134 : : * of space allocated.
135 : : */
136 : : #ifdef THIRTY_TWO_BIT
137 : : static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, const BN_ULONG b)
138 : : {
139 : : register BN_ULONG h, l, s;
140 : : BN_ULONG tab[8], top2b = a >> 30;
141 : : register BN_ULONG a1, a2, a4;
142 : :
143 : : a1 = a & (0x3FFFFFFF); a2 = a1 << 1; a4 = a2 << 1;
144 : :
145 : : tab[0] = 0; tab[1] = a1; tab[2] = a2; tab[3] = a1^a2;
146 : : tab[4] = a4; tab[5] = a1^a4; tab[6] = a2^a4; tab[7] = a1^a2^a4;
147 : :
148 : : s = tab[b & 0x7]; l = s;
149 : : s = tab[b >> 3 & 0x7]; l ^= s << 3; h = s >> 29;
150 : : s = tab[b >> 6 & 0x7]; l ^= s << 6; h ^= s >> 26;
151 : : s = tab[b >> 9 & 0x7]; l ^= s << 9; h ^= s >> 23;
152 : : s = tab[b >> 12 & 0x7]; l ^= s << 12; h ^= s >> 20;
153 : : s = tab[b >> 15 & 0x7]; l ^= s << 15; h ^= s >> 17;
154 : : s = tab[b >> 18 & 0x7]; l ^= s << 18; h ^= s >> 14;
155 : : s = tab[b >> 21 & 0x7]; l ^= s << 21; h ^= s >> 11;
156 : : s = tab[b >> 24 & 0x7]; l ^= s << 24; h ^= s >> 8;
157 : : s = tab[b >> 27 & 0x7]; l ^= s << 27; h ^= s >> 5;
158 : : s = tab[b >> 30 ]; l ^= s << 30; h ^= s >> 2;
159 : :
160 : : /* compensate for the top two bits of a */
161 : :
162 : : if (top2b & 01) { l ^= b << 30; h ^= b >> 2; }
163 : : if (top2b & 02) { l ^= b << 31; h ^= b >> 1; }
164 : :
165 : : *r1 = h; *r0 = l;
166 : : }
167 : : #endif
168 : : #if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
169 : : static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, const BN_ULONG b)
170 : : {
171 : : register BN_ULONG h, l, s;
172 : : BN_ULONG tab[16], top3b = a >> 61;
173 : : register BN_ULONG a1, a2, a4, a8;
174 : :
175 : : a1 = a & (0x1FFFFFFFFFFFFFFFULL); a2 = a1 << 1; a4 = a2 << 1; a8 = a4 << 1;
176 : :
177 : : tab[ 0] = 0; tab[ 1] = a1; tab[ 2] = a2; tab[ 3] = a1^a2;
178 : : tab[ 4] = a4; tab[ 5] = a1^a4; tab[ 6] = a2^a4; tab[ 7] = a1^a2^a4;
179 : : tab[ 8] = a8; tab[ 9] = a1^a8; tab[10] = a2^a8; tab[11] = a1^a2^a8;
180 : : tab[12] = a4^a8; tab[13] = a1^a4^a8; tab[14] = a2^a4^a8; tab[15] = a1^a2^a4^a8;
181 : :
182 : : s = tab[b & 0xF]; l = s;
183 : : s = tab[b >> 4 & 0xF]; l ^= s << 4; h = s >> 60;
184 : : s = tab[b >> 8 & 0xF]; l ^= s << 8; h ^= s >> 56;
185 : : s = tab[b >> 12 & 0xF]; l ^= s << 12; h ^= s >> 52;
186 : : s = tab[b >> 16 & 0xF]; l ^= s << 16; h ^= s >> 48;
187 : : s = tab[b >> 20 & 0xF]; l ^= s << 20; h ^= s >> 44;
188 : : s = tab[b >> 24 & 0xF]; l ^= s << 24; h ^= s >> 40;
189 : : s = tab[b >> 28 & 0xF]; l ^= s << 28; h ^= s >> 36;
190 : : s = tab[b >> 32 & 0xF]; l ^= s << 32; h ^= s >> 32;
191 : : s = tab[b >> 36 & 0xF]; l ^= s << 36; h ^= s >> 28;
192 : : s = tab[b >> 40 & 0xF]; l ^= s << 40; h ^= s >> 24;
193 : : s = tab[b >> 44 & 0xF]; l ^= s << 44; h ^= s >> 20;
194 : : s = tab[b >> 48 & 0xF]; l ^= s << 48; h ^= s >> 16;
195 : : s = tab[b >> 52 & 0xF]; l ^= s << 52; h ^= s >> 12;
196 : : s = tab[b >> 56 & 0xF]; l ^= s << 56; h ^= s >> 8;
197 : : s = tab[b >> 60 ]; l ^= s << 60; h ^= s >> 4;
198 : :
199 : : /* compensate for the top three bits of a */
200 : :
201 : : if (top3b & 01) { l ^= b << 61; h ^= b >> 3; }
202 : : if (top3b & 02) { l ^= b << 62; h ^= b >> 2; }
203 : : if (top3b & 04) { l ^= b << 63; h ^= b >> 1; }
204 : :
205 : : *r1 = h; *r0 = l;
206 : : }
207 : : #endif
208 : :
209 : : /* Product of two polynomials a, b each with degree < 2 * BN_BITS2 - 1,
210 : : * result is a polynomial r with degree < 4 * BN_BITS2 - 1
211 : : * The caller MUST ensure that the variables have the right amount
212 : : * of space allocated.
213 : : */
214 : : 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)
215 : : {
216 : : BN_ULONG m1, m0;
217 : : /* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */
218 : : bn_GF2m_mul_1x1(r+3, r+2, a1, b1);
219 : : bn_GF2m_mul_1x1(r+1, r, a0, b0);
220 : : bn_GF2m_mul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1);
221 : : /* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */
222 : : r[2] ^= m1 ^ r[1] ^ r[3]; /* h0 ^= m1 ^ l1 ^ h1; */
223 : : r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0; /* l1 ^= l0 ^ h0 ^ m0; */
224 : : }
225 : : #else
226 : : void bn_GF2m_mul_2x2(BN_ULONG *r, BN_ULONG a1, BN_ULONG a0, BN_ULONG b1, BN_ULONG b0);
227 : : #endif
228 : :
229 : : /* Add polynomials a and b and store result in r; r could be a or b, a and b
230 : : * could be equal; r is the bitwise XOR of a and b.
231 : : */
232 : 1833438 : int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
233 : : {
234 : : int i;
235 : : const BIGNUM *at, *bt;
236 : :
237 : : bn_check_top(a);
238 : : bn_check_top(b);
239 : :
240 [ + + ]: 1833438 : if (a->top < b->top) { at = b; bt = a; }
241 : 1826106 : else { at = a; bt = b; }
242 : :
243 [ + + ][ + - ]: 1833438 : if(bn_wexpand(r, at->top) == NULL)
244 : : return 0;
245 : :
246 [ + + ]: 8625293 : for (i = 0; i < bt->top; i++)
247 : : {
248 : 6791855 : r->d[i] = at->d[i] ^ bt->d[i];
249 : : }
250 [ + + ]: 1926718 : for (; i < at->top; i++)
251 : : {
252 : 93280 : r->d[i] = at->d[i];
253 : : }
254 : :
255 : 1833438 : r->top = at->top;
256 [ + - ][ + + ]: 1848108 : bn_correct_top(r);
[ + + ]
257 : :
258 : : return 1;
259 : : }
260 : :
261 : :
262 : : /* Some functions allow for representation of the irreducible polynomials
263 : : * as an int[], say p. The irreducible f(t) is then of the form:
264 : : * t^p[0] + t^p[1] + ... + t^p[k]
265 : : * where m = p[0] > p[1] > ... > p[k] = 0.
266 : : */
267 : :
268 : :
269 : : /* Performs modular reduction of a and store result in r. r could be a. */
270 : 6906760 : int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[])
271 : : {
272 : : int j, k;
273 : : int n, dN, d0, d1;
274 : : BN_ULONG zz, *z;
275 : :
276 : : bn_check_top(a);
277 : :
278 [ - + ]: 6906760 : if (!p[0])
279 : : {
280 : : /* reduction mod 1 => return 0 */
281 : 0 : BN_zero(r);
282 : 0 : return 1;
283 : : }
284 : :
285 : : /* Since the algorithm does reduction in the r value, if a != r, copy
286 : : * the contents of a into r so we can do reduction in r.
287 : : */
288 [ + - ]: 6906760 : if (a != r)
289 : : {
290 [ + + ][ + - ]: 6906760 : if (!bn_wexpand(r, a->top)) return 0;
291 [ + + ]: 56003082 : for (j = 0; j < a->top; j++)
292 : : {
293 : 49096322 : r->d[j] = a->d[j];
294 : : }
295 : 6906760 : r->top = a->top;
296 : : }
297 : 6906760 : z = r->d;
298 : :
299 : : /* start reduction */
300 : 6906760 : dN = p[0] / BN_BITS2;
301 [ + + ]: 54912071 : for (j = r->top - 1; j > dN;)
302 : : {
303 : 48005311 : zz = z[j];
304 [ + + ]: 48005311 : if (z[j] == 0) { j--; continue; }
305 : 24002629 : z[j] = 0;
306 : :
307 [ + + ]: 86207508 : for (k = 1; p[k] != 0; k++)
308 : : {
309 : : /* reducing component t^p[k] */
310 : 62204879 : n = p[0] - p[k];
311 : 62204879 : d0 = n % BN_BITS2; d1 = BN_BITS2 - d0;
312 : 62204879 : n /= BN_BITS2;
313 : 62204879 : z[j-n] ^= (zz>>d0);
314 [ + + ]: 62204879 : if (d0) z[j-n-1] ^= (zz<<d1);
315 : : }
316 : :
317 : : /* reducing component t^0 */
318 : 24002629 : n = dN;
319 : 24002629 : d0 = p[0] % BN_BITS2;
320 : 24002629 : d1 = BN_BITS2 - d0;
321 : 24002629 : z[j-n] ^= (zz >> d0);
322 [ + - ]: 48005311 : if (d0) z[j-n-1] ^= (zz << d1);
323 : : }
324 : :
325 : : /* final round of reduction */
326 [ + + ]: 13648918 : while (j == dN)
327 : : {
328 : :
329 : 13643836 : d0 = p[0] % BN_BITS2;
330 : 13643836 : zz = z[dN] >> d0;
331 [ + + ]: 13643836 : if (zz == 0) break;
332 : 6742158 : d1 = BN_BITS2 - d0;
333 : :
334 : : /* clear up the top d1 bits */
335 [ + - ]: 6742158 : if (d0)
336 : 6742158 : z[dN] = (z[dN] << d1) >> d1;
337 : : else
338 : 0 : z[dN] = 0;
339 : 6742158 : z[0] ^= zz; /* reduction t^0 component */
340 : :
341 [ + + ]: 31792682 : for (k = 1; p[k] != 0; k++)
342 : : {
343 : : BN_ULONG tmp_ulong;
344 : :
345 : : /* reducing component t^p[k]*/
346 : 18143764 : n = p[k] / BN_BITS2;
347 : 18143764 : d0 = p[k] % BN_BITS2;
348 : 18143764 : d1 = BN_BITS2 - d0;
349 : 18143764 : z[n] ^= (zz << d0);
350 : 18143764 : tmp_ulong = zz >> d1;
351 [ + + ]: 18143764 : if (d0 && tmp_ulong)
352 : 488403 : z[n+1] ^= tmp_ulong;
353 : : }
354 : :
355 : :
356 : : }
357 : :
358 [ + + ][ + + ]: 31079989 : bn_correct_top(r);
[ + + ]
359 : : return 1;
360 : : }
361 : :
362 : : /* Performs modular reduction of a by p and store result in r. r could be a.
363 : : *
364 : : * This function calls down to the BN_GF2m_mod_arr implementation; this wrapper
365 : : * function is only provided for convenience; for best performance, use the
366 : : * BN_GF2m_mod_arr function.
367 : : */
368 : 16030 : int BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p)
369 : : {
370 : 16030 : int ret = 0;
371 : : int arr[6];
372 : : bn_check_top(a);
373 : : bn_check_top(p);
374 : 16030 : ret = BN_GF2m_poly2arr(p, arr, sizeof(arr)/sizeof(arr[0]));
375 [ - + ]: 16030 : if (!ret || ret > (int)(sizeof(arr)/sizeof(arr[0])))
376 : : {
377 : 0 : BNerr(BN_F_BN_GF2M_MOD,BN_R_INVALID_LENGTH);
378 : 0 : return 0;
379 : : }
380 : 16030 : ret = BN_GF2m_mod_arr(r, a, arr);
381 : : bn_check_top(r);
382 : 16030 : return ret;
383 : : }
384 : :
385 : :
386 : : /* Compute the product of two polynomials a and b, reduce modulo p, and store
387 : : * the result in r. r could be a or b; a could be b.
388 : : */
389 : 3634044 : int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p[], BN_CTX *ctx)
390 : : {
391 : 3634044 : int zlen, i, j, k, ret = 0;
392 : : BIGNUM *s;
393 : : BN_ULONG x1, x0, y1, y0, zz[4];
394 : :
395 : : bn_check_top(a);
396 : : bn_check_top(b);
397 : :
398 [ - + ]: 3634044 : if (a == b)
399 : : {
400 : 0 : return BN_GF2m_mod_sqr_arr(r, a, p, ctx);
401 : : }
402 : :
403 : 3634044 : BN_CTX_start(ctx);
404 [ + - ]: 3634044 : if ((s = BN_CTX_get(ctx)) == NULL) goto err;
405 : :
406 : 3634044 : zlen = a->top + b->top + 4;
407 [ + + ][ + - ]: 3634044 : if (!bn_wexpand(s, zlen)) goto err;
408 : 3634044 : s->top = zlen;
409 : :
410 [ + + ]: 45007765 : for (i = 0; i < zlen; i++) s->d[i] = 0;
411 : :
412 [ + + ]: 12165250 : for (j = 0; j < b->top; j += 2)
413 : : {
414 : 8531206 : y0 = b->d[j];
415 [ + + ]: 8531206 : y1 = ((j+1) == b->top) ? 0 : b->d[j+1];
416 [ + + ]: 29343980 : for (i = 0; i < a->top; i += 2)
417 : : {
418 : 20812774 : x0 = a->d[i];
419 [ + + ]: 20812774 : x1 = ((i+1) == a->top) ? 0 : a->d[i+1];
420 : 20812774 : bn_GF2m_mul_2x2(zz, x1, x0, y1, y0);
421 [ + + ]: 104063870 : for (k = 0; k < 4; k++) s->d[i+j+k] ^= zz[k];
422 : : }
423 : : }
424 : :
425 [ + - ][ + + ]: 18754830 : bn_correct_top(s);
[ + + ]
426 [ + - ]: 3634044 : if (BN_GF2m_mod_arr(r, s, p))
427 : 3634044 : ret = 1;
428 : : bn_check_top(r);
429 : :
430 : : err:
431 : 3634044 : BN_CTX_end(ctx);
432 : 3634044 : return ret;
433 : : }
434 : :
435 : : /* Compute the product of two polynomials a and b, reduce modulo p, and store
436 : : * the result in r. r could be a or b; a could equal b.
437 : : *
438 : : * This function calls down to the BN_GF2m_mod_mul_arr implementation; this wrapper
439 : : * function is only provided for convenience; for best performance, use the
440 : : * BN_GF2m_mod_mul_arr function.
441 : : */
442 : 16526 : int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx)
443 : : {
444 : 16526 : int ret = 0;
445 : 16526 : const int max = BN_num_bits(p) + 1;
446 : 16526 : int *arr=NULL;
447 : : bn_check_top(a);
448 : : bn_check_top(b);
449 : : bn_check_top(p);
450 [ + - ]: 16526 : if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
451 : 16526 : ret = BN_GF2m_poly2arr(p, arr, max);
452 [ - + ]: 16526 : if (!ret || ret > max)
453 : : {
454 : 0 : BNerr(BN_F_BN_GF2M_MOD_MUL,BN_R_INVALID_LENGTH);
455 : 0 : goto err;
456 : : }
457 : 16526 : ret = BN_GF2m_mod_mul_arr(r, a, b, arr, ctx);
458 : : bn_check_top(r);
459 : : err:
460 [ + - ]: 16526 : if (arr) OPENSSL_free(arr);
461 : 16526 : return ret;
462 : : }
463 : :
464 : :
465 : : /* Square a, reduce the result mod p, and store it in a. r could be a. */
466 : 3249483 : int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[], BN_CTX *ctx)
467 : : {
468 : 3249483 : int i, ret = 0;
469 : : BIGNUM *s;
470 : :
471 : : bn_check_top(a);
472 : 3249483 : BN_CTX_start(ctx);
473 [ + - ]: 3249483 : if ((s = BN_CTX_get(ctx)) == NULL) return 0;
474 [ + + ][ + - ]: 3249483 : if (!bn_wexpand(s, 2 * a->top)) goto err;
475 : :
476 [ + + ]: 14903317 : for (i = a->top - 1; i >= 0; i--)
477 : : {
478 : 11653834 : s->d[2*i+1] = SQR1(a->d[i]);
479 : 11653834 : s->d[2*i ] = SQR0(a->d[i]);
480 : : }
481 : :
482 : 3249483 : s->top = 2 * a->top;
483 [ + + ][ + + ]: 3840724 : bn_correct_top(s);
[ + - ]
484 [ + - ]: 3249483 : if (!BN_GF2m_mod_arr(r, s, p)) goto err;
485 : : bn_check_top(r);
486 : 3249483 : ret = 1;
487 : : err:
488 : 3249483 : BN_CTX_end(ctx);
489 : 3249483 : return ret;
490 : : }
491 : :
492 : : /* Square a, reduce the result mod p, and store it in a. r could be a.
493 : : *
494 : : * This function calls down to the BN_GF2m_mod_sqr_arr implementation; this wrapper
495 : : * function is only provided for convenience; for best performance, use the
496 : : * BN_GF2m_mod_sqr_arr function.
497 : : */
498 : 504 : int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
499 : : {
500 : 504 : int ret = 0;
501 : 504 : const int max = BN_num_bits(p) + 1;
502 : 504 : int *arr=NULL;
503 : :
504 : : bn_check_top(a);
505 : : bn_check_top(p);
506 [ + - ]: 504 : if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
507 : 504 : ret = BN_GF2m_poly2arr(p, arr, max);
508 [ - + ]: 504 : if (!ret || ret > max)
509 : : {
510 : 0 : BNerr(BN_F_BN_GF2M_MOD_SQR,BN_R_INVALID_LENGTH);
511 : 0 : goto err;
512 : : }
513 : 504 : ret = BN_GF2m_mod_sqr_arr(r, a, arr, ctx);
514 : : bn_check_top(r);
515 : : err:
516 [ + - ]: 504 : if (arr) OPENSSL_free(arr);
517 : 504 : return ret;
518 : : }
519 : :
520 : :
521 : : /* Invert a, reduce modulo p, and store the result in r. r could be a.
522 : : * Uses Modified Almost Inverse Algorithm (Algorithm 10) from
523 : : * Hankerson, D., Hernandez, J.L., and Menezes, A. "Software Implementation
524 : : * of Elliptic Curve Cryptography Over Binary Fields".
525 : : */
526 : 15326 : int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
527 : : {
528 : 15326 : BIGNUM *b, *c = NULL, *u = NULL, *v = NULL, *tmp;
529 : 15326 : int ret = 0;
530 : :
531 : : bn_check_top(a);
532 : : bn_check_top(p);
533 : :
534 : 15326 : BN_CTX_start(ctx);
535 : :
536 [ + - ]: 15326 : if ((b = BN_CTX_get(ctx))==NULL) goto err;
537 [ + - ]: 15326 : if ((c = BN_CTX_get(ctx))==NULL) goto err;
538 [ + - ]: 15326 : if ((u = BN_CTX_get(ctx))==NULL) goto err;
539 [ + - ]: 15326 : if ((v = BN_CTX_get(ctx))==NULL) goto err;
540 : :
541 [ + - ]: 15326 : if (!BN_GF2m_mod(u, a, p)) goto err;
542 [ + - ]: 15326 : if (BN_is_zero(u)) goto err;
543 : :
544 [ + - ]: 15326 : if (!BN_copy(v, p)) goto err;
545 : : #if 0
546 : : if (!BN_one(b)) goto err;
547 : :
548 : : while (1)
549 : : {
550 : : while (!BN_is_odd(u))
551 : : {
552 : : if (BN_is_zero(u)) goto err;
553 : : if (!BN_rshift1(u, u)) goto err;
554 : : if (BN_is_odd(b))
555 : : {
556 : : if (!BN_GF2m_add(b, b, p)) goto err;
557 : : }
558 : : if (!BN_rshift1(b, b)) goto err;
559 : : }
560 : :
561 : : if (BN_abs_is_word(u, 1)) break;
562 : :
563 : : if (BN_num_bits(u) < BN_num_bits(v))
564 : : {
565 : : tmp = u; u = v; v = tmp;
566 : : tmp = b; b = c; c = tmp;
567 : : }
568 : :
569 : : if (!BN_GF2m_add(u, u, v)) goto err;
570 : : if (!BN_GF2m_add(b, b, c)) goto err;
571 : : }
572 : : #else
573 : : {
574 : 15326 : int i, ubits = BN_num_bits(u),
575 : 15326 : vbits = BN_num_bits(v), /* v is copy of p */
576 : 15326 : top = p->top;
577 : : BN_ULONG *udp,*bdp,*vdp,*cdp;
578 : :
579 [ + + ]: 15326 : bn_wexpand(u,top); udp = u->d;
580 [ + + ]: 15494 : for (i=u->top;i<top;i++) udp[i] = 0;
581 : 15326 : u->top = top;
582 [ + + ]: 15326 : bn_wexpand(b,top); bdp = b->d;
583 : 15326 : bdp[0] = 1;
584 [ + + ]: 91678 : for (i=1;i<top;i++) bdp[i] = 0;
585 : 15326 : b->top = top;
586 [ + + ]: 15326 : bn_wexpand(c,top); cdp = c->d;
587 [ + + ]: 107004 : for (i=0;i<top;i++) cdp[i] = 0;
588 : 15326 : c->top = top;
589 : 15326 : vdp = v->d; /* It pays off to "cache" *->d pointers, because
590 : : * it allows optimizer to be more aggressive.
591 : : * But we don't have to "cache" p->d, because *p
592 : : * is declared 'const'... */
593 : : while (1)
594 : : {
595 [ + - ][ + + ]: 13682911 : while (ubits && !(udp[0]&1))
596 : : {
597 : : BN_ULONG u0,u1,b0,b1,mask;
598 : :
599 : 9116439 : u0 = udp[0];
600 : 9116439 : b0 = bdp[0];
601 : 9116439 : mask = (BN_ULONG)0-(b0&1);
602 : 9116439 : b0 ^= p->d[0]&mask;
603 [ + + ]: 65001217 : for (i=0;i<top-1;i++)
604 : : {
605 : 55884778 : u1 = udp[i+1];
606 : 55884778 : udp[i] = ((u0>>1)|(u1<<(BN_BITS2-1)))&BN_MASK2;
607 : 55884778 : u0 = u1;
608 : 55884778 : b1 = bdp[i+1]^(p->d[i+1]&mask);
609 : 55884778 : bdp[i] = ((b0>>1)|(b1<<(BN_BITS2-1)))&BN_MASK2;
610 : 55884778 : b0 = b1;
611 : : }
612 : 9116439 : udp[i] = u0>>1;
613 : 9116439 : bdp[i] = b0>>1;
614 : 13667585 : ubits--;
615 : : }
616 : :
617 [ + + ][ + + ]: 4566472 : if (ubits<=BN_BITS2 && udp[0]==1) break;
618 : :
619 [ + + ]: 4551146 : if (ubits<vbits)
620 : : {
621 : 1825217 : i = ubits; ubits = vbits; vbits = i;
622 : 1825217 : tmp = u; u = v; v = tmp;
623 : 1825217 : tmp = b; b = c; c = tmp;
624 : 1825217 : udp = vdp; vdp = v->d;
625 : 1825217 : bdp = cdp; cdp = c->d;
626 : : }
627 [ + + ]: 37003985 : for(i=0;i<top;i++)
628 : : {
629 : 32452839 : udp[i] ^= vdp[i];
630 : 32452839 : bdp[i] ^= cdp[i];
631 : : }
632 [ + + ]: 4551146 : if (ubits==vbits)
633 : : {
634 : : BN_ULONG ul;
635 : 908402 : int utop = (ubits-1)/BN_BITS2;
636 : :
637 [ + + ][ + - ]: 933688 : while ((ul=udp[utop])==0 && utop) utop--;
638 : 908402 : ubits = utop*BN_BITS2 + BN_num_bits_word(ul);
639 : : }
640 : : }
641 [ + - ][ + + ]: 15486 : bn_correct_top(b);
[ + - ]
642 : : }
643 : : #endif
644 : :
645 [ + - ]: 15326 : if (!BN_copy(r, b)) goto err;
646 : : bn_check_top(r);
647 : 15326 : ret = 1;
648 : :
649 : : err:
650 : : #ifdef BN_DEBUG /* BN_CTX_end would complain about the expanded form */
651 : : bn_correct_top(c);
652 : : bn_correct_top(u);
653 : : bn_correct_top(v);
654 : : #endif
655 : 15326 : BN_CTX_end(ctx);
656 : 15326 : return ret;
657 : : }
658 : :
659 : : /* Invert xx, reduce modulo p, and store the result in r. r could be xx.
660 : : *
661 : : * This function calls down to the BN_GF2m_mod_inv implementation; this wrapper
662 : : * function is only provided for convenience; for best performance, use the
663 : : * BN_GF2m_mod_inv function.
664 : : */
665 : 0 : int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *xx, const int p[], BN_CTX *ctx)
666 : : {
667 : : BIGNUM *field;
668 : 0 : int ret = 0;
669 : :
670 : : bn_check_top(xx);
671 : 0 : BN_CTX_start(ctx);
672 [ # # ]: 0 : if ((field = BN_CTX_get(ctx)) == NULL) goto err;
673 [ # # ]: 0 : if (!BN_GF2m_arr2poly(p, field)) goto err;
674 : :
675 : 0 : ret = BN_GF2m_mod_inv(r, xx, field, ctx);
676 : : bn_check_top(r);
677 : :
678 : : err:
679 : 0 : BN_CTX_end(ctx);
680 : 0 : return ret;
681 : : }
682 : :
683 : :
684 : : #ifndef OPENSSL_SUN_GF2M_DIV
685 : : /* Divide y by x, reduce modulo p, and store the result in r. r could be x
686 : : * or y, x could equal y.
687 : : */
688 : 15126 : int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p, BN_CTX *ctx)
689 : : {
690 : 15126 : BIGNUM *xinv = NULL;
691 : 15126 : int ret = 0;
692 : :
693 : : bn_check_top(y);
694 : : bn_check_top(x);
695 : : bn_check_top(p);
696 : :
697 : 15126 : BN_CTX_start(ctx);
698 : 15126 : xinv = BN_CTX_get(ctx);
699 [ + - ]: 15126 : if (xinv == NULL) goto err;
700 : :
701 [ + - ]: 15126 : if (!BN_GF2m_mod_inv(xinv, x, p, ctx)) goto err;
702 [ + - ]: 15126 : if (!BN_GF2m_mod_mul(r, y, xinv, p, ctx)) goto err;
703 : : bn_check_top(r);
704 : 15126 : ret = 1;
705 : :
706 : : err:
707 : 15126 : BN_CTX_end(ctx);
708 : 15126 : return ret;
709 : : }
710 : : #else
711 : : /* Divide y by x, reduce modulo p, and store the result in r. r could be x
712 : : * or y, x could equal y.
713 : : * Uses algorithm Modular_Division_GF(2^m) from
714 : : * Chang-Shantz, S. "From Euclid's GCD to Montgomery Multiplication to
715 : : * the Great Divide".
716 : : */
717 : : int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p, BN_CTX *ctx)
718 : : {
719 : : BIGNUM *a, *b, *u, *v;
720 : : int ret = 0;
721 : :
722 : : bn_check_top(y);
723 : : bn_check_top(x);
724 : : bn_check_top(p);
725 : :
726 : : BN_CTX_start(ctx);
727 : :
728 : : a = BN_CTX_get(ctx);
729 : : b = BN_CTX_get(ctx);
730 : : u = BN_CTX_get(ctx);
731 : : v = BN_CTX_get(ctx);
732 : : if (v == NULL) goto err;
733 : :
734 : : /* reduce x and y mod p */
735 : : if (!BN_GF2m_mod(u, y, p)) goto err;
736 : : if (!BN_GF2m_mod(a, x, p)) goto err;
737 : : if (!BN_copy(b, p)) goto err;
738 : :
739 : : while (!BN_is_odd(a))
740 : : {
741 : : if (!BN_rshift1(a, a)) goto err;
742 : : if (BN_is_odd(u)) if (!BN_GF2m_add(u, u, p)) goto err;
743 : : if (!BN_rshift1(u, u)) goto err;
744 : : }
745 : :
746 : : do
747 : : {
748 : : if (BN_GF2m_cmp(b, a) > 0)
749 : : {
750 : : if (!BN_GF2m_add(b, b, a)) goto err;
751 : : if (!BN_GF2m_add(v, v, u)) goto err;
752 : : do
753 : : {
754 : : if (!BN_rshift1(b, b)) goto err;
755 : : if (BN_is_odd(v)) if (!BN_GF2m_add(v, v, p)) goto err;
756 : : if (!BN_rshift1(v, v)) goto err;
757 : : } while (!BN_is_odd(b));
758 : : }
759 : : else if (BN_abs_is_word(a, 1))
760 : : break;
761 : : else
762 : : {
763 : : if (!BN_GF2m_add(a, a, b)) goto err;
764 : : if (!BN_GF2m_add(u, u, v)) goto err;
765 : : do
766 : : {
767 : : if (!BN_rshift1(a, a)) goto err;
768 : : if (BN_is_odd(u)) if (!BN_GF2m_add(u, u, p)) goto err;
769 : : if (!BN_rshift1(u, u)) goto err;
770 : : } while (!BN_is_odd(a));
771 : : }
772 : : } while (1);
773 : :
774 : : if (!BN_copy(r, u)) goto err;
775 : : bn_check_top(r);
776 : : ret = 1;
777 : :
778 : : err:
779 : : BN_CTX_end(ctx);
780 : : return ret;
781 : : }
782 : : #endif
783 : :
784 : : /* Divide yy by xx, reduce modulo p, and store the result in r. r could be xx
785 : : * or yy, xx could equal yy.
786 : : *
787 : : * This function calls down to the BN_GF2m_mod_div implementation; this wrapper
788 : : * function is only provided for convenience; for best performance, use the
789 : : * BN_GF2m_mod_div function.
790 : : */
791 : 0 : int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *yy, const BIGNUM *xx, const int p[], BN_CTX *ctx)
792 : : {
793 : : BIGNUM *field;
794 : 0 : int ret = 0;
795 : :
796 : : bn_check_top(yy);
797 : : bn_check_top(xx);
798 : :
799 : 0 : BN_CTX_start(ctx);
800 [ # # ]: 0 : if ((field = BN_CTX_get(ctx)) == NULL) goto err;
801 [ # # ]: 0 : if (!BN_GF2m_arr2poly(p, field)) goto err;
802 : :
803 : 0 : ret = BN_GF2m_mod_div(r, yy, xx, field, ctx);
804 : : bn_check_top(r);
805 : :
806 : : err:
807 : 0 : BN_CTX_end(ctx);
808 : 0 : return ret;
809 : : }
810 : :
811 : :
812 : : /* Compute the bth power of a, reduce modulo p, and store
813 : : * the result in r. r could be a.
814 : : * Uses simple square-and-multiply algorithm A.5.1 from IEEE P1363.
815 : : */
816 : 800 : int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p[], BN_CTX *ctx)
817 : : {
818 : 800 : int ret = 0, i, n;
819 : : BIGNUM *u;
820 : :
821 : : bn_check_top(a);
822 : : bn_check_top(b);
823 : :
824 [ - + ]: 800 : if (BN_is_zero(b))
825 : 0 : return(BN_one(r));
826 : :
827 [ - + ][ # # ]: 800 : if (BN_abs_is_word(b, 1))
828 : 0 : return (BN_copy(r, a) != NULL);
829 : :
830 : 800 : BN_CTX_start(ctx);
831 [ + - ]: 800 : if ((u = BN_CTX_get(ctx)) == NULL) goto err;
832 : :
833 [ + - ]: 800 : if (!BN_GF2m_mod_arr(u, a, p)) goto err;
834 : :
835 : 800 : n = BN_num_bits(b) - 1;
836 [ + + ]: 343000 : for (i = n - 1; i >= 0; i--)
837 : : {
838 [ + - ]: 342200 : if (!BN_GF2m_mod_sqr_arr(u, u, p, ctx)) goto err;
839 [ + + ]: 342200 : if (BN_is_bit_set(b, i))
840 : : {
841 [ + - ]: 153868 : if (!BN_GF2m_mod_mul_arr(u, u, a, p, ctx)) goto err;
842 : : }
843 : : }
844 [ + - ]: 800 : if (!BN_copy(r, u)) goto err;
845 : : bn_check_top(r);
846 : 800 : ret = 1;
847 : : err:
848 : 800 : BN_CTX_end(ctx);
849 : 800 : return ret;
850 : : }
851 : :
852 : : /* Compute the bth power of a, reduce modulo p, and store
853 : : * the result in r. r could be a.
854 : : *
855 : : * This function calls down to the BN_GF2m_mod_exp_arr implementation; this wrapper
856 : : * function is only provided for convenience; for best performance, use the
857 : : * BN_GF2m_mod_exp_arr function.
858 : : */
859 : 600 : int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx)
860 : : {
861 : 600 : int ret = 0;
862 : 600 : const int max = BN_num_bits(p) + 1;
863 : 600 : int *arr=NULL;
864 : : bn_check_top(a);
865 : : bn_check_top(b);
866 : : bn_check_top(p);
867 [ + - ]: 600 : if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
868 : 600 : ret = BN_GF2m_poly2arr(p, arr, max);
869 [ - + ]: 600 : if (!ret || ret > max)
870 : : {
871 : 0 : BNerr(BN_F_BN_GF2M_MOD_EXP,BN_R_INVALID_LENGTH);
872 : 0 : goto err;
873 : : }
874 : 600 : ret = BN_GF2m_mod_exp_arr(r, a, b, arr, ctx);
875 : : bn_check_top(r);
876 : : err:
877 [ + - ]: 600 : if (arr) OPENSSL_free(arr);
878 : 600 : return ret;
879 : : }
880 : :
881 : : /* Compute the square root of a, reduce modulo p, and store
882 : : * the result in r. r could be a.
883 : : * Uses exponentiation as in algorithm A.4.1 from IEEE P1363.
884 : : */
885 : 200 : int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, const int p[], BN_CTX *ctx)
886 : : {
887 : 200 : int ret = 0;
888 : : BIGNUM *u;
889 : :
890 : : bn_check_top(a);
891 : :
892 [ - + ]: 200 : if (!p[0])
893 : : {
894 : : /* reduction mod 1 => return 0 */
895 : 0 : BN_zero(r);
896 : 0 : return 1;
897 : : }
898 : :
899 : 200 : BN_CTX_start(ctx);
900 [ + - ]: 200 : if ((u = BN_CTX_get(ctx)) == NULL) goto err;
901 : :
902 [ + - ]: 200 : if (!BN_set_bit(u, p[0] - 1)) goto err;
903 : 200 : ret = BN_GF2m_mod_exp_arr(r, a, u, p, ctx);
904 : : bn_check_top(r);
905 : :
906 : : err:
907 : 200 : BN_CTX_end(ctx);
908 : 200 : return ret;
909 : : }
910 : :
911 : : /* Compute the square root of a, reduce modulo p, and store
912 : : * the result in r. r could be a.
913 : : *
914 : : * This function calls down to the BN_GF2m_mod_sqrt_arr implementation; this wrapper
915 : : * function is only provided for convenience; for best performance, use the
916 : : * BN_GF2m_mod_sqrt_arr function.
917 : : */
918 : 200 : int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
919 : : {
920 : 200 : int ret = 0;
921 : 200 : const int max = BN_num_bits(p) + 1;
922 : 200 : int *arr=NULL;
923 : : bn_check_top(a);
924 : : bn_check_top(p);
925 [ + - ]: 200 : if ((arr = (int *)OPENSSL_malloc(sizeof(int) * max)) == NULL) goto err;
926 : 200 : ret = BN_GF2m_poly2arr(p, arr, max);
927 [ - + ]: 200 : if (!ret || ret > max)
928 : : {
929 : 0 : BNerr(BN_F_BN_GF2M_MOD_SQRT,BN_R_INVALID_LENGTH);
930 : 0 : goto err;
931 : : }
932 : 200 : ret = BN_GF2m_mod_sqrt_arr(r, a, arr, ctx);
933 : : bn_check_top(r);
934 : : err:
935 [ + - ]: 200 : if (arr) OPENSSL_free(arr);
936 : 200 : return ret;
937 : : }
938 : :
939 : : /* Find r such that r^2 + r = a mod p. r could be a. If no r exists returns 0.
940 : : * Uses algorithms A.4.7 and A.4.6 from IEEE P1363.
941 : : */
942 : 200 : int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[], BN_CTX *ctx)
943 : : {
944 : 200 : int ret = 0, count = 0, j;
945 : : BIGNUM *a, *z, *rho, *w, *w2, *tmp;
946 : :
947 : : bn_check_top(a_);
948 : :
949 [ - + ]: 200 : if (!p[0])
950 : : {
951 : : /* reduction mod 1 => return 0 */
952 : 0 : BN_zero(r);
953 : 0 : return 1;
954 : : }
955 : :
956 : 200 : BN_CTX_start(ctx);
957 : 200 : a = BN_CTX_get(ctx);
958 : 200 : z = BN_CTX_get(ctx);
959 : 200 : w = BN_CTX_get(ctx);
960 [ + - ]: 200 : if (w == NULL) goto err;
961 : :
962 [ + - ]: 200 : if (!BN_GF2m_mod_arr(a, a_, p)) goto err;
963 : :
964 [ - + ]: 200 : if (BN_is_zero(a))
965 : : {
966 : 0 : BN_zero(r);
967 : 0 : ret = 1;
968 : 0 : goto err;
969 : : }
970 : :
971 [ + - ]: 200 : if (p[0] & 0x1) /* m is odd */
972 : : {
973 : : /* compute half-trace of a */
974 [ + - ]: 200 : if (!BN_copy(z, a)) goto err;
975 [ + + ]: 17900 : for (j = 1; j <= (p[0] - 1) / 2; j++)
976 : : {
977 [ + - ]: 17700 : if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err;
978 [ + - ]: 17700 : if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err;
979 [ + - ]: 17700 : if (!BN_GF2m_add(z, z, a)) goto err;
980 : : }
981 : :
982 : : }
983 : : else /* m is even */
984 : : {
985 : 0 : rho = BN_CTX_get(ctx);
986 : 0 : w2 = BN_CTX_get(ctx);
987 : 0 : tmp = BN_CTX_get(ctx);
988 [ # # ]: 0 : if (tmp == NULL) goto err;
989 : : do
990 : : {
991 [ # # ]: 0 : if (!BN_rand(rho, p[0], 0, 0)) goto err;
992 [ # # ]: 0 : if (!BN_GF2m_mod_arr(rho, rho, p)) goto err;
993 : 0 : BN_zero(z);
994 [ # # ]: 0 : if (!BN_copy(w, rho)) goto err;
995 [ # # ]: 0 : for (j = 1; j <= p[0] - 1; j++)
996 : : {
997 [ # # ]: 0 : if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) goto err;
998 [ # # ]: 0 : if (!BN_GF2m_mod_sqr_arr(w2, w, p, ctx)) goto err;
999 [ # # ]: 0 : if (!BN_GF2m_mod_mul_arr(tmp, w2, a, p, ctx)) goto err;
1000 [ # # ]: 0 : if (!BN_GF2m_add(z, z, tmp)) goto err;
1001 [ # # ]: 0 : if (!BN_GF2m_add(w, w2, rho)) goto err;
1002 : : }
1003 : 0 : count++;
1004 [ # # ][ # # ]: 0 : } while (BN_is_zero(w) && (count < MAX_ITERATIONS));
1005 [ # # ]: 0 : if (BN_is_zero(w))
1006 : : {
1007 : 0 : BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR,BN_R_TOO_MANY_ITERATIONS);
1008 : 0 : goto err;
1009 : : }
1010 : : }
1011 : :
1012 [ + - ]: 200 : if (!BN_GF2m_mod_sqr_arr(w, z, p, ctx)) goto err;
1013 [ + - ]: 200 : if (!BN_GF2m_add(w, z, w)) goto err;
1014 [ + + ]: 200 : if (BN_GF2m_cmp(w, a))
1015 : : {
1016 : 96 : BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_NO_SOLUTION);
1017 : 96 : goto err;
1018 : : }
1019 : :
1020 [ + - ]: 104 : if (!BN_copy(r, z)) goto err;
1021 : : bn_check_top(r);
1022 : :
1023 : 104 : ret = 1;
1024 : :
1025 : : err:
1026 : 200 : BN_CTX_end(ctx);
1027 : 200 : return ret;
1028 : : }
1029 : :
1030 : : /* Find r such that r^2 + r = a mod p. r could be a. If no r exists returns 0.
1031 : : *
1032 : : * This function calls down to the BN_GF2m_mod_solve_quad_arr implementation; this wrapper
1033 : : * function is only provided for convenience; for best performance, use the
1034 : : * BN_GF2m_mod_solve_quad_arr function.
1035 : : */
1036 : 200 : int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
1037 : : {
1038 : 200 : int ret = 0;
1039 : 200 : const int max = BN_num_bits(p) + 1;
1040 : 200 : int *arr=NULL;
1041 : : bn_check_top(a);
1042 : : bn_check_top(p);
1043 [ + - ]: 200 : if ((arr = (int *)OPENSSL_malloc(sizeof(int) *
1044 : : max)) == NULL) goto err;
1045 : 200 : ret = BN_GF2m_poly2arr(p, arr, max);
1046 [ - + ]: 200 : if (!ret || ret > max)
1047 : : {
1048 : 0 : BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD,BN_R_INVALID_LENGTH);
1049 : 0 : goto err;
1050 : : }
1051 : 200 : ret = BN_GF2m_mod_solve_quad_arr(r, a, arr, ctx);
1052 : : bn_check_top(r);
1053 : : err:
1054 [ + - ]: 200 : if (arr) OPENSSL_free(arr);
1055 : 200 : return ret;
1056 : : }
1057 : :
1058 : : /* Convert the bit-string representation of a polynomial
1059 : : * ( \sum_{i=0}^n a_i * x^i) into an array of integers corresponding
1060 : : * to the bits with non-zero coefficient. Array is terminated with -1.
1061 : : * Up to max elements of the array will be filled. Return value is total
1062 : : * number of array elements that would be filled if array was large enough.
1063 : : */
1064 : 35545 : int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max)
1065 : : {
1066 : 35545 : int i, j, k = 0;
1067 : : BN_ULONG mask;
1068 : :
1069 [ + - ]: 35545 : if (BN_is_zero(a))
1070 : : return 0;
1071 : :
1072 [ + + ]: 235504 : for (i = a->top - 1; i >= 0; i--)
1073 : : {
1074 [ + + ]: 199959 : if (!a->d[i])
1075 : : /* skip word if a->d[i] == 0 */
1076 : 120490 : continue;
1077 : : mask = BN_TBIT;
1078 [ + + ]: 5165485 : for (j = BN_BITS2 - 1; j >= 0; j--)
1079 : : {
1080 [ + + ]: 5086016 : if (a->d[i] & mask)
1081 : : {
1082 [ + - ]: 155751 : if (k < max) p[k] = BN_BITS2 * i + j;
1083 : 155751 : k++;
1084 : : }
1085 : 5086016 : mask >>= 1;
1086 : : }
1087 : : }
1088 : :
1089 [ + - ]: 35545 : if (k < max) {
1090 : 35545 : p[k] = -1;
1091 : 35545 : k++;
1092 : : }
1093 : :
1094 : 35545 : return k;
1095 : : }
1096 : :
1097 : : /* Convert the coefficient array representation of a polynomial to a
1098 : : * bit-string. The array must be terminated by -1.
1099 : : */
1100 : 16 : int BN_GF2m_arr2poly(const int p[], BIGNUM *a)
1101 : : {
1102 : : int i;
1103 : :
1104 : : bn_check_top(a);
1105 : 16 : BN_zero(a);
1106 [ + + ]: 80 : for (i = 0; p[i] != -1; i++)
1107 : : {
1108 [ + - ]: 64 : if (BN_set_bit(a, p[i]) == 0)
1109 : : return 0;
1110 : : }
1111 : : bn_check_top(a);
1112 : :
1113 : : return 1;
1114 : : }
1115 : :
1116 : : #endif
|