Commit 3aef36ff authored by Rich Salz's avatar Rich Salz Committed by Rich Salz
Browse files

Add CRYPTO_EX_DATA; remove EC_EXTRA_DATA



Add CRYPTO_EX_DATA add EndC_KEY_[gs]et_method, From Roumen Petrov.
Had to add various exdata calls to init/copy/free the exdata.
Had to remove const from some EC functions because exdata isn't
const-correct. :(
Also remove EC_EXTRA_DATA and use a union to hold the possible
pre-computed values and an enum to tell which value is in the
union. (Rich Salz)

Reviewed-by: default avatarDr. Stephen Henson <steve@openssl.org>
parent 8ffcca65
Loading
Loading
Loading
Loading
+7 −54
Original line number Diff line number Diff line
@@ -120,19 +120,16 @@ void EC_KEY_free(EC_KEY *r)
        ENGINE_finish(r->engine);
#endif

    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data);
    EC_GROUP_free(r->group);
    EC_POINT_free(r->pub_key);
    BN_clear_free(r->priv_key);

    EC_EX_DATA_free_all_data(&r->method_data);

    OPENSSL_clear_free((void *)r, sizeof(EC_KEY));
}

EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
EC_KEY *EC_KEY_copy(EC_KEY *dest, EC_KEY *src)
{
    EC_EXTRA_DATA *d;

    if (dest == NULL || src == NULL) {
        ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
        return NULL;
@@ -176,25 +173,15 @@ EC_KEY *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 NULL;
    }

    /* copy the rest */
    dest->enc_flag = src->enc_flag;
    dest->conv_form = src->conv_form;
    dest->version = src->version;
    dest->flags = src->flags;
    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY,
                            &dest->ex_data, &src->ex_data))
        return NULL;

    if (src->meth != dest->meth) {
#ifndef OPENSSL_NO_ENGINE
@@ -211,9 +198,10 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
    return dest;
}

EC_KEY *EC_KEY_dup(const EC_KEY *ec_key)
EC_KEY *EC_KEY_dup(EC_KEY *ec_key)
{
    EC_KEY *ret = EC_KEY_new_method(ec_key->engine);

    if (ret == NULL)
        return NULL;
    if (EC_KEY_copy(ret, ec_key) == NULL) {
@@ -513,41 +501,6 @@ void 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)
{
    if (key->group != NULL)
+32 −2
Original line number Diff line number Diff line
@@ -93,6 +93,31 @@ void EC_KEY_set_default_method(const EC_KEY_METHOD *meth)
        default_ec_key_meth = meth;
}

const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key)
{
    return key->meth;
}

int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth)
{
    void (*finish)(EC_KEY *key) = key->meth->finish;

    if (finish != NULL)
        finish(key);

#ifndef OPENSSL_NO_ENGINE
    if (key->engine != NULL) {
        ENGINE_finish(key->engine);
        key->engine = NULL;
    }
#endif

    key->meth = meth;
    if (meth->init != NULL)
        return meth->init(key);
    return 1;
}

EC_KEY *EC_KEY_new_method(ENGINE *engine)
{
    EC_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
@@ -101,6 +126,11 @@ EC_KEY *EC_KEY_new_method(ENGINE *engine)
        ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE);
        return (NULL);
    }
    if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data)) {
        OPENSSL_free(ret);
        return NULL;
    }

    ret->meth = EC_KEY_get_default_method();
#ifndef OPENSSL_NO_ENGINE
    if (engine != NULL) {
@@ -146,8 +176,8 @@ int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,

EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *meth)
{
    EC_KEY_METHOD *ret;
    ret = OPENSSL_zalloc(sizeof(*meth));
    EC_KEY_METHOD *ret = OPENSSL_zalloc(sizeof(*meth));

    if (ret == NULL)
        return NULL;
    if (meth != NULL)
+39 −31
Original line number Diff line number Diff line
@@ -198,13 +198,14 @@ struct ec_method_st {
    int (*field_set_to_one) (const EC_GROUP *, BIGNUM *r, BN_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 */
/*
 * Types and functions to manipulate pre-computed values.
 */
typedef struct nistp224_pre_comp_st NISTP224_PRE_COMP;
typedef struct nistp256_pre_comp_st NISTP256_PRE_COMP;
typedef struct nistp512_pre_comp_st NISTP521_PRE_COMP;
typedef struct nistz256_pre_comp_st NISTZ256_PRE_COMP;
typedef struct ec_pre_comp_st EC_PRE_COMP;

struct ec_group_st {
    const EC_METHOD *meth;
@@ -216,7 +217,6 @@ struct ec_group_st {
    unsigned char *seed;        /* optional seed for parameters (appears in
                                 * ASN1) */
    size_t seed_len;
    EC_EXTRA_DATA *extra_data;  /* linked list */
    /*
     * The following members are handled by the method functions, even if
     * they appear generic
@@ -254,8 +254,26 @@ struct ec_group_st {
                           BN_CTX *);
    /* data for ECDSA inverse */
    BN_MONT_CTX *mont_data;

    /* precomputed values for speed. */
    enum {
        pct_none,
        pct_nistp224, pct_nistp256, pct_nistp521, pct_nistz256,
        pct_ec } pre_comp_type;
    union {
        NISTP224_PRE_COMP *nistp224;
        NISTP256_PRE_COMP *nistp256;
        NISTP521_PRE_COMP *nistp521;
        NISTZ256_PRE_COMP *nistz256;
        EC_PRE_COMP *ec;
    } pre_comp;
} /* EC_GROUP */ ;

#define SETPRECOMP(g, type, pre) \
    g->pre_comp_type = pct_##type, g->pre_comp.type = pre
#define HAVEPRECOMP(g, type) \
    g->pre_comp_type == pct_##type && g->pre_comp.type != NULL

struct ec_key_st {
    const EC_KEY_METHOD *meth;
    ENGINE *engine;
@@ -267,31 +285,9 @@ struct ec_key_st {
    point_conversion_form_t conv_form;
    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 **);

struct ec_point_st {
    const EC_METHOD *meth;
    /*
@@ -306,6 +302,18 @@ struct ec_point_st {
                                 * special case */
} /* EC_POINT */ ;

NISTP224_PRE_COMP *EC_nistp224_pre_comp_dup(NISTP224_PRE_COMP *);
NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *);
NISTP521_PRE_COMP *EC_nistp521_pre_comp_dup(NISTP521_PRE_COMP *);
NISTZ256_PRE_COMP *EC_nistz256_pre_comp_dup(NISTZ256_PRE_COMP *);
NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *);
EC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *);
void EC_nistp224_pre_comp_free(NISTP224_PRE_COMP *);
void EC_nistp256_pre_comp_free(NISTP256_PRE_COMP *);
void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *);
void EC_nistz256_pre_comp_free(NISTZ256_PRE_COMP *);
void EC_ec_pre_comp_free(EC_PRE_COMP *);

/*
 * method functions in ec_mult.c (ec_lib.c uses these as defaults if
 * group->method->mul is 0)
+61 −162
Original line number Diff line number Diff line
@@ -109,6 +109,32 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
    return NULL;
}

static void ec_group_free_precomp(EC_GROUP *group)
{
    switch (group->pre_comp_type) {
    default:
        break;
    case pct_nistz256:
        EC_nistz256_pre_comp_free(group->pre_comp.nistz256);
        break;
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
    case pct_nistp224:
        EC_nistp224_pre_comp_free(group->pre_comp.nistp224);
        break;
    case pct_nistp256:
        EC_nistp256_pre_comp_free(group->pre_comp.nistp256);
        break;
    case pct_nistp521:
        EC_nistp521_pre_comp_free(group->pre_comp.nistp521);
        break;
#endif
    case pct_ec:
        EC_ec_pre_comp_free(group->pre_comp.ec);
        break;
    }
    group->pre_comp.ec = NULL;
}

void EC_GROUP_free(EC_GROUP *group)
{
    if (!group)
@@ -117,7 +143,7 @@ void EC_GROUP_free(EC_GROUP *group)
    if (group->meth->group_finish != 0)
        group->meth->group_finish(group);

    EC_EX_DATA_free_all_data(&group->extra_data);
    ec_group_free_precomp(group);
    BN_MONT_CTX_free(group->mont_data);
    EC_POINT_free(group->generator);
    BN_free(group->order);
@@ -136,10 +162,8 @@ void EC_GROUP_clear_free(EC_GROUP *group)
    else if (group->meth->group_finish != 0)
        group->meth->group_finish(group);

    EC_EX_DATA_clear_free_all_data(&group->extra_data);

    ec_group_free_precomp(group);
    BN_MONT_CTX_free(group->mont_data);

    EC_POINT_clear_free(group->generator);
    BN_clear_free(group->order);
    BN_clear_free(group->cofactor);
@@ -149,8 +173,6 @@ void 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 == 0) {
        ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
        return 0;
@@ -162,17 +184,29 @@ int 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;
    /* Copy precomputed */
    dest->pre_comp_type = src->pre_comp_type;
    switch (src->pre_comp_type) {
    default:
        dest->pre_comp.ec = NULL;
        break;
    case pct_nistz256:
        dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256);
        break;
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
    case pct_nistp224:
        dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224);
        break;
    case pct_nistp256:
        dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256);
        break;
    case pct_nistp521:
        dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521);
        break;
#endif
    case pct_ec:
        dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec);
        break;
    }

    if (src->mont_data != NULL) {
@@ -518,151 +552,6 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
    return r;
}

/* 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) {
            ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
            return 0;
        }
    }

    if (data == NULL)
        /* no explicit entry needed */
        return 1;

    d = OPENSSL_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);
            OPENSSL_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);
            OPENSSL_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);
        OPENSSL_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);
        OPENSSL_free(d);

        d = next;
    }
    *ex_data = NULL;
}

/* functions for EC_POINT objects */

EC_POINT *EC_POINT_new(const EC_GROUP *group)
@@ -1091,3 +980,13 @@ int ec_precompute_mont_data(EC_GROUP *group)
    BN_CTX_free(ctx);
    return ret;
}

int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg)
{
    return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
}

void *EC_KEY_get_ex_data(const EC_KEY *key, int idx)
{
    return CRYPTO_get_ex_data(&key->ex_data, idx);
}
+19 −72
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@
 */

/* structure for precomputed multiples of the generator */
typedef struct ec_pre_comp_st {
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
@@ -86,12 +86,7 @@ typedef struct ec_pre_comp_st {
                                 * 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)
{
@@ -112,63 +107,29 @@ static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group)
    return ret;
}

static void *ec_pre_comp_dup(void *src_)
EC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *pre)
{
    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_;
    if (pre != NULL)
        CRYPTO_add(&pre->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
    return pre;
}

static void ec_pre_comp_free(void *pre_)
void EC_ec_pre_comp_free(EC_PRE_COMP *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)
    if (pre == NULL
        || CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP) > 0)
        return;

    if (pre->points) {
        EC_POINT **p;
    if (pre->points != NULL) {
        EC_POINT **pts;

        for (p = pre->points; *p != NULL; p++)
            EC_POINT_free(*p);
        for (pts = pre->points; *pts != NULL; pts++)
            EC_POINT_free(*pts);
        OPENSSL_free(pre->points);
    }
    OPENSSL_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_clear_free(*p);
            OPENSSL_cleanse(p, sizeof(*p));
        }
        OPENSSL_free(pre->points);
    }
    OPENSSL_clear_free(pre, sizeof(*pre));
}

/*
 * TODO: table should be optimised for the wNAF-based implementation,
 * sometimes smaller windows will give better performance (thus the
@@ -250,10 +211,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,

        /* 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);

        pre_comp = group->pre_comp.ec;
        if (pre_comp && pre_comp->numblocks
            && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) ==
                0)) {
@@ -604,9 +562,7 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
    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);

    EC_ec_pre_comp_free(group->pre_comp.ec);
    if ((pre_comp = ec_pre_comp_new(group)) == NULL)
        return 0;

@@ -728,19 +684,15 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
    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;
    SETPRECOMP(group, ec, pre_comp);
    pre_comp = NULL;

    ret = 1;

 err:
    if (ctx != NULL)
        BN_CTX_end(ctx);
    BN_CTX_free(new_ctx);
    ec_pre_comp_free(pre_comp);
    EC_ec_pre_comp_free(pre_comp);
    if (points) {
        EC_POINT **p;

@@ -755,10 +707,5 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)

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;
    return HAVEPRECOMP(group, ec);
}
Loading