~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/freebl/ecl/ecp_fp.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
4
 * The contents of this file are subject to the Mozilla Public License Version
 
5
 * 1.1 (the "License"); you may not use this file except in compliance with
 
6
 * the License. You may obtain a copy of the License at
 
7
 * http://www.mozilla.org/MPL/
 
8
 *
 
9
 * Software distributed under the License is distributed on an "AS IS" basis,
 
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
11
 * for the specific language governing rights and limitations under the
 
12
 * License.
 
13
 *
 
14
 * The Original Code is the elliptic curve math library for prime
 
15
 * field curves using floating point operations.
 
16
 *
 
17
 * The Initial Developer of the Original Code is Sun Microsystems, Inc.
 
18
 * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
 
19
 * Sun Microsystems, Inc. All Rights Reserved.
 
20
 *
 
21
 * Contributor(s):
 
22
 *      Sheueling Chang-Shantz <sheueling.chang@sun.com>,
 
23
 *      Stephen Fung <fungstep@hotmail.com>, and
 
24
 *      Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
 
25
 *
 
26
 * Alternatively, the contents of this file may be used under the terms of
 
27
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
28
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
29
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
30
 * of those above. If you wish to allow use of your version of this file only
 
31
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
32
 * use your version of this file under the terms of the MPL, indicate your
 
33
 * decision by deleting the provisions above and replace them with the notice
 
34
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
35
 * the provisions above, a recipient may use your version of this file under
 
36
 * the terms of any one of the MPL, the GPL or the LGPL.
 
37
 *
 
38
 */
 
39
 
 
40
#include "ecp_fp.h"
 
41
#include "ecl-priv.h"
 
42
#include <stdlib.h>
 
43
 
 
44
/* Performs tidying on a short multi-precision floating point integer (the 
 
45
 * lower group->numDoubles floats). */
 
46
void
 
47
ecfp_tidyShort(double *t, const EC_group_fp * group)
 
48
{
 
49
        group->ecfp_tidy(t, group->alpha, group);
 
50
}
 
51
 
 
52
/* Performs tidying on only the upper float digits of a multi-precision
 
53
 * floating point integer, i.e. the digits beyond the regular length which 
 
54
 * are removed in the reduction step. */
 
55
void
 
56
ecfp_tidyUpper(double *t, const EC_group_fp * group)
 
57
{
 
58
        group->ecfp_tidy(t + group->numDoubles,
 
59
                                         group->alpha + group->numDoubles, group);
 
60
}
 
61
 
 
62
/* Performs a "tidy" operation, which performs carrying, moving excess
 
63
 * bits from one double to the next double, so that the precision of the
 
64
 * doubles is reduced to the regular precision group->doubleBitSize. This
 
65
 * might result in some float digits being negative. Alternative C version 
 
66
 * for portability. */
 
67
void
 
68
ecfp_tidy(double *t, const double *alpha, const EC_group_fp * group)
 
69
{
 
70
        double q;
 
71
        int i;
 
72
 
 
73
        /* Do carrying */
 
74
        for (i = 0; i < group->numDoubles - 1; i++) {
 
75
                q = t[i] + alpha[i + 1];
 
76
                q -= alpha[i + 1];
 
77
                t[i] -= q;
 
78
                t[i + 1] += q;
 
79
 
 
80
                /* If we don't assume that truncation rounding is used, then q
 
81
                 * might be 2^n bigger than expected (if it rounds up), then t[0]
 
82
                 * could be negative and t[1] 2^n larger than expected. */
 
83
        }
 
84
}
 
85
 
 
86
/* Performs a more mathematically precise "tidying" so that each term is
 
87
 * positive.  This is slower than the regular tidying, and is used for
 
88
 * conversion from floating point to integer. */
 
89
void
 
90
ecfp_positiveTidy(double *t, const EC_group_fp * group)
 
91
{
 
92
        double q;
 
93
        int i;
 
94
 
 
95
        /* Do carrying */
 
96
        for (i = 0; i < group->numDoubles - 1; i++) {
 
97
                /* Subtract beta to force rounding down */
 
98
                q = t[i] - ecfp_beta[i + 1];
 
99
                q += group->alpha[i + 1];
 
100
                q -= group->alpha[i + 1];
 
101
                t[i] -= q;
 
102
                t[i + 1] += q;
 
103
 
 
104
                /* Due to subtracting ecfp_beta, we should have each term a
 
105
                 * non-negative int */
 
106
                ECFP_ASSERT(t[i] / ecfp_exp[i] ==
 
107
                                        (unsigned long long) (t[i] / ecfp_exp[i]));
 
108
                ECFP_ASSERT(t[i] >= 0);
 
109
        }
 
110
}
 
111
 
 
112
/* Converts from a floating point representation into an mp_int. Expects
 
113
 * that d is already reduced. */
 
114
void
 
115
ecfp_fp2i(mp_int *mpout, double *d, const ECGroup *ecgroup)
 
116
{
 
117
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
118
        unsigned short i16[(group->primeBitSize + 15) / 16];
 
119
        double q = 1;
 
120
 
 
121
#ifdef ECL_THIRTY_TWO_BIT
 
122
        /* TEST uint32_t z = 0; */
 
123
        unsigned int z = 0;
 
124
#else
 
125
        uint64_t z = 0;
 
126
#endif
 
127
        int zBits = 0;
 
128
        int copiedBits = 0;
 
129
        int i = 0;
 
130
        int j = 0;
 
131
 
 
132
        mp_digit *out;
 
133
 
 
134
        /* Result should always be >= 0, so set sign accordingly */
 
135
        MP_SIGN(mpout) = MP_ZPOS;
 
136
 
 
137
        /* Tidy up so we're just dealing with positive numbers */
 
138
        ecfp_positiveTidy(d, group);
 
139
 
 
140
        /* We might need to do this reduction step more than once if the
 
141
         * reduction adds smaller terms which carry-over to cause another
 
142
         * reduction. However, this should happen very rarely, if ever,
 
143
         * depending on the elliptic curve. */
 
144
        do {
 
145
                /* Init loop data */
 
146
                z = 0;
 
147
                zBits = 0;
 
148
                q = 1;
 
149
                i = 0;
 
150
                j = 0;
 
151
                copiedBits = 0;
 
152
 
 
153
                /* Might have to do a bit more reduction */
 
154
                group->ecfp_singleReduce(d, group);
 
155
 
 
156
                /* Grow the size of the mpint if it's too small */
 
157
                s_mp_grow(mpout, group->numInts);
 
158
                MP_USED(mpout) = group->numInts;
 
159
                out = MP_DIGITS(mpout);
 
160
 
 
161
                /* Convert double to 16 bit integers */
 
162
                while (copiedBits < group->primeBitSize) {
 
163
                        if (zBits < 16) {
 
164
                                z += d[i] * q;
 
165
                                i++;
 
166
                                ECFP_ASSERT(i < (group->primeBitSize + 15) / 16);
 
167
                                zBits += group->doubleBitSize;
 
168
                        }
 
169
                        i16[j] = z;
 
170
                        j++;
 
171
                        z >>= 16;
 
172
                        zBits -= 16;
 
173
                        q *= ecfp_twom16;
 
174
                        copiedBits += 16;
 
175
                }
 
176
        } while (z != 0);
 
177
 
 
178
        /* Convert 16 bit integers to mp_digit */
 
179
#ifdef ECL_THIRTY_TWO_BIT
 
180
        for (i = 0; i < (group->primeBitSize + 15) / 16; i += 2) {
 
181
                *out = 0;
 
182
                if (i + 1 < (group->primeBitSize + 15) / 16) {
 
183
                        *out = i16[i + 1];
 
184
                        *out <<= 16;
 
185
                }
 
186
                *out++ += i16[i];
 
187
        }
 
188
#else                                                   /* 64 bit */
 
189
        for (i = 0; i < (group->primeBitSize + 15) / 16; i += 4) {
 
190
                *out = 0;
 
191
                if (i + 3 < (group->primeBitSize + 15) / 16) {
 
192
                        *out = i16[i + 3];
 
193
                        *out <<= 16;
 
194
                }
 
195
                if (i + 2 < (group->primeBitSize + 15) / 16) {
 
196
                        *out += i16[i + 2];
 
197
                        *out <<= 16;
 
198
                }
 
199
                if (i + 1 < (group->primeBitSize + 15) / 16) {
 
200
                        *out += i16[i + 1];
 
201
                        *out <<= 16;
 
202
                }
 
203
                *out++ += i16[i];
 
204
        }
 
205
#endif
 
206
 
 
207
        /* Perform final reduction.  mpout should already be the same number
 
208
         * of bits as p, but might not be less than p.  Make it so. Since
 
209
         * mpout has the same number of bits as p, and 2p has a larger bit
 
210
         * size, then mpout < 2p, so a single subtraction of p will suffice. */
 
211
        if (mp_cmp(mpout, &ecgroup->meth->irr) >= 0) {
 
212
                mp_sub(mpout, &ecgroup->meth->irr, mpout);
 
213
        }
 
214
 
 
215
        /* Shrink the size of the mp_int to the actual used size (required for 
 
216
         * mp_cmp_z == 0) */
 
217
        out = MP_DIGITS(mpout);
 
218
        for (i = group->numInts - 1; i > 0; i--) {
 
219
                if (out[i] != 0)
 
220
                        break;
 
221
        }
 
222
        MP_USED(mpout) = i + 1;
 
223
 
 
224
        /* Should be between 0 and p-1 */
 
225
        ECFP_ASSERT(mp_cmp(mpout, &ecgroup->meth->irr) < 0);
 
226
        ECFP_ASSERT(mp_cmp_z(mpout) >= 0);
 
227
}
 
228
 
 
229
/* Converts from an mpint into a floating point representation. */
 
230
void
 
231
ecfp_i2fp(double *out, const mp_int *x, const ECGroup *ecgroup)
 
232
{
 
233
        int i;
 
234
        int j = 0;
 
235
        int size;
 
236
        double shift = 1;
 
237
        mp_digit *in;
 
238
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
239
 
 
240
#ifdef ECL_DEBUG
 
241
        /* if debug mode, convert result back using ecfp_fp2i into cmp, then
 
242
         * compare to x. */
 
243
        mp_int cmp;
 
244
 
 
245
        MP_DIGITS(&cmp) = NULL;
 
246
        mp_init(&cmp);
 
247
#endif
 
248
 
 
249
        ECFP_ASSERT(group != NULL);
 
250
 
 
251
        /* init output to 0 (since we skip over some terms) */
 
252
        for (i = 0; i < group->numDoubles; i++)
 
253
                out[i] = 0;
 
254
        i = 0;
 
255
 
 
256
        size = MP_USED(x);
 
257
        in = MP_DIGITS(x);
 
258
 
 
259
        /* Copy from int into doubles */
 
260
#ifdef ECL_THIRTY_TWO_BIT
 
261
        while (j < size) {
 
262
                while (group->doubleBitSize * (i + 1) <= 32 * j) {
 
263
                        i++;
 
264
                }
 
265
                ECFP_ASSERT(group->doubleBitSize * i <= 32 * j);
 
266
                out[i] = in[j];
 
267
                out[i] *= shift;
 
268
                shift *= ecfp_two32;
 
269
                j++;
 
270
        }
 
271
#else
 
272
        while (j < size) {
 
273
                while (group->doubleBitSize * (i + 1) <= 64 * j) {
 
274
                        i++;
 
275
                }
 
276
                ECFP_ASSERT(group->doubleBitSize * i <= 64 * j);
 
277
                out[i] = (in[j] & 0x00000000FFFFFFFF) * shift;
 
278
 
 
279
                while (group->doubleBitSize * (i + 1) <= 64 * j + 32) {
 
280
                        i++;
 
281
                }
 
282
                ECFP_ASSERT(24 * i <= 64 * j + 32);
 
283
                out[i] = (in[j] & 0xFFFFFFFF00000000) * shift;
 
284
 
 
285
                shift *= ecfp_two64;
 
286
                j++;
 
287
        }
 
288
#endif
 
289
        /* Realign bits to match double boundaries */
 
290
        ecfp_tidyShort(out, group);
 
291
 
 
292
#ifdef ECL_DEBUG
 
293
        /* Convert result back to mp_int, compare to original */
 
294
        ecfp_fp2i(&cmp, out, ecgroup);
 
295
        ECFP_ASSERT(mp_cmp(&cmp, x) == 0);
 
296
        mp_clear(&cmp);
 
297
#endif
 
298
}
 
299
 
 
300
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
 
301
 * a, b and p are the elliptic curve coefficients and the prime that
 
302
 * determines the field GFp.  Elliptic curve points P and R can be
 
303
 * identical.  Uses Jacobian coordinates. Uses 4-bit window method. */
 
304
mp_err
 
305
ec_GFp_point_mul_jac_4w_fp(const mp_int *n, const mp_int *px,
 
306
                                                   const mp_int *py, mp_int *rx, mp_int *ry,
 
307
                                                   const ECGroup *ecgroup)
 
308
{
 
309
        mp_err res = MP_OKAY;
 
310
        ecfp_jac_pt precomp[16], r;
 
311
        ecfp_aff_pt p;
 
312
        EC_group_fp *group;
 
313
 
 
314
        mp_int rz;
 
315
        int i, ni, d;
 
316
 
 
317
        ARGCHK(ecgroup != NULL, MP_BADARG);
 
318
        ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
 
319
 
 
320
        group = (EC_group_fp *) ecgroup->extra1;
 
321
        MP_DIGITS(&rz) = 0;
 
322
        MP_CHECKOK(mp_init(&rz));
 
323
 
 
324
        /* init p, da */
 
325
        ecfp_i2fp(p.x, px, ecgroup);
 
326
        ecfp_i2fp(p.y, py, ecgroup);
 
327
        ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
 
328
 
 
329
        /* Do precomputation */
 
330
        group->precompute_jac(precomp, &p, group);
 
331
 
 
332
        /* Do main body of calculations */
 
333
        d = (mpl_significant_bits(n) + 3) / 4;
 
334
 
 
335
        /* R = inf */
 
336
        for (i = 0; i < group->numDoubles; i++) {
 
337
                r.z[i] = 0;
 
338
        }
 
339
 
 
340
        for (i = d - 1; i >= 0; i--) {
 
341
                /* compute window ni */
 
342
                ni = MP_GET_BIT(n, 4 * i + 3);
 
343
                ni <<= 1;
 
344
                ni |= MP_GET_BIT(n, 4 * i + 2);
 
345
                ni <<= 1;
 
346
                ni |= MP_GET_BIT(n, 4 * i + 1);
 
347
                ni <<= 1;
 
348
                ni |= MP_GET_BIT(n, 4 * i);
 
349
 
 
350
                /* R = 2^4 * R */
 
351
                group->pt_dbl_jac(&r, &r, group);
 
352
                group->pt_dbl_jac(&r, &r, group);
 
353
                group->pt_dbl_jac(&r, &r, group);
 
354
                group->pt_dbl_jac(&r, &r, group);
 
355
 
 
356
                /* R = R + (ni * P) */
 
357
                group->pt_add_jac(&r, &precomp[ni], &r, group);
 
358
        }
 
359
 
 
360
        /* Convert back to integer */
 
361
        ecfp_fp2i(rx, r.x, ecgroup);
 
362
        ecfp_fp2i(ry, r.y, ecgroup);
 
363
        ecfp_fp2i(&rz, r.z, ecgroup);
 
364
 
 
365
        /* convert result S to affine coordinates */
 
366
        MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, ecgroup));
 
367
 
 
368
  CLEANUP:
 
369
        mp_clear(&rz);
 
370
        return res;
 
371
}
 
372
 
 
373
/* Uses mixed Jacobian-affine coordinates to perform a point
 
374
 * multiplication: R = n * P, n scalar. Uses mixed Jacobian-affine
 
375
 * coordinates (Jacobian coordinates for doubles and affine coordinates
 
376
 * for additions; based on recommendation from Brown et al.). Not very
 
377
 * time efficient but quite space efficient, no precomputation needed.
 
378
 * group contains the elliptic curve coefficients and the prime that
 
379
 * determines the field GFp.  Elliptic curve points P and R can be
 
380
 * identical. Performs calculations in floating point number format, since 
 
381
 * this is faster than the integer operations on the ULTRASPARC III.
 
382
 * Uses left-to-right binary method (double & add) (algorithm 9) for
 
383
 * scalar-point multiplication from Brown, Hankerson, Lopez, Menezes.
 
384
 * Software Implementation of the NIST Elliptic Curves Over Prime Fields. */
 
385
mp_err
 
386
ec_GFp_pt_mul_jac_fp(const mp_int *n, const mp_int *px, const mp_int *py,
 
387
                                         mp_int *rx, mp_int *ry, const ECGroup *ecgroup)
 
388
{
 
389
        mp_err res;
 
390
        mp_int sx, sy, sz;
 
391
 
 
392
        ecfp_aff_pt p;
 
393
        ecfp_jac_pt r;
 
394
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
395
 
 
396
        int i, l;
 
397
 
 
398
        MP_DIGITS(&sx) = 0;
 
399
        MP_DIGITS(&sy) = 0;
 
400
        MP_DIGITS(&sz) = 0;
 
401
        MP_CHECKOK(mp_init(&sx));
 
402
        MP_CHECKOK(mp_init(&sy));
 
403
        MP_CHECKOK(mp_init(&sz));
 
404
 
 
405
        /* if n = 0 then r = inf */
 
406
        if (mp_cmp_z(n) == 0) {
 
407
                mp_zero(rx);
 
408
                mp_zero(ry);
 
409
                res = MP_OKAY;
 
410
                goto CLEANUP;
 
411
                /* if n < 0 then out of range error */
 
412
        } else if (mp_cmp_z(n) < 0) {
 
413
                res = MP_RANGE;
 
414
                goto CLEANUP;
 
415
        }
 
416
 
 
417
        /* Convert from integer to floating point */
 
418
        ecfp_i2fp(p.x, px, ecgroup);
 
419
        ecfp_i2fp(p.y, py, ecgroup);
 
420
        ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);
 
421
 
 
422
        /* Init r to point at infinity */
 
423
        for (i = 0; i < group->numDoubles; i++) {
 
424
                r.z[i] = 0;
 
425
        }
 
426
 
 
427
        /* double and add method */
 
428
        l = mpl_significant_bits(n) - 1;
 
429
 
 
430
        for (i = l; i >= 0; i--) {
 
431
                /* R = 2R */
 
432
                group->pt_dbl_jac(&r, &r, group);
 
433
 
 
434
                /* if n_i = 1, then R = R + Q */
 
435
                if (MP_GET_BIT(n, i) != 0) {
 
436
                        group->pt_add_jac_aff(&r, &p, &r, group);
 
437
                }
 
438
        }
 
439
 
 
440
        /* Convert from floating point to integer */
 
441
        ecfp_fp2i(&sx, r.x, ecgroup);
 
442
        ecfp_fp2i(&sy, r.y, ecgroup);
 
443
        ecfp_fp2i(&sz, r.z, ecgroup);
 
444
 
 
445
        /* convert result R to affine coordinates */
 
446
        MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup));
 
447
 
 
448
  CLEANUP:
 
449
        mp_clear(&sx);
 
450
        mp_clear(&sy);
 
451
        mp_clear(&sz);
 
452
        return res;
 
453
}
 
454
 
 
455
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
 
456
 * curve points P and R can be identical. Uses mixed Modified-Jacobian
 
457
 * co-ordinates for doubling and Chudnovsky Jacobian coordinates for
 
458
 * additions. Uses 5-bit window NAF method (algorithm 11) for scalar-point 
 
459
 * multiplication from Brown, Hankerson, Lopez, Menezes. Software
 
460
 * Implementation of the NIST Elliptic Curves Over Prime Fields. */
 
461
mp_err
 
462
ec_GFp_point_mul_wNAF_fp(const mp_int *n, const mp_int *px,
 
463
                                                 const mp_int *py, mp_int *rx, mp_int *ry,
 
464
                                                 const ECGroup *ecgroup)
 
465
{
 
466
        mp_err res = MP_OKAY;
 
467
        mp_int sx, sy, sz;
 
468
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
469
        ecfp_chud_pt precomp[16];
 
470
 
 
471
        ecfp_aff_pt p;
 
472
        ecfp_jm_pt r;
 
473
 
 
474
        signed char naf[group->orderBitSize + 1];
 
475
        int i;
 
476
 
 
477
        MP_DIGITS(&sx) = 0;
 
478
        MP_DIGITS(&sy) = 0;
 
479
        MP_DIGITS(&sz) = 0;
 
480
        MP_CHECKOK(mp_init(&sx));
 
481
        MP_CHECKOK(mp_init(&sy));
 
482
        MP_CHECKOK(mp_init(&sz));
 
483
 
 
484
        /* if n = 0 then r = inf */
 
485
        if (mp_cmp_z(n) == 0) {
 
486
                mp_zero(rx);
 
487
                mp_zero(ry);
 
488
                res = MP_OKAY;
 
489
                goto CLEANUP;
 
490
                /* if n < 0 then out of range error */
 
491
        } else if (mp_cmp_z(n) < 0) {
 
492
                res = MP_RANGE;
 
493
                goto CLEANUP;
 
494
        }
 
495
 
 
496
        /* Convert from integer to floating point */
 
497
        ecfp_i2fp(p.x, px, ecgroup);
 
498
        ecfp_i2fp(p.y, py, ecgroup);
 
499
        ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);
 
500
 
 
501
        /* Perform precomputation */
 
502
        group->precompute_chud(precomp, &p, group);
 
503
 
 
504
        /* Compute 5NAF */
 
505
        ec_compute_wNAF(naf, group->orderBitSize, n, 5);
 
506
 
 
507
        /* Init R = pt at infinity */
 
508
        for (i = 0; i < group->numDoubles; i++) {
 
509
                r.z[i] = 0;
 
510
        }
 
511
 
 
512
        /* wNAF method */
 
513
        for (i = group->orderBitSize; i >= 0; i--) {
 
514
                /* R = 2R */
 
515
                group->pt_dbl_jm(&r, &r, group);
 
516
 
 
517
                if (naf[i] != 0) {
 
518
                        group->pt_add_jm_chud(&r, &precomp[(naf[i] + 15) / 2], &r,
 
519
                                                                  group);
 
520
                }
 
521
        }
 
522
 
 
523
        /* Convert from floating point to integer */
 
524
        ecfp_fp2i(&sx, r.x, ecgroup);
 
525
        ecfp_fp2i(&sy, r.y, ecgroup);
 
526
        ecfp_fp2i(&sz, r.z, ecgroup);
 
527
 
 
528
        /* convert result R to affine coordinates */
 
529
        MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup));
 
530
 
 
531
  CLEANUP:
 
532
        mp_clear(&sx);
 
533
        mp_clear(&sy);
 
534
        mp_clear(&sz);
 
535
        return res;
 
536
}
 
537
 
 
538
/* Cleans up extra memory allocated in ECGroup for this implementation. */
 
539
void
 
540
ec_GFp_extra_free_fp(ECGroup *group)
 
541
{
 
542
        if (group->extra1 != NULL) {
 
543
                free(group->extra1);
 
544
                group->extra1 = NULL;
 
545
        }
 
546
}
 
547
 
 
548
/* Tests what precision floating point arithmetic is set to. This should
 
549
 * be either a 53-bit mantissa (IEEE standard) or a 64-bit mantissa
 
550
 * (extended precision on x86) and sets it into the EC_group_fp. Returns
 
551
 * either 53 or 64 accordingly. */
 
552
int
 
553
ec_set_fp_precision(EC_group_fp * group)
 
554
{
 
555
        double a = 9007199254740992.0;  /* 2^53 */
 
556
        double b = a + 1;
 
557
 
 
558
        if (a == b) {
 
559
                group->fpPrecision = 53;
 
560
                group->alpha = ecfp_alpha_53;
 
561
                return 53;
 
562
        }
 
563
        group->fpPrecision = 64;
 
564
        group->alpha = ecfp_alpha_64;
 
565
        return 64;
 
566
}