示例#1
0
/**
 * Multiplies a prime elliptic curve point by an integer using the COMBS
 * method.
 *
 * @param[out] r 				- the result.
 * @param[in] t					- the precomputed table.
 * @param[in] k					- the integer.
 */
static void ed_mul_combs_endom(ed_t r, const ed_t *t, const bn_t k) {
	int i, j, l, w0, w1, n0, n1, p0, p1, s0, s1;
	bn_t n, k0, k1, v1[3], v2[3];
	ed_t u;

	bn_null(n);
	bn_null(k0);
	bn_null(k1);
	ed_null(u);

	TRY {
		bn_new(n);
		bn_new(k0);
		bn_new(k1);
		ed_new(u);
		for (i = 0; i < 3; i++) {
			bn_null(v1[i]);
			bn_null(v2[i]);
			bn_new(v1[i]);
			bn_new(v2[i]);
		}

		ed_curve_get_ord(n);
		ed_curve_get_v1(v1);
		ed_curve_get_v2(v2);
		l = bn_bits(n);
		l = ((l % (2 * ED_DEPTH)) ==
				0 ? (l / (2 * ED_DEPTH)) : (l / (2 * ED_DEPTH)) + 1);

		bn_rec_glv(k0, k1, k, n, (const bn_t *)v1, (const bn_t *)v2);
		s0 = bn_sign(k0);
		s1 = bn_sign(k1);
		bn_abs(k0, k0);
		bn_abs(k1, k1);

		n0 = bn_bits(k0);
		n1 = bn_bits(k1);

		p0 = (ED_DEPTH) * l - 1;

		ed_set_infty(r);

		for (i = l - 1; i >= 0; i--) {
			ed_dbl(r, r);

			w0 = 0;
			w1 = 0;
			p1 = p0--;
			for (j = ED_DEPTH - 1; j >= 0; j--, p1 -= l) {
				w0 = w0 << 1;
				w1 = w1 << 1;
				if (p1 < n0 && bn_get_bit(k0, p1)) {
					w0 = w0 | 1;
				}
				if (p1 < n1 && bn_get_bit(k1, p1)) {
					w1 = w1 | 1;
				}
			}
			if (w0 > 0) {
				if (s0 == BN_POS) {
					ed_add(r, r, t[w0]);
				} else {
					ed_sub(r, r, t[w0]);
				}
			}
			if (w1 > 0) {
				ed_copy(u, t[w1]);
				fp_mul(u->x, u->x, ed_curve_get_beta());
				if (s1 == BN_NEG) {
					ed_neg(u, u);
				}
				ed_add(r, r, u);
			}
		}
		ed_norm(r, r);
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(n);
		bn_free(k0);
		bn_free(k1);
		ed_free(u);
		for (i = 0; i < 3; i++) {
			bn_free(v1[i]);
			bn_free(v2[i]);
		}
	}
}
/**
 * Multiplies and adds two prime elliptic curve points simultaneously,
 * optionally choosing the first point as the generator depending on an optional
 * table of precomputed points.
 *
 * @param[out] r 				- the result.
 * @param[in] p					- the first point to multiply.
 * @param[in] k					- the first integer.
 * @param[in] q					- the second point to multiply.
 * @param[in] m					- the second integer.
 * @param[in] t					- the pointer to the precomputed table.
 */
void ep_mul_sim_endom(ep_t r, const ep_t p, const bn_t k, const ep_t q,
		const bn_t m, const ep_t *t) {
	int len, len0, len1, len2, len3, i, n, sk0, sk1, sl0, sl1, w, g = 0;
	int8_t naf0[FP_BITS + 1], naf1[FP_BITS + 1], *t0, *t1;
	int8_t naf2[FP_BITS + 1], naf3[FP_BITS + 1], *t2, *t3;
	bn_t k0, k1, l0, l1;
	bn_t ord, v1[3], v2[3];
	ep_t u;
	ep_t tab0[1 << (EP_WIDTH - 2)];
	ep_t tab1[1 << (EP_WIDTH - 2)];

	bn_null(ord);
	bn_null(k0);
	bn_null(k1);
	bn_null(l0);
	bn_null(l1);
	ep_null(u);

	for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) {
		ep_null(tab0[i]);
		ep_null(tab1[i]);
	}

	bn_new(ord);
	bn_new(k0);
	bn_new(k1);
	bn_new(l0);
	bn_new(l1);
	ep_new(u);

	TRY {
		for (i = 0; i < 3; i++) {
			bn_null(v1[i]);
			bn_null(v2[i]);
			bn_new(v1[i]);
			bn_new(v2[i]);
		}

		ep_curve_get_ord(ord);
		ep_curve_get_v1(v1);
		ep_curve_get_v2(v2);

		bn_rec_glv(k0, k1, k, ord, (const bn_t *)v1, (const bn_t *)v2);
		sk0 = bn_sign(k0);
		sk1 = bn_sign(k1);
		bn_abs(k0, k0);
		bn_abs(k1, k1);

		bn_rec_glv(l0, l1, m, ord, (const bn_t *)v1, (const bn_t *)v2);
		sl0 = bn_sign(l0);
		sl1 = bn_sign(l1);
		bn_abs(l0, l0);
		bn_abs(l1, l1);

		g = (t == NULL ? 0 : 1);
		if (!g) {
			for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) {
				ep_new(tab0[i]);
			}
			ep_tab(tab0, p, EP_WIDTH);
			t = (const ep_t *)tab0;
		}

		/* Prepare the precomputation table. */
		for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) {
			ep_new(tab1[i]);
		}
		/* Compute the precomputation table. */
		ep_tab(tab1, q, EP_WIDTH);

		/* Compute the w-TNAF representation of k and l */
		if (g) {
			w = EP_DEPTH;
		} else {
			w = EP_WIDTH;
		}
		len0 = len1 = len2 = len3 = FP_BITS + 1;
		bn_rec_naf(naf0, &len0, k0, w);
		bn_rec_naf(naf1, &len1, k1, w);
		bn_rec_naf(naf2, &len2, l0, EP_WIDTH);
		bn_rec_naf(naf3, &len3, l1, EP_WIDTH);

		len = MAX(MAX(len0, len1), MAX(len2, len3));
		t0 = naf0 + len - 1;
		t1 = naf1 + len - 1;
		t2 = naf2 + len - 1;
		t3 = naf3 + len - 1;
		for (i = len0; i < len; i++) {
			naf0[i] = 0;
		}
		for (i = len1; i < len; i++) {
			naf1[i] = 0;
		}
		for (i = len2; i < len; i++) {
			naf2[i] = 0;
		}
		for (i = len3; i < len; i++) {
			naf3[i] = 0;
		}

		ep_set_infty(r);
		for (i = len - 1; i >= 0; i--, t0--, t1--, t2--, t3--) {
			ep_dbl(r, r);

			n = *t0;
			if (n > 0) {
				if (sk0 == BN_POS) {
					ep_add(r, r, t[n / 2]);
				} else {
					ep_sub(r, r, t[n / 2]);
				}
			}
			if (n < 0) {
				if (sk0 == BN_POS) {
					ep_sub(r, r, t[-n / 2]);
				} else {
					ep_add(r, r, t[-n / 2]);
				}
			}
			n = *t1;
			if (n > 0) {
				ep_copy(u, t[n / 2]);
				fp_mul(u->x, u->x, ep_curve_get_beta());
				if (sk1 == BN_NEG) {
					ep_neg(u, u);
				}
				ep_add(r, r, u);
			}
			if (n < 0) {
				ep_copy(u, t[-n / 2]);
				fp_mul(u->x, u->x, ep_curve_get_beta());
				if (sk1 == BN_NEG) {
					ep_neg(u, u);
				}
				ep_sub(r, r, u);
			}

			n = *t2;
			if (n > 0) {
				if (sl0 == BN_POS) {
					ep_add(r, r, tab1[n / 2]);
				} else {
					ep_sub(r, r, tab1[n / 2]);
				}
			}
			if (n < 0) {
				if (sl0 == BN_POS) {
					ep_sub(r, r, tab1[-n / 2]);
				} else {
					ep_add(r, r, tab1[-n / 2]);
				}
			}
			n = *t3;
			if (n > 0) {
				ep_copy(u, tab1[n / 2]);
				fp_mul(u->x, u->x, ep_curve_get_beta());
				if (sl1 == BN_NEG) {
					ep_neg(u, u);
				}
				ep_add(r, r, u);
			}
			if (n < 0) {
				ep_copy(u, tab1[-n / 2]);
				fp_mul(u->x, u->x, ep_curve_get_beta());
				if (sl1 == BN_NEG) {
					ep_neg(u, u);
				}
				ep_sub(r, r, u);
			}
		}
		/* Convert r to affine coordinates. */
		ep_norm(r, r);
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(ord);
		bn_free(k0);
		bn_free(k1);
		bn_free(l0);
		bn_free(l1);
		ep_free(u);

		if (!g) {
			for (i = 0; i < 1 << (EP_WIDTH - 2); i++) {
				ep_free(tab0[i]);
			}
		}
		/* Free the precomputation tables. */
		for (i = 0; i < 1 << (EP_WIDTH - 2); i++) {
			ep_free(tab1[i]);
		}
		for (i = 0; i < 3; i++) {
			bn_free(v1[i]);
			bn_free(v2[i]);
		}
	}
}