ec_lib.c revision 296465
11541Srgrimes/* crypto/ec/ec_lib.c */
21541Srgrimes/*
31541Srgrimes * Originally written by Bodo Moeller for the OpenSSL project.
41541Srgrimes */
51541Srgrimes/* ====================================================================
61541Srgrimes * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
71541Srgrimes *
81541Srgrimes * Redistribution and use in source and binary forms, with or without
91541Srgrimes * modification, are permitted provided that the following conditions
101541Srgrimes * are met:
111541Srgrimes *
121541Srgrimes * 1. Redistributions of source code must retain the above copyright
131541Srgrimes *    notice, this list of conditions and the following disclaimer.
141541Srgrimes *
151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161541Srgrimes *    notice, this list of conditions and the following disclaimer in
171541Srgrimes *    the documentation and/or other materials provided with the
181541Srgrimes *    distribution.
191541Srgrimes *
201541Srgrimes * 3. All advertising materials mentioning features or use of this
211541Srgrimes *    software must display the following acknowledgment:
221541Srgrimes *    "This product includes software developed by the OpenSSL Project
231541Srgrimes *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
241541Srgrimes *
251541Srgrimes * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
261541Srgrimes *    endorse or promote products derived from this software without
271541Srgrimes *    prior written permission. For written permission, please contact
281541Srgrimes *    openssl-core@openssl.org.
291541Srgrimes *
301541Srgrimes * 5. Products derived from this software may not be called "OpenSSL"
311541Srgrimes *    nor may "OpenSSL" appear in their names without prior written
321541Srgrimes *    permission of the OpenSSL Project.
331541Srgrimes *
341541Srgrimes * 6. Redistributions of any form whatsoever must retain the following
351541Srgrimes *    acknowledgment:
3622521Sdyson *    "This product includes software developed by the OpenSSL Project
3732011Sbde *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
381541Srgrimes *
391541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4022521Sdyson * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
411541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
429336Sdfr * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
431541Srgrimes * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
441541Srgrimes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
451541Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
461541Srgrimes * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
471541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
489336Sdfr * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
499336Sdfr * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
501541Srgrimes * OF THE POSSIBILITY OF SUCH DAMAGE.
511541Srgrimes * ====================================================================
521541Srgrimes *
531541Srgrimes * This product includes cryptographic software written by Eric Young
541541Srgrimes * (eay@cryptsoft.com).  This product includes software written by Tim
551541Srgrimes * Hudson (tjh@cryptsoft.com).
561541Srgrimes *
579336Sdfr */
581960Sdg/* ====================================================================
591541Srgrimes * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
601541Srgrimes * Binary polynomial ECC support in OpenSSL originally developed by
6112662Sdg * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
6232011Sbde */
631541Srgrimes
6429363Speter#include <string.h>
651541Srgrimes
661541Srgrimes#include <openssl/err.h>
671541Srgrimes#include <openssl/opensslv.h>
689336Sdfr
691541Srgrimes#include "ec_lcl.h"
701541Srgrimes
711541Srgrimesstatic const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
721541Srgrimes
731541Srgrimes/* functions for EC_GROUP objects */
741541Srgrimes
751541SrgrimesEC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
769336Sdfr{
779336Sdfr    EC_GROUP *ret;
789336Sdfr
799336Sdfr    if (meth == NULL) {
801541Srgrimes        ECerr(EC_F_EC_GROUP_NEW, ERR_R_PASSED_NULL_PARAMETER);
811541Srgrimes        return NULL;
821541Srgrimes    }
831541Srgrimes    if (meth->group_init == 0) {
841541Srgrimes        ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
859336Sdfr        return NULL;
869336Sdfr    }
879336Sdfr
889336Sdfr    ret = OPENSSL_malloc(sizeof *ret);
899336Sdfr    if (ret == NULL) {
909336Sdfr        ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
919336Sdfr        return NULL;
929336Sdfr    }
9311921Sphk
9411921Sphk    ret->meth = meth;
9511921Sphk
9611921Sphk    ret->extra_data = NULL;
9711921Sphk
9811921Sphk    ret->generator = NULL;
9929363Speter    BN_init(&ret->order);
10011921Sphk    BN_init(&ret->cofactor);
10111921Sphk
10230118Sphk    ret->curve_name = 0;
10311921Sphk    ret->asn1_flag = 0;
10411921Sphk    ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
10511921Sphk
10611921Sphk    ret->seed = NULL;
10711921Sphk    ret->seed_len = 0;
10811921Sphk
10911921Sphk    if (!meth->group_init(ret)) {
11011921Sphk        OPENSSL_free(ret);
11111921Sphk        return NULL;
11211921Sphk    }
11311921Sphk
11411921Sphk    return ret;
11511921Sphk}
11611921Sphk
11711921Sphkvoid EC_GROUP_free(EC_GROUP *group)
11811921Sphk{
11911921Sphk    if (!group)
12011921Sphk        return;
12111921Sphk
12211921Sphk    if (group->meth->group_finish != 0)
12311921Sphk        group->meth->group_finish(group);
12411921Sphk
12511921Sphk    EC_EX_DATA_free_all_data(&group->extra_data);
12611921Sphk
12711921Sphk    if (group->generator != NULL)
12811921Sphk        EC_POINT_free(group->generator);
1299336Sdfr    BN_free(&group->order);
1301541Srgrimes    BN_free(&group->cofactor);
1311541Srgrimes
13212158Sbde    if (group->seed)
13311921Sphk        OPENSSL_free(group->seed);
13430743Sphk
13530431Sphk    OPENSSL_free(group);
13630431Sphk}
13730431Sphk
13830431Sphkvoid EC_GROUP_clear_free(EC_GROUP *group)
13930431Sphk{
14030431Sphk    if (!group)
14130431Sphk        return;
14230431Sphk
14330431Sphk    if (group->meth->group_clear_finish != 0)
14430434Sphk        group->meth->group_clear_finish(group);
14530434Sphk    else if (group->meth->group_finish != 0)
14630743Sphk        group->meth->group_finish(group);
14730431Sphk
14830474Sphk    EC_EX_DATA_clear_free_all_data(&group->extra_data);
14930431Sphk
15030431Sphk    if (group->generator != NULL)
15130431Sphk        EC_POINT_clear_free(group->generator);
15230431Sphk    BN_clear_free(&group->order);
15330431Sphk    BN_clear_free(&group->cofactor);
15430431Sphk
15530431Sphk    if (group->seed) {
15630431Sphk        OPENSSL_cleanse(group->seed, group->seed_len);
15730431Sphk        OPENSSL_free(group->seed);
15830434Sphk    }
15930431Sphk
16030431Sphk    OPENSSL_cleanse(group, sizeof *group);
16130431Sphk    OPENSSL_free(group);
16230431Sphk}
16330431Sphk
16430434Sphkint EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
16530431Sphk{
16630431Sphk    EC_EXTRA_DATA *d;
16712158Sbde
1681541Srgrimes    if (dest->meth->group_copy == 0) {
16911921Sphk        ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1701541Srgrimes        return 0;
1712946Swollman    }
1721541Srgrimes    if (dest->meth != src->meth) {
1731541Srgrimes        ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
1741541Srgrimes        return 0;
1751541Srgrimes    }
17612158Sbde    if (dest == src)
17730496Sphk        return 1;
17830439Sphk
17930431Sphk    EC_EX_DATA_free_all_data(&dest->extra_data);
18030431Sphk
18130431Sphk    for (d = src->extra_data; d != NULL; d = d->next) {
18230431Sphk        void *t = d->dup_func(d->data);
18330434Sphk
18430474Sphk        if (t == NULL)
18530431Sphk            return 0;
18630431Sphk        if (!EC_EX_DATA_set_data
18730431Sphk            (&dest->extra_data, t, d->dup_func, d->free_func,
18830431Sphk             d->clear_free_func))
18930431Sphk            return 0;
19012158Sbde    }
1911541Srgrimes
19211921Sphk    if (src->generator != NULL) {
19330496Sphk        if (dest->generator == NULL) {
1942946Swollman            dest->generator = EC_POINT_new(dest);
1951541Srgrimes            if (dest->generator == NULL)
19612158Sbde                return 0;
19730496Sphk        }
19830439Sphk        if (!EC_POINT_copy(dest->generator, src->generator))
19930431Sphk            return 0;
20030431Sphk    } else {
20130431Sphk        /* src->generator == NULL */
20230431Sphk        if (dest->generator != NULL) {
20330434Sphk            EC_POINT_clear_free(dest->generator);
20430474Sphk            dest->generator = NULL;
20530431Sphk        }
20630431Sphk    }
20730431Sphk
20830431Sphk    if (!BN_copy(&dest->order, &src->order))
20930431Sphk        return 0;
21012158Sbde    if (!BN_copy(&dest->cofactor, &src->cofactor))
2111541Srgrimes        return 0;
21211921Sphk
21330496Sphk    dest->curve_name = src->curve_name;
2142946Swollman    dest->asn1_flag = src->asn1_flag;
2151541Srgrimes    dest->asn1_form = src->asn1_form;
21612457Sbde
21712457Sbde    if (src->seed) {
21812457Sbde        if (dest->seed)
21912457Sbde            OPENSSL_free(dest->seed);
22012457Sbde        dest->seed = OPENSSL_malloc(src->seed_len);
22112457Sbde        if (dest->seed == NULL)
22212457Sbde            return 0;
22312457Sbde        if (!memcpy(dest->seed, src->seed, src->seed_len))
22412457Sbde            return 0;
22512457Sbde        dest->seed_len = src->seed_len;
22612457Sbde    } else {
22712457Sbde        if (dest->seed)
22812457Sbde            OPENSSL_free(dest->seed);
22912457Sbde        dest->seed = NULL;
2301541Srgrimes        dest->seed_len = 0;
2311541Srgrimes    }
2321541Srgrimes
2331541Srgrimes    return dest->meth->group_copy(dest, src);
2349336Sdfr}
2359336Sdfr
2369336SdfrEC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
2371541Srgrimes{
23819449Sdfr    EC_GROUP *t = NULL;
2391541Srgrimes    int ok = 0;
2401541Srgrimes
2411541Srgrimes    if (a == NULL)
2421541Srgrimes        return NULL;
2431541Srgrimes
2449336Sdfr    if ((t = EC_GROUP_new(a->meth)) == NULL)
2459336Sdfr        return (NULL);
2469336Sdfr    if (!EC_GROUP_copy(t, a))
2471541Srgrimes        goto err;
24811921Sphk
2491541Srgrimes    ok = 1;
2501541Srgrimes
2511541Srgrimes err:
2521541Srgrimes    if (!ok) {
2531541Srgrimes        if (t)
2541541Srgrimes            EC_GROUP_free(t);
2551541Srgrimes        return NULL;
2561541Srgrimes    } else
2571541Srgrimes        return t;
2581541Srgrimes}
2591541Srgrimes
2609336Sdfrconst EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
2619336Sdfr{
2629336Sdfr    return group->meth;
2631541Srgrimes}
2649336Sdfr
2659336Sdfrint EC_METHOD_get_field_type(const EC_METHOD *meth)
2661541Srgrimes{
2671541Srgrimes    return meth->field_type;
26811644Sdg}
26911644Sdg
27011644Sdgint EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
27111644Sdg                           const BIGNUM *order, const BIGNUM *cofactor)
27211644Sdg{
27311644Sdg    if (generator == NULL) {
27411644Sdg        ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
27511644Sdg        return 0;
27611644Sdg    }
27711644Sdg
27811644Sdg    if (group->generator == NULL) {
2799336Sdfr        group->generator = EC_POINT_new(group);
2801541Srgrimes        if (group->generator == NULL)
2811541Srgrimes            return 0;
2821541Srgrimes    }
2831541Srgrimes    if (!EC_POINT_copy(group->generator, generator))
2841541Srgrimes        return 0;
2851541Srgrimes
2869336Sdfr    if (order != NULL) {
2879336Sdfr        if (!BN_copy(&group->order, order))
2889336Sdfr            return 0;
2899336Sdfr    } else
2909336Sdfr        BN_zero(&group->order);
2911541Srgrimes
2929336Sdfr    if (cofactor != NULL) {
2931541Srgrimes        if (!BN_copy(&group->cofactor, cofactor))
2949336Sdfr            return 0;
2959336Sdfr    } else
2969336Sdfr        BN_zero(&group->cofactor);
2979336Sdfr
2989336Sdfr    return 1;
2999336Sdfr}
3009336Sdfr
3019336Sdfrconst EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
3029336Sdfr{
3039336Sdfr    return group->generator;
3049336Sdfr}
3059336Sdfr
3069336Sdfrint EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
3079336Sdfr{
3089336Sdfr    if (!BN_copy(order, &group->order))
3099336Sdfr        return 0;
3109336Sdfr
3119336Sdfr    return !BN_is_zero(order);
3129336Sdfr}
3139336Sdfr
3149336Sdfrint EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
3159336Sdfr                          BN_CTX *ctx)
3169336Sdfr{
3179336Sdfr    if (!BN_copy(cofactor, &group->cofactor))
3189336Sdfr        return 0;
3199336Sdfr
3209336Sdfr    return !BN_is_zero(&group->cofactor);
3211541Srgrimes}
3221541Srgrimes
32325611Sdfrvoid EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
32425611Sdfr{
32525611Sdfr    group->curve_name = nid;
32625611Sdfr}
32725611Sdfr
32825611Sdfrint EC_GROUP_get_curve_name(const EC_GROUP *group)
32925611Sdfr{
33025611Sdfr    return group->curve_name;
33125611Sdfr}
33225611Sdfr
33325611Sdfrvoid EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
33425611Sdfr{
33525611Sdfr    group->asn1_flag = flag;
33625611Sdfr}
33725611Sdfr
33825611Sdfrint EC_GROUP_get_asn1_flag(const EC_GROUP *group)
33925611Sdfr{
34025611Sdfr    return group->asn1_flag;
34125611Sdfr}
34225611Sdfr
34325611Sdfrvoid EC_GROUP_set_point_conversion_form(EC_GROUP *group,
34425611Sdfr                                        point_conversion_form_t form)
34525611Sdfr{
34625611Sdfr    group->asn1_form = form;
34725611Sdfr}
34825611Sdfr
34925611Sdfrpoint_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
35025611Sdfr                                                           *group)
35125611Sdfr{
35225611Sdfr    return group->asn1_form;
35331017Sphk}
35431017Sphk
35531017Sphksize_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
35625611Sdfr{
35725611Sdfr    if (group->seed) {
35831017Sphk        OPENSSL_free(group->seed);
35925611Sdfr        group->seed = NULL;
36025611Sdfr        group->seed_len = 0;
36125611Sdfr    }
36225611Sdfr
36325611Sdfr    if (!len || !p)
36425611Sdfr        return 1;
36525611Sdfr
3661541Srgrimes    if ((group->seed = OPENSSL_malloc(len)) == NULL)
3671541Srgrimes        return 0;
3681541Srgrimes    memcpy(group->seed, p, len);
3691541Srgrimes    group->seed_len = len;
3701541Srgrimes
3711541Srgrimes    return len;
3721541Srgrimes}
3731541Srgrimes
3741541Srgrimesunsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
3751541Srgrimes{
37611921Sphk    return group->seed;
3771541Srgrimes}
3781541Srgrimes
3791541Srgrimessize_t EC_GROUP_get_seed_len(const EC_GROUP *group)
3801541Srgrimes{
3811541Srgrimes    return group->seed_len;
3821541Srgrimes}
3831541Srgrimes
3841541Srgrimesint EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
3851541Srgrimes                           const BIGNUM *b, BN_CTX *ctx)
3861541Srgrimes{
3871541Srgrimes    if (group->meth->group_set_curve == 0) {
3881541Srgrimes        ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
3891541Srgrimes        return 0;
3901541Srgrimes    }
3911541Srgrimes    return group->meth->group_set_curve(group, p, a, b, ctx);
3929336Sdfr}
3931541Srgrimes
3949336Sdfrint EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
3952384Sdg                           BIGNUM *b, BN_CTX *ctx)
3962384Sdg{
3972384Sdg    if (group->meth->group_get_curve == 0) {
3982384Sdg        ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
3999336Sdfr        return 0;
4001541Srgrimes    }
4019336Sdfr    return group->meth->group_get_curve(group, p, a, b, ctx);
4029336Sdfr}
4031541Srgrimes
4041541Srgrimesint EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
4051541Srgrimes                            const BIGNUM *b, BN_CTX *ctx)
4061541Srgrimes{
4071541Srgrimes    if (group->meth->group_set_curve == 0) {
4081541Srgrimes        ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M,
4091541Srgrimes              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
4101541Srgrimes        return 0;
41122521Sdyson    }
4121541Srgrimes    return group->meth->group_set_curve(group, p, a, b, ctx);
4131541Srgrimes}
4141541Srgrimes
4152384Sdgint EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
4161541Srgrimes                            BIGNUM *b, BN_CTX *ctx)
4171541Srgrimes{
4181541Srgrimes    if (group->meth->group_get_curve == 0) {
4191541Srgrimes        ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M,
4201541Srgrimes              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
4219336Sdfr        return 0;
4229336Sdfr    }
4233305Sphk    return group->meth->group_get_curve(group, p, a, b, ctx);
4243305Sphk}
4251541Srgrimes
42618397Snateint EC_GROUP_get_degree(const EC_GROUP *group)
4271541Srgrimes{
4283305Sphk    if (group->meth->group_get_degree == 0) {
4293305Sphk        ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
4301541Srgrimes        return 0;
43118397Snate    }
4329336Sdfr    return group->meth->group_get_degree(group);
4339336Sdfr}
4341541Srgrimes
4351541Srgrimesint EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
4361541Srgrimes{
43718397Snate    if (group->meth->group_check_discriminant == 0) {
4381541Srgrimes        ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,
4391541Srgrimes              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
4402384Sdg        return 0;
4412384Sdg    }
4421541Srgrimes    return group->meth->group_check_discriminant(group, ctx);
4431541Srgrimes}
4441541Srgrimes
4451541Srgrimesint EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
4461541Srgrimes{
4471541Srgrimes    int r = 0;
4489336Sdfr    BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
4499336Sdfr    BN_CTX *ctx_new = NULL;
4509336Sdfr
4519336Sdfr    /* compare the field types */
4529336Sdfr    if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
4539336Sdfr        EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
4549336Sdfr        return 1;
4559336Sdfr    /* compare the curve name (if present in both) */
4569336Sdfr    if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
4579336Sdfr        EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
4589336Sdfr        return 1;
4599336Sdfr
4609336Sdfr    if (!ctx)
4619336Sdfr        ctx_new = ctx = BN_CTX_new();
4629336Sdfr    if (!ctx)
4639336Sdfr        return -1;
4649336Sdfr
4659336Sdfr    BN_CTX_start(ctx);
4669336Sdfr    a1 = BN_CTX_get(ctx);
4679336Sdfr    a2 = BN_CTX_get(ctx);
4689336Sdfr    a3 = BN_CTX_get(ctx);
4699336Sdfr    b1 = BN_CTX_get(ctx);
4709336Sdfr    b2 = BN_CTX_get(ctx);
4719336Sdfr    b3 = BN_CTX_get(ctx);
4729336Sdfr    if (!b3) {
4739336Sdfr        BN_CTX_end(ctx);
4749336Sdfr        if (ctx_new)
4751541Srgrimes            BN_CTX_free(ctx);
4761541Srgrimes        return -1;
47711921Sphk    }
4781541Srgrimes
4791541Srgrimes    /*
4801541Srgrimes     * XXX This approach assumes that the external representation of curves
4811541Srgrimes     * over the same field type is the same.
4821541Srgrimes     */
4831541Srgrimes    if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
4841541Srgrimes        !b->meth->group_get_curve(b, b1, b2, b3, ctx))
4851541Srgrimes        r = 1;
4861541Srgrimes
4871541Srgrimes    if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
4881541Srgrimes        r = 1;
4891541Srgrimes
4901541Srgrimes    /* XXX EC_POINT_cmp() assumes that the methods are equal */
4911541Srgrimes    if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
4921541Srgrimes                          EC_GROUP_get0_generator(b), ctx))
4931541Srgrimes        r = 1;
4949522Sdfr
4959336Sdfr    if (!r) {
4969522Sdfr        /* compare the order and cofactor */
4979522Sdfr        if (!EC_GROUP_get_order(a, a1, ctx) ||
4989336Sdfr            !EC_GROUP_get_order(b, b1, ctx) ||
4991541Srgrimes            !EC_GROUP_get_cofactor(a, a2, ctx) ||
5001541Srgrimes            !EC_GROUP_get_cofactor(b, b2, ctx)) {
5011541Srgrimes            BN_CTX_end(ctx);
5021541Srgrimes            if (ctx_new)
5031541Srgrimes                BN_CTX_free(ctx);
5041541Srgrimes            return -1;
5051541Srgrimes        }
5061541Srgrimes        if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
5071541Srgrimes            r = 1;
5081541Srgrimes    }
5091541Srgrimes
5101541Srgrimes    BN_CTX_end(ctx);
5111541Srgrimes    if (ctx_new)
51211921Sphk        BN_CTX_free(ctx);
5131541Srgrimes
5141541Srgrimes    return r;
5151541Srgrimes}
5161541Srgrimes
5171541Srgrimes/* this has 'package' visibility */
5181541Srgrimesint EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
5191541Srgrimes                        void *(*dup_func) (void *),
5201541Srgrimes                        void (*free_func) (void *),
5211541Srgrimes                        void (*clear_free_func) (void *))
5221541Srgrimes{
5231541Srgrimes    EC_EXTRA_DATA *d;
5249336Sdfr
5259336Sdfr    if (ex_data == NULL)
5261541Srgrimes        return 0;
5271541Srgrimes
5281541Srgrimes    for (d = *ex_data; d != NULL; d = d->next) {
5299336Sdfr        if (d->dup_func == dup_func && d->free_func == free_func
53022521Sdyson            && d->clear_free_func == clear_free_func) {
5311541Srgrimes            ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
5321541Srgrimes            return 0;
5331541Srgrimes        }
5341541Srgrimes    }
5351541Srgrimes
5361541Srgrimes    if (data == NULL)
5371541Srgrimes        /* no explicit entry needed */
5381541Srgrimes        return 1;
5391541Srgrimes
5401541Srgrimes    d = OPENSSL_malloc(sizeof *d);
5411541Srgrimes    if (d == NULL)
5429336Sdfr        return 0;
5439336Sdfr
5441541Srgrimes    d->data = data;
5459336Sdfr    d->dup_func = dup_func;
5469336Sdfr    d->free_func = free_func;
5471541Srgrimes    d->clear_free_func = clear_free_func;
5481541Srgrimes
5491541Srgrimes    d->next = *ex_data;
5501541Srgrimes    *ex_data = d;
5511541Srgrimes
5521541Srgrimes    return 1;
5531541Srgrimes}
55411921Sphk
5551541Srgrimes/* this has 'package' visibility */
5561541Srgrimesvoid *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
5571541Srgrimes                          void *(*dup_func) (void *),
5581541Srgrimes                          void (*free_func) (void *),
5591541Srgrimes                          void (*clear_free_func) (void *))
5601541Srgrimes{
5611541Srgrimes    const EC_EXTRA_DATA *d;
5621541Srgrimes
5631541Srgrimes    for (d = ex_data; d != NULL; d = d->next) {
5641541Srgrimes        if (d->dup_func == dup_func && d->free_func == free_func
5651541Srgrimes            && d->clear_free_func == clear_free_func)
5661541Srgrimes            return d->data;
5679336Sdfr    }
5689336Sdfr
5691541Srgrimes    return NULL;
5709336Sdfr}
5719336Sdfr
5729336Sdfr/* this has 'package' visibility */
57311644Sdgvoid EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
57411644Sdg                          void *(*dup_func) (void *),
57511644Sdg                          void (*free_func) (void *),
57622521Sdyson                          void (*clear_free_func) (void *))
57718397Snate{
57818397Snate    EC_EXTRA_DATA **p;
57911644Sdg
58011644Sdg    if (ex_data == NULL)
5813664Sphk        return;
5829336Sdfr
5839336Sdfr    for (p = ex_data; *p != NULL; p = &((*p)->next)) {
5849336Sdfr        if ((*p)->dup_func == dup_func && (*p)->free_func == free_func
5859336Sdfr            && (*p)->clear_free_func == clear_free_func) {
5869336Sdfr            EC_EXTRA_DATA *next = (*p)->next;
58722521Sdyson
58822521Sdyson            (*p)->free_func((*p)->data);
58918397Snate            OPENSSL_free(*p);
59018397Snate
5913664Sphk            *p = next;
5929336Sdfr            return;
5939336Sdfr        }
5943664Sphk    }
5959336Sdfr}
5969336Sdfr
5979336Sdfr/* this has 'package' visibility */
59811644Sdgvoid EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
59911644Sdg                                void *(*dup_func) (void *),
60011644Sdg                                void (*free_func) (void *),
60111644Sdg                                void (*clear_free_func) (void *))
60211644Sdg{
60311644Sdg    EC_EXTRA_DATA **p;
60422521Sdyson
60522521Sdyson    if (ex_data == NULL)
6069336Sdfr        return;
6079336Sdfr
60822521Sdyson    for (p = ex_data; *p != NULL; p = &((*p)->next)) {
6099336Sdfr        if ((*p)->dup_func == dup_func && (*p)->free_func == free_func
6109336Sdfr            && (*p)->clear_free_func == clear_free_func) {
61122521Sdyson            EC_EXTRA_DATA *next = (*p)->next;
6129336Sdfr
61322521Sdyson            (*p)->clear_free_func((*p)->data);
6149336Sdfr            OPENSSL_free(*p);
6159336Sdfr
6169336Sdfr            *p = next;
6179336Sdfr            return;
61818397Snate        }
61922521Sdyson    }
6209336Sdfr}
6219336Sdfr
6229336Sdfr/* this has 'package' visibility */
6239336Sdfrvoid EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
6249336Sdfr{
6259681Sdfr    EC_EXTRA_DATA *d;
6269681Sdfr
6279336Sdfr    if (ex_data == NULL)
6289336Sdfr        return;
6299336Sdfr
6309336Sdfr    d = *ex_data;
6319336Sdfr    while (d) {
6329336Sdfr        EC_EXTRA_DATA *next = d->next;
6339336Sdfr
6349336Sdfr        d->free_func(d->data);
63511921Sphk        OPENSSL_free(d);
6369336Sdfr
6379336Sdfr        d = next;
6389336Sdfr    }
6399336Sdfr    *ex_data = NULL;
6409336Sdfr}
6419336Sdfr
6429336Sdfr/* this has 'package' visibility */
6439336Sdfrvoid EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
6449336Sdfr{
6459336Sdfr    EC_EXTRA_DATA *d;
6469336Sdfr
6479336Sdfr    if (ex_data == NULL)
6489336Sdfr        return;
6499336Sdfr
6509336Sdfr    d = *ex_data;
6519336Sdfr    while (d) {
6529336Sdfr        EC_EXTRA_DATA *next = d->next;
6539336Sdfr
6549336Sdfr        d->clear_free_func(d->data);
6559336Sdfr        OPENSSL_free(d);
6569336Sdfr
6579336Sdfr        d = next;
6589336Sdfr    }
6599336Sdfr    *ex_data = NULL;
6609336Sdfr}
6619336Sdfr
6629336Sdfr/* functions for EC_POINT objects */
6639336Sdfr
6649336SdfrEC_POINT *EC_POINT_new(const EC_GROUP *group)
6659336Sdfr{
6669336Sdfr    EC_POINT *ret;
6679336Sdfr
6689336Sdfr    if (group == NULL) {
6699336Sdfr        ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
6709336Sdfr        return NULL;
6719336Sdfr    }
6729336Sdfr    if (group->meth->point_init == 0) {
6739336Sdfr        ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
6749336Sdfr        return NULL;
6759336Sdfr    }
6769336Sdfr
6779336Sdfr    ret = OPENSSL_malloc(sizeof *ret);
6789336Sdfr    if (ret == NULL) {
6799336Sdfr        ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
6809336Sdfr        return NULL;
6819336Sdfr    }
6829336Sdfr
6839336Sdfr    ret->meth = group->meth;
6849336Sdfr
6859336Sdfr    if (!ret->meth->point_init(ret)) {
6869336Sdfr        OPENSSL_free(ret);
68718397Snate        return NULL;
68818397Snate    }
6899336Sdfr
6909336Sdfr    return ret;
6919336Sdfr}
6929336Sdfr
6939336Sdfrvoid EC_POINT_free(EC_POINT *point)
6949336Sdfr{
6951541Srgrimes    if (!point)
6969336Sdfr        return;
6979336Sdfr
6989336Sdfr    if (point->meth->point_finish != 0)
6993664Sphk        point->meth->point_finish(point);
70018397Snate    OPENSSL_free(point);
70118397Snate}
7029336Sdfr
7039336Sdfrvoid EC_POINT_clear_free(EC_POINT *point)
70417186Sdfr{
7059336Sdfr    if (!point)
7069336Sdfr        return;
7079336Sdfr
7089336Sdfr    if (point->meth->point_clear_finish != 0)
7099336Sdfr        point->meth->point_clear_finish(point);
7109336Sdfr    else if (point->meth != NULL && point->meth->point_finish != 0)
7119336Sdfr        point->meth->point_finish(point);
7129336Sdfr    OPENSSL_cleanse(point, sizeof *point);
7139336Sdfr    OPENSSL_free(point);
7149336Sdfr}
7151541Srgrimes
7169336Sdfrint EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
7179336Sdfr{
7189336Sdfr    if (dest->meth->point_copy == 0) {
7199336Sdfr        ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
7209336Sdfr        return 0;
7219336Sdfr    }
7229336Sdfr    if (dest->meth != src->meth) {
7239336Sdfr        ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
7249336Sdfr        return 0;
7259336Sdfr    }
7269336Sdfr    if (dest == src)
7279336Sdfr        return 1;
7289336Sdfr    return dest->meth->point_copy(dest, src);
7299336Sdfr}
7309336Sdfr
7319336SdfrEC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
7321541Srgrimes{
7339336Sdfr    EC_POINT *t;
7349336Sdfr    int r;
7359336Sdfr
7369336Sdfr    if (a == NULL)
7379336Sdfr        return NULL;
7381541Srgrimes
7391541Srgrimes    t = EC_POINT_new(group);
7401541Srgrimes    if (t == NULL)
7411541Srgrimes        return (NULL);
7421541Srgrimes    r = EC_POINT_copy(t, a);
7431541Srgrimes    if (!r) {
74430118Sphk        EC_POINT_free(t);
74530118Sphk        return NULL;
7461541Srgrimes    } else
74711921Sphk        return t;
7481541Srgrimes}
74930118Sphk
7501541Srgrimesconst EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
7511541Srgrimes{
7521541Srgrimes    return point->meth;
7531541Srgrimes}
7541541Srgrimes
7551541Srgrimesint EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
7561541Srgrimes{
7571541Srgrimes    if (group->meth->point_set_to_infinity == 0) {
7581541Srgrimes        ECerr(EC_F_EC_POINT_SET_TO_INFINITY,
7591541Srgrimes              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
7609336Sdfr        return 0;
7611541Srgrimes    }
7621541Srgrimes    if (group->meth != point->meth) {
7631541Srgrimes        ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
7641541Srgrimes        return 0;
7651541Srgrimes    }
7661541Srgrimes    return group->meth->point_set_to_infinity(group, point);
7671541Srgrimes}
7689336Sdfr
7691541Srgrimesint EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
7709336Sdfr                                             EC_POINT *point, const BIGNUM *x,
7719336Sdfr                                             const BIGNUM *y, const BIGNUM *z,
77222521Sdyson                                             BN_CTX *ctx)
7731541Srgrimes{
77430118Sphk    if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
77530118Sphk        ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
77630118Sphk              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
7779336Sdfr        return 0;
77830118Sphk    }
77930118Sphk    if (group->meth != point->meth) {
7801541Srgrimes        ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
7811541Srgrimes              EC_R_INCOMPATIBLE_OBJECTS);
7821541Srgrimes        return 0;
7831541Srgrimes    }
78430118Sphk    return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x,
78530118Sphk                                                              y, z, ctx);
78630118Sphk}
78730118Sphk
78830118Sphkint EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
78930118Sphk                                             const EC_POINT *point, BIGNUM *x,
79030118Sphk                                             BIGNUM *y, BIGNUM *z,
79130118Sphk                                             BN_CTX *ctx)
79230118Sphk{
79330118Sphk    if (group->meth->point_get_Jprojective_coordinates_GFp == 0) {
79430118Sphk        ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
79530118Sphk              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
79630118Sphk        return 0;
79730118Sphk    }
79830118Sphk    if (group->meth != point->meth) {
79930118Sphk        ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
80030118Sphk              EC_R_INCOMPATIBLE_OBJECTS);
80130118Sphk        return 0;
80230118Sphk    }
80330118Sphk    return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x,
80430118Sphk                                                              y, z, ctx);
80530118Sphk}
80630118Sphk
80730118Sphkint EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
80830118Sphk                                        EC_POINT *point, const BIGNUM *x,
80930118Sphk                                        const BIGNUM *y, BN_CTX *ctx)
81030118Sphk{
81130118Sphk    if (group->meth->point_set_affine_coordinates == 0) {
81230118Sphk        ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
81330118Sphk              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
81430118Sphk        return 0;
81530118Sphk    }
81630118Sphk    if (group->meth != point->meth) {
81730118Sphk        ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
81830118Sphk              EC_R_INCOMPATIBLE_OBJECTS);
81930118Sphk        return 0;
82030118Sphk    }
82130118Sphk    return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
82230118Sphk}
82330118Sphk
82430118Sphkint EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
82530118Sphk                                         EC_POINT *point, const BIGNUM *x,
82630118Sphk                                         const BIGNUM *y, BN_CTX *ctx)
82730118Sphk{
82830118Sphk    if (group->meth->point_set_affine_coordinates == 0) {
82930118Sphk        ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
83030118Sphk              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
83130118Sphk        return 0;
83230118Sphk    }
8331541Srgrimes    if (group->meth != point->meth) {
8349336Sdfr        ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
8351541Srgrimes              EC_R_INCOMPATIBLE_OBJECTS);
8361541Srgrimes        return 0;
8371541Srgrimes    }
8389336Sdfr    return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
8399336Sdfr}
8409336Sdfr
8411541Srgrimesint EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
8421541Srgrimes                                        const EC_POINT *point, BIGNUM *x,
8431541Srgrimes                                        BIGNUM *y, BN_CTX *ctx)
8449336Sdfr{
8459336Sdfr    if (group->meth->point_get_affine_coordinates == 0) {
8469336Sdfr        ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
8471541Srgrimes              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
8489336Sdfr        return 0;
8491541Srgrimes    }
8501541Srgrimes    if (group->meth != point->meth) {
8511541Srgrimes        ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
8521541Srgrimes              EC_R_INCOMPATIBLE_OBJECTS);
8531541Srgrimes        return 0;
8549336Sdfr    }
8551541Srgrimes    return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
8561541Srgrimes}
8571541Srgrimes
8589336Sdfrint EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
8591541Srgrimes                                         const EC_POINT *point, BIGNUM *x,
8601541Srgrimes                                         BIGNUM *y, BN_CTX *ctx)
8611541Srgrimes{
8621541Srgrimes    if (group->meth->point_get_affine_coordinates == 0) {
8639336Sdfr        ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
8649336Sdfr              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
8659336Sdfr        return 0;
8669336Sdfr    }
8679336Sdfr    if (group->meth != point->meth) {
8681541Srgrimes        ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
8691541Srgrimes              EC_R_INCOMPATIBLE_OBJECTS);
8701541Srgrimes        return 0;
8719336Sdfr    }
87222521Sdyson    return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
8731541Srgrimes}
8741541Srgrimes
8751541Srgrimesint EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
8769336Sdfr                                            EC_POINT *point, const BIGNUM *x,
87722521Sdyson                                            int y_bit, BN_CTX *ctx)
8789336Sdfr{
8799336Sdfr    if (group->meth->point_set_compressed_coordinates == 0) {
88022521Sdyson        ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP,
8819336Sdfr              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
8829336Sdfr        return 0;
8839336Sdfr    }
8849336Sdfr    if (group->meth != point->meth) {
88522521Sdyson        ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP,
8869336Sdfr              EC_R_INCOMPATIBLE_OBJECTS);
8879336Sdfr        return 0;
8889336Sdfr    }
8899336Sdfr    return group->meth->point_set_compressed_coordinates(group, point, x,
8901541Srgrimes                                                         y_bit, ctx);
8911541Srgrimes}
8921541Srgrimes
8939336Sdfrint EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group,
8941541Srgrimes                                             EC_POINT *point, const BIGNUM *x,
8951541Srgrimes                                             int y_bit, BN_CTX *ctx)
8961541Srgrimes{
8979336Sdfr    if (group->meth->point_set_compressed_coordinates == 0) {
89822521Sdyson        ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M,
8991541Srgrimes              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
9001541Srgrimes        return 0;
9019336Sdfr    }
9029336Sdfr    if (group->meth != point->meth) {
9039336Sdfr        ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M,
9049336Sdfr              EC_R_INCOMPATIBLE_OBJECTS);
9059336Sdfr        return 0;
9061541Srgrimes    }
9071541Srgrimes    return group->meth->point_set_compressed_coordinates(group, point, x,
9081541Srgrimes                                                         y_bit, ctx);
9091541Srgrimes}
91018397Snate
9119336Sdfrsize_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
9121541Srgrimes                          point_conversion_form_t form, unsigned char *buf,
9139336Sdfr                          size_t len, BN_CTX *ctx)
9149336Sdfr{
9159336Sdfr    if (group->meth->point2oct == 0) {
91626928Sdfr        ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
9179336Sdfr        return 0;
91826928Sdfr    }
91926928Sdfr    if (group->meth != point->meth) {
9209336Sdfr        ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
9219336Sdfr        return 0;
9229336Sdfr    }
92322521Sdyson    return group->meth->point2oct(group, point, form, buf, len, ctx);
92411644Sdg}
92511644Sdg
92611644Sdgint EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
92711644Sdg                       const unsigned char *buf, size_t len, BN_CTX *ctx)
9289336Sdfr{
9299336Sdfr    if (group->meth->oct2point == 0) {
9309336Sdfr        ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
9319336Sdfr        return 0;
9329336Sdfr    }
9331541Srgrimes    if (group->meth != point->meth) {
9341541Srgrimes        ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
9351541Srgrimes        return 0;
9361541Srgrimes    }
9371541Srgrimes    return group->meth->oct2point(group, point, buf, len, ctx);
9381541Srgrimes}
93911921Sphk
9401541Srgrimesint EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
9411541Srgrimes                 const EC_POINT *b, BN_CTX *ctx)
9421541Srgrimes{
9431541Srgrimes    if (group->meth->add == 0) {
9441541Srgrimes        ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
9451541Srgrimes        return 0;
9461541Srgrimes    }
9471541Srgrimes    if ((group->meth != r->meth) || (r->meth != a->meth)
9481541Srgrimes        || (a->meth != b->meth)) {
9491541Srgrimes        ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
9501541Srgrimes        return 0;
9511541Srgrimes    }
95225930Sdfr    return group->meth->add(group, r, a, b, ctx);
9531541Srgrimes}
9541541Srgrimes
9551541Srgrimesint EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
9561541Srgrimes                 BN_CTX *ctx)
9571541Srgrimes{
95811921Sphk    if (group->meth->dbl == 0) {
9591541Srgrimes        ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
9601541Srgrimes        return 0;
9611541Srgrimes    }
9621541Srgrimes    if ((group->meth != r->meth) || (r->meth != a->meth)) {
9631541Srgrimes        ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
9641541Srgrimes        return 0;
9651541Srgrimes    }
9661541Srgrimes    return group->meth->dbl(group, r, a, ctx);
9671541Srgrimes}
9681541Srgrimes
9691541Srgrimesint EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
97025930Sdfr{
9711541Srgrimes    if (group->meth->invert == 0) {
9721541Srgrimes        ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
9731541Srgrimes        return 0;
9741541Srgrimes    }
9751541Srgrimes    if (group->meth != a->meth) {
9761541Srgrimes        ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
9771541Srgrimes        return 0;
9781541Srgrimes    }
9791541Srgrimes    return group->meth->invert(group, a, ctx);
9801541Srgrimes}
9811541Srgrimes
9821541Srgrimesint EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
9831541Srgrimes{
9841541Srgrimes    if (group->meth->is_at_infinity == 0) {
9859336Sdfr        ECerr(EC_F_EC_POINT_IS_AT_INFINITY,
9861541Srgrimes              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
9879336Sdfr        return 0;
9881541Srgrimes    }
9899336Sdfr    if (group->meth != point->meth) {
9901541Srgrimes        ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
9911541Srgrimes        return 0;
9929336Sdfr    }
9939336Sdfr    return group->meth->is_at_infinity(group, point);
9941541Srgrimes}
9959336Sdfr
9969336Sdfr/*
9979336Sdfr * Check whether an EC_POINT is on the curve or not. Note that the return
9989336Sdfr * value for this function should NOT be treated as a boolean. Return values:
9999336Sdfr *  1: The point is on the curve
10009336Sdfr *  0: The point is not on the curve
10011541Srgrimes * -1: An error occurred
10021541Srgrimes */
10031541Srgrimesint EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
10041541Srgrimes                         BN_CTX *ctx)
10051541Srgrimes{
10061541Srgrimes    if (group->meth->is_on_curve == 0) {
10071541Srgrimes        ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
10081541Srgrimes        return 0;
10091541Srgrimes    }
10101541Srgrimes    if (group->meth != point->meth) {
10111541Srgrimes        ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
10121541Srgrimes        return 0;
10131541Srgrimes    }
10141541Srgrimes    return group->meth->is_on_curve(group, point, ctx);
10151541Srgrimes}
10161541Srgrimes
10179336Sdfrint EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
10181541Srgrimes                 BN_CTX *ctx)
10191541Srgrimes{
10201541Srgrimes    if (group->meth->point_cmp == 0) {
10219336Sdfr        ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
10229336Sdfr        return -1;
10231541Srgrimes    }
10249336Sdfr    if ((group->meth != a->meth) || (a->meth != b->meth)) {
10259336Sdfr        ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
10269336Sdfr        return -1;
10271541Srgrimes    }
10281541Srgrimes    return group->meth->point_cmp(group, a, b, ctx);
10299336Sdfr}
10301541Srgrimes
10311541Srgrimesint EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
10321541Srgrimes{
10331541Srgrimes    if (group->meth->make_affine == 0) {
10349336Sdfr        ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
10359336Sdfr        return 0;
10369336Sdfr    }
10379336Sdfr    if (group->meth != point->meth) {
10381541Srgrimes        ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
10391541Srgrimes        return 0;
10401541Srgrimes    }
10411541Srgrimes    return group->meth->make_affine(group, point, ctx);
10421541Srgrimes}
10431541Srgrimes
10441541Srgrimesint EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
10451541Srgrimes                          EC_POINT *points[], BN_CTX *ctx)
10469336Sdfr{
10479336Sdfr    size_t i;
10489336Sdfr
10499336Sdfr    if (group->meth->points_make_affine == 0) {
10509336Sdfr        ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
10519336Sdfr        return 0;
10529336Sdfr    }
10539336Sdfr    for (i = 0; i < num; i++) {
10549336Sdfr        if (group->meth != points[i]->meth) {
10559336Sdfr            ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
10561541Srgrimes            return 0;
10571541Srgrimes        }
10581541Srgrimes    }
10599336Sdfr    return group->meth->points_make_affine(group, num, points, ctx);
10609336Sdfr}
10619336Sdfr
10629336Sdfr/*
10639336Sdfr * Functions for point multiplication. If group->meth->mul is 0, we use the
10641541Srgrimes * wNAF-based implementations in ec_mult.c; otherwise we dispatch through
10651541Srgrimes * methods.
10661541Srgrimes */
10671541Srgrimes
10681541Srgrimesint EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
10691541Srgrimes                  size_t num, const EC_POINT *points[],
10701541Srgrimes                  const BIGNUM *scalars[], BN_CTX *ctx)
10711541Srgrimes{
10721541Srgrimes    if (group->meth->mul == 0)
10731541Srgrimes        /* use default */
10749336Sdfr        return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
10751541Srgrimes
10769336Sdfr    return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
10771541Srgrimes}
10789336Sdfr
10791541Srgrimesint EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
10801541Srgrimes                 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
10811541Srgrimes{
10829336Sdfr    /* just a convenient interface to EC_POINTs_mul() */
10831541Srgrimes
10841541Srgrimes    const EC_POINT *points[1];
10859336Sdfr    const BIGNUM *scalars[1];
10869336Sdfr
10879336Sdfr    points[0] = point;
10881541Srgrimes    scalars[0] = p_scalar;
10899336Sdfr
10909336Sdfr    return EC_POINTs_mul(group, r, g_scalar,
10919336Sdfr                         (point != NULL
10929336Sdfr                          && p_scalar != NULL), points, scalars, ctx);
10939336Sdfr}
10941541Srgrimes
10959336Sdfrint EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
10961541Srgrimes{
10971541Srgrimes    if (group->meth->mul == 0)
10981541Srgrimes        /* use default */
10991541Srgrimes        return ec_wNAF_precompute_mult(group, ctx);
11001541Srgrimes
11019336Sdfr    if (group->meth->precompute_mult != 0)
11029336Sdfr        return group->meth->precompute_mult(group, ctx);
11039336Sdfr    else
11049336Sdfr        return 1;               /* nothing to do, so report success */
11051541Srgrimes}
11061541Srgrimes
11079336Sdfrint EC_GROUP_have_precompute_mult(const EC_GROUP *group)
11089336Sdfr{
11091541Srgrimes    if (group->meth->mul == 0)
11109336Sdfr        /* use default */
11111541Srgrimes        return ec_wNAF_have_precompute_mult(group);
11121541Srgrimes
11131541Srgrimes    if (group->meth->have_precompute_mult != 0)
11141541Srgrimes        return group->meth->have_precompute_mult(group);
11151541Srgrimes    else
11161541Srgrimes        return 0;               /* cannot tell whether precomputation has
11179336Sdfr                                 * been performed */
11189336Sdfr}
11199336Sdfr