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