security/nss/lib/freebl/ecl/ecp_fp.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial