This commit is contained in:
purplerain 2023-06-25 21:25:02 +00:00
parent 82bafdd0b3
commit ae25582c29
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
37 changed files with 421 additions and 1406 deletions

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ec_key.c,v 1.32 2023/03/27 10:25:02 tb Exp $ */
/* $OpenBSD: ec_key.c,v 1.33 2023/06/25 18:52:27 tb Exp $ */
/*
* Written by Nils Larsch for the OpenSSL project.
*/
@ -122,16 +122,12 @@ EC_KEY_free(EC_KEY *r)
EC_POINT_free(r->pub_key);
BN_free(r->priv_key);
EC_EX_DATA_free_all_data(&r->method_data);
freezero(r, sizeof(EC_KEY));
}
EC_KEY *
EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
{
EC_EXTRA_DATA *d;
if (dest == NULL || src == NULL) {
ECerror(ERR_R_PASSED_NULL_PARAMETER);
return NULL;
@ -175,18 +171,6 @@ EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
if (!bn_copy(dest->priv_key, src->priv_key))
return NULL;
}
/* copy method/extra data */
EC_EX_DATA_free_all_data(&dest->method_data);
for (d = src->method_data; d != NULL; d = d->next) {
void *t = d->dup_func(d->data);
if (t == NULL)
return 0;
if (!EC_EX_DATA_set_data(&dest->method_data, t, d->dup_func,
d->free_func, d->clear_free_func))
return 0;
}
/* copy the rest */
dest->enc_flag = src->enc_flag;
@ -526,38 +510,6 @@ EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
EC_GROUP_set_point_conversion_form(key->group, cform);
}
void *
EC_KEY_get_key_method_data(EC_KEY *key,
void *(*dup_func) (void *),
void (*free_func) (void *),
void (*clear_free_func) (void *))
{
void *ret;
CRYPTO_r_lock(CRYPTO_LOCK_EC);
ret = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
CRYPTO_r_unlock(CRYPTO_LOCK_EC);
return ret;
}
void *
EC_KEY_insert_key_method_data(EC_KEY *key, void *data,
void *(*dup_func) (void *),
void (*free_func) (void *),
void (*clear_free_func) (void *))
{
EC_EXTRA_DATA *ex_data;
CRYPTO_w_lock(CRYPTO_LOCK_EC);
ex_data = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
if (ex_data == NULL)
EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, clear_free_func);
CRYPTO_w_unlock(CRYPTO_LOCK_EC);
return ex_data;
}
void
EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
{

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ec_kmeth.c,v 1.7 2022/11/26 16:08:52 tb Exp $ */
/* $OpenBSD: ec_kmeth.c,v 1.8 2023/06/25 18:52:27 tb Exp $ */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
@ -168,7 +168,6 @@ EC_KEY_new_method(ENGINE *engine)
ret->enc_flag = 0;
ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
ret->references = 1;
ret->method_data = NULL;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data))
goto err;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ec_lib.c,v 1.58 2023/06/20 14:37:15 tb Exp $ */
/* $OpenBSD: ec_lib.c,v 1.61 2023/06/25 18:52:27 tb Exp $ */
/*
* Originally written by Bodo Moeller for the OpenSSL project.
*/
@ -93,8 +93,6 @@ EC_GROUP_new(const EC_METHOD *meth)
}
ret->meth = meth;
ret->extra_data = NULL;
ret->generator = NULL;
BN_init(&ret->order);
BN_init(&ret->cofactor);
@ -123,8 +121,6 @@ EC_GROUP_free(EC_GROUP *group)
if (group->meth->group_finish != NULL)
group->meth->group_finish(group);
EC_EX_DATA_clear_free_all_data(&group->extra_data);
EC_POINT_free(group->generator);
BN_free(&group->order);
BN_free(&group->cofactor);
@ -142,8 +138,6 @@ EC_GROUP_clear_free(EC_GROUP *group)
int
EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
{
EC_EXTRA_DATA *d;
if (dest->meth->group_copy == NULL) {
ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
@ -155,18 +149,6 @@ EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
if (dest == src)
return 1;
EC_EX_DATA_free_all_data(&dest->extra_data);
for (d = src->extra_data; d != NULL; d = d->next) {
void *t = d->dup_func(d->data);
if (t == NULL)
return 0;
if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func,
d->free_func, d->clear_free_func))
return 0;
}
if (src->generator != NULL) {
if (dest->generator == NULL) {
dest->generator = EC_POINT_new(dest);
@ -669,158 +651,6 @@ ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx)
return group->meth->blind_coordinates(group, p, ctx);
}
/* this has 'package' visibility */
int
EC_EX_DATA_set_data(EC_EXTRA_DATA ** ex_data, void *data,
void *(*dup_func) (void *),
void (*free_func) (void *),
void (*clear_free_func) (void *))
{
EC_EXTRA_DATA *d;
if (ex_data == NULL)
return 0;
for (d = *ex_data; d != NULL; d = d->next) {
if (d->dup_func == dup_func && d->free_func == free_func &&
d->clear_free_func == clear_free_func) {
ECerror(EC_R_SLOT_FULL);
return 0;
}
}
if (data == NULL)
/* no explicit entry needed */
return 1;
d = malloc(sizeof *d);
if (d == NULL)
return 0;
d->data = data;
d->dup_func = dup_func;
d->free_func = free_func;
d->clear_free_func = clear_free_func;
d->next = *ex_data;
*ex_data = d;
return 1;
}
/* this has 'package' visibility */
void *
EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
void *(*dup_func) (void *),
void (*free_func) (void *),
void (*clear_free_func) (void *))
{
const EC_EXTRA_DATA *d;
for (d = ex_data; d != NULL; d = d->next) {
if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
return d->data;
}
return NULL;
}
/* this has 'package' visibility */
void
EC_EX_DATA_free_data(EC_EXTRA_DATA ** ex_data,
void *(*dup_func) (void *),
void (*free_func) (void *),
void (*clear_free_func) (void *))
{
EC_EXTRA_DATA **p;
if (ex_data == NULL)
return;
for (p = ex_data; *p != NULL; p = &((*p)->next)) {
if ((*p)->dup_func == dup_func &&
(*p)->free_func == free_func &&
(*p)->clear_free_func == clear_free_func) {
EC_EXTRA_DATA *next = (*p)->next;
(*p)->free_func((*p)->data);
free(*p);
*p = next;
return;
}
}
}
/* this has 'package' visibility */
void
EC_EX_DATA_clear_free_data(EC_EXTRA_DATA ** ex_data,
void *(*dup_func) (void *),
void (*free_func) (void *),
void (*clear_free_func) (void *))
{
EC_EXTRA_DATA **p;
if (ex_data == NULL)
return;
for (p = ex_data; *p != NULL; p = &((*p)->next)) {
if ((*p)->dup_func == dup_func &&
(*p)->free_func == free_func &&
(*p)->clear_free_func == clear_free_func) {
EC_EXTRA_DATA *next = (*p)->next;
(*p)->clear_free_func((*p)->data);
free(*p);
*p = next;
return;
}
}
}
/* this has 'package' visibility */
void
EC_EX_DATA_free_all_data(EC_EXTRA_DATA ** ex_data)
{
EC_EXTRA_DATA *d;
if (ex_data == NULL)
return;
d = *ex_data;
while (d) {
EC_EXTRA_DATA *next = d->next;
d->free_func(d->data);
free(d);
d = next;
}
*ex_data = NULL;
}
/* this has 'package' visibility */
void
EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA ** ex_data)
{
EC_EXTRA_DATA *d;
if (ex_data == NULL)
return;
d = *ex_data;
while (d) {
EC_EXTRA_DATA *next = d->next;
d->clear_free_func(d->data);
free(d);
d = next;
}
*ex_data = NULL;
}
EC_POINT *
EC_POINT_new(const EC_GROUP *group)
{
@ -1408,33 +1238,13 @@ EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
int
EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx_in)
{
BN_CTX *ctx;
int ret = 0;
if (group->meth->precompute_mult == NULL)
return 1;
if ((ctx = ctx_in) == NULL)
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
ret = group->meth->precompute_mult(group, ctx);
err:
if (ctx != ctx_in)
BN_CTX_free(ctx);
return ret;
return 1;
}
int
EC_GROUP_have_precompute_mult(const EC_GROUP *group)
{
if (group->meth->have_precompute_mult == NULL)
return 0;
return group->meth->have_precompute_mult(group);
return 0;
}
int

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ec_local.h,v 1.14 2023/06/12 18:17:18 jsing Exp $ */
/* $OpenBSD: ec_local.h,v 1.21 2023/06/25 19:22:21 tb Exp $ */
/*
* Originally written by Bodo Moeller for the OpenSSL project.
*/
@ -145,8 +145,6 @@ struct ec_method_st {
int (*mul_double_nonct)(const EC_GROUP *group, EC_POINT *r,
const BIGNUM *g_scalar, const BIGNUM *p_scalar,
const EC_POINT *point, BN_CTX *);
int (*precompute_mult)(EC_GROUP *group, BN_CTX *);
int (*have_precompute_mult)(const EC_GROUP *group);
/*
* Internal methods.
@ -175,14 +173,6 @@ struct ec_method_st {
BN_CTX *ctx);
} /* EC_METHOD */;
typedef struct ec_extra_data_st {
struct ec_extra_data_st *next;
void *data;
void *(*dup_func)(void *);
void (*free_func)(void *);
void (*clear_free_func)(void *);
} EC_EXTRA_DATA; /* used in EC_GROUP */
struct ec_group_st {
/*
* Methods and members exposed via the public API.
@ -209,8 +199,6 @@ struct ec_group_st {
* if they appear to be generic.
*/
EC_EXTRA_DATA *extra_data;
/*
* Field specification. For GF(p) this is the modulus; for GF(2^m),
* this is the irreducible polynomial defining the field.
@ -264,28 +252,9 @@ struct ec_key_st {
int references;
int flags;
EC_EXTRA_DATA *method_data;
CRYPTO_EX_DATA ex_data;
} /* EC_KEY */;
/* Basically a 'mixin' for extra data, but available for EC_GROUPs/EC_KEYs only
* (with visibility limited to 'package' level for now).
* We use the function pointers as index for retrieval; this obviates
* global ex_data-style index tables.
*/
int EC_EX_DATA_set_data(EC_EXTRA_DATA **, void *data,
void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *,
void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
void EC_EX_DATA_free_data(EC_EXTRA_DATA **,
void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **,
void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **);
void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **);
int ec_group_simple_order_bits(const EC_GROUP *group);
struct ec_point_st {
const EC_METHOD *meth;
@ -308,9 +277,6 @@ struct ec_point_st {
* (ec_lib.c uses these as defaults if group->method->mul is 0) */
int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *);
int ec_wNAF_have_precompute_mult(const EC_GROUP *group);
/* method functions in ecp_smpl.c */
int ec_GFp_simple_group_init(EC_GROUP *);
@ -355,6 +321,7 @@ int ec_GFp_simple_mul_single_ct(const EC_GROUP *, EC_POINT *r, const BIGNUM *sca
int ec_GFp_simple_mul_double_nonct(const EC_GROUP *, EC_POINT *r, const BIGNUM *g_scalar,
const BIGNUM *p_scalar, const EC_POINT *point, BN_CTX *);
int ec_group_simple_order_bits(const EC_GROUP *group);
int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
/* EC_METHOD definitions */
@ -395,12 +362,11 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey);
void *EC_KEY_get_key_method_data(EC_KEY *key,
void *(*dup_func)(void *), void (*free_func)(void *),
void (*clear_free_func)(void *));
void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data,
void *(*dup_func)(void *), void (*free_func)(void *),
void (*clear_free_func)(void *));
/*
* ECDH Key Derivation Function as defined in ANSI X9.63.
*/
int ecdh_KDF_X9_63(unsigned char *out, size_t outlen, const unsigned char *Z,
size_t Zlen, const unsigned char *sinfo, size_t sinfolen, const EVP_MD *md);
int EC_POINT_set_Jprojective_coordinates(const EC_GROUP *group, EC_POINT *p,
const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ec_mult.c,v 1.29 2023/04/11 18:58:20 jsing Exp $ */
/* $OpenBSD: ec_mult.c,v 1.31 2023/06/24 17:49:44 jsing Exp $ */
/*
* Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.
*/
@ -67,7 +67,6 @@
#include "ec_local.h"
/*
* This file implements the wNAF-based interleaving multi-exponentation method
* (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp>);
@ -75,114 +74,6 @@
* (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp>).
*/
/* structure for precomputed multiples of the generator */
typedef struct ec_pre_comp_st {
const EC_GROUP *group; /* parent EC_GROUP object */
size_t blocksize; /* block size for wNAF splitting */
size_t numblocks; /* max. number of blocks for which we have
* precomputation */
size_t w; /* window size */
EC_POINT **points; /* array with pre-calculated multiples of
* generator: 'num' pointers to EC_POINT
* objects followed by a NULL */
size_t num; /* numblocks * 2^(w-1) */
int references;
} EC_PRE_COMP;
/* functions to manage EC_PRE_COMP within the EC_GROUP extra_data framework */
static void *ec_pre_comp_dup(void *);
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_)
{
EC_PRE_COMP *src = src_;
/* no need to actually copy, these objects never change! */
CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
return src_;
}
static void
ec_pre_comp_free(void *pre_)
{
int i;
EC_PRE_COMP *pre = pre_;
if (!pre)
return;
i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
if (i > 0)
return;
if (pre->points) {
EC_POINT **p;
for (p = pre->points; *p != NULL; p++)
EC_POINT_free(*p);
free(pre->points);
}
free(pre);
}
static void
ec_pre_comp_clear_free(void *pre_)
{
int i;
EC_PRE_COMP *pre = pre_;
if (!pre)
return;
i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
if (i > 0)
return;
if (pre->points) {
EC_POINT **p;
for (p = pre->points; *p != NULL; p++) {
EC_POINT_free(*p);
explicit_bzero(p, sizeof *p);
}
free(pre->points);
}
freezero(pre, sizeof *pre);
}
/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'.
* This is an array r[] of values that are either zero or odd with an
* absolute value less than 2^w satisfying
@ -338,8 +229,7 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
const EC_POINT *generator = NULL;
EC_POINT *tmp = NULL;
size_t totalnum;
size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */
size_t pre_points_per_block = 0;
size_t numblocks = 0; /* for wNAF splitting */
size_t i, j;
int k;
int r_is_inverted = 0;
@ -354,7 +244,6 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
EC_POINT **v;
EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or
* 'pre_comp->points' */
const EC_PRE_COMP *pre_comp = NULL;
int num_scalar = 0; /* flag: will be set to 1 if 'scalar' must be
* treated like other scalars, i.e.
* precomputation is not available */
@ -380,42 +269,10 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
ECerror(EC_R_UNDEFINED_GENERATOR);
goto err;
}
/* look if we can use precomputed multiples of generator */
pre_comp = EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free);
if (pre_comp && pre_comp->numblocks &&
(EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) == 0)) {
blocksize = pre_comp->blocksize;
/*
* determine maximum number of blocks that wNAF
* splitting may yield (NB: maximum wNAF length is
* bit length plus one)
*/
numblocks = (BN_num_bits(scalar) / blocksize) + 1;
/*
* we cannot use more blocks than we have
* precomputation for
*/
if (numblocks > pre_comp->numblocks)
numblocks = pre_comp->numblocks;
pre_points_per_block = (size_t) 1 << (pre_comp->w - 1);
/* check that pre_comp looks sane */
if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) {
ECerror(ERR_R_INTERNAL_ERROR);
goto err;
}
} else {
/* can't use precomputation */
pre_comp = NULL;
numblocks = 1;
num_scalar = 1; /* treat 'scalar' like 'num'-th
* element of 'scalars' */
}
numblocks = 1;
num_scalar = 1; /* treat 'scalar' like 'num'-th
* element of 'scalars' */
}
totalnum = num + numblocks;
@ -457,111 +314,9 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
if (numblocks) {
/* we go here iff scalar != NULL */
if (pre_comp == NULL) {
if (num_scalar != 1) {
ECerror(ERR_R_INTERNAL_ERROR);
goto err;
}
/* we have already generated a wNAF for 'scalar' */
} else {
size_t tmp_len = 0;
if (num_scalar != 0) {
ECerror(ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* use the window size for which we have
* precomputation
*/
wsize[num] = pre_comp->w;
tmp_wNAF = compute_wNAF(scalar, wsize[num], &tmp_len);
if (tmp_wNAF == NULL)
goto err;
if (tmp_len <= max_len) {
/*
* One of the other wNAFs is at least as long
* as the wNAF belonging to the generator, so
* wNAF splitting will not buy us anything.
*/
numblocks = 1;
totalnum = num + 1; /* don't use wNAF
* splitting */
wNAF[num] = tmp_wNAF;
tmp_wNAF = NULL;
wNAF[num + 1] = NULL;
wNAF_len[num] = tmp_len;
if (tmp_len > max_len)
max_len = tmp_len;
/*
* pre_comp->points starts with the points
* that we need here:
*/
val_sub[num] = pre_comp->points;
} else {
/*
* don't include tmp_wNAF directly into wNAF
* array - use wNAF splitting and include the
* blocks
*/
signed char *pp;
EC_POINT **tmp_points;
if (tmp_len < numblocks * blocksize) {
/*
* possibly we can do with fewer
* blocks than estimated
*/
numblocks = (tmp_len + blocksize - 1) / blocksize;
if (numblocks > pre_comp->numblocks) {
ECerror(ERR_R_INTERNAL_ERROR);
goto err;
}
totalnum = num + numblocks;
}
/* split wNAF in 'numblocks' parts */
pp = tmp_wNAF;
tmp_points = pre_comp->points;
for (i = num; i < totalnum; i++) {
if (i < totalnum - 1) {
wNAF_len[i] = blocksize;
if (tmp_len < blocksize) {
ECerror(ERR_R_INTERNAL_ERROR);
goto err;
}
tmp_len -= blocksize;
} else
/*
* last block gets whatever
* is left (this could be
* more or less than
* 'blocksize'!)
*/
wNAF_len[i] = tmp_len;
wNAF[i + 1] = NULL;
wNAF[i] = malloc(wNAF_len[i]);
if (wNAF[i] == NULL) {
ECerror(ERR_R_MALLOC_FAILURE);
goto err;
}
memcpy(wNAF[i], pp, wNAF_len[i]);
if (wNAF_len[i] > max_len)
max_len = wNAF_len[i];
if (*tmp_points == NULL) {
ECerror(ERR_R_INTERNAL_ERROR);
goto err;
}
val_sub[i] = tmp_points;
tmp_points += pre_points_per_block;
pp += blocksize;
}
}
if (num_scalar != 1) {
ECerror(ERR_R_INTERNAL_ERROR);
goto err;
}
}
/*
@ -693,181 +448,3 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
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;
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ec_pmeth.c,v 1.17 2023/04/25 15:48:48 tb Exp $ */
/* $OpenBSD: ec_pmeth.c,v 1.18 2023/06/25 19:26:04 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
@ -68,7 +68,6 @@
#include "bn_local.h"
#include "ec_local.h"
#include "ech_local.h"
#include "evp_local.h"
/* EC pkey context structure */