1109998Smarkm/* crypto/ec/ec_lib.c */
2160814Ssimon/*
3160814Ssimon * Originally written by Bodo Moeller for the OpenSSL project.
4160814Ssimon */
5109998Smarkm/* ====================================================================
6160814Ssimon * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
7109998Smarkm *
8109998Smarkm * Redistribution and use in source and binary forms, with or without
9109998Smarkm * modification, are permitted provided that the following conditions
10109998Smarkm * are met:
11109998Smarkm *
12109998Smarkm * 1. Redistributions of source code must retain the above copyright
13296465Sdelphij *    notice, this list of conditions and the following disclaimer.
14109998Smarkm *
15109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright
16109998Smarkm *    notice, this list of conditions and the following disclaimer in
17109998Smarkm *    the documentation and/or other materials provided with the
18109998Smarkm *    distribution.
19109998Smarkm *
20109998Smarkm * 3. All advertising materials mentioning features or use of this
21109998Smarkm *    software must display the following acknowledgment:
22109998Smarkm *    "This product includes software developed by the OpenSSL Project
23109998Smarkm *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24109998Smarkm *
25109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26109998Smarkm *    endorse or promote products derived from this software without
27109998Smarkm *    prior written permission. For written permission, please contact
28109998Smarkm *    openssl-core@openssl.org.
29109998Smarkm *
30109998Smarkm * 5. Products derived from this software may not be called "OpenSSL"
31109998Smarkm *    nor may "OpenSSL" appear in their names without prior written
32109998Smarkm *    permission of the OpenSSL Project.
33109998Smarkm *
34109998Smarkm * 6. Redistributions of any form whatsoever must retain the following
35109998Smarkm *    acknowledgment:
36109998Smarkm *    "This product includes software developed by the OpenSSL Project
37109998Smarkm *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38109998Smarkm *
39109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42109998Smarkm * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE.
51109998Smarkm * ====================================================================
52109998Smarkm *
53109998Smarkm * This product includes cryptographic software written by Eric Young
54109998Smarkm * (eay@cryptsoft.com).  This product includes software written by Tim
55109998Smarkm * Hudson (tjh@cryptsoft.com).
56109998Smarkm *
57109998Smarkm */
58160814Ssimon/* ====================================================================
59160814Ssimon * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60296465Sdelphij * Binary polynomial ECC support in OpenSSL originally developed by
61160814Ssimon * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
62160814Ssimon */
63109998Smarkm
64109998Smarkm#include <string.h>
65109998Smarkm
66109998Smarkm#include <openssl/err.h>
67109998Smarkm#include <openssl/opensslv.h>
68109998Smarkm
69109998Smarkm#include "ec_lcl.h"
70109998Smarkm
71109998Smarkmstatic const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
72109998Smarkm
73109998Smarkm/* functions for EC_GROUP objects */
74109998Smarkm
75109998SmarkmEC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
76296465Sdelphij{
77296465Sdelphij    EC_GROUP *ret;
78109998Smarkm
79296465Sdelphij    if (meth == NULL) {
80296465Sdelphij        ECerr(EC_F_EC_GROUP_NEW, ERR_R_PASSED_NULL_PARAMETER);
81296465Sdelphij        return NULL;
82296465Sdelphij    }
83296465Sdelphij    if (meth->group_init == 0) {
84296465Sdelphij        ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
85296465Sdelphij        return NULL;
86296465Sdelphij    }
87109998Smarkm
88296465Sdelphij    ret = OPENSSL_malloc(sizeof *ret);
89296465Sdelphij    if (ret == NULL) {
90296465Sdelphij        ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
91296465Sdelphij        return NULL;
92296465Sdelphij    }
93109998Smarkm
94296465Sdelphij    ret->meth = meth;
95109998Smarkm
96296465Sdelphij    ret->extra_data = NULL;
97160814Ssimon
98296465Sdelphij    ret->generator = NULL;
99296465Sdelphij    BN_init(&ret->order);
100296465Sdelphij    BN_init(&ret->cofactor);
101160814Ssimon
102296465Sdelphij    ret->curve_name = 0;
103296465Sdelphij    ret->asn1_flag = 0;
104296465Sdelphij    ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
105160814Ssimon
106296465Sdelphij    ret->seed = NULL;
107296465Sdelphij    ret->seed_len = 0;
108160814Ssimon
109296465Sdelphij    if (!meth->group_init(ret)) {
110296465Sdelphij        OPENSSL_free(ret);
111296465Sdelphij        return NULL;
112296465Sdelphij    }
113109998Smarkm
114296465Sdelphij    return ret;
115296465Sdelphij}
116109998Smarkm
117109998Smarkmvoid EC_GROUP_free(EC_GROUP *group)
118296465Sdelphij{
119296465Sdelphij    if (!group)
120296465Sdelphij        return;
121109998Smarkm
122296465Sdelphij    if (group->meth->group_finish != 0)
123296465Sdelphij        group->meth->group_finish(group);
124109998Smarkm
125296465Sdelphij    EC_EX_DATA_free_all_data(&group->extra_data);
126109998Smarkm
127296465Sdelphij    if (group->generator != NULL)
128296465Sdelphij        EC_POINT_free(group->generator);
129296465Sdelphij    BN_free(&group->order);
130296465Sdelphij    BN_free(&group->cofactor);
131160814Ssimon
132296465Sdelphij    if (group->seed)
133296465Sdelphij        OPENSSL_free(group->seed);
134160814Ssimon
135296465Sdelphij    OPENSSL_free(group);
136296465Sdelphij}
137109998Smarkm
138109998Smarkmvoid EC_GROUP_clear_free(EC_GROUP *group)
139296465Sdelphij{
140296465Sdelphij    if (!group)
141296465Sdelphij        return;
142109998Smarkm
143296465Sdelphij    if (group->meth->group_clear_finish != 0)
144296465Sdelphij        group->meth->group_clear_finish(group);
145296465Sdelphij    else if (group->meth->group_finish != 0)
146296465Sdelphij        group->meth->group_finish(group);
147109998Smarkm
148296465Sdelphij    EC_EX_DATA_clear_free_all_data(&group->extra_data);
149109998Smarkm
150296465Sdelphij    if (group->generator != NULL)
151296465Sdelphij        EC_POINT_clear_free(group->generator);
152296465Sdelphij    BN_clear_free(&group->order);
153296465Sdelphij    BN_clear_free(&group->cofactor);
154160814Ssimon
155296465Sdelphij    if (group->seed) {
156296465Sdelphij        OPENSSL_cleanse(group->seed, group->seed_len);
157296465Sdelphij        OPENSSL_free(group->seed);
158296465Sdelphij    }
159160814Ssimon
160296465Sdelphij    OPENSSL_cleanse(group, sizeof *group);
161296465Sdelphij    OPENSSL_free(group);
162296465Sdelphij}
163109998Smarkm
164109998Smarkmint EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
165296465Sdelphij{
166296465Sdelphij    EC_EXTRA_DATA *d;
167160814Ssimon
168296465Sdelphij    if (dest->meth->group_copy == 0) {
169296465Sdelphij        ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
170296465Sdelphij        return 0;
171296465Sdelphij    }
172296465Sdelphij    if (dest->meth != src->meth) {
173296465Sdelphij        ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
174296465Sdelphij        return 0;
175296465Sdelphij    }
176296465Sdelphij    if (dest == src)
177296465Sdelphij        return 1;
178160814Ssimon
179296465Sdelphij    EC_EX_DATA_free_all_data(&dest->extra_data);
180160814Ssimon
181296465Sdelphij    for (d = src->extra_data; d != NULL; d = d->next) {
182296465Sdelphij        void *t = d->dup_func(d->data);
183109998Smarkm
184296465Sdelphij        if (t == NULL)
185296465Sdelphij            return 0;
186296465Sdelphij        if (!EC_EX_DATA_set_data
187296465Sdelphij            (&dest->extra_data, t, d->dup_func, d->free_func,
188296465Sdelphij             d->clear_free_func))
189296465Sdelphij            return 0;
190296465Sdelphij    }
191160814Ssimon
192296465Sdelphij    if (src->generator != NULL) {
193296465Sdelphij        if (dest->generator == NULL) {
194296465Sdelphij            dest->generator = EC_POINT_new(dest);
195296465Sdelphij            if (dest->generator == NULL)
196296465Sdelphij                return 0;
197296465Sdelphij        }
198296465Sdelphij        if (!EC_POINT_copy(dest->generator, src->generator))
199296465Sdelphij            return 0;
200296465Sdelphij    } else {
201296465Sdelphij        /* src->generator == NULL */
202296465Sdelphij        if (dest->generator != NULL) {
203296465Sdelphij            EC_POINT_clear_free(dest->generator);
204296465Sdelphij            dest->generator = NULL;
205296465Sdelphij        }
206296465Sdelphij    }
207160814Ssimon
208296465Sdelphij    if (!BN_copy(&dest->order, &src->order))
209296465Sdelphij        return 0;
210296465Sdelphij    if (!BN_copy(&dest->cofactor, &src->cofactor))
211296465Sdelphij        return 0;
212109998Smarkm
213296465Sdelphij    dest->curve_name = src->curve_name;
214296465Sdelphij    dest->asn1_flag = src->asn1_flag;
215296465Sdelphij    dest->asn1_form = src->asn1_form;
216109998Smarkm
217296465Sdelphij    if (src->seed) {
218296465Sdelphij        if (dest->seed)
219296465Sdelphij            OPENSSL_free(dest->seed);
220296465Sdelphij        dest->seed = OPENSSL_malloc(src->seed_len);
221296465Sdelphij        if (dest->seed == NULL)
222296465Sdelphij            return 0;
223296465Sdelphij        if (!memcpy(dest->seed, src->seed, src->seed_len))
224296465Sdelphij            return 0;
225296465Sdelphij        dest->seed_len = src->seed_len;
226296465Sdelphij    } else {
227296465Sdelphij        if (dest->seed)
228296465Sdelphij            OPENSSL_free(dest->seed);
229296465Sdelphij        dest->seed = NULL;
230296465Sdelphij        dest->seed_len = 0;
231296465Sdelphij    }
232109998Smarkm
233296465Sdelphij    return dest->meth->group_copy(dest, src);
234296465Sdelphij}
235296465Sdelphij
236160814SsimonEC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
237296465Sdelphij{
238296465Sdelphij    EC_GROUP *t = NULL;
239296465Sdelphij    int ok = 0;
240160814Ssimon
241296465Sdelphij    if (a == NULL)
242296465Sdelphij        return NULL;
243160814Ssimon
244296465Sdelphij    if ((t = EC_GROUP_new(a->meth)) == NULL)
245296465Sdelphij        return (NULL);
246296465Sdelphij    if (!EC_GROUP_copy(t, a))
247296465Sdelphij        goto err;
248160814Ssimon
249296465Sdelphij    ok = 1;
250160814Ssimon
251296465Sdelphij err:
252296465Sdelphij    if (!ok) {
253296465Sdelphij        if (t)
254296465Sdelphij            EC_GROUP_free(t);
255296465Sdelphij        return NULL;
256296465Sdelphij    } else
257296465Sdelphij        return t;
258296465Sdelphij}
259160814Ssimon
260109998Smarkmconst EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
261296465Sdelphij{
262296465Sdelphij    return group->meth;
263296465Sdelphij}
264109998Smarkm
265160814Ssimonint EC_METHOD_get_field_type(const EC_METHOD *meth)
266296465Sdelphij{
267296465Sdelphij    return meth->field_type;
268296465Sdelphij}
269160814Ssimon
270296465Sdelphijint EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
271296465Sdelphij                           const BIGNUM *order, const BIGNUM *cofactor)
272296465Sdelphij{
273296465Sdelphij    if (generator == NULL) {
274296465Sdelphij        ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
275296465Sdelphij        return 0;
276296465Sdelphij    }
277160814Ssimon
278296465Sdelphij    if (group->generator == NULL) {
279296465Sdelphij        group->generator = EC_POINT_new(group);
280296465Sdelphij        if (group->generator == NULL)
281296465Sdelphij            return 0;
282296465Sdelphij    }
283296465Sdelphij    if (!EC_POINT_copy(group->generator, generator))
284296465Sdelphij        return 0;
285160814Ssimon
286296465Sdelphij    if (order != NULL) {
287296465Sdelphij        if (!BN_copy(&group->order, order))
288296465Sdelphij            return 0;
289296465Sdelphij    } else
290296465Sdelphij        BN_zero(&group->order);
291160814Ssimon
292296465Sdelphij    if (cofactor != NULL) {
293296465Sdelphij        if (!BN_copy(&group->cofactor, cofactor))
294296465Sdelphij            return 0;
295296465Sdelphij    } else
296296465Sdelphij        BN_zero(&group->cofactor);
297160814Ssimon
298296465Sdelphij    return 1;
299296465Sdelphij}
300160814Ssimon
301160814Ssimonconst EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
302296465Sdelphij{
303296465Sdelphij    return group->generator;
304296465Sdelphij}
305160814Ssimon
306160814Ssimonint EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
307296465Sdelphij{
308296465Sdelphij    if (!BN_copy(order, &group->order))
309296465Sdelphij        return 0;
310160814Ssimon
311296465Sdelphij    return !BN_is_zero(order);
312296465Sdelphij}
313160814Ssimon
314296465Sdelphijint EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
315296465Sdelphij                          BN_CTX *ctx)
316296465Sdelphij{
317296465Sdelphij    if (!BN_copy(cofactor, &group->cofactor))
318296465Sdelphij        return 0;
319160814Ssimon
320296465Sdelphij    return !BN_is_zero(&group->cofactor);
321296465Sdelphij}
322160814Ssimon
323160814Ssimonvoid EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
324296465Sdelphij{
325296465Sdelphij    group->curve_name = nid;
326296465Sdelphij}
327160814Ssimon
328160814Ssimonint EC_GROUP_get_curve_name(const EC_GROUP *group)
329296465Sdelphij{
330296465Sdelphij    return group->curve_name;
331296465Sdelphij}
332160814Ssimon
333160814Ssimonvoid EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
334296465Sdelphij{
335296465Sdelphij    group->asn1_flag = flag;
336296465Sdelphij}
337160814Ssimon
338160814Ssimonint EC_GROUP_get_asn1_flag(const EC_GROUP *group)
339296465Sdelphij{
340296465Sdelphij    return group->asn1_flag;
341296465Sdelphij}
342160814Ssimon
343296465Sdelphijvoid EC_GROUP_set_point_conversion_form(EC_GROUP *group,
344160814Ssimon                                        point_conversion_form_t form)
345296465Sdelphij{
346296465Sdelphij    group->asn1_form = form;
347296465Sdelphij}
348160814Ssimon
349296465Sdelphijpoint_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
350296465Sdelphij                                                           *group)
351296465Sdelphij{
352296465Sdelphij    return group->asn1_form;
353296465Sdelphij}
354160814Ssimon
355160814Ssimonsize_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
356296465Sdelphij{
357296465Sdelphij    if (group->seed) {
358296465Sdelphij        OPENSSL_free(group->seed);
359296465Sdelphij        group->seed = NULL;
360296465Sdelphij        group->seed_len = 0;
361296465Sdelphij    }
362160814Ssimon
363296465Sdelphij    if (!len || !p)
364296465Sdelphij        return 1;
365160814Ssimon
366296465Sdelphij    if ((group->seed = OPENSSL_malloc(len)) == NULL)
367296465Sdelphij        return 0;
368296465Sdelphij    memcpy(group->seed, p, len);
369296465Sdelphij    group->seed_len = len;
370160814Ssimon
371296465Sdelphij    return len;
372296465Sdelphij}
373160814Ssimon
374160814Ssimonunsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
375296465Sdelphij{
376296465Sdelphij    return group->seed;
377296465Sdelphij}
378160814Ssimon
379160814Ssimonsize_t EC_GROUP_get_seed_len(const EC_GROUP *group)
380296465Sdelphij{
381296465Sdelphij    return group->seed_len;
382296465Sdelphij}
383160814Ssimon
384296465Sdelphijint EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
385296465Sdelphij                           const BIGNUM *b, BN_CTX *ctx)
386296465Sdelphij{
387296465Sdelphij    if (group->meth->group_set_curve == 0) {
388296465Sdelphij        ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
389296465Sdelphij        return 0;
390296465Sdelphij    }
391296465Sdelphij    return group->meth->group_set_curve(group, p, a, b, ctx);
392296465Sdelphij}
393160814Ssimon
394296465Sdelphijint EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
395296465Sdelphij                           BIGNUM *b, BN_CTX *ctx)
396296465Sdelphij{
397296465Sdelphij    if (group->meth->group_get_curve == 0) {
398296465Sdelphij        ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
399296465Sdelphij        return 0;
400296465Sdelphij    }
401296465Sdelphij    return group->meth->group_get_curve(group, p, a, b, ctx);
402296465Sdelphij}
403109998Smarkm
404296465Sdelphijint EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
405296465Sdelphij                            const BIGNUM *b, BN_CTX *ctx)
406296465Sdelphij{
407296465Sdelphij    if (group->meth->group_set_curve == 0) {
408296465Sdelphij        ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M,
409296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
410296465Sdelphij        return 0;
411296465Sdelphij    }
412296465Sdelphij    return group->meth->group_set_curve(group, p, a, b, ctx);
413296465Sdelphij}
414109998Smarkm
415296465Sdelphijint EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
416296465Sdelphij                            BIGNUM *b, BN_CTX *ctx)
417296465Sdelphij{
418296465Sdelphij    if (group->meth->group_get_curve == 0) {
419296465Sdelphij        ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M,
420296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
421296465Sdelphij        return 0;
422296465Sdelphij    }
423296465Sdelphij    return group->meth->group_get_curve(group, p, a, b, ctx);
424296465Sdelphij}
425109998Smarkm
426160814Ssimonint EC_GROUP_get_degree(const EC_GROUP *group)
427296465Sdelphij{
428296465Sdelphij    if (group->meth->group_get_degree == 0) {
429296465Sdelphij        ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
430296465Sdelphij        return 0;
431296465Sdelphij    }
432296465Sdelphij    return group->meth->group_get_degree(group);
433296465Sdelphij}
434109998Smarkm
435160814Ssimonint EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
436296465Sdelphij{
437296465Sdelphij    if (group->meth->group_check_discriminant == 0) {
438296465Sdelphij        ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,
439296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
440296465Sdelphij        return 0;
441296465Sdelphij    }
442296465Sdelphij    return group->meth->group_check_discriminant(group, ctx);
443296465Sdelphij}
444109998Smarkm
445160814Ssimonint EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
446296465Sdelphij{
447296465Sdelphij    int r = 0;
448296465Sdelphij    BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
449296465Sdelphij    BN_CTX *ctx_new = NULL;
450160814Ssimon
451296465Sdelphij    /* compare the field types */
452296465Sdelphij    if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
453296465Sdelphij        EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
454296465Sdelphij        return 1;
455296465Sdelphij    /* compare the curve name (if present in both) */
456296465Sdelphij    if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
457296465Sdelphij        EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
458296465Sdelphij        return 1;
459160814Ssimon
460296465Sdelphij    if (!ctx)
461296465Sdelphij        ctx_new = ctx = BN_CTX_new();
462296465Sdelphij    if (!ctx)
463296465Sdelphij        return -1;
464109998Smarkm
465296465Sdelphij    BN_CTX_start(ctx);
466296465Sdelphij    a1 = BN_CTX_get(ctx);
467296465Sdelphij    a2 = BN_CTX_get(ctx);
468296465Sdelphij    a3 = BN_CTX_get(ctx);
469296465Sdelphij    b1 = BN_CTX_get(ctx);
470296465Sdelphij    b2 = BN_CTX_get(ctx);
471296465Sdelphij    b3 = BN_CTX_get(ctx);
472296465Sdelphij    if (!b3) {
473296465Sdelphij        BN_CTX_end(ctx);
474296465Sdelphij        if (ctx_new)
475296465Sdelphij            BN_CTX_free(ctx);
476296465Sdelphij        return -1;
477296465Sdelphij    }
478160814Ssimon
479296465Sdelphij    /*
480296465Sdelphij     * XXX This approach assumes that the external representation of curves
481296465Sdelphij     * over the same field type is the same.
482296465Sdelphij     */
483296465Sdelphij    if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
484296465Sdelphij        !b->meth->group_get_curve(b, b1, b2, b3, ctx))
485296465Sdelphij        r = 1;
486160814Ssimon
487296465Sdelphij    if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
488296465Sdelphij        r = 1;
489160814Ssimon
490296465Sdelphij    /* XXX EC_POINT_cmp() assumes that the methods are equal */
491296465Sdelphij    if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
492296465Sdelphij                          EC_GROUP_get0_generator(b), ctx))
493296465Sdelphij        r = 1;
494160814Ssimon
495296465Sdelphij    if (!r) {
496296465Sdelphij        /* compare the order and cofactor */
497296465Sdelphij        if (!EC_GROUP_get_order(a, a1, ctx) ||
498296465Sdelphij            !EC_GROUP_get_order(b, b1, ctx) ||
499296465Sdelphij            !EC_GROUP_get_cofactor(a, a2, ctx) ||
500296465Sdelphij            !EC_GROUP_get_cofactor(b, b2, ctx)) {
501296465Sdelphij            BN_CTX_end(ctx);
502296465Sdelphij            if (ctx_new)
503296465Sdelphij                BN_CTX_free(ctx);
504296465Sdelphij            return -1;
505296465Sdelphij        }
506296465Sdelphij        if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
507296465Sdelphij            r = 1;
508296465Sdelphij    }
509160814Ssimon
510296465Sdelphij    BN_CTX_end(ctx);
511296465Sdelphij    if (ctx_new)
512296465Sdelphij        BN_CTX_free(ctx);
513109998Smarkm
514296465Sdelphij    return r;
515296465Sdelphij}
516109998Smarkm
517109998Smarkm/* this has 'package' visibility */
518160814Ssimonint EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
519296465Sdelphij                        void *(*dup_func) (void *),
520296465Sdelphij                        void (*free_func) (void *),
521296465Sdelphij                        void (*clear_free_func) (void *))
522296465Sdelphij{
523296465Sdelphij    EC_EXTRA_DATA *d;
524160814Ssimon
525296465Sdelphij    if (ex_data == NULL)
526296465Sdelphij        return 0;
527160814Ssimon
528296465Sdelphij    for (d = *ex_data; d != NULL; d = d->next) {
529296465Sdelphij        if (d->dup_func == dup_func && d->free_func == free_func
530296465Sdelphij            && d->clear_free_func == clear_free_func) {
531296465Sdelphij            ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
532296465Sdelphij            return 0;
533296465Sdelphij        }
534296465Sdelphij    }
535109998Smarkm
536296465Sdelphij    if (data == NULL)
537296465Sdelphij        /* no explicit entry needed */
538296465Sdelphij        return 1;
539160814Ssimon
540296465Sdelphij    d = OPENSSL_malloc(sizeof *d);
541296465Sdelphij    if (d == NULL)
542296465Sdelphij        return 0;
543160814Ssimon
544296465Sdelphij    d->data = data;
545296465Sdelphij    d->dup_func = dup_func;
546296465Sdelphij    d->free_func = free_func;
547296465Sdelphij    d->clear_free_func = clear_free_func;
548160814Ssimon
549296465Sdelphij    d->next = *ex_data;
550296465Sdelphij    *ex_data = d;
551160814Ssimon
552296465Sdelphij    return 1;
553296465Sdelphij}
554109998Smarkm
555160814Ssimon/* this has 'package' visibility */
556160814Ssimonvoid *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
557296465Sdelphij                          void *(*dup_func) (void *),
558296465Sdelphij                          void (*free_func) (void *),
559296465Sdelphij                          void (*clear_free_func) (void *))
560296465Sdelphij{
561296465Sdelphij    const EC_EXTRA_DATA *d;
562109998Smarkm
563296465Sdelphij    for (d = ex_data; d != NULL; d = d->next) {
564296465Sdelphij        if (d->dup_func == dup_func && d->free_func == free_func
565296465Sdelphij            && d->clear_free_func == clear_free_func)
566296465Sdelphij            return d->data;
567296465Sdelphij    }
568160814Ssimon
569296465Sdelphij    return NULL;
570296465Sdelphij}
571296465Sdelphij
572109998Smarkm/* this has 'package' visibility */
573160814Ssimonvoid EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
574296465Sdelphij                          void *(*dup_func) (void *),
575296465Sdelphij                          void (*free_func) (void *),
576296465Sdelphij                          void (*clear_free_func) (void *))
577296465Sdelphij{
578296465Sdelphij    EC_EXTRA_DATA **p;
579160814Ssimon
580296465Sdelphij    if (ex_data == NULL)
581296465Sdelphij        return;
582160814Ssimon
583296465Sdelphij    for (p = ex_data; *p != NULL; p = &((*p)->next)) {
584296465Sdelphij        if ((*p)->dup_func == dup_func && (*p)->free_func == free_func
585296465Sdelphij            && (*p)->clear_free_func == clear_free_func) {
586296465Sdelphij            EC_EXTRA_DATA *next = (*p)->next;
587160814Ssimon
588296465Sdelphij            (*p)->free_func((*p)->data);
589296465Sdelphij            OPENSSL_free(*p);
590109998Smarkm
591296465Sdelphij            *p = next;
592296465Sdelphij            return;
593296465Sdelphij        }
594296465Sdelphij    }
595296465Sdelphij}
596296465Sdelphij
597160814Ssimon/* this has 'package' visibility */
598160814Ssimonvoid EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
599296465Sdelphij                                void *(*dup_func) (void *),
600296465Sdelphij                                void (*free_func) (void *),
601296465Sdelphij                                void (*clear_free_func) (void *))
602296465Sdelphij{
603296465Sdelphij    EC_EXTRA_DATA **p;
604109998Smarkm
605296465Sdelphij    if (ex_data == NULL)
606296465Sdelphij        return;
607160814Ssimon
608296465Sdelphij    for (p = ex_data; *p != NULL; p = &((*p)->next)) {
609296465Sdelphij        if ((*p)->dup_func == dup_func && (*p)->free_func == free_func
610296465Sdelphij            && (*p)->clear_free_func == clear_free_func) {
611296465Sdelphij            EC_EXTRA_DATA *next = (*p)->next;
612160814Ssimon
613296465Sdelphij            (*p)->clear_free_func((*p)->data);
614296465Sdelphij            OPENSSL_free(*p);
615160814Ssimon
616296465Sdelphij            *p = next;
617296465Sdelphij            return;
618296465Sdelphij        }
619296465Sdelphij    }
620296465Sdelphij}
621296465Sdelphij
622109998Smarkm/* this has 'package' visibility */
623160814Ssimonvoid EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
624296465Sdelphij{
625296465Sdelphij    EC_EXTRA_DATA *d;
626160814Ssimon
627296465Sdelphij    if (ex_data == NULL)
628296465Sdelphij        return;
629160814Ssimon
630296465Sdelphij    d = *ex_data;
631296465Sdelphij    while (d) {
632296465Sdelphij        EC_EXTRA_DATA *next = d->next;
633109998Smarkm
634296465Sdelphij        d->free_func(d->data);
635296465Sdelphij        OPENSSL_free(d);
636296465Sdelphij
637296465Sdelphij        d = next;
638296465Sdelphij    }
639296465Sdelphij    *ex_data = NULL;
640296465Sdelphij}
641296465Sdelphij
642160814Ssimon/* this has 'package' visibility */
643160814Ssimonvoid EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
644296465Sdelphij{
645296465Sdelphij    EC_EXTRA_DATA *d;
646109998Smarkm
647296465Sdelphij    if (ex_data == NULL)
648296465Sdelphij        return;
649109998Smarkm
650296465Sdelphij    d = *ex_data;
651296465Sdelphij    while (d) {
652296465Sdelphij        EC_EXTRA_DATA *next = d->next;
653160814Ssimon
654296465Sdelphij        d->clear_free_func(d->data);
655296465Sdelphij        OPENSSL_free(d);
656160814Ssimon
657296465Sdelphij        d = next;
658296465Sdelphij    }
659296465Sdelphij    *ex_data = NULL;
660296465Sdelphij}
661296465Sdelphij
662109998Smarkm/* functions for EC_POINT objects */
663109998Smarkm
664109998SmarkmEC_POINT *EC_POINT_new(const EC_GROUP *group)
665296465Sdelphij{
666296465Sdelphij    EC_POINT *ret;
667109998Smarkm
668296465Sdelphij    if (group == NULL) {
669296465Sdelphij        ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
670296465Sdelphij        return NULL;
671296465Sdelphij    }
672296465Sdelphij    if (group->meth->point_init == 0) {
673296465Sdelphij        ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
674296465Sdelphij        return NULL;
675296465Sdelphij    }
676109998Smarkm
677296465Sdelphij    ret = OPENSSL_malloc(sizeof *ret);
678296465Sdelphij    if (ret == NULL) {
679296465Sdelphij        ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
680296465Sdelphij        return NULL;
681296465Sdelphij    }
682109998Smarkm
683296465Sdelphij    ret->meth = group->meth;
684109998Smarkm
685296465Sdelphij    if (!ret->meth->point_init(ret)) {
686296465Sdelphij        OPENSSL_free(ret);
687296465Sdelphij        return NULL;
688296465Sdelphij    }
689109998Smarkm
690296465Sdelphij    return ret;
691296465Sdelphij}
692296465Sdelphij
693109998Smarkmvoid EC_POINT_free(EC_POINT *point)
694296465Sdelphij{
695296465Sdelphij    if (!point)
696296465Sdelphij        return;
697109998Smarkm
698296465Sdelphij    if (point->meth->point_finish != 0)
699296465Sdelphij        point->meth->point_finish(point);
700296465Sdelphij    OPENSSL_free(point);
701296465Sdelphij}
702109998Smarkm
703109998Smarkmvoid EC_POINT_clear_free(EC_POINT *point)
704296465Sdelphij{
705296465Sdelphij    if (!point)
706296465Sdelphij        return;
707109998Smarkm
708296465Sdelphij    if (point->meth->point_clear_finish != 0)
709296465Sdelphij        point->meth->point_clear_finish(point);
710296465Sdelphij    else if (point->meth != NULL && point->meth->point_finish != 0)
711296465Sdelphij        point->meth->point_finish(point);
712296465Sdelphij    OPENSSL_cleanse(point, sizeof *point);
713296465Sdelphij    OPENSSL_free(point);
714296465Sdelphij}
715109998Smarkm
716109998Smarkmint EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
717296465Sdelphij{
718296465Sdelphij    if (dest->meth->point_copy == 0) {
719296465Sdelphij        ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
720296465Sdelphij        return 0;
721296465Sdelphij    }
722296465Sdelphij    if (dest->meth != src->meth) {
723296465Sdelphij        ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
724296465Sdelphij        return 0;
725296465Sdelphij    }
726296465Sdelphij    if (dest == src)
727296465Sdelphij        return 1;
728296465Sdelphij    return dest->meth->point_copy(dest, src);
729296465Sdelphij}
730109998Smarkm
731160814SsimonEC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
732296465Sdelphij{
733296465Sdelphij    EC_POINT *t;
734296465Sdelphij    int r;
735160814Ssimon
736296465Sdelphij    if (a == NULL)
737296465Sdelphij        return NULL;
738160814Ssimon
739296465Sdelphij    t = EC_POINT_new(group);
740296465Sdelphij    if (t == NULL)
741296465Sdelphij        return (NULL);
742296465Sdelphij    r = EC_POINT_copy(t, a);
743296465Sdelphij    if (!r) {
744296465Sdelphij        EC_POINT_free(t);
745296465Sdelphij        return NULL;
746296465Sdelphij    } else
747296465Sdelphij        return t;
748296465Sdelphij}
749160814Ssimon
750109998Smarkmconst EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
751296465Sdelphij{
752296465Sdelphij    return point->meth;
753296465Sdelphij}
754109998Smarkm
755109998Smarkmint EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
756296465Sdelphij{
757296465Sdelphij    if (group->meth->point_set_to_infinity == 0) {
758296465Sdelphij        ECerr(EC_F_EC_POINT_SET_TO_INFINITY,
759296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
760296465Sdelphij        return 0;
761296465Sdelphij    }
762296465Sdelphij    if (group->meth != point->meth) {
763296465Sdelphij        ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
764296465Sdelphij        return 0;
765296465Sdelphij    }
766296465Sdelphij    return group->meth->point_set_to_infinity(group, point);
767296465Sdelphij}
768109998Smarkm
769296465Sdelphijint EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
770296465Sdelphij                                             EC_POINT *point, const BIGNUM *x,
771296465Sdelphij                                             const BIGNUM *y, const BIGNUM *z,
772296465Sdelphij                                             BN_CTX *ctx)
773296465Sdelphij{
774296465Sdelphij    if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
775296465Sdelphij        ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
776296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
777296465Sdelphij        return 0;
778296465Sdelphij    }
779296465Sdelphij    if (group->meth != point->meth) {
780296465Sdelphij        ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
781296465Sdelphij              EC_R_INCOMPATIBLE_OBJECTS);
782296465Sdelphij        return 0;
783296465Sdelphij    }
784296465Sdelphij    return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x,
785296465Sdelphij                                                              y, z, ctx);
786296465Sdelphij}
787109998Smarkm
788296465Sdelphijint EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
789296465Sdelphij                                             const EC_POINT *point, BIGNUM *x,
790296465Sdelphij                                             BIGNUM *y, BIGNUM *z,
791296465Sdelphij                                             BN_CTX *ctx)
792296465Sdelphij{
793296465Sdelphij    if (group->meth->point_get_Jprojective_coordinates_GFp == 0) {
794296465Sdelphij        ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
795296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
796296465Sdelphij        return 0;
797296465Sdelphij    }
798296465Sdelphij    if (group->meth != point->meth) {
799296465Sdelphij        ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
800296465Sdelphij              EC_R_INCOMPATIBLE_OBJECTS);
801296465Sdelphij        return 0;
802296465Sdelphij    }
803296465Sdelphij    return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x,
804296465Sdelphij                                                              y, z, ctx);
805296465Sdelphij}
806109998Smarkm
807296465Sdelphijint EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
808296465Sdelphij                                        EC_POINT *point, const BIGNUM *x,
809296465Sdelphij                                        const BIGNUM *y, BN_CTX *ctx)
810296465Sdelphij{
811296465Sdelphij    if (group->meth->point_set_affine_coordinates == 0) {
812296465Sdelphij        ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
813296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
814296465Sdelphij        return 0;
815296465Sdelphij    }
816296465Sdelphij    if (group->meth != point->meth) {
817296465Sdelphij        ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
818296465Sdelphij              EC_R_INCOMPATIBLE_OBJECTS);
819296465Sdelphij        return 0;
820296465Sdelphij    }
821296465Sdelphij    return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
822296465Sdelphij}
823109998Smarkm
824296465Sdelphijint EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
825296465Sdelphij                                         EC_POINT *point, const BIGNUM *x,
826296465Sdelphij                                         const BIGNUM *y, BN_CTX *ctx)
827296465Sdelphij{
828296465Sdelphij    if (group->meth->point_set_affine_coordinates == 0) {
829296465Sdelphij        ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
830296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
831296465Sdelphij        return 0;
832296465Sdelphij    }
833296465Sdelphij    if (group->meth != point->meth) {
834296465Sdelphij        ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
835296465Sdelphij              EC_R_INCOMPATIBLE_OBJECTS);
836296465Sdelphij        return 0;
837296465Sdelphij    }
838296465Sdelphij    return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
839296465Sdelphij}
840109998Smarkm
841296465Sdelphijint EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
842296465Sdelphij                                        const EC_POINT *point, BIGNUM *x,
843296465Sdelphij                                        BIGNUM *y, BN_CTX *ctx)
844296465Sdelphij{
845296465Sdelphij    if (group->meth->point_get_affine_coordinates == 0) {
846296465Sdelphij        ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
847296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
848296465Sdelphij        return 0;
849296465Sdelphij    }
850296465Sdelphij    if (group->meth != point->meth) {
851296465Sdelphij        ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
852296465Sdelphij              EC_R_INCOMPATIBLE_OBJECTS);
853296465Sdelphij        return 0;
854296465Sdelphij    }
855296465Sdelphij    return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
856296465Sdelphij}
857109998Smarkm
858296465Sdelphijint EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
859296465Sdelphij                                         const EC_POINT *point, BIGNUM *x,
860296465Sdelphij                                         BIGNUM *y, BN_CTX *ctx)
861296465Sdelphij{
862296465Sdelphij    if (group->meth->point_get_affine_coordinates == 0) {
863296465Sdelphij        ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
864296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
865296465Sdelphij        return 0;
866296465Sdelphij    }
867296465Sdelphij    if (group->meth != point->meth) {
868296465Sdelphij        ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
869296465Sdelphij              EC_R_INCOMPATIBLE_OBJECTS);
870296465Sdelphij        return 0;
871296465Sdelphij    }
872296465Sdelphij    return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
873296465Sdelphij}
874109998Smarkm
875296465Sdelphijint EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
876296465Sdelphij                                            EC_POINT *point, const BIGNUM *x,
877296465Sdelphij                                            int y_bit, BN_CTX *ctx)
878296465Sdelphij{
879296465Sdelphij    if (group->meth->point_set_compressed_coordinates == 0) {
880296465Sdelphij        ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP,
881296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
882296465Sdelphij        return 0;
883296465Sdelphij    }
884296465Sdelphij    if (group->meth != point->meth) {
885296465Sdelphij        ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP,
886296465Sdelphij              EC_R_INCOMPATIBLE_OBJECTS);
887296465Sdelphij        return 0;
888296465Sdelphij    }
889296465Sdelphij    return group->meth->point_set_compressed_coordinates(group, point, x,
890296465Sdelphij                                                         y_bit, ctx);
891296465Sdelphij}
892109998Smarkm
893296465Sdelphijint EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group,
894296465Sdelphij                                             EC_POINT *point, const BIGNUM *x,
895296465Sdelphij                                             int y_bit, BN_CTX *ctx)
896296465Sdelphij{
897296465Sdelphij    if (group->meth->point_set_compressed_coordinates == 0) {
898296465Sdelphij        ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M,
899296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
900296465Sdelphij        return 0;
901296465Sdelphij    }
902296465Sdelphij    if (group->meth != point->meth) {
903296465Sdelphij        ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M,
904296465Sdelphij              EC_R_INCOMPATIBLE_OBJECTS);
905296465Sdelphij        return 0;
906296465Sdelphij    }
907296465Sdelphij    return group->meth->point_set_compressed_coordinates(group, point, x,
908296465Sdelphij                                                         y_bit, ctx);
909296465Sdelphij}
910160814Ssimon
911296465Sdelphijsize_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
912296465Sdelphij                          point_conversion_form_t form, unsigned char *buf,
913296465Sdelphij                          size_t len, BN_CTX *ctx)
914296465Sdelphij{
915296465Sdelphij    if (group->meth->point2oct == 0) {
916296465Sdelphij        ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
917296465Sdelphij        return 0;
918296465Sdelphij    }
919296465Sdelphij    if (group->meth != point->meth) {
920296465Sdelphij        ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
921296465Sdelphij        return 0;
922296465Sdelphij    }
923296465Sdelphij    return group->meth->point2oct(group, point, form, buf, len, ctx);
924296465Sdelphij}
925160814Ssimon
926109998Smarkmint EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
927296465Sdelphij                       const unsigned char *buf, size_t len, BN_CTX *ctx)
928296465Sdelphij{
929296465Sdelphij    if (group->meth->oct2point == 0) {
930296465Sdelphij        ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
931296465Sdelphij        return 0;
932296465Sdelphij    }
933296465Sdelphij    if (group->meth != point->meth) {
934296465Sdelphij        ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
935296465Sdelphij        return 0;
936296465Sdelphij    }
937296465Sdelphij    return group->meth->oct2point(group, point, buf, len, ctx);
938296465Sdelphij}
939109998Smarkm
940296465Sdelphijint EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
941296465Sdelphij                 const EC_POINT *b, BN_CTX *ctx)
942296465Sdelphij{
943296465Sdelphij    if (group->meth->add == 0) {
944296465Sdelphij        ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
945296465Sdelphij        return 0;
946296465Sdelphij    }
947296465Sdelphij    if ((group->meth != r->meth) || (r->meth != a->meth)
948296465Sdelphij        || (a->meth != b->meth)) {
949296465Sdelphij        ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
950296465Sdelphij        return 0;
951296465Sdelphij    }
952296465Sdelphij    return group->meth->add(group, r, a, b, ctx);
953296465Sdelphij}
954109998Smarkm
955296465Sdelphijint EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
956296465Sdelphij                 BN_CTX *ctx)
957296465Sdelphij{
958296465Sdelphij    if (group->meth->dbl == 0) {
959296465Sdelphij        ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
960296465Sdelphij        return 0;
961296465Sdelphij    }
962296465Sdelphij    if ((group->meth != r->meth) || (r->meth != a->meth)) {
963296465Sdelphij        ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
964296465Sdelphij        return 0;
965296465Sdelphij    }
966296465Sdelphij    return group->meth->dbl(group, r, a, ctx);
967296465Sdelphij}
968109998Smarkm
969109998Smarkmint EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
970296465Sdelphij{
971296465Sdelphij    if (group->meth->invert == 0) {
972296465Sdelphij        ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
973296465Sdelphij        return 0;
974296465Sdelphij    }
975296465Sdelphij    if (group->meth != a->meth) {
976296465Sdelphij        ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
977296465Sdelphij        return 0;
978296465Sdelphij    }
979296465Sdelphij    return group->meth->invert(group, a, ctx);
980296465Sdelphij}
981109998Smarkm
982109998Smarkmint EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
983296465Sdelphij{
984296465Sdelphij    if (group->meth->is_at_infinity == 0) {
985296465Sdelphij        ECerr(EC_F_EC_POINT_IS_AT_INFINITY,
986296465Sdelphij              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
987296465Sdelphij        return 0;
988296465Sdelphij    }
989296465Sdelphij    if (group->meth != point->meth) {
990296465Sdelphij        ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
991296465Sdelphij        return 0;
992296465Sdelphij    }
993296465Sdelphij    return group->meth->is_at_infinity(group, point);
994296465Sdelphij}
995109998Smarkm
996284295Sdelphij/*
997284295Sdelphij * Check whether an EC_POINT is on the curve or not. Note that the return
998284295Sdelphij * value for this function should NOT be treated as a boolean. Return values:
999284295Sdelphij *  1: The point is on the curve
1000284295Sdelphij *  0: The point is not on the curve
1001284295Sdelphij * -1: An error occurred
1002284295Sdelphij */
1003284295Sdelphijint EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
1004284295Sdelphij                         BN_CTX *ctx)
1005296465Sdelphij{
1006296465Sdelphij    if (group->meth->is_on_curve == 0) {
1007296465Sdelphij        ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1008296465Sdelphij        return 0;
1009296465Sdelphij    }
1010296465Sdelphij    if (group->meth != point->meth) {
1011296465Sdelphij        ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
1012296465Sdelphij        return 0;
1013296465Sdelphij    }
1014296465Sdelphij    return group->meth->is_on_curve(group, point, ctx);
1015296465Sdelphij}
1016109998Smarkm
1017296465Sdelphijint EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
1018296465Sdelphij                 BN_CTX *ctx)
1019296465Sdelphij{
1020296465Sdelphij    if (group->meth->point_cmp == 0) {
1021296465Sdelphij        ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1022296465Sdelphij        return -1;
1023296465Sdelphij    }
1024296465Sdelphij    if ((group->meth != a->meth) || (a->meth != b->meth)) {
1025296465Sdelphij        ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
1026296465Sdelphij        return -1;
1027296465Sdelphij    }
1028296465Sdelphij    return group->meth->point_cmp(group, a, b, ctx);
1029296465Sdelphij}
1030109998Smarkm
1031109998Smarkmint EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1032296465Sdelphij{
1033296465Sdelphij    if (group->meth->make_affine == 0) {
1034296465Sdelphij        ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1035296465Sdelphij        return 0;
1036296465Sdelphij    }
1037296465Sdelphij    if (group->meth != point->meth) {
1038296465Sdelphij        ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1039296465Sdelphij        return 0;
1040296465Sdelphij    }
1041296465Sdelphij    return group->meth->make_affine(group, point, ctx);
1042296465Sdelphij}
1043109998Smarkm
1044296465Sdelphijint EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
1045296465Sdelphij                          EC_POINT *points[], BN_CTX *ctx)
1046296465Sdelphij{
1047296465Sdelphij    size_t i;
1048109998Smarkm
1049296465Sdelphij    if (group->meth->points_make_affine == 0) {
1050296465Sdelphij        ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1051296465Sdelphij        return 0;
1052296465Sdelphij    }
1053296465Sdelphij    for (i = 0; i < num; i++) {
1054296465Sdelphij        if (group->meth != points[i]->meth) {
1055296465Sdelphij            ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1056296465Sdelphij            return 0;
1057296465Sdelphij        }
1058296465Sdelphij    }
1059296465Sdelphij    return group->meth->points_make_affine(group, num, points, ctx);
1060296465Sdelphij}
1061109998Smarkm
1062296465Sdelphij/*
1063296465Sdelphij * Functions for point multiplication. If group->meth->mul is 0, we use the
1064296465Sdelphij * wNAF-based implementations in ec_mult.c; otherwise we dispatch through
1065296465Sdelphij * methods.
1066160814Ssimon */
1067160814Ssimon
1068160814Ssimonint EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1069296465Sdelphij                  size_t num, const EC_POINT *points[],
1070296465Sdelphij                  const BIGNUM *scalars[], BN_CTX *ctx)
1071296465Sdelphij{
1072296465Sdelphij    if (group->meth->mul == 0)
1073296465Sdelphij        /* use default */
1074296465Sdelphij        return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
1075160814Ssimon
1076296465Sdelphij    return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
1077296465Sdelphij}
1078160814Ssimon
1079160814Ssimonint EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1080296465Sdelphij                 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
1081296465Sdelphij{
1082296465Sdelphij    /* just a convenient interface to EC_POINTs_mul() */
1083160814Ssimon
1084296465Sdelphij    const EC_POINT *points[1];
1085296465Sdelphij    const BIGNUM *scalars[1];
1086160814Ssimon
1087296465Sdelphij    points[0] = point;
1088296465Sdelphij    scalars[0] = p_scalar;
1089160814Ssimon
1090296465Sdelphij    return EC_POINTs_mul(group, r, g_scalar,
1091296465Sdelphij                         (point != NULL
1092296465Sdelphij                          && p_scalar != NULL), points, scalars, ctx);
1093296465Sdelphij}
1094160814Ssimon
1095160814Ssimonint EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1096296465Sdelphij{
1097296465Sdelphij    if (group->meth->mul == 0)
1098296465Sdelphij        /* use default */
1099296465Sdelphij        return ec_wNAF_precompute_mult(group, ctx);
1100160814Ssimon
1101296465Sdelphij    if (group->meth->precompute_mult != 0)
1102296465Sdelphij        return group->meth->precompute_mult(group, ctx);
1103296465Sdelphij    else
1104296465Sdelphij        return 1;               /* nothing to do, so report success */
1105296465Sdelphij}
1106160814Ssimon
1107160814Ssimonint EC_GROUP_have_precompute_mult(const EC_GROUP *group)
1108296465Sdelphij{
1109296465Sdelphij    if (group->meth->mul == 0)
1110296465Sdelphij        /* use default */
1111296465Sdelphij        return ec_wNAF_have_precompute_mult(group);
1112160814Ssimon
1113296465Sdelphij    if (group->meth->have_precompute_mult != 0)
1114296465Sdelphij        return group->meth->have_precompute_mult(group);
1115296465Sdelphij    else
1116296465Sdelphij        return 0;               /* cannot tell whether precomputation has
1117296465Sdelphij                                 * been performed */
1118296465Sdelphij}
1119