ecp_nistp256.c 63.4 KB
Newer Older
			g_secret,
			mixed, (const smallfelem (*)[17][3]) pre_comp,
			g_pre_comp);
		}
	else
		/* do the multiplication without generator precomputation */
		batch_mul(x_out, y_out, z_out,
			(const felem_bytearray (*)) secrets, num_points,
			NULL, mixed, (const smallfelem (*)[17][3]) pre_comp, NULL);
	/* reduce the output to its unique minimal representation */
	felem_contract(x_in, x_out);
	felem_contract(y_in, y_out);
	felem_contract(z_in, z_out);
	if ((!smallfelem_to_BN(x, x_in)) || (!smallfelem_to_BN(y, y_in)) ||
		(!smallfelem_to_BN(z, z_in)))
		{
		ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
		goto err;
		}
	ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);

err:
	BN_CTX_end(ctx);
	if (generator != NULL)
		EC_POINT_free(generator);
	if (new_ctx != NULL)
		BN_CTX_free(new_ctx);
	if (secrets != NULL)
		OPENSSL_free(secrets);
	if (pre_comp != NULL)
		OPENSSL_free(pre_comp);
	if (tmp_smallfelems != NULL)
		OPENSSL_free(tmp_smallfelems);
	return ret;
	}

int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
	{
	int ret = 0;
	NISTP256_PRE_COMP *pre = NULL;
	int i, j;
	BN_CTX *new_ctx = NULL;
	BIGNUM *x, *y;
	EC_POINT *generator = NULL;
	smallfelem tmp_smallfelems[32];
	felem x_tmp, y_tmp, z_tmp;

	/* throw away old precomputation */
	EC_EX_DATA_free_data(&group->extra_data, nistp256_pre_comp_dup,
		nistp256_pre_comp_free, nistp256_pre_comp_clear_free);
	if (ctx == NULL)
		if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
	BN_CTX_start(ctx);
	if (((x = BN_CTX_get(ctx)) == NULL) ||
		((y = BN_CTX_get(ctx)) == NULL))
		goto err;
	/* get the generator */
	if (group->generator == NULL) goto err;
	generator = EC_POINT_new(group);
	if (generator == NULL)
		goto err;
	BN_bin2bn(nistp256_curve_params[3], sizeof (felem_bytearray), x);
	BN_bin2bn(nistp256_curve_params[4], sizeof (felem_bytearray), y);
	if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx))
		goto err;
	if ((pre = nistp256_pre_comp_new()) == NULL)
		goto err;
	/* if the generator is the standard one, use built-in precomputation */
	if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
		{
		memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp));
		ret = 1;
		goto err;
		}
	if ((!BN_to_felem(x_tmp, &group->generator->X)) ||
		(!BN_to_felem(y_tmp, &group->generator->Y)) ||
		(!BN_to_felem(z_tmp, &group->generator->Z)))
		goto err;
	felem_shrink(pre->g_pre_comp[0][1][0], x_tmp);
	felem_shrink(pre->g_pre_comp[0][1][1], y_tmp);
	felem_shrink(pre->g_pre_comp[0][1][2], z_tmp);
	/* compute 2^64*G, 2^128*G, 2^192*G for the first table,
	 * 2^32*G, 2^96*G, 2^160*G, 2^224*G for the second one
	 */
	for (i = 1; i <= 8; i <<= 1)
		{
		point_double_small(
			pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2],
			pre->g_pre_comp[0][i][0], pre->g_pre_comp[0][i][1], pre->g_pre_comp[0][i][2]);
		for (j = 0; j < 31; ++j)
			{
			point_double_small(
				pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2],
				pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]);
			}
		if (i == 8)
			break;
		point_double_small(
			pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2],
			pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]);
		for (j = 0; j < 31; ++j)
			{
			point_double_small(
				pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2],
				pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2]);
			}
		}
	for (i = 0; i < 2; i++)
		{
		/* g_pre_comp[i][0] is the point at infinity */
		memset(pre->g_pre_comp[i][0], 0, sizeof(pre->g_pre_comp[i][0]));
		/* the remaining multiples */
		/* 2^64*G + 2^128*G resp. 2^96*G + 2^160*G */
		point_add_small(
			pre->g_pre_comp[i][6][0], pre->g_pre_comp[i][6][1], pre->g_pre_comp[i][6][2],
			pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2],
			pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], pre->g_pre_comp[i][2][2]);
		/* 2^64*G + 2^192*G resp. 2^96*G + 2^224*G */
		point_add_small(
			pre->g_pre_comp[i][10][0], pre->g_pre_comp[i][10][1], pre->g_pre_comp[i][10][2],
			pre->g_pre_comp[i][8][0], pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2],
			pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], pre->g_pre_comp[i][2][2]);
		/* 2^128*G + 2^192*G resp. 2^160*G + 2^224*G */
		point_add_small(
			pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2],
			pre->g_pre_comp[i][8][0], pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2],
			pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2]);
		/* 2^64*G + 2^128*G + 2^192*G resp. 2^96*G + 2^160*G + 2^224*G */
		point_add_small(
			pre->g_pre_comp[i][14][0], pre->g_pre_comp[i][14][1], pre->g_pre_comp[i][14][2],
			pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2],
			pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], pre->g_pre_comp[i][2][2]);
		for (j = 1; j < 8; ++j)
			{
			/* odd multiples: add G resp. 2^32*G */
			point_add_small(
				pre->g_pre_comp[i][2*j+1][0], pre->g_pre_comp[i][2*j+1][1], pre->g_pre_comp[i][2*j+1][2],
				pre->g_pre_comp[i][2*j][0], pre->g_pre_comp[i][2*j][1], pre->g_pre_comp[i][2*j][2],
				pre->g_pre_comp[i][1][0], pre->g_pre_comp[i][1][1], pre->g_pre_comp[i][1][2]);
			}
		}
	make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_smallfelems);

	if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp256_pre_comp_dup,
			nistp256_pre_comp_free, nistp256_pre_comp_clear_free))
		goto err;
	ret = 1;
	pre = NULL;
 err:
	BN_CTX_end(ctx);
	if (generator != NULL)
		EC_POINT_free(generator);
	if (new_ctx != NULL)
		BN_CTX_free(new_ctx);
	if (pre)
		nistp256_pre_comp_free(pre);
	return ret;
	}

int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group)
	{
	if (EC_EX_DATA_get_data(group->extra_data, nistp256_pre_comp_dup,
			nistp256_pre_comp_free, nistp256_pre_comp_clear_free)
		!= NULL)
		return 1;
	else
		return 0;
	}
#else
static void *dummy=&dummy;
#endif