CRYPTO_push_info("ec_wNAF_precompute_mult");
int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)	{	const EC_POINT *generator;	EC_POINT *tmp_point = NULL, *base = NULL, **var;	BN_CTX *new_ctx = NULL;	BIGNUM *order;	size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;	EC_POINT **points = NULL;	EC_PRE_COMP *pre_comp, *new_pre_comp = NULL;	int ret = 0;	pre_comp = EC_GROUP_get_extra_data(group, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free);	if (pre_comp == NULL)		if ((pre_comp = new_pre_comp = ec_pre_comp_new(group)) == NULL)			return 0;CRYPTO_push_info("ec_wNAF_precompute_mult");	generator = EC_GROUP_get0_generator(group);	if (generator == NULL)		{		ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR);		goto err;		}	if (ctx == NULL)		{		ctx = new_ctx = BN_CTX_new();		if (ctx == NULL)			goto err;		}		BN_CTX_start(ctx);	order = BN_CTX_get(ctx);	if (order == NULL) goto err;		if (!EC_GROUP_get_order(group, order, ctx)) goto err;			if (BN_is_zero(order))		{		ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER);		goto err;		}	bits = BN_num_bits(order);	/* The following parameters mean we precompute (approximately)	 * one point per bit.	 *	 * TBD: The combination  8, 4  is perfect for 160 bits; for other	 * bit lengths, other parameter combinations might provide better	 * efficiency.	 */	blocksize = 8;	w = 4;	if (EC_window_bits_for_scalar_size(bits) > w)		{		/* let's not make the window too small ... */		w = EC_window_bits_for_scalar_size(bits);		}	numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks to use for wNAF splitting */		pre_points_per_block = 1u << (w - 1);	num = pre_points_per_block * numblocks; /* number of points to compute and store */	points = OPENSSL_malloc(sizeof (EC_POINT*)*(num + 1));	if (!points)		{		ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);		goto err;		}	var = points;	var[num] = NULL; /* pivot */	for (i = 0; i < num; i++)		{		if ((var[i] = EC_POINT_new(group)) == NULL)			{			ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);			goto err;			}		}	if (!(tmp_point = EC_POINT_new(group)) || !(base = EC_POINT_new(group)))		{		ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);		goto err;		}			if (!EC_POINT_copy(base, generator))		goto err;		/* do the precomputation */	for (i = 0; i < numblocks; i++)		{		size_t j;		if (!EC_POINT_dbl(group, tmp_point, base, ctx))			goto err;		if (!EC_POINT_copy(*var++, base))			goto err;		for (j = 1; j < pre_points_per_block; j++, var++)			{			/* calculate odd multiples of the current base point */			if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx))				goto err;			}		if (i < numblocks - 1)			{			/* get the next base (multiply current one by 2^blocksize) */			size_t k;			if (blocksize <= 2)				{				ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR);				goto err;				}							if (!EC_POINT_dbl(group, base, tmp_point, ctx))				goto err;			for (k = 2; k < blocksize; k++)				{				if (!EC_POINT_dbl(group,base,base,ctx))					goto err;				}			} 		}	if (!EC_POINTs_make_affine(group, num, points, ctx))		goto err;		pre_comp->group = group;	pre_comp->blocksize = blocksize;	pre_comp->numblocks = numblocks;	pre_comp->w = w;	if (pre_comp->points)		{		EC_POINT **p;		for (p = pre_comp->points; *p != NULL; p++)			EC_POINT_free(*p);		OPENSSL_free(pre_comp->points);		}	pre_comp->points = points;	points = NULL;	pre_comp->num = num;	if (new_pre_comp)		{		if (!EC_GROUP_set_extra_data(group, new_pre_comp, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free))			goto err;		new_pre_comp = NULL;		}	ret = 1; err:	CRYPTO_pop_info();	BN_CTX_end(ctx);	if (new_ctx != NULL)		BN_CTX_free(new_ctx);	if (new_pre_comp)		ec_pre_comp_free(new_pre_comp);	if (points)		{		EC_POINT **p;		for (p = points; *p != NULL; p++)			EC_POINT_free(*p);		OPENSSL_free(points);		}	if (tmp_point)		EC_POINT_free(tmp_point);	if (base)		EC_POINT_free(base);	return ret;	}