security/nss/lib/freebl/ecl/ecp_fpinc.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 /* This source file is meant to be included by other source files
     6  * (ecp_fp###.c, where ### is one of 160, 192, 224) and should not
     7  * constitute an independent compilation unit. It requires the following
     8  * preprocessor definitions be made: ECFP_BSIZE - the number of bits in
     9  * the field's prime 
    10  * ECFP_NUMDOUBLES - the number of doubles to store one
    11  * multi-precision integer in floating point 
    13 /* Adds a prefix to a given token to give a unique token name. Prefixes
    14  * with "ecfp" + ECFP_BSIZE + "_". e.g. if ECFP_BSIZE = 160, then
    15  * PREFIX(hello) = ecfp160_hello This optimization allows static function
    16  * linking and compiler loop unrolling without code duplication. */
    17 #ifndef PREFIX
    18 #define PREFIX(b) PREFIX1(ECFP_BSIZE, b)
    19 #define PREFIX1(bsize, b) PREFIX2(bsize, b)
    20 #define PREFIX2(bsize, b) ecfp ## bsize ## _ ## b
    21 #endif
    23 /* Returns true iff every double in d is 0. (If d == 0 and it is tidied,
    24  * this will be true.) */
    25 mp_err PREFIX(isZero) (const double *d) {
    26 	int i;
    28 	for (i = 0; i < ECFP_NUMDOUBLES; i++) {
    29 		if (d[i] != 0)
    30 			return MP_NO;
    31 	}
    32 	return MP_YES;
    33 }
    35 /* Sets the multi-precision floating point number at t = 0 */
    36 void PREFIX(zero) (double *t) {
    37 	int i;
    39 	for (i = 0; i < ECFP_NUMDOUBLES; i++) {
    40 		t[i] = 0;
    41 	}
    42 }
    44 /* Sets the multi-precision floating point number at t = 1 */
    45 void PREFIX(one) (double *t) {
    46 	int i;
    48 	t[0] = 1;
    49 	for (i = 1; i < ECFP_NUMDOUBLES; i++) {
    50 		t[i] = 0;
    51 	}
    52 }
    54 /* Checks if point P(x, y, z) is at infinity. Uses Jacobian coordinates. */
    55 mp_err PREFIX(pt_is_inf_jac) (const ecfp_jac_pt * p) {
    56 	return PREFIX(isZero) (p->z);
    57 }
    59 /* Sets the Jacobian point P to be at infinity. */
    60 void PREFIX(set_pt_inf_jac) (ecfp_jac_pt * p) {
    61 	PREFIX(zero) (p->z);
    62 }
    64 /* Checks if point P(x, y) is at infinity. Uses Affine coordinates. */
    65 mp_err PREFIX(pt_is_inf_aff) (const ecfp_aff_pt * p) {
    66 	if (PREFIX(isZero) (p->x) == MP_YES && PREFIX(isZero) (p->y) == MP_YES)
    67 		return MP_YES;
    68 	return MP_NO;
    69 }
    71 /* Sets the affine point P to be at infinity. */
    72 void PREFIX(set_pt_inf_aff) (ecfp_aff_pt * p) {
    73 	PREFIX(zero) (p->x);
    74 	PREFIX(zero) (p->y);
    75 }
    77 /* Checks if point P(x, y, z, a*z^4) is at infinity. Uses Modified
    78  * Jacobian coordinates. */
    79 mp_err PREFIX(pt_is_inf_jm) (const ecfp_jm_pt * p) {
    80 	return PREFIX(isZero) (p->z);
    81 }
    83 /* Sets the Modified Jacobian point P to be at infinity. */
    84 void PREFIX(set_pt_inf_jm) (ecfp_jm_pt * p) {
    85 	PREFIX(zero) (p->z);
    86 }
    88 /* Checks if point P(x, y, z, z^2, z^3) is at infinity. Uses Chudnovsky
    89  * Jacobian coordinates */
    90 mp_err PREFIX(pt_is_inf_chud) (const ecfp_chud_pt * p) {
    91 	return PREFIX(isZero) (p->z);
    92 }
    94 /* Sets the Chudnovsky Jacobian point P to be at infinity. */
    95 void PREFIX(set_pt_inf_chud) (ecfp_chud_pt * p) {
    96 	PREFIX(zero) (p->z);
    97 }
    99 /* Copies a multi-precision floating point number, Setting dest = src */
   100 void PREFIX(copy) (double *dest, const double *src) {
   101 	int i;
   103 	for (i = 0; i < ECFP_NUMDOUBLES; i++) {
   104 		dest[i] = src[i];
   105 	}
   106 }
   108 /* Sets dest = -src */
   109 void PREFIX(negLong) (double *dest, const double *src) {
   110 	int i;
   112 	for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) {
   113 		dest[i] = -src[i];
   114 	}
   115 }
   117 /* Sets r = -p p = (x, y, z, z2, z3) r = (x, -y, z, z2, z3) Uses
   118  * Chudnovsky Jacobian coordinates. */
   119 /* TODO reverse order */
   120 void PREFIX(pt_neg_chud) (const ecfp_chud_pt * p, ecfp_chud_pt * r) {
   121 	int i;
   123 	PREFIX(copy) (r->x, p->x);
   124 	PREFIX(copy) (r->z, p->z);
   125 	PREFIX(copy) (r->z2, p->z2);
   126 	PREFIX(copy) (r->z3, p->z3);
   127 	for (i = 0; i < ECFP_NUMDOUBLES; i++) {
   128 		r->y[i] = -p->y[i];
   129 	}
   130 }
   132 /* Computes r = x + y. Does not tidy or reduce. Any combinations of r, x,
   133  * y can point to the same data. Componentwise adds first ECFP_NUMDOUBLES
   134  * doubles of x and y and stores the result in r. */
   135 void PREFIX(addShort) (double *r, const double *x, const double *y) {
   136 	int i;
   138 	for (i = 0; i < ECFP_NUMDOUBLES; i++) {
   139 		*r++ = *x++ + *y++;
   140 	}
   141 }
   143 /* Computes r = x + y. Does not tidy or reduce. Any combinations of r, x,
   144  * y can point to the same data. Componentwise adds first
   145  * 2*ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */
   146 void PREFIX(addLong) (double *r, const double *x, const double *y) {
   147 	int i;
   149 	for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) {
   150 		*r++ = *x++ + *y++;
   151 	}
   152 }
   154 /* Computes r = x - y. Does not tidy or reduce. Any combinations of r, x,
   155  * y can point to the same data. Componentwise subtracts first
   156  * ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */
   157 void PREFIX(subtractShort) (double *r, const double *x, const double *y) {
   158 	int i;
   160 	for (i = 0; i < ECFP_NUMDOUBLES; i++) {
   161 		*r++ = *x++ - *y++;
   162 	}
   163 }
   165 /* Computes r = x - y. Does not tidy or reduce. Any combinations of r, x,
   166  * y can point to the same data. Componentwise subtracts first
   167  * 2*ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */
   168 void PREFIX(subtractLong) (double *r, const double *x, const double *y) {
   169 	int i;
   171 	for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) {
   172 		*r++ = *x++ - *y++;
   173 	}
   174 }
   176 /* Computes r = x*y.  Both x and y should be tidied and reduced,
   177  * r must be different (point to different memory) than x and y.
   178  * Does not tidy or reduce. */
   179 void PREFIX(multiply)(double *r, const double *x, const double *y) {
   180 	int i, j;
   182 	for(j=0;j<ECFP_NUMDOUBLES-1;j++) {
   183 		r[j] = x[0] * y[j];
   184 		r[j+(ECFP_NUMDOUBLES-1)] = x[ECFP_NUMDOUBLES-1] * y[j];
   185 	}
   186 	r[ECFP_NUMDOUBLES-1] = x[0] * y[ECFP_NUMDOUBLES-1];
   187 	r[ECFP_NUMDOUBLES-1] += x[ECFP_NUMDOUBLES-1] * y[0];
   188 	r[2*ECFP_NUMDOUBLES-2] = x[ECFP_NUMDOUBLES-1] * y[ECFP_NUMDOUBLES-1];
   189 	r[2*ECFP_NUMDOUBLES-1] = 0;
   191 	for(i=1;i<ECFP_NUMDOUBLES-1;i++) {
   192 		for(j=0;j<ECFP_NUMDOUBLES;j++) {
   193 			r[i+j] += (x[i] * y[j]);
   194 		}
   195 	}
   196 }
   198 /* Computes the square of x and stores the result in r.  x should be
   199  * tidied & reduced, r will be neither tidied nor reduced. 
   200  * r should point to different memory than x */
   201 void PREFIX(square) (double *r, const double *x) {
   202 	PREFIX(multiply) (r, x, x);
   203 }
   205 /* Perform a point doubling in Jacobian coordinates. Input and output
   206  * should be multi-precision floating point integers. */
   207 void PREFIX(pt_dbl_jac) (const ecfp_jac_pt * dp, ecfp_jac_pt * dr,
   208 						 const EC_group_fp * group) {
   209 	double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
   210 		M[2 * ECFP_NUMDOUBLES], S[2 * ECFP_NUMDOUBLES];
   212 	/* Check for point at infinity */
   213 	if (PREFIX(pt_is_inf_jac) (dp) == MP_YES) {
   214 		/* Set r = pt at infinity */
   215 		PREFIX(set_pt_inf_jac) (dr);
   216 		goto CLEANUP;
   217 	}
   219 	/* Perform typical point doubling operations */
   221 	/* TODO? is it worthwhile to do optimizations for when pz = 1? */
   223 	if (group->aIsM3) {
   224 		/* When a = -3, M = 3(px - pz^2)(px + pz^2) */
   225 		PREFIX(square) (t1, dp->z);
   226 		group->ecfp_reduce(t1, t1, group);	/* 2^23 since the negative
   227 											 * rounding buys another bit */
   228 		PREFIX(addShort) (t0, dp->x, t1);	/* 2*2^23 */
   229 		PREFIX(subtractShort) (t1, dp->x, t1);	/* 2 * 2^23 */
   230 		PREFIX(multiply) (M, t0, t1);	/* 40 * 2^46 */
   231 		PREFIX(addLong) (t0, M, M);	/* 80 * 2^46 */
   232 		PREFIX(addLong) (M, t0, M);	/* 120 * 2^46 < 2^53 */
   233 		group->ecfp_reduce(M, M, group);
   234 	} else {
   235 		/* Generic case */
   236 		/* M = 3 (px^2) + a*(pz^4) */
   237 		PREFIX(square) (t0, dp->x);
   238 		PREFIX(addLong) (M, t0, t0);
   239 		PREFIX(addLong) (t0, t0, M);	/* t0 = 3(px^2) */
   240 		PREFIX(square) (M, dp->z);
   241 		group->ecfp_reduce(M, M, group);
   242 		PREFIX(square) (t1, M);
   243 		group->ecfp_reduce(t1, t1, group);
   244 		PREFIX(multiply) (M, t1, group->curvea);	/* M = a(pz^4) */
   245 		PREFIX(addLong) (M, M, t0);
   246 		group->ecfp_reduce(M, M, group);
   247 	}
   249 	/* rz = 2 * py * pz */
   250 	PREFIX(multiply) (t1, dp->y, dp->z);
   251 	PREFIX(addLong) (t1, t1, t1);
   252 	group->ecfp_reduce(dr->z, t1, group);
   254 	/* t0 = 2y^2 */
   255 	PREFIX(square) (t0, dp->y);
   256 	group->ecfp_reduce(t0, t0, group);
   257 	PREFIX(addShort) (t0, t0, t0);
   259 	/* S = 4 * px * py^2 = 2 * px * t0 */
   260 	PREFIX(multiply) (S, dp->x, t0);
   261 	PREFIX(addLong) (S, S, S);
   262 	group->ecfp_reduce(S, S, group);
   264 	/* rx = M^2 - 2 * S */
   265 	PREFIX(square) (t1, M);
   266 	PREFIX(subtractShort) (t1, t1, S);
   267 	PREFIX(subtractShort) (t1, t1, S);
   268 	group->ecfp_reduce(dr->x, t1, group);
   270 	/* ry = M * (S - rx) - 8 * py^4 */
   271 	PREFIX(square) (t1, t0);	/* t1 = 4y^4 */
   272 	PREFIX(subtractShort) (S, S, dr->x);
   273 	PREFIX(multiply) (t0, M, S);
   274 	PREFIX(subtractLong) (t0, t0, t1);
   275 	PREFIX(subtractLong) (t0, t0, t1);
   276 	group->ecfp_reduce(dr->y, t0, group);
   278   CLEANUP:
   279 	return;
   280 }
   282 /* Perform a point addition using coordinate system Jacobian + Affine ->
   283  * Jacobian. Input and output should be multi-precision floating point
   284  * integers. */
   285 void PREFIX(pt_add_jac_aff) (const ecfp_jac_pt * p, const ecfp_aff_pt * q,
   286 							 ecfp_jac_pt * r, const EC_group_fp * group) {
   287 	/* Temporary storage */
   288 	double A[2 * ECFP_NUMDOUBLES], B[2 * ECFP_NUMDOUBLES],
   289 		C[2 * ECFP_NUMDOUBLES], C2[2 * ECFP_NUMDOUBLES],
   290 		D[2 * ECFP_NUMDOUBLES], C3[2 * ECFP_NUMDOUBLES];
   292 	/* Check for point at infinity for p or q */
   293 	if (PREFIX(pt_is_inf_aff) (q) == MP_YES) {
   294 		PREFIX(copy) (r->x, p->x);
   295 		PREFIX(copy) (r->y, p->y);
   296 		PREFIX(copy) (r->z, p->z);
   297 		goto CLEANUP;
   298 	} else if (PREFIX(pt_is_inf_jac) (p) == MP_YES) {
   299 		PREFIX(copy) (r->x, q->x);
   300 		PREFIX(copy) (r->y, q->y);
   301 		/* Since the affine point is not infinity, we can set r->z = 1 */
   302 		PREFIX(one) (r->z);
   303 		goto CLEANUP;
   304 	}
   306 	/* Calculates c = qx * pz^2 - px d = (qy * b - py) rx = d^2 - c^3 + 2
   307 	 * (px * c^2) ry = d * (c-rx) - py*c^3 rz = c * pz */
   309 	/* A = pz^2, B = pz^3 */
   310 	PREFIX(square) (A, p->z);
   311 	group->ecfp_reduce(A, A, group);
   312 	PREFIX(multiply) (B, A, p->z);
   313 	group->ecfp_reduce(B, B, group);
   315 	/* C = qx * A - px */
   316 	PREFIX(multiply) (C, q->x, A);
   317 	PREFIX(subtractShort) (C, C, p->x);
   318 	group->ecfp_reduce(C, C, group);
   320 	/* D = qy * B - py */
   321 	PREFIX(multiply) (D, q->y, B);
   322 	PREFIX(subtractShort) (D, D, p->y);
   323 	group->ecfp_reduce(D, D, group);
   325 	/* C2 = C^2, C3 = C^3 */
   326 	PREFIX(square) (C2, C);
   327 	group->ecfp_reduce(C2, C2, group);
   328 	PREFIX(multiply) (C3, C2, C);
   329 	group->ecfp_reduce(C3, C3, group);
   331 	/* rz = A = pz * C */
   332 	PREFIX(multiply) (A, p->z, C);
   333 	group->ecfp_reduce(r->z, A, group);
   335 	/* C = px * C^2, untidied, unreduced */
   336 	PREFIX(multiply) (C, p->x, C2);
   338 	/* A = D^2, untidied, unreduced */
   339 	PREFIX(square) (A, D);
   341 	/* rx = B = A - C3 - C - C = D^2 - (C^3 + 2 * (px * C^2) */
   342 	PREFIX(subtractShort) (A, A, C3);
   343 	PREFIX(subtractLong) (A, A, C);
   344 	PREFIX(subtractLong) (A, A, C);
   345 	group->ecfp_reduce(r->x, A, group);
   347 	/* B = py * C3, untidied, unreduced */
   348 	PREFIX(multiply) (B, p->y, C3);
   350 	/* C = px * C^2 - rx */
   351 	PREFIX(subtractShort) (C, C, r->x);
   352 	group->ecfp_reduce(C, C, group);
   354 	/* ry = A = D * C - py * C^3 */
   355 	PREFIX(multiply) (A, D, C);
   356 	PREFIX(subtractLong) (A, A, B);
   357 	group->ecfp_reduce(r->y, A, group);
   359   CLEANUP:
   360 	return;
   361 }
   363 /* Perform a point addition using Jacobian coordinate system. Input and
   364  * output should be multi-precision floating point integers. */
   365 void PREFIX(pt_add_jac) (const ecfp_jac_pt * p, const ecfp_jac_pt * q,
   366 						 ecfp_jac_pt * r, const EC_group_fp * group) {
   368 	/* Temporary Storage */
   369 	double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
   370 		U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES],
   371 		S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES],
   372 		H3[2 * ECFP_NUMDOUBLES];
   374 	/* Check for point at infinity for p, if so set r = q */
   375 	if (PREFIX(pt_is_inf_jac) (p) == MP_YES) {
   376 		PREFIX(copy) (r->x, q->x);
   377 		PREFIX(copy) (r->y, q->y);
   378 		PREFIX(copy) (r->z, q->z);
   379 		goto CLEANUP;
   380 	}
   382 	/* Check for point at infinity for p, if so set r = q */
   383 	if (PREFIX(pt_is_inf_jac) (q) == MP_YES) {
   384 		PREFIX(copy) (r->x, p->x);
   385 		PREFIX(copy) (r->y, p->y);
   386 		PREFIX(copy) (r->z, p->z);
   387 		goto CLEANUP;
   388 	}
   390 	/* U = px * qz^2 , S = py * qz^3 */
   391 	PREFIX(square) (t0, q->z);
   392 	group->ecfp_reduce(t0, t0, group);
   393 	PREFIX(multiply) (U, p->x, t0);
   394 	group->ecfp_reduce(U, U, group);
   395 	PREFIX(multiply) (t1, t0, q->z);
   396 	group->ecfp_reduce(t1, t1, group);
   397 	PREFIX(multiply) (t0, p->y, t1);
   398 	group->ecfp_reduce(S, t0, group);
   400 	/* H = qx*(pz)^2 - U , R = (qy * pz^3 - S) */
   401 	PREFIX(square) (t0, p->z);
   402 	group->ecfp_reduce(t0, t0, group);
   403 	PREFIX(multiply) (H, q->x, t0);
   404 	PREFIX(subtractShort) (H, H, U);
   405 	group->ecfp_reduce(H, H, group);
   406 	PREFIX(multiply) (t1, t0, p->z);	/* t1 = pz^3 */
   407 	group->ecfp_reduce(t1, t1, group);
   408 	PREFIX(multiply) (t0, t1, q->y);	/* t0 = qy * pz^3 */
   409 	PREFIX(subtractShort) (t0, t0, S);
   410 	group->ecfp_reduce(R, t0, group);
   412 	/* U = U*H^2, H3 = H^3 */
   413 	PREFIX(square) (t0, H);
   414 	group->ecfp_reduce(t0, t0, group);
   415 	PREFIX(multiply) (t1, U, t0);
   416 	group->ecfp_reduce(U, t1, group);
   417 	PREFIX(multiply) (H3, t0, H);
   418 	group->ecfp_reduce(H3, H3, group);
   420 	/* rz = pz * qz * H */
   421 	PREFIX(multiply) (t0, q->z, H);
   422 	group->ecfp_reduce(t0, t0, group);
   423 	PREFIX(multiply) (t1, t0, p->z);
   424 	group->ecfp_reduce(r->z, t1, group);
   426 	/* rx = R^2 - H^3 - 2 * U */
   427 	PREFIX(square) (t0, R);
   428 	PREFIX(subtractShort) (t0, t0, H3);
   429 	PREFIX(subtractShort) (t0, t0, U);
   430 	PREFIX(subtractShort) (t0, t0, U);
   431 	group->ecfp_reduce(r->x, t0, group);
   433 	/* ry = R(U - rx) - S*H3 */
   434 	PREFIX(subtractShort) (t1, U, r->x);
   435 	PREFIX(multiply) (t0, t1, R);
   436 	PREFIX(multiply) (t1, S, H3);
   437 	PREFIX(subtractLong) (t1, t0, t1);
   438 	group->ecfp_reduce(r->y, t1, group);
   440   CLEANUP:
   441 	return;
   442 }
   444 /* Perform a point doubling in Modified Jacobian coordinates. Input and
   445  * output should be multi-precision floating point integers. */
   446 void PREFIX(pt_dbl_jm) (const ecfp_jm_pt * p, ecfp_jm_pt * r,
   447 						const EC_group_fp * group) {
   449 	/* Temporary storage */
   450 	double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
   451 		M[2 * ECFP_NUMDOUBLES], S[2 * ECFP_NUMDOUBLES],
   452 		U[2 * ECFP_NUMDOUBLES], T[2 * ECFP_NUMDOUBLES];
   454 	/* Check for point at infinity */
   455 	if (PREFIX(pt_is_inf_jm) (p) == MP_YES) {
   456 		/* Set r = pt at infinity by setting rz = 0 */
   457 		PREFIX(set_pt_inf_jm) (r);
   458 		goto CLEANUP;
   459 	}
   461 	/* M = 3 (px^2) + a*(pz^4) */
   462 	PREFIX(square) (t0, p->x);
   463 	PREFIX(addLong) (M, t0, t0);
   464 	PREFIX(addLong) (t0, t0, M);	/* t0 = 3(px^2) */
   465 	PREFIX(addShort) (t0, t0, p->az4);
   466 	group->ecfp_reduce(M, t0, group);
   468 	/* rz = 2 * py * pz */
   469 	PREFIX(multiply) (t1, p->y, p->z);
   470 	PREFIX(addLong) (t1, t1, t1);
   471 	group->ecfp_reduce(r->z, t1, group);
   473 	/* t0 = 2y^2, U = 8y^4 */
   474 	PREFIX(square) (t0, p->y);
   475 	group->ecfp_reduce(t0, t0, group);
   476 	PREFIX(addShort) (t0, t0, t0);
   477 	PREFIX(square) (U, t0);
   478 	group->ecfp_reduce(U, U, group);
   479 	PREFIX(addShort) (U, U, U);
   481 	/* S = 4 * px * py^2 = 2 * px * t0 */
   482 	PREFIX(multiply) (S, p->x, t0);
   483 	group->ecfp_reduce(S, S, group);
   484 	PREFIX(addShort) (S, S, S);
   486 	/* rx = M^2 - 2S */
   487 	PREFIX(square) (T, M);
   488 	PREFIX(subtractShort) (T, T, S);
   489 	PREFIX(subtractShort) (T, T, S);
   490 	group->ecfp_reduce(r->x, T, group);
   492 	/* ry = M * (S - rx) - U */
   493 	PREFIX(subtractShort) (S, S, r->x);
   494 	PREFIX(multiply) (t0, M, S);
   495 	PREFIX(subtractShort) (t0, t0, U);
   496 	group->ecfp_reduce(r->y, t0, group);
   498 	/* ra*z^4 = 2*U*(apz4) */
   499 	PREFIX(multiply) (t1, U, p->az4);
   500 	PREFIX(addLong) (t1, t1, t1);
   501 	group->ecfp_reduce(r->az4, t1, group);
   503   CLEANUP:
   504 	return;
   505 }
   507 /* Perform a point doubling using coordinates Affine -> Chudnovsky
   508  * Jacobian. Input and output should be multi-precision floating point
   509  * integers. */
   510 void PREFIX(pt_dbl_aff2chud) (const ecfp_aff_pt * p, ecfp_chud_pt * r,
   511 							  const EC_group_fp * group) {
   512 	double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
   513 		M[2 * ECFP_NUMDOUBLES], twoY2[2 * ECFP_NUMDOUBLES],
   514 		S[2 * ECFP_NUMDOUBLES];
   516 	/* Check for point at infinity for p, if so set r = O */
   517 	if (PREFIX(pt_is_inf_aff) (p) == MP_YES) {
   518 		PREFIX(set_pt_inf_chud) (r);
   519 		goto CLEANUP;
   520 	}
   522 	/* M = 3(px)^2 + a */
   523 	PREFIX(square) (t0, p->x);
   524 	PREFIX(addLong) (t1, t0, t0);
   525 	PREFIX(addLong) (t1, t1, t0);
   526 	PREFIX(addShort) (t1, t1, group->curvea);
   527 	group->ecfp_reduce(M, t1, group);
   529 	/* twoY2 = 2*(py)^2, S = 4(px)(py)^2 */
   530 	PREFIX(square) (twoY2, p->y);
   531 	PREFIX(addLong) (twoY2, twoY2, twoY2);
   532 	group->ecfp_reduce(twoY2, twoY2, group);
   533 	PREFIX(multiply) (S, p->x, twoY2);
   534 	PREFIX(addLong) (S, S, S);
   535 	group->ecfp_reduce(S, S, group);
   537 	/* rx = M^2 - 2S */
   538 	PREFIX(square) (t0, M);
   539 	PREFIX(subtractShort) (t0, t0, S);
   540 	PREFIX(subtractShort) (t0, t0, S);
   541 	group->ecfp_reduce(r->x, t0, group);
   543 	/* ry = M(S-rx) - 8y^4 */
   544 	PREFIX(subtractShort) (t0, S, r->x);
   545 	PREFIX(multiply) (t1, t0, M);
   546 	PREFIX(square) (t0, twoY2);
   547 	PREFIX(subtractLong) (t1, t1, t0);
   548 	PREFIX(subtractLong) (t1, t1, t0);
   549 	group->ecfp_reduce(r->y, t1, group);
   551 	/* rz = 2py */
   552 	PREFIX(addShort) (r->z, p->y, p->y);
   554 	/* rz2 = rz^2 */
   555 	PREFIX(square) (t0, r->z);
   556 	group->ecfp_reduce(r->z2, t0, group);
   558 	/* rz3 = rz^3 */
   559 	PREFIX(multiply) (t0, r->z, r->z2);
   560 	group->ecfp_reduce(r->z3, t0, group);
   562   CLEANUP:
   563 	return;
   564 }
   566 /* Perform a point addition using coordinates: Modified Jacobian +
   567  * Chudnovsky Jacobian -> Modified Jacobian. Input and output should be
   568  * multi-precision floating point integers. */
   569 void PREFIX(pt_add_jm_chud) (ecfp_jm_pt * p, ecfp_chud_pt * q,
   570 							 ecfp_jm_pt * r, const EC_group_fp * group) {
   572 	double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
   573 		U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES],
   574 		S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES],
   575 		H3[2 * ECFP_NUMDOUBLES], pz2[2 * ECFP_NUMDOUBLES];
   577 	/* Check for point at infinity for p, if so set r = q need to convert
   578 	 * from Chudnovsky form to Modified Jacobian form */
   579 	if (PREFIX(pt_is_inf_jm) (p) == MP_YES) {
   580 		PREFIX(copy) (r->x, q->x);
   581 		PREFIX(copy) (r->y, q->y);
   582 		PREFIX(copy) (r->z, q->z);
   583 		PREFIX(square) (t0, q->z2);
   584 		group->ecfp_reduce(t0, t0, group);
   585 		PREFIX(multiply) (t1, t0, group->curvea);
   586 		group->ecfp_reduce(r->az4, t1, group);
   587 		goto CLEANUP;
   588 	}
   589 	/* Check for point at infinity for q, if so set r = p */
   590 	if (PREFIX(pt_is_inf_chud) (q) == MP_YES) {
   591 		PREFIX(copy) (r->x, p->x);
   592 		PREFIX(copy) (r->y, p->y);
   593 		PREFIX(copy) (r->z, p->z);
   594 		PREFIX(copy) (r->az4, p->az4);
   595 		goto CLEANUP;
   596 	}
   598 	/* U = px * qz^2 */
   599 	PREFIX(multiply) (U, p->x, q->z2);
   600 	group->ecfp_reduce(U, U, group);
   602 	/* H = qx*(pz)^2 - U */
   603 	PREFIX(square) (t0, p->z);
   604 	group->ecfp_reduce(pz2, t0, group);
   605 	PREFIX(multiply) (H, pz2, q->x);
   606 	group->ecfp_reduce(H, H, group);
   607 	PREFIX(subtractShort) (H, H, U);
   609 	/* U = U*H^2, H3 = H^3 */
   610 	PREFIX(square) (t0, H);
   611 	group->ecfp_reduce(t0, t0, group);
   612 	PREFIX(multiply) (t1, U, t0);
   613 	group->ecfp_reduce(U, t1, group);
   614 	PREFIX(multiply) (H3, t0, H);
   615 	group->ecfp_reduce(H3, H3, group);
   617 	/* S = py * qz^3 */
   618 	PREFIX(multiply) (S, p->y, q->z3);
   619 	group->ecfp_reduce(S, S, group);
   621 	/* R = (qy * z1^3 - s) */
   622 	PREFIX(multiply) (t0, pz2, p->z);
   623 	group->ecfp_reduce(t0, t0, group);
   624 	PREFIX(multiply) (R, t0, q->y);
   625 	PREFIX(subtractShort) (R, R, S);
   626 	group->ecfp_reduce(R, R, group);
   628 	/* rz = pz * qz * H */
   629 	PREFIX(multiply) (t1, q->z, H);
   630 	group->ecfp_reduce(t1, t1, group);
   631 	PREFIX(multiply) (t0, p->z, t1);
   632 	group->ecfp_reduce(r->z, t0, group);
   634 	/* rx = R^2 - H^3 - 2 * U */
   635 	PREFIX(square) (t0, R);
   636 	PREFIX(subtractShort) (t0, t0, H3);
   637 	PREFIX(subtractShort) (t0, t0, U);
   638 	PREFIX(subtractShort) (t0, t0, U);
   639 	group->ecfp_reduce(r->x, t0, group);
   641 	/* ry = R(U - rx) - S*H3 */
   642 	PREFIX(subtractShort) (t1, U, r->x);
   643 	PREFIX(multiply) (t0, t1, R);
   644 	PREFIX(multiply) (t1, S, H3);
   645 	PREFIX(subtractLong) (t1, t0, t1);
   646 	group->ecfp_reduce(r->y, t1, group);
   648 	if (group->aIsM3) {			/* a == -3 */
   649 		/* a(rz^4) = -3 * ((rz^2)^2) */
   650 		PREFIX(square) (t0, r->z);
   651 		group->ecfp_reduce(t0, t0, group);
   652 		PREFIX(square) (t1, t0);
   653 		PREFIX(addLong) (t0, t1, t1);
   654 		PREFIX(addLong) (t0, t0, t1);
   655 		PREFIX(negLong) (t0, t0);
   656 		group->ecfp_reduce(r->az4, t0, group);
   657 	} else {					/* Generic case */
   658 		/* a(rz^4) = a * ((rz^2)^2) */
   659 		PREFIX(square) (t0, r->z);
   660 		group->ecfp_reduce(t0, t0, group);
   661 		PREFIX(square) (t1, t0);
   662 		group->ecfp_reduce(t1, t1, group);
   663 		PREFIX(multiply) (t0, group->curvea, t1);
   664 		group->ecfp_reduce(r->az4, t0, group);
   665 	}
   666   CLEANUP:
   667 	return;
   668 }
   670 /* Perform a point addition using Chudnovsky Jacobian coordinates. Input
   671  * and output should be multi-precision floating point integers. */
   672 void PREFIX(pt_add_chud) (const ecfp_chud_pt * p, const ecfp_chud_pt * q,
   673 						  ecfp_chud_pt * r, const EC_group_fp * group) {
   675 	/* Temporary Storage */
   676 	double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
   677 		U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES],
   678 		S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES],
   679 		H3[2 * ECFP_NUMDOUBLES];
   681 	/* Check for point at infinity for p, if so set r = q */
   682 	if (PREFIX(pt_is_inf_chud) (p) == MP_YES) {
   683 		PREFIX(copy) (r->x, q->x);
   684 		PREFIX(copy) (r->y, q->y);
   685 		PREFIX(copy) (r->z, q->z);
   686 		PREFIX(copy) (r->z2, q->z2);
   687 		PREFIX(copy) (r->z3, q->z3);
   688 		goto CLEANUP;
   689 	}
   691 	/* Check for point at infinity for p, if so set r = q */
   692 	if (PREFIX(pt_is_inf_chud) (q) == MP_YES) {
   693 		PREFIX(copy) (r->x, p->x);
   694 		PREFIX(copy) (r->y, p->y);
   695 		PREFIX(copy) (r->z, p->z);
   696 		PREFIX(copy) (r->z2, p->z2);
   697 		PREFIX(copy) (r->z3, p->z3);
   698 		goto CLEANUP;
   699 	}
   701 	/* U = px * qz^2 */
   702 	PREFIX(multiply) (U, p->x, q->z2);
   703 	group->ecfp_reduce(U, U, group);
   705 	/* H = qx*(pz)^2 - U */
   706 	PREFIX(multiply) (H, q->x, p->z2);
   707 	PREFIX(subtractShort) (H, H, U);
   708 	group->ecfp_reduce(H, H, group);
   710 	/* U = U*H^2, H3 = H^3 */
   711 	PREFIX(square) (t0, H);
   712 	group->ecfp_reduce(t0, t0, group);
   713 	PREFIX(multiply) (t1, U, t0);
   714 	group->ecfp_reduce(U, t1, group);
   715 	PREFIX(multiply) (H3, t0, H);
   716 	group->ecfp_reduce(H3, H3, group);
   718 	/* S = py * qz^3 */
   719 	PREFIX(multiply) (S, p->y, q->z3);
   720 	group->ecfp_reduce(S, S, group);
   722 	/* rz = pz * qz * H */
   723 	PREFIX(multiply) (t0, q->z, H);
   724 	group->ecfp_reduce(t0, t0, group);
   725 	PREFIX(multiply) (t1, t0, p->z);
   726 	group->ecfp_reduce(r->z, t1, group);
   728 	/* R = (qy * z1^3 - s) */
   729 	PREFIX(multiply) (t0, q->y, p->z3);
   730 	PREFIX(subtractShort) (t0, t0, S);
   731 	group->ecfp_reduce(R, t0, group);
   733 	/* rx = R^2 - H^3 - 2 * U */
   734 	PREFIX(square) (t0, R);
   735 	PREFIX(subtractShort) (t0, t0, H3);
   736 	PREFIX(subtractShort) (t0, t0, U);
   737 	PREFIX(subtractShort) (t0, t0, U);
   738 	group->ecfp_reduce(r->x, t0, group);
   740 	/* ry = R(U - rx) - S*H3 */
   741 	PREFIX(subtractShort) (t1, U, r->x);
   742 	PREFIX(multiply) (t0, t1, R);
   743 	PREFIX(multiply) (t1, S, H3);
   744 	PREFIX(subtractLong) (t1, t0, t1);
   745 	group->ecfp_reduce(r->y, t1, group);
   747 	/* rz2 = rz^2 */
   748 	PREFIX(square) (t0, r->z);
   749 	group->ecfp_reduce(r->z2, t0, group);
   751 	/* rz3 = rz^3 */
   752 	PREFIX(multiply) (t0, r->z, r->z2);
   753 	group->ecfp_reduce(r->z3, t0, group);
   755   CLEANUP:
   756 	return;
   757 }
   759 /* Expects out to be an array of size 16 of Chudnovsky Jacobian points.
   760  * Fills in Chudnovsky Jacobian form (x, y, z, z^2, z^3), for -15P, -13P,
   761  * -11P, -9P, -7P, -5P, -3P, -P, P, 3P, 5P, 7P, 9P, 11P, 13P, 15P */
   762 void PREFIX(precompute_chud) (ecfp_chud_pt * out, const ecfp_aff_pt * p,
   763 							  const EC_group_fp * group) {
   765 	ecfp_chud_pt p2;
   767 	/* Set out[8] = P */
   768 	PREFIX(copy) (out[8].x, p->x);
   769 	PREFIX(copy) (out[8].y, p->y);
   770 	PREFIX(one) (out[8].z);
   771 	PREFIX(one) (out[8].z2);
   772 	PREFIX(one) (out[8].z3);
   774 	/* Set p2 = 2P */
   775 	PREFIX(pt_dbl_aff2chud) (p, &p2, group);
   777 	/* Set 3P, 5P, ..., 15P */
   778 	PREFIX(pt_add_chud) (&out[8], &p2, &out[9], group);
   779 	PREFIX(pt_add_chud) (&out[9], &p2, &out[10], group);
   780 	PREFIX(pt_add_chud) (&out[10], &p2, &out[11], group);
   781 	PREFIX(pt_add_chud) (&out[11], &p2, &out[12], group);
   782 	PREFIX(pt_add_chud) (&out[12], &p2, &out[13], group);
   783 	PREFIX(pt_add_chud) (&out[13], &p2, &out[14], group);
   784 	PREFIX(pt_add_chud) (&out[14], &p2, &out[15], group);
   786 	/* Set -15P, -13P, ..., -P */
   787 	PREFIX(pt_neg_chud) (&out[8], &out[7]);
   788 	PREFIX(pt_neg_chud) (&out[9], &out[6]);
   789 	PREFIX(pt_neg_chud) (&out[10], &out[5]);
   790 	PREFIX(pt_neg_chud) (&out[11], &out[4]);
   791 	PREFIX(pt_neg_chud) (&out[12], &out[3]);
   792 	PREFIX(pt_neg_chud) (&out[13], &out[2]);
   793 	PREFIX(pt_neg_chud) (&out[14], &out[1]);
   794 	PREFIX(pt_neg_chud) (&out[15], &out[0]);
   795 }
   797 /* Expects out to be an array of size 16 of Jacobian points. Fills in
   798  * Jacobian form (x, y, z), for O, P, 2P, ... 15P */
   799 void PREFIX(precompute_jac) (ecfp_jac_pt * precomp, const ecfp_aff_pt * p,
   800 							 const EC_group_fp * group) {
   801 	int i;
   803 	/* fill precomputation table */
   804 	/* set precomp[0] */
   805 	PREFIX(set_pt_inf_jac) (&precomp[0]);
   806 	/* set precomp[1] */
   807 	PREFIX(copy) (precomp[1].x, p->x);
   808 	PREFIX(copy) (precomp[1].y, p->y);
   809 	if (PREFIX(pt_is_inf_aff) (p) == MP_YES) {
   810 		PREFIX(zero) (precomp[1].z);
   811 	} else {
   812 		PREFIX(one) (precomp[1].z);
   813 	}
   814 	/* set precomp[2] */
   815 	group->pt_dbl_jac(&precomp[1], &precomp[2], group);
   817 	/* set rest of precomp */
   818 	for (i = 3; i < 16; i++) {
   819 		group->pt_add_jac_aff(&precomp[i - 1], p, &precomp[i], group);
   820 	}
   821 }

mercurial