-/* $OpenBSD: ec_mult.c,v 1.29 2023/04/11 18:58:20 jsing Exp $ */
+/* $OpenBSD: ec_mult.c,v 1.30 2023/06/24 17:18:15 jsing Exp $ */
/*
* Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.
*/
static void ec_pre_comp_free(void *);
static void ec_pre_comp_clear_free(void *);
-static EC_PRE_COMP *
-ec_pre_comp_new(const EC_GROUP *group)
-{
- EC_PRE_COMP *ret = NULL;
-
- if (!group)
- return NULL;
-
- ret = malloc(sizeof(EC_PRE_COMP));
- if (!ret) {
- ECerror(ERR_R_MALLOC_FAILURE);
- return ret;
- }
- ret->group = group;
- ret->blocksize = 8; /* default */
- ret->numblocks = 0;
- ret->w = 4; /* default */
- ret->points = NULL;
- ret->num = 0;
- ret->references = 1;
- return ret;
-}
-
static void *
ec_pre_comp_dup(void *src_)
{
free(val_sub);
return ret;
}
-
-
-/* ec_wNAF_precompute_mult()
- * creates an EC_PRE_COMP object with preprecomputed multiples of the generator
- * for use with wNAF splitting as implemented in ec_wNAF_mul().
- *
- * 'pre_comp->points' is an array of multiples of the generator
- * of the following form:
- * points[0] = generator;
- * points[1] = 3 * generator;
- * ...
- * points[2^(w-1)-1] = (2^(w-1)-1) * generator;
- * points[2^(w-1)] = 2^blocksize * generator;
- * points[2^(w-1)+1] = 3 * 2^blocksize * generator;
- * ...
- * points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) * 2^(blocksize*(numblocks-2)) * generator
- * points[2^(w-1)*(numblocks-1)] = 2^(blocksize*(numblocks-1)) * generator
- * ...
- * points[2^(w-1)*numblocks-1] = (2^(w-1)) * 2^(blocksize*(numblocks-1)) * generator
- * points[2^(w-1)*numblocks] = NULL
- */
-int
-ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
-{
- const EC_POINT *generator;
- EC_POINT *tmp_point = NULL, *base = NULL, **var;
- BIGNUM *order;
- size_t i, bits, w, pre_points_per_block, blocksize, numblocks,
- num;
- EC_POINT **points = NULL;
- EC_PRE_COMP *pre_comp;
- int ret = 0;
-
- /* if there is an old EC_PRE_COMP object, throw it away */
- EC_EX_DATA_free_data(&group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free);
-
- if ((pre_comp = ec_pre_comp_new(group)) == NULL)
- return 0;
-
- generator = EC_GROUP_get0_generator(group);
- if (generator == NULL) {
- ECerror(EC_R_UNDEFINED_GENERATOR);
- goto err;
- }
-
- BN_CTX_start(ctx);
-
- if ((order = BN_CTX_get(ctx)) == NULL)
- goto err;
-
- if (!EC_GROUP_get_order(group, order, ctx))
- goto err;
- if (BN_is_zero(order)) {
- ECerror(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 = (size_t) 1 << (w - 1);
- num = pre_points_per_block * numblocks; /* number of points to
- * compute and store */
-
- points = reallocarray(NULL, (num + 1), sizeof(EC_POINT *));
- if (!points) {
- ECerror(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) {
- ECerror(ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
-
- if (!(tmp_point = EC_POINT_new(group)) || !(base = EC_POINT_new(group))) {
- ECerror(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) {
- ECerror(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;
- pre_comp->points = points;
- points = NULL;
- pre_comp->num = num;
-
- if (!EC_EX_DATA_set_data(&group->extra_data, pre_comp,
- ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free))
- goto err;
- pre_comp = NULL;
-
- ret = 1;
-
- err:
- BN_CTX_end(ctx);
- ec_pre_comp_free(pre_comp);
- if (points) {
- EC_POINT **p;
-
- for (p = points; *p != NULL; p++)
- EC_POINT_free(*p);
- free(points);
- }
- EC_POINT_free(tmp_point);
- EC_POINT_free(base);
- return ret;
-}
-
-
-int
-ec_wNAF_have_precompute_mult(const EC_GROUP *group)
-{
- if (EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free) != NULL)
- return 1;
- else
- return 0;
-}