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.

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

mercurial