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