Coverage Report

Created: 2022-08-24 06:30

/src/libressl/crypto/bn/bn_gf2m.c
Line
Count
Source (jump to first uncovered line)
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
0
#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
0
    SQR_tb[(w) >> 60 & 0xF] << 56 | SQR_tb[(w) >> 56 & 0xF] << 48 | \
112
0
    SQR_tb[(w) >> 52 & 0xF] << 40 | SQR_tb[(w) >> 48 & 0xF] << 32 | \
113
0
    SQR_tb[(w) >> 44 & 0xF] << 24 | SQR_tb[(w) >> 40 & 0xF] << 16 | \
114
0
    SQR_tb[(w) >> 36 & 0xF] <<  8 | SQR_tb[(w) >> 32 & 0xF]
115
#define SQR0(w) \
116
0
    SQR_tb[(w) >> 28 & 0xF] << 56 | SQR_tb[(w) >> 24 & 0xF] << 48 | \
117
0
    SQR_tb[(w) >> 20 & 0xF] << 40 | SQR_tb[(w) >> 16 & 0xF] << 32 | \
118
0
    SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >>  8 & 0xF] << 16 | \
119
0
    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
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
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
323
BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
324
0
{
325
0
  int i;
326
0
  const BIGNUM *at, *bt;
327
328
0
  bn_check_top(a);
329
0
  bn_check_top(b);
330
331
0
  if (a->top < b->top) {
332
0
    at = b;
333
0
    bt = a;
334
0
  } else {
335
0
    at = a;
336
0
    bt = b;
337
0
  }
338
339
0
  if (bn_wexpand(r, at->top) == NULL)
340
0
    return 0;
341
342
0
  for (i = 0; i < bt->top; i++) {
343
0
    r->d[i] = at->d[i] ^ bt->d[i];
344
0
  }
345
0
  for (; i < at->top; i++) {
346
0
    r->d[i] = at->d[i];
347
0
  }
348
349
0
  r->top = at->top;
350
0
  bn_correct_top(r);
351
352
0
  return 1;
353
0
}
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
365
BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[])
366
0
{
367
0
  int j, k;
368
0
  int n, dN, d0, d1;
369
0
  BN_ULONG zz, *z;
370
371
0
  bn_check_top(a);
372
373
0
  if (!p[0]) {
374
    /* reduction mod 1 => return 0 */
375
0
    BN_zero(r);
376
0
    return 1;
377
0
  }
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
0
  if (a != r) {
383
0
    if (!bn_wexpand(r, a->top))
384
0
      return 0;
385
0
    for (j = 0; j < a->top; j++) {
386
0
      r->d[j] = a->d[j];
387
0
    }
388
0
    r->top = a->top;
389
0
  }
390
0
  z = r->d;
391
392
  /* start reduction */
393
0
  dN = p[0] / BN_BITS2;
394
0
  for (j = r->top - 1; j > dN; ) {
395
0
    zz = z[j];
396
0
    if (z[j] == 0) {
397
0
      j--;
398
0
      continue;
399
0
    }
400
0
    z[j] = 0;
401
402
0
    for (k = 1; p[k] != 0; k++) {
403
      /* reducing component t^p[k] */
404
0
      n = p[0] - p[k];
405
0
      d0 = n % BN_BITS2;
406
0
      d1 = BN_BITS2 - d0;
407
0
      n /= BN_BITS2;
408
0
      z[j - n] ^= (zz >> d0);
409
0
      if (d0)
410
0
        z[j - n - 1] ^= (zz << d1);
411
0
    }
412
413
    /* reducing component t^0 */
414
0
    n = dN;
415
0
    d0 = p[0] % BN_BITS2;
416
0
    d1 = BN_BITS2 - d0;
417
0
    z[j - n] ^= (zz >> d0);
418
0
    if (d0)
419
0
      z[j - n - 1] ^= (zz << d1);
420
0
  }
421
422
  /* final round of reduction */
423
0
  while (j == dN) {
424
425
0
    d0 = p[0] % BN_BITS2;
426
0
    zz = z[dN] >> d0;
427
0
    if (zz == 0)
428
0
      break;
429
0
    d1 = BN_BITS2 - d0;
430
431
    /* clear up the top d1 bits */
432
0
    if (d0)
433
0
      z[dN] = (z[dN] << d1) >> d1;
434
0
    else
435
0
      z[dN] = 0;
436
0
    z[0] ^= zz; /* reduction t^0 component */
437
438
0
    for (k = 1; p[k] != 0; k++) {
439
0
      BN_ULONG tmp_ulong;
440
441
      /* reducing component t^p[k]*/
442
0
      n = p[k] / BN_BITS2;
443
0
      d0 = p[k] % BN_BITS2;
444
0
      d1 = BN_BITS2 - d0;
445
0
      z[n] ^= (zz << d0);
446
0
      if (d0 && (tmp_ulong = zz >> d1))
447
0
        z[n + 1] ^= tmp_ulong;
448
0
    }
449
450
451
0
  }
452
453
0
  bn_correct_top(r);
454
0
  return 1;
455
0
}
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
464
BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p)
465
0
{
466
0
  int ret = 0;
467
0
  int arr[6];
468
469
0
  bn_check_top(a);
470
0
  bn_check_top(p);
471
0
  ret = BN_GF2m_poly2arr(p, arr, sizeof(arr) / sizeof(arr[0]));
472
0
  if (!ret || ret > (int)(sizeof(arr) / sizeof(arr[0]))) {
473
0
    BNerror(BN_R_INVALID_LENGTH);
474
0
    return 0;
475
0
  }
476
0
  ret = BN_GF2m_mod_arr(r, a, arr);
477
0
  bn_check_top(r);
478
0
  return ret;
479
0
}
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
486
BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p[],
487
    BN_CTX *ctx)
488
0
{
489
0
  int zlen, i, j, k, ret = 0;
490
0
  BIGNUM *s;
491
0
  BN_ULONG x1, x0, y1, y0, zz[4];
492
493
0
  bn_check_top(a);
494
0
  bn_check_top(b);
495
496
0
  if (a == b) {
497
0
    return BN_GF2m_mod_sqr_arr(r, a, p, ctx);
498
0
  }
499
500
0
  BN_CTX_start(ctx);
501
0
  if ((s = BN_CTX_get(ctx)) == NULL)
502
0
    goto err;
503
504
0
  zlen = a->top + b->top + 4;
505
0
  if (!bn_wexpand(s, zlen))
506
0
    goto err;
507
0
  s->top = zlen;
508
509
0
  for (i = 0; i < zlen; i++)
510
0
    s->d[i] = 0;
511
512
0
  for (j = 0; j < b->top; j += 2) {
513
0
    y0 = b->d[j];
514
0
    y1 = ((j + 1) == b->top) ? 0 : b->d[j + 1];
515
0
    for (i = 0; i < a->top; i += 2) {
516
0
      x0 = a->d[i];
517
0
      x1 = ((i + 1) == a->top) ? 0 : a->d[i + 1];
518
0
      bn_GF2m_mul_2x2(zz, x1, x0, y1, y0);
519
0
      for (k = 0; k < 4; k++)
520
0
        s->d[i + j + k] ^= zz[k];
521
0
    }
522
0
  }
523
524
0
  bn_correct_top(s);
525
0
  if (BN_GF2m_mod_arr(r, s, p))
526
0
    ret = 1;
527
0
  bn_check_top(r);
528
529
0
err:
530
0
  BN_CTX_end(ctx);
531
0
  return ret;
532
0
}
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
542
BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p,
543
    BN_CTX *ctx)
544
0
{
545
0
  int ret = 0;
546
0
  const int max = BN_num_bits(p) + 1;
547
0
  int *arr = NULL;
548
549
0
  bn_check_top(a);
550
0
  bn_check_top(b);
551
0
  bn_check_top(p);
552
0
  if ((arr = reallocarray(NULL, max, sizeof(int))) == NULL)
553
0
    goto err;
554
0
  ret = BN_GF2m_poly2arr(p, arr, max);
555
0
  if (!ret || ret > max) {
556
0
    BNerror(BN_R_INVALID_LENGTH);
557
0
    goto err;
558
0
  }
559
0
  ret = BN_GF2m_mod_mul_arr(r, a, b, arr, ctx);
560
0
  bn_check_top(r);
561
562
0
err:
563
0
  free(arr);
564
0
  return ret;
565
0
}
566
567
568
/* Square a, reduce the result mod p, and store it in a.  r could be a. */
569
int
570
BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[], BN_CTX *ctx)
571
0
{
572
0
  int i, ret = 0;
573
0
  BIGNUM *s;
574
575
0
  bn_check_top(a);
576
0
  BN_CTX_start(ctx);
577
0
  if ((s = BN_CTX_get(ctx)) == NULL)
578
0
    goto err;
579
0
  if (!bn_wexpand(s, 2 * a->top))
580
0
    goto err;
581
582
0
  for (i = a->top - 1; i >= 0; i--) {
583
0
    s->d[2 * i + 1] = SQR1(a->d[i]);
584
0
    s->d[2 * i] = SQR0(a->d[i]);
585
0
  }
586
587
0
  s->top = 2 * a->top;
588
0
  bn_correct_top(s);
589
0
  if (!BN_GF2m_mod_arr(r, s, p))
590
0
    goto err;
591
0
  bn_check_top(r);
592
0
  ret = 1;
593
594
0
err:
595
0
  BN_CTX_end(ctx);
596
0
  return ret;
597
0
}
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
606
BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
607
0
{
608
0
  int ret = 0;
609
0
  const int max = BN_num_bits(p) + 1;
610
0
  int *arr = NULL;
611
612
0
  bn_check_top(a);
613
0
  bn_check_top(p);
614
0
  if ((arr = reallocarray(NULL, max, sizeof(int))) == NULL)
615
0
    goto err;
616
0
  ret = BN_GF2m_poly2arr(p, arr, max);
617
0
  if (!ret || ret > max) {
618
0
    BNerror(BN_R_INVALID_LENGTH);
619
0
    goto err;
620
0
  }
621
0
  ret = BN_GF2m_mod_sqr_arr(r, a, arr, ctx);
622
0
  bn_check_top(r);
623
624
0
err:
625
0
  free(arr);
626
0
  return ret;
627
0
}
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
636
BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
637
0
{
638
0
  BIGNUM *b, *c = NULL, *u = NULL, *v = NULL, *tmp;
639
0
  int ret = 0;
640
641
0
  bn_check_top(a);
642
0
  bn_check_top(p);
643
644
0
  BN_CTX_start(ctx);
645
646
0
  if ((b = BN_CTX_get(ctx)) == NULL)
647
0
    goto err;
648
0
  if ((c = BN_CTX_get(ctx)) == NULL)
649
0
    goto err;
650
0
  if ((u = BN_CTX_get(ctx)) == NULL)
651
0
    goto err;
652
0
  if ((v = BN_CTX_get(ctx)) == NULL)
653
0
    goto err;
654
655
0
  if (!BN_GF2m_mod(u, a, p))
656
0
    goto err;
657
0
  if (BN_is_zero(u))
658
0
    goto err;
659
660
0
  if (!BN_copy(v, p))
661
0
    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
0
  {
699
0
    int i,  ubits = BN_num_bits(u),
700
0
    vbits = BN_num_bits(v), /* v is copy of p */
701
0
    top = p->top;
702
0
    BN_ULONG *udp, *bdp, *vdp, *cdp;
703
704
0
    if (!bn_wexpand(u, top))
705
0
                        goto err;
706
0
    udp = u->d;
707
0
    for (i = u->top; i < top; i++)
708
0
      udp[i] = 0;
709
0
    u->top = top;
710
0
    if (!bn_wexpand(b, top))
711
0
                        goto err;
712
0
    bdp = b->d;
713
0
    bdp[0] = 1;
714
0
    for (i = 1; i < top; i++)
715
0
      bdp[i] = 0;
716
0
    b->top = top;
717
0
    if (!bn_wexpand(c, top))
718
0
                        goto err;
719
0
    cdp = c->d;
720
0
    for (i = 0; i < top; i++)
721
0
      cdp[i] = 0;
722
0
    c->top = top;
723
0
    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
0
    while (1) {
728
0
      while (ubits && !(udp[0]&1)) {
729
0
        BN_ULONG u0, u1, b0, b1, mask;
730
731
0
        u0 = udp[0];
732
0
        b0 = bdp[0];
733
0
        mask = (BN_ULONG)0 - (b0 & 1);
734
0
        b0  ^= p->d[0] & mask;
735
0
        for (i = 0; i < top - 1; i++) {
736
0
          u1 = udp[i + 1];
737
0
          udp[i] = ((u0 >> 1) |
738
0
              (u1 << (BN_BITS2 - 1))) & BN_MASK2;
739
0
          u0 = u1;
740
0
          b1 = bdp[i + 1] ^ (p->d[i + 1] & mask);
741
0
          bdp[i] = ((b0 >> 1) |
742
0
              (b1 << (BN_BITS2 - 1))) & BN_MASK2;
743
0
          b0 = b1;
744
0
        }
745
0
        udp[i] = u0 >> 1;
746
0
        bdp[i] = b0 >> 1;
747
0
        ubits--;
748
0
      }
749
750
0
      if (ubits <= BN_BITS2) {
751
        /* See if poly was reducible. */
752
0
        if (udp[0] == 0)
753
0
          goto err;
754
0
        if (udp[0] == 1)
755
0
          break;
756
0
      }
757
758
0
      if (ubits < vbits) {
759
0
        i = ubits;
760
0
        ubits = vbits;
761
0
        vbits = i;
762
0
        tmp = u;
763
0
        u = v;
764
0
        v = tmp;
765
0
        tmp = b;
766
0
        b = c;
767
0
        c = tmp;
768
0
        udp = vdp;
769
0
        vdp = v->d;
770
0
        bdp = cdp;
771
0
        cdp = c->d;
772
0
      }
773
0
      for (i = 0; i < top; i++) {
774
0
        udp[i] ^= vdp[i];
775
0
        bdp[i] ^= cdp[i];
776
0
      }
777
0
      if (ubits == vbits) {
778
0
        BN_ULONG ul;
779
0
        int utop = (ubits - 1) / BN_BITS2;
780
781
0
        while ((ul = udp[utop]) == 0 && utop)
782
0
          utop--;
783
0
        ubits = utop*BN_BITS2 + BN_num_bits_word(ul);
784
0
      }
785
0
    }
786
0
    bn_correct_top(b);
787
0
  }
788
0
#endif
789
790
0
  if (!BN_copy(r, b))
791
0
    goto err;
792
0
  bn_check_top(r);
793
0
  ret = 1;
794
795
0
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
0
  BN_CTX_end(ctx);
802
0
  return ret;
803
0
}
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
812
BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *xx, const int p[], BN_CTX *ctx)
813
0
{
814
0
  BIGNUM *field;
815
0
  int ret = 0;
816
817
0
  bn_check_top(xx);
818
0
  BN_CTX_start(ctx);
819
0
  if ((field = BN_CTX_get(ctx)) == NULL)
820
0
    goto err;
821
0
  if (!BN_GF2m_arr2poly(p, field))
822
0
    goto err;
823
824
0
  ret = BN_GF2m_mod_inv(r, xx, field, ctx);
825
0
  bn_check_top(r);
826
827
0
err:
828
0
  BN_CTX_end(ctx);
829
0
  return ret;
830
0
}
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
838
BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, const BIGNUM *p,
839
    BN_CTX *ctx)
840
0
{
841
0
  BIGNUM *xinv = NULL;
842
0
  int ret = 0;
843
844
0
  bn_check_top(y);
845
0
  bn_check_top(x);
846
0
  bn_check_top(p);
847
848
0
  BN_CTX_start(ctx);
849
0
  if ((xinv = BN_CTX_get(ctx)) == NULL)
850
0
    goto err;
851
852
0
  if (!BN_GF2m_mod_inv(xinv, x, p, ctx))
853
0
    goto err;
854
0
  if (!BN_GF2m_mod_mul(r, y, xinv, p, ctx))
855
0
    goto err;
856
0
  bn_check_top(r);
857
0
  ret = 1;
858
859
0
err:
860
0
  BN_CTX_end(ctx);
861
0
  return ret;
862
0
}
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
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
963
BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *yy, const BIGNUM *xx,
964
    const int p[], BN_CTX *ctx)
965
0
{
966
0
  BIGNUM *field;
967
0
  int ret = 0;
968
969
0
  bn_check_top(yy);
970
0
  bn_check_top(xx);
971
972
0
  BN_CTX_start(ctx);
973
0
  if ((field = BN_CTX_get(ctx)) == NULL)
974
0
    goto err;
975
0
  if (!BN_GF2m_arr2poly(p, field))
976
0
    goto err;
977
978
0
  ret = BN_GF2m_mod_div(r, yy, xx, field, ctx);
979
0
  bn_check_top(r);
980
981
0
err:
982
0
  BN_CTX_end(ctx);
983
0
  return ret;
984
0
}
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
992
BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const int p[],
993
    BN_CTX *ctx)
994
0
{
995
0
  int ret = 0, i, n;
996
0
  BIGNUM *u;
997
998
0
  bn_check_top(a);
999
0
  bn_check_top(b);
1000
1001
0
  if (BN_is_zero(b))
1002
0
    return (BN_one(r));
1003
1004
0
  if (BN_abs_is_word(b, 1))
1005
0
    return (BN_copy(r, a) != NULL);
1006
1007
0
  BN_CTX_start(ctx);
1008
0
  if ((u = BN_CTX_get(ctx)) == NULL)
1009
0
    goto err;
1010
1011
0
  if (!BN_GF2m_mod_arr(u, a, p))
1012
0
    goto err;
1013
1014
0
  n = BN_num_bits(b) - 1;
1015
0
  for (i = n - 1; i >= 0; i--) {
1016
0
    if (!BN_GF2m_mod_sqr_arr(u, u, p, ctx))
1017
0
      goto err;
1018
0
    if (BN_is_bit_set(b, i)) {
1019
0
      if (!BN_GF2m_mod_mul_arr(u, u, a, p, ctx))
1020
0
        goto err;
1021
0
    }
1022
0
  }
1023
0
  if (!BN_copy(r, u))
1024
0
    goto err;
1025
0
  bn_check_top(r);
1026
0
  ret = 1;
1027
1028
0
err:
1029
0
  BN_CTX_end(ctx);
1030
0
  return ret;
1031
0
}
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
1041
BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *p,
1042
    BN_CTX *ctx)
1043
0
{
1044
0
  int ret = 0;
1045
0
  const int max = BN_num_bits(p) + 1;
1046
0
  int *arr = NULL;
1047
1048
0
  bn_check_top(a);
1049
0
  bn_check_top(b);
1050
0
  bn_check_top(p);
1051
0
  if ((arr = reallocarray(NULL, max, sizeof(int))) == NULL)
1052
0
    goto err;
1053
0
  ret = BN_GF2m_poly2arr(p, arr, max);
1054
0
  if (!ret || ret > max) {
1055
0
    BNerror(BN_R_INVALID_LENGTH);
1056
0
    goto err;
1057
0
  }
1058
0
  ret = BN_GF2m_mod_exp_arr(r, a, b, arr, ctx);
1059
0
  bn_check_top(r);
1060
1061
0
err:
1062
0
  free(arr);
1063
0
  return ret;
1064
0
}
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
1071
BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, const int p[], BN_CTX *ctx)
1072
0
{
1073
0
  int ret = 0;
1074
0
  BIGNUM *u;
1075
1076
0
  bn_check_top(a);
1077
1078
0
  if (!p[0]) {
1079
    /* reduction mod 1 => return 0 */
1080
0
    BN_zero(r);
1081
0
    return 1;
1082
0
  }
1083
1084
0
  BN_CTX_start(ctx);
1085
0
  if ((u = BN_CTX_get(ctx)) == NULL)
1086
0
    goto err;
1087
1088
0
  if (!BN_set_bit(u, p[0] - 1))
1089
0
    goto err;
1090
0
  ret = BN_GF2m_mod_exp_arr(r, a, u, p, ctx);
1091
0
  bn_check_top(r);
1092
1093
0
err:
1094
0
  BN_CTX_end(ctx);
1095
0
  return ret;
1096
0
}
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
1106
BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
1107
0
{
1108
0
  int ret = 0;
1109
0
  const int max = BN_num_bits(p) + 1;
1110
0
  int *arr = NULL;
1111
0
  bn_check_top(a);
1112
0
  bn_check_top(p);
1113
0
  if ((arr = reallocarray(NULL, max, sizeof(int))) == NULL)
1114
0
    goto err;
1115
0
  ret = BN_GF2m_poly2arr(p, arr, max);
1116
0
  if (!ret || ret > max) {
1117
0
    BNerror(BN_R_INVALID_LENGTH);
1118
0
    goto err;
1119
0
  }
1120
0
  ret = BN_GF2m_mod_sqrt_arr(r, a, arr, ctx);
1121
0
  bn_check_top(r);
1122
1123
0
err:
1124
0
  free(arr);
1125
0
  return ret;
1126
0
}
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
1132
BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[],
1133
    BN_CTX *ctx)
1134
0
{
1135
0
  int ret = 0, count = 0, j;
1136
0
  BIGNUM *a, *z, *rho, *w, *w2, *tmp;
1137
1138
0
  bn_check_top(a_);
1139
1140
0
  if (!p[0]) {
1141
    /* reduction mod 1 => return 0 */
1142
0
    BN_zero(r);
1143
0
    return 1;
1144
0
  }
1145
1146
0
  BN_CTX_start(ctx);
1147
0
  if ((a = BN_CTX_get(ctx)) == NULL)
1148
0
    goto err;
1149
0
  if ((z = BN_CTX_get(ctx)) == NULL)
1150
0
    goto err;
1151
0
  if ((w = BN_CTX_get(ctx)) == NULL)
1152
0
    goto err;
1153
1154
0
  if (!BN_GF2m_mod_arr(a, a_, p))
1155
0
    goto err;
1156
1157
0
  if (BN_is_zero(a)) {
1158
0
    BN_zero(r);
1159
0
    ret = 1;
1160
0
    goto err;
1161
0
  }
1162
1163
0
  if (p[0] & 0x1) /* m is odd */
1164
0
  {
1165
    /* compute half-trace of a */
1166
0
    if (!BN_copy(z, a))
1167
0
      goto err;
1168
0
    for (j = 1; j <= (p[0] - 1) / 2; j++) {
1169
0
      if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx))
1170
0
        goto err;
1171
0
      if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx))
1172
0
        goto err;
1173
0
      if (!BN_GF2m_add(z, z, a))
1174
0
        goto err;
1175
0
    }
1176
1177
0
  }
1178
0
  else /* m is even */
1179
0
  {
1180
0
    if ((rho = BN_CTX_get(ctx)) == NULL)
1181
0
      goto err;
1182
0
    if ((w2 = BN_CTX_get(ctx)) == NULL)
1183
0
      goto err;
1184
0
    if ((tmp = BN_CTX_get(ctx)) == NULL)
1185
0
      goto err;
1186
0
    do {
1187
0
      if (!BN_rand(rho, p[0], 0, 0))
1188
0
        goto err;
1189
0
      if (!BN_GF2m_mod_arr(rho, rho, p))
1190
0
        goto err;
1191
0
      BN_zero(z);
1192
0
      if (!BN_copy(w, rho))
1193
0
        goto err;
1194
0
      for (j = 1; j <= p[0] - 1; j++) {
1195
0
        if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx))
1196
0
          goto err;
1197
0
        if (!BN_GF2m_mod_sqr_arr(w2, w, p, ctx))
1198
0
          goto err;
1199
0
        if (!BN_GF2m_mod_mul_arr(tmp, w2, a, p, ctx))
1200
0
          goto err;
1201
0
        if (!BN_GF2m_add(z, z, tmp))
1202
0
          goto err;
1203
0
        if (!BN_GF2m_add(w, w2, rho))
1204
0
          goto err;
1205
0
      }
1206
0
      count++;
1207
0
    } while (BN_is_zero(w) && (count < MAX_ITERATIONS));
1208
0
    if (BN_is_zero(w)) {
1209
0
      BNerror(BN_R_TOO_MANY_ITERATIONS);
1210
0
      goto err;
1211
0
    }
1212
0
  }
1213
1214
0
  if (!BN_GF2m_mod_sqr_arr(w, z, p, ctx))
1215
0
    goto err;
1216
0
  if (!BN_GF2m_add(w, z, w))
1217
0
    goto err;
1218
0
  if (BN_GF2m_cmp(w, a)) {
1219
0
    BNerror(BN_R_NO_SOLUTION);
1220
0
    goto err;
1221
0
  }
1222
1223
0
  if (!BN_copy(r, z))
1224
0
    goto err;
1225
0
  bn_check_top(r);
1226
1227
0
  ret = 1;
1228
1229
0
err:
1230
0
  BN_CTX_end(ctx);
1231
0
  return ret;
1232
0
}
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
1241
BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
1242
0
{
1243
0
  int ret = 0;
1244
0
  const int max = BN_num_bits(p) + 1;
1245
0
  int *arr = NULL;
1246
1247
0
  bn_check_top(a);
1248
0
  bn_check_top(p);
1249
0
  if ((arr = reallocarray(NULL, max, sizeof(int))) == NULL)
1250
0
    goto err;
1251
0
  ret = BN_GF2m_poly2arr(p, arr, max);
1252
0
  if (!ret || ret > max) {
1253
0
    BNerror(BN_R_INVALID_LENGTH);
1254
0
    goto err;
1255
0
  }
1256
0
  ret = BN_GF2m_mod_solve_quad_arr(r, a, arr, ctx);
1257
0
  bn_check_top(r);
1258
1259
0
err:
1260
0
  free(arr);
1261
0
  return ret;
1262
0
}
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
1271
BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max)
1272
0
{
1273
0
  int i, j, k = 0;
1274
0
  BN_ULONG mask;
1275
1276
0
  if (BN_is_zero(a))
1277
0
    return 0;
1278
1279
0
  for (i = a->top - 1; i >= 0; i--) {
1280
0
    if (!a->d[i])
1281
      /* skip word if a->d[i] == 0 */
1282
0
      continue;
1283
0
    mask = BN_TBIT;
1284
0
    for (j = BN_BITS2 - 1; j >= 0; j--) {
1285
0
      if (a->d[i] & mask) {
1286
0
        if (k < max)
1287
0
          p[k] = BN_BITS2 * i + j;
1288
0
        k++;
1289
0
      }
1290
0
      mask >>= 1;
1291
0
    }
1292
0
  }
1293
1294
0
  if (k < max) {
1295
0
    p[k] = -1;
1296
0
    k++;
1297
0
  }
1298
1299
0
  return k;
1300
0
}
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
1306
BN_GF2m_arr2poly(const int p[], BIGNUM *a)
1307
0
{
1308
0
  int i;
1309
1310
0
  bn_check_top(a);
1311
0
  BN_zero(a);
1312
0
  for (i = 0; p[i] != -1; i++) {
1313
0
    if (BN_set_bit(a, p[i]) == 0)
1314
0
      return 0;
1315
0
  }
1316
0
  bn_check_top(a);
1317
1318
0
  return 1;
1319
0
}
1320
1321
#endif