Coverage Report

Created: 2024-02-25 06:31

/src/nss/lib/freebl/mpi/mp_gf2m.c
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#include "mp_gf2m.h"
6
#include "mp_gf2m-priv.h"
7
#include "mplogic.h"
8
#include "mpi-priv.h"
9
10
const mp_digit mp_gf2m_sqr_tb[16] = {
11
    0, 1, 4, 5, 16, 17, 20, 21,
12
    64, 65, 68, 69, 80, 81, 84, 85
13
};
14
15
/* Multiply two binary polynomials mp_digits a, b.
16
 * Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1.
17
 * Output in two mp_digits rh, rl.
18
 */
19
#if MP_DIGIT_BITS == 32
20
void
21
s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b)
22
{
23
    register mp_digit h, l, s;
24
    mp_digit tab[8], top2b = a >> 30;
25
    register mp_digit a1, a2, a4;
26
27
    a1 = a & (0x3FFFFFFF);
28
    a2 = a1 << 1;
29
    a4 = a2 << 1;
30
31
    tab[0] = 0;
32
    tab[1] = a1;
33
    tab[2] = a2;
34
    tab[3] = a1 ^ a2;
35
    tab[4] = a4;
36
    tab[5] = a1 ^ a4;
37
    tab[6] = a2 ^ a4;
38
    tab[7] = a1 ^ a2 ^ a4;
39
40
    s = tab[b & 0x7];
41
    l = s;
42
    s = tab[b >> 3 & 0x7];
43
    l ^= s << 3;
44
    h = s >> 29;
45
    s = tab[b >> 6 & 0x7];
46
    l ^= s << 6;
47
    h ^= s >> 26;
48
    s = tab[b >> 9 & 0x7];
49
    l ^= s << 9;
50
    h ^= s >> 23;
51
    s = tab[b >> 12 & 0x7];
52
    l ^= s << 12;
53
    h ^= s >> 20;
54
    s = tab[b >> 15 & 0x7];
55
    l ^= s << 15;
56
    h ^= s >> 17;
57
    s = tab[b >> 18 & 0x7];
58
    l ^= s << 18;
59
    h ^= s >> 14;
60
    s = tab[b >> 21 & 0x7];
61
    l ^= s << 21;
62
    h ^= s >> 11;
63
    s = tab[b >> 24 & 0x7];
64
    l ^= s << 24;
65
    h ^= s >> 8;
66
    s = tab[b >> 27 & 0x7];
67
    l ^= s << 27;
68
    h ^= s >> 5;
69
    s = tab[b >> 30];
70
    l ^= s << 30;
71
    h ^= s >> 2;
72
73
    /* compensate for the top two bits of a */
74
75
    if (top2b & 01) {
76
        l ^= b << 30;
77
        h ^= b >> 2;
78
    }
79
    if (top2b & 02) {
80
        l ^= b << 31;
81
        h ^= b >> 1;
82
    }
83
84
    *rh = h;
85
    *rl = l;
86
}
87
#else
88
void
89
s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b)
90
0
{
91
0
    register mp_digit h, l, s;
92
0
    mp_digit tab[16], top3b = a >> 61;
93
0
    register mp_digit a1, a2, a4, a8;
94
95
0
    a1 = a & (0x1FFFFFFFFFFFFFFFULL);
96
0
    a2 = a1 << 1;
97
0
    a4 = a2 << 1;
98
0
    a8 = a4 << 1;
99
0
    tab[0] = 0;
100
0
    tab[1] = a1;
101
0
    tab[2] = a2;
102
0
    tab[3] = a1 ^ a2;
103
0
    tab[4] = a4;
104
0
    tab[5] = a1 ^ a4;
105
0
    tab[6] = a2 ^ a4;
106
0
    tab[7] = a1 ^ a2 ^ a4;
107
0
    tab[8] = a8;
108
0
    tab[9] = a1 ^ a8;
109
0
    tab[10] = a2 ^ a8;
110
0
    tab[11] = a1 ^ a2 ^ a8;
111
0
    tab[12] = a4 ^ a8;
112
0
    tab[13] = a1 ^ a4 ^ a8;
113
0
    tab[14] = a2 ^ a4 ^ a8;
114
0
    tab[15] = a1 ^ a2 ^ a4 ^ a8;
115
116
0
    s = tab[b & 0xF];
117
0
    l = s;
118
0
    s = tab[b >> 4 & 0xF];
119
0
    l ^= s << 4;
120
0
    h = s >> 60;
121
0
    s = tab[b >> 8 & 0xF];
122
0
    l ^= s << 8;
123
0
    h ^= s >> 56;
124
0
    s = tab[b >> 12 & 0xF];
125
0
    l ^= s << 12;
126
0
    h ^= s >> 52;
127
0
    s = tab[b >> 16 & 0xF];
128
0
    l ^= s << 16;
129
0
    h ^= s >> 48;
130
0
    s = tab[b >> 20 & 0xF];
131
0
    l ^= s << 20;
132
0
    h ^= s >> 44;
133
0
    s = tab[b >> 24 & 0xF];
134
0
    l ^= s << 24;
135
0
    h ^= s >> 40;
136
0
    s = tab[b >> 28 & 0xF];
137
0
    l ^= s << 28;
138
0
    h ^= s >> 36;
139
0
    s = tab[b >> 32 & 0xF];
140
0
    l ^= s << 32;
141
0
    h ^= s >> 32;
142
0
    s = tab[b >> 36 & 0xF];
143
0
    l ^= s << 36;
144
0
    h ^= s >> 28;
145
0
    s = tab[b >> 40 & 0xF];
146
0
    l ^= s << 40;
147
0
    h ^= s >> 24;
148
0
    s = tab[b >> 44 & 0xF];
149
0
    l ^= s << 44;
150
0
    h ^= s >> 20;
151
0
    s = tab[b >> 48 & 0xF];
152
0
    l ^= s << 48;
153
0
    h ^= s >> 16;
154
0
    s = tab[b >> 52 & 0xF];
155
0
    l ^= s << 52;
156
0
    h ^= s >> 12;
157
0
    s = tab[b >> 56 & 0xF];
158
0
    l ^= s << 56;
159
0
    h ^= s >> 8;
160
0
    s = tab[b >> 60];
161
0
    l ^= s << 60;
162
0
    h ^= s >> 4;
163
164
    /* compensate for the top three bits of a */
165
166
0
    if (top3b & 01) {
167
0
        l ^= b << 61;
168
0
        h ^= b >> 3;
169
0
    }
170
0
    if (top3b & 02) {
171
0
        l ^= b << 62;
172
0
        h ^= b >> 2;
173
0
    }
174
0
    if (top3b & 04) {
175
0
        l ^= b << 63;
176
0
        h ^= b >> 1;
177
0
    }
178
179
0
    *rh = h;
180
0
    *rl = l;
181
0
}
182
#endif
183
184
/* Compute xor-multiply of two binary polynomials  (a1, a0) x (b1, b0)
185
 * result is a binary polynomial in 4 mp_digits r[4].
186
 * The caller MUST ensure that r has the right amount of space allocated.
187
 */
188
void
189
s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1,
190
           const mp_digit b0)
191
0
{
192
0
    mp_digit m1, m0;
193
    /* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */
194
0
    s_bmul_1x1(r + 3, r + 2, a1, b1);
195
0
    s_bmul_1x1(r + 1, r, a0, b0);
196
0
    s_bmul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1);
197
    /* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */
198
0
    r[2] ^= m1 ^ r[1] ^ r[3];            /* h0 ^= m1 ^ l1 ^ h1; */
199
0
    r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0; /* l1 ^= l0 ^ h0 ^ m0; */
200
0
}
201
202
/* Compute xor-multiply of two binary polynomials  (a2, a1, a0) x (b2, b1, b0)
203
 * result is a binary polynomial in 6 mp_digits r[6].
204
 * The caller MUST ensure that r has the right amount of space allocated.
205
 */
206
void
207
s_bmul_3x3(mp_digit *r, const mp_digit a2, const mp_digit a1, const mp_digit a0,
208
           const mp_digit b2, const mp_digit b1, const mp_digit b0)
209
0
{
210
0
    mp_digit zm[4];
211
212
0
    s_bmul_1x1(r + 5, r + 4, a2, b2);         /* fill top 2 words */
213
0
    s_bmul_2x2(zm, a1, a2 ^ a0, b1, b2 ^ b0); /* fill middle 4 words */
214
0
    s_bmul_2x2(r, a1, a0, b1, b0);            /* fill bottom 4 words */
215
216
0
    zm[3] ^= r[3];
217
0
    zm[2] ^= r[2];
218
0
    zm[1] ^= r[1] ^ r[5];
219
0
    zm[0] ^= r[0] ^ r[4];
220
221
0
    r[5] ^= zm[3];
222
0
    r[4] ^= zm[2];
223
0
    r[3] ^= zm[1];
224
0
    r[2] ^= zm[0];
225
0
}
226
227
/* Compute xor-multiply of two binary polynomials  (a3, a2, a1, a0) x (b3, b2, b1, b0)
228
 * result is a binary polynomial in 8 mp_digits r[8].
229
 * The caller MUST ensure that r has the right amount of space allocated.
230
 */
231
void
232
s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1,
233
           const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1,
234
           const mp_digit b0)
235
0
{
236
0
    mp_digit zm[4];
237
238
0
    s_bmul_2x2(r + 4, a3, a2, b3, b2);                  /* fill top 4 words */
239
0
    s_bmul_2x2(zm, a3 ^ a1, a2 ^ a0, b3 ^ b1, b2 ^ b0); /* fill middle 4 words */
240
0
    s_bmul_2x2(r, a1, a0, b1, b0);                      /* fill bottom 4 words */
241
242
0
    zm[3] ^= r[3] ^ r[7];
243
0
    zm[2] ^= r[2] ^ r[6];
244
0
    zm[1] ^= r[1] ^ r[5];
245
0
    zm[0] ^= r[0] ^ r[4];
246
247
0
    r[5] ^= zm[3];
248
0
    r[4] ^= zm[2];
249
0
    r[3] ^= zm[1];
250
0
    r[2] ^= zm[0];
251
0
}
252
253
/* Compute addition of two binary polynomials a and b,
254
 * store result in c; c could be a or b, a and b could be equal;
255
 * c is the bitwise XOR of a and b.
256
 */
257
mp_err
258
mp_badd(const mp_int *a, const mp_int *b, mp_int *c)
259
0
{
260
0
    mp_digit *pa, *pb, *pc;
261
0
    mp_size ix;
262
0
    mp_size used_pa, used_pb;
263
0
    mp_err res = MP_OKAY;
264
265
    /* Add all digits up to the precision of b.  If b had more
266
     * precision than a initially, swap a, b first
267
     */
268
0
    if (MP_USED(a) >= MP_USED(b)) {
269
0
        pa = MP_DIGITS(a);
270
0
        pb = MP_DIGITS(b);
271
0
        used_pa = MP_USED(a);
272
0
        used_pb = MP_USED(b);
273
0
    } else {
274
0
        pa = MP_DIGITS(b);
275
0
        pb = MP_DIGITS(a);
276
0
        used_pa = MP_USED(b);
277
0
        used_pb = MP_USED(a);
278
0
    }
279
280
    /* Make sure c has enough precision for the output value */
281
0
    MP_CHECKOK(s_mp_pad(c, used_pa));
282
283
    /* Do word-by-word xor */
284
0
    pc = MP_DIGITS(c);
285
0
    for (ix = 0; ix < used_pb; ix++) {
286
0
        (*pc++) = (*pa++) ^ (*pb++);
287
0
    }
288
289
    /* Finish the rest of digits until we're actually done */
290
0
    for (; ix < used_pa; ++ix) {
291
0
        *pc++ = *pa++;
292
0
    }
293
294
0
    MP_USED(c) = used_pa;
295
0
    MP_SIGN(c) = ZPOS;
296
0
    s_mp_clamp(c);
297
298
0
CLEANUP:
299
0
    return res;
300
0
}
301
302
0
#define s_mp_div2(a) MP_CHECKOK(mpl_rsh((a), (a), 1));
303
304
/* Compute binary polynomial multiply d = a * b */
305
static void
306
s_bmul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *d)
307
0
{
308
0
    mp_digit a_i, a0b0, a1b1, carry = 0;
309
0
    while (a_len--) {
310
0
        a_i = *a++;
311
0
        s_bmul_1x1(&a1b1, &a0b0, a_i, b);
312
0
        *d++ = a0b0 ^ carry;
313
0
        carry = a1b1;
314
0
    }
315
0
    *d = carry;
316
0
}
317
318
/* Compute binary polynomial xor multiply accumulate d ^= a * b */
319
static void
320
s_bmul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *d)
321
0
{
322
0
    mp_digit a_i, a0b0, a1b1, carry = 0;
323
0
    while (a_len--) {
324
0
        a_i = *a++;
325
0
        s_bmul_1x1(&a1b1, &a0b0, a_i, b);
326
0
        *d++ ^= a0b0 ^ carry;
327
0
        carry = a1b1;
328
0
    }
329
0
    *d ^= carry;
330
0
}
331
332
/* Compute binary polynomial xor multiply c = a * b.
333
 * All parameters may be identical.
334
 */
335
mp_err
336
mp_bmul(const mp_int *a, const mp_int *b, mp_int *c)
337
0
{
338
0
    mp_digit *pb, b_i;
339
0
    mp_int tmp;
340
0
    mp_size ib, a_used, b_used;
341
0
    mp_err res = MP_OKAY;
342
343
0
    MP_DIGITS(&tmp) = 0;
344
345
0
    ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
346
347
0
    if (a == c) {
348
0
        MP_CHECKOK(mp_init_copy(&tmp, a));
349
0
        if (a == b)
350
0
            b = &tmp;
351
0
        a = &tmp;
352
0
    } else if (b == c) {
353
0
        MP_CHECKOK(mp_init_copy(&tmp, b));
354
0
        b = &tmp;
355
0
    }
356
357
0
    if (MP_USED(a) < MP_USED(b)) {
358
0
        const mp_int *xch = b; /* switch a and b if b longer */
359
0
        b = a;
360
0
        a = xch;
361
0
    }
362
363
0
    MP_USED(c) = 1;
364
0
    MP_DIGIT(c, 0) = 0;
365
0
    MP_CHECKOK(s_mp_pad(c, USED(a) + USED(b)));
366
367
0
    pb = MP_DIGITS(b);
368
0
    s_bmul_d(MP_DIGITS(a), MP_USED(a), *pb++, MP_DIGITS(c));
369
370
    /* Outer loop:  Digits of b */
371
0
    a_used = MP_USED(a);
372
0
    b_used = MP_USED(b);
373
0
    MP_USED(c) = a_used + b_used;
374
0
    for (ib = 1; ib < b_used; ib++) {
375
0
        b_i = *pb++;
376
377
        /* Inner product:  Digits of a */
378
0
        if (b_i)
379
0
            s_bmul_d_add(MP_DIGITS(a), a_used, b_i, MP_DIGITS(c) + ib);
380
0
        else
381
0
            MP_DIGIT(c, ib + a_used) = b_i;
382
0
    }
383
384
0
    s_mp_clamp(c);
385
386
0
    SIGN(c) = ZPOS;
387
388
0
CLEANUP:
389
0
    mp_clear(&tmp);
390
0
    return res;
391
0
}
392
393
/* Compute modular reduction of a and store result in r.
394
 * r could be a.
395
 * For modular arithmetic, the irreducible polynomial f(t) is represented
396
 * as an array of int[], where f(t) is of the form:
397
 *     f(t) = t^p[0] + t^p[1] + ... + t^p[k]
398
 * where m = p[0] > p[1] > ... > p[k] = 0.
399
 */
400
mp_err
401
mp_bmod(const mp_int *a, const unsigned int p[], mp_int *r)
402
0
{
403
0
    int j, k;
404
0
    int n, dN, d0, d1;
405
0
    mp_digit zz, *z, tmp;
406
0
    mp_size used;
407
0
    mp_err res = MP_OKAY;
408
409
    /* The algorithm does the reduction in place in r,
410
     * if a != r, copy a into r first so reduction can be done in r
411
     */
412
0
    if (a != r) {
413
0
        MP_CHECKOK(mp_copy(a, r));
414
0
    }
415
0
    z = MP_DIGITS(r);
416
417
    /* start reduction */
418
    /*dN = p[0] / MP_DIGIT_BITS; */
419
0
    dN = p[0] >> MP_DIGIT_BITS_LOG_2;
420
0
    used = MP_USED(r);
421
422
0
    for (j = used - 1; j > dN;) {
423
424
0
        zz = z[j];
425
0
        if (zz == 0) {
426
0
            j--;
427
0
            continue;
428
0
        }
429
0
        z[j] = 0;
430
431
0
        for (k = 1; p[k] > 0; k++) {
432
            /* reducing component t^p[k] */
433
0
            n = p[0] - p[k];
434
            /*d0 = n % MP_DIGIT_BITS;   */
435
0
            d0 = n & MP_DIGIT_BITS_MASK;
436
0
            d1 = MP_DIGIT_BITS - d0;
437
            /*n /= MP_DIGIT_BITS; */
438
0
            n >>= MP_DIGIT_BITS_LOG_2;
439
0
            z[j - n] ^= (zz >> d0);
440
0
            if (d0)
441
0
                z[j - n - 1] ^= (zz << d1);
442
0
        }
443
444
        /* reducing component t^0 */
445
0
        n = dN;
446
        /*d0 = p[0] % MP_DIGIT_BITS;*/
447
0
        d0 = p[0] & MP_DIGIT_BITS_MASK;
448
0
        d1 = MP_DIGIT_BITS - d0;
449
0
        z[j - n] ^= (zz >> d0);
450
0
        if (d0)
451
0
            z[j - n - 1] ^= (zz << d1);
452
0
    }
453
454
    /* final round of reduction */
455
0
    while (j == dN) {
456
457
        /* d0 = p[0] % MP_DIGIT_BITS; */
458
0
        d0 = p[0] & MP_DIGIT_BITS_MASK;
459
0
        zz = z[dN] >> d0;
460
0
        if (zz == 0)
461
0
            break;
462
0
        d1 = MP_DIGIT_BITS - d0;
463
464
        /* clear up the top d1 bits */
465
0
        if (d0) {
466
0
            z[dN] = (z[dN] << d1) >> d1;
467
0
        } else {
468
0
            z[dN] = 0;
469
0
        }
470
0
        *z ^= zz; /* reduction t^0 component */
471
472
0
        for (k = 1; p[k] > 0; k++) {
473
            /* reducing component t^p[k]*/
474
            /* n = p[k] / MP_DIGIT_BITS; */
475
0
            n = p[k] >> MP_DIGIT_BITS_LOG_2;
476
            /* d0 = p[k] % MP_DIGIT_BITS; */
477
0
            d0 = p[k] & MP_DIGIT_BITS_MASK;
478
0
            d1 = MP_DIGIT_BITS - d0;
479
0
            z[n] ^= (zz << d0);
480
0
            tmp = zz >> d1;
481
0
            if (d0 && tmp)
482
0
                z[n + 1] ^= tmp;
483
0
        }
484
0
    }
485
486
0
    s_mp_clamp(r);
487
0
CLEANUP:
488
0
    return res;
489
0
}
490
491
/* Compute the product of two polynomials a and b, reduce modulo p,
492
 * Store the result in r.  r could be a or b; a could be b.
493
 */
494
mp_err
495
mp_bmulmod(const mp_int *a, const mp_int *b, const unsigned int p[], mp_int *r)
496
0
{
497
0
    mp_err res;
498
499
0
    if (a == b)
500
0
        return mp_bsqrmod(a, p, r);
501
0
    if ((res = mp_bmul(a, b, r)) != MP_OKAY)
502
0
        return res;
503
0
    return mp_bmod(r, p, r);
504
0
}
505
506
/* Compute binary polynomial squaring c = a*a mod p .
507
 * Parameter r and a can be identical.
508
 */
509
510
mp_err
511
mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r)
512
0
{
513
0
    mp_digit *pa, *pr, a_i;
514
0
    mp_int tmp;
515
0
    mp_size ia, a_used;
516
0
    mp_err res;
517
518
0
    ARGCHK(a != NULL && r != NULL, MP_BADARG);
519
0
    MP_DIGITS(&tmp) = 0;
520
521
0
    if (a == r) {
522
0
        MP_CHECKOK(mp_init_copy(&tmp, a));
523
0
        a = &tmp;
524
0
    }
525
526
0
    MP_USED(r) = 1;
527
0
    MP_DIGIT(r, 0) = 0;
528
0
    MP_CHECKOK(s_mp_pad(r, 2 * USED(a)));
529
530
0
    pa = MP_DIGITS(a);
531
0
    pr = MP_DIGITS(r);
532
0
    a_used = MP_USED(a);
533
0
    MP_USED(r) = 2 * a_used;
534
535
0
    for (ia = 0; ia < a_used; ia++) {
536
0
        a_i = *pa++;
537
0
        *pr++ = gf2m_SQR0(a_i);
538
0
        *pr++ = gf2m_SQR1(a_i);
539
0
    }
540
541
0
    MP_CHECKOK(mp_bmod(r, p, r));
542
0
    s_mp_clamp(r);
543
0
    SIGN(r) = ZPOS;
544
545
0
CLEANUP:
546
0
    mp_clear(&tmp);
547
0
    return res;
548
0
}
549
550
/* Compute binary polynomial y/x mod p, y divided by x, reduce modulo p.
551
 * Store the result in r. r could be x or y, and x could equal y.
552
 * Uses algorithm Modular_Division_GF(2^m) from
553
 *     Chang-Shantz, S.  "From Euclid's GCD to Montgomery Multiplication to
554
 *     the Great Divide".
555
 */
556
int
557
mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp,
558
           const unsigned int p[], mp_int *r)
559
0
{
560
0
    mp_int aa, bb, uu;
561
0
    mp_int *a, *b, *u, *v;
562
0
    mp_err res = MP_OKAY;
563
564
0
    MP_DIGITS(&aa) = 0;
565
0
    MP_DIGITS(&bb) = 0;
566
0
    MP_DIGITS(&uu) = 0;
567
568
0
    MP_CHECKOK(mp_init_copy(&aa, x));
569
0
    MP_CHECKOK(mp_init_copy(&uu, y));
570
0
    MP_CHECKOK(mp_init_copy(&bb, pp));
571
0
    MP_CHECKOK(s_mp_pad(r, USED(pp)));
572
0
    MP_USED(r) = 1;
573
0
    MP_DIGIT(r, 0) = 0;
574
575
0
    a = &aa;
576
0
    b = &bb;
577
0
    u = &uu;
578
0
    v = r;
579
    /* reduce x and y mod p */
580
0
    MP_CHECKOK(mp_bmod(a, p, a));
581
0
    MP_CHECKOK(mp_bmod(u, p, u));
582
583
0
    while (!mp_isodd(a)) {
584
0
        s_mp_div2(a);
585
0
        if (mp_isodd(u)) {
586
0
            MP_CHECKOK(mp_badd(u, pp, u));
587
0
        }
588
0
        s_mp_div2(u);
589
0
    }
590
591
0
    do {
592
0
        if (mp_cmp_mag(b, a) > 0) {
593
0
            MP_CHECKOK(mp_badd(b, a, b));
594
0
            MP_CHECKOK(mp_badd(v, u, v));
595
0
            do {
596
0
                s_mp_div2(b);
597
0
                if (mp_isodd(v)) {
598
0
                    MP_CHECKOK(mp_badd(v, pp, v));
599
0
                }
600
0
                s_mp_div2(v);
601
0
            } while (!mp_isodd(b));
602
0
        } else if ((MP_DIGIT(a, 0) == 1) && (MP_USED(a) == 1))
603
0
            break;
604
0
        else {
605
0
            MP_CHECKOK(mp_badd(a, b, a));
606
0
            MP_CHECKOK(mp_badd(u, v, u));
607
0
            do {
608
0
                s_mp_div2(a);
609
0
                if (mp_isodd(u)) {
610
0
                    MP_CHECKOK(mp_badd(u, pp, u));
611
0
                }
612
0
                s_mp_div2(u);
613
0
            } while (!mp_isodd(a));
614
0
        }
615
0
    } while (1);
616
617
0
    MP_CHECKOK(mp_copy(u, r));
618
619
0
CLEANUP:
620
0
    mp_clear(&aa);
621
0
    mp_clear(&bb);
622
0
    mp_clear(&uu);
623
0
    return res;
624
0
}
625
626
/* Convert the bit-string representation of a polynomial a into an array
627
 * of integers corresponding to the bits with non-zero coefficient.
628
 * Up to max elements of the array will be filled.  Return value is total
629
 * number of coefficients that would be extracted if array was large enough.
630
 */
631
int
632
mp_bpoly2arr(const mp_int *a, unsigned int p[], int max)
633
0
{
634
0
    int i, j, k;
635
0
    mp_digit top_bit, mask;
636
637
0
    top_bit = 1;
638
0
    top_bit <<= MP_DIGIT_BIT - 1;
639
640
0
    for (k = 0; k < max; k++)
641
0
        p[k] = 0;
642
0
    k = 0;
643
644
0
    for (i = MP_USED(a) - 1; i >= 0; i--) {
645
0
        mask = top_bit;
646
0
        for (j = MP_DIGIT_BIT - 1; j >= 0; j--) {
647
0
            if (MP_DIGITS(a)[i] & mask) {
648
0
                if (k < max)
649
0
                    p[k] = MP_DIGIT_BIT * i + j;
650
0
                k++;
651
0
            }
652
0
            mask >>= 1;
653
0
        }
654
0
    }
655
656
0
    return k;
657
0
}
658
659
/* Convert the coefficient array representation of a polynomial to a
660
 * bit-string.  The array must be terminated by 0.
661
 */
662
mp_err
663
mp_barr2poly(const unsigned int p[], mp_int *a)
664
0
{
665
666
0
    mp_err res = MP_OKAY;
667
0
    int i;
668
669
0
    mp_zero(a);
670
0
    for (i = 0; p[i] > 0; i++) {
671
0
        MP_CHECKOK(mpl_set_bit(a, p[i], 1));
672
0
    }
673
0
    MP_CHECKOK(mpl_set_bit(a, 0, 1));
674
675
0
CLEANUP:
676
0
    return res;
677
0
}