ec_lib.c revision 284295
183998Sbrooks/* crypto/ec/ec_lib.c */
283998Sbrooks/*
383998Sbrooks * Originally written by Bodo Moeller for the OpenSSL project.
483998Sbrooks */
583998Sbrooks/* ====================================================================
683998Sbrooks * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
783998Sbrooks *
883998Sbrooks * Redistribution and use in source and binary forms, with or without
984000Sbrooks * modification, are permitted provided that the following conditions
1083998Sbrooks * are met:
1184000Sbrooks *
1283998Sbrooks * 1. Redistributions of source code must retain the above copyright
1384000Sbrooks *    notice, this list of conditions and the following disclaimer.
1483998Sbrooks *
1584000Sbrooks * 2. Redistributions in binary form must reproduce the above copyright
1684000Sbrooks *    notice, this list of conditions and the following disclaimer in
1783998Sbrooks *    the documentation and/or other materials provided with the
1883998Sbrooks *    distribution.
1983998Sbrooks *
2083998Sbrooks * 3. All advertising materials mentioning features or use of this
2183998Sbrooks *    software must display the following acknowledgment:
2283998Sbrooks *    "This product includes software developed by the OpenSSL Project
2383998Sbrooks *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
2483998Sbrooks *
2583998Sbrooks * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2683998Sbrooks *    endorse or promote products derived from this software without
2783998Sbrooks *    prior written permission. For written permission, please contact
2883998Sbrooks *    openssl-core@openssl.org.
2983998Sbrooks *
3083998Sbrooks * 5. Products derived from this software may not be called "OpenSSL"
3183998Sbrooks *    nor may "OpenSSL" appear in their names without prior written
3283998Sbrooks *    permission of the OpenSSL Project.
3383998Sbrooks *
3483998Sbrooks * 6. Redistributions of any form whatsoever must retain the following
3583998Sbrooks *    acknowledgment:
3683998Sbrooks *    "This product includes software developed by the OpenSSL Project
3783998Sbrooks *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
3883998Sbrooks *
3983998Sbrooks * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4083998Sbrooks * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4183998Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4283998Sbrooks * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4383998Sbrooks * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4483998Sbrooks * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4583998Sbrooks * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4683998Sbrooks * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4783998Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4883998Sbrooks * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4983998Sbrooks * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5083998Sbrooks * OF THE POSSIBILITY OF SUCH DAMAGE.
5183998Sbrooks * ====================================================================
5283998Sbrooks *
5383998Sbrooks * This product includes cryptographic software written by Eric Young
5483998Sbrooks * (eay@cryptsoft.com).  This product includes software written by Tim
5583998Sbrooks * Hudson (tjh@cryptsoft.com).
5683998Sbrooks *
5783998Sbrooks */
5883998Sbrooks/* ====================================================================
5983998Sbrooks * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
6083998Sbrooks * Binary polynomial ECC support in OpenSSL originally developed by
6183998Sbrooks * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
6283998Sbrooks */
6383998Sbrooks
6483998Sbrooks#include <string.h>
6583998Sbrooks
6683998Sbrooks#include <openssl/err.h>
6783998Sbrooks#include <openssl/opensslv.h>
6883998Sbrooks
6983998Sbrooks#include "ec_lcl.h"
7083998Sbrooks
7183998Sbrooksstatic const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
7283998Sbrooks
7383998Sbrooks
7483998Sbrooks/* functions for EC_GROUP objects */
7583998Sbrooks
7683998SbrooksEC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
7783998Sbrooks	{
7883998Sbrooks	EC_GROUP *ret;
7983998Sbrooks
8083998Sbrooks	if (meth == NULL)
8183998Sbrooks		{
8283998Sbrooks		ECerr(EC_F_EC_GROUP_NEW, ERR_R_PASSED_NULL_PARAMETER);
8383998Sbrooks		return NULL;
8483998Sbrooks		}
8583998Sbrooks	if (meth->group_init == 0)
8683998Sbrooks		{
8783998Sbrooks		ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
8883998Sbrooks		return NULL;
8983998Sbrooks		}
9083998Sbrooks
91132780Skan	ret = OPENSSL_malloc(sizeof *ret);
9283998Sbrooks	if (ret == NULL)
9383998Sbrooks		{
9483998Sbrooks		ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
9583998Sbrooks		return NULL;
9683998Sbrooks		}
9783998Sbrooks
9883998Sbrooks	ret->meth = meth;
9983998Sbrooks
10083998Sbrooks	ret->extra_data = NULL;
10183998Sbrooks
10283998Sbrooks	ret->generator = NULL;
10383998Sbrooks	BN_init(&ret->order);
10483998Sbrooks	BN_init(&ret->cofactor);
10583998Sbrooks
10683998Sbrooks	ret->curve_name = 0;
10783998Sbrooks	ret->asn1_flag  = 0;
10883998Sbrooks	ret->asn1_form  = POINT_CONVERSION_UNCOMPRESSED;
10983998Sbrooks
110131155Sjulian	ret->seed = NULL;
11183998Sbrooks	ret->seed_len = 0;
11283998Sbrooks
11383998Sbrooks	if (!meth->group_init(ret))
11483998Sbrooks		{
11583998Sbrooks		OPENSSL_free(ret);
11683998Sbrooks		return NULL;
11783998Sbrooks		}
11883998Sbrooks
11983998Sbrooks	return ret;
12083998Sbrooks	}
12183998Sbrooks
12283998Sbrooks
12383998Sbrooksvoid EC_GROUP_free(EC_GROUP *group)
12483998Sbrooks	{
12583998Sbrooks	if (!group) return;
12683998Sbrooks
12783998Sbrooks	if (group->meth->group_finish != 0)
12883998Sbrooks		group->meth->group_finish(group);
12983998Sbrooks
13083998Sbrooks	EC_EX_DATA_free_all_data(&group->extra_data);
13183998Sbrooks
13283998Sbrooks	if (group->generator != NULL)
13383998Sbrooks		EC_POINT_free(group->generator);
13483998Sbrooks	BN_free(&group->order);
13583998Sbrooks	BN_free(&group->cofactor);
13683998Sbrooks
13783998Sbrooks	if (group->seed)
13883998Sbrooks		OPENSSL_free(group->seed);
13983998Sbrooks
14083998Sbrooks	OPENSSL_free(group);
14183998Sbrooks	}
142129823Sjulian
143129823Sjulian
144129823Sjulianvoid EC_GROUP_clear_free(EC_GROUP *group)
145129823Sjulian	{
146129823Sjulian	if (!group) return;
147129823Sjulian
148129823Sjulian	if (group->meth->group_clear_finish != 0)
149129823Sjulian		group->meth->group_clear_finish(group);
150129823Sjulian	else if (group->meth->group_finish != 0)
151129823Sjulian		group->meth->group_finish(group);
152129823Sjulian
15383998Sbrooks	EC_EX_DATA_clear_free_all_data(&group->extra_data);
15483998Sbrooks
15583998Sbrooks	if (group->generator != NULL)
15683998Sbrooks		EC_POINT_clear_free(group->generator);
15783998Sbrooks	BN_clear_free(&group->order);
15883998Sbrooks	BN_clear_free(&group->cofactor);
15983998Sbrooks
16083998Sbrooks	if (group->seed)
16183998Sbrooks		{
16283998Sbrooks		OPENSSL_cleanse(group->seed, group->seed_len);
16383998Sbrooks		OPENSSL_free(group->seed);
16483998Sbrooks		}
16583998Sbrooks
16683998Sbrooks	OPENSSL_cleanse(group, sizeof *group);
16783998Sbrooks	OPENSSL_free(group);
16883998Sbrooks	}
16983998Sbrooks
17083998Sbrooks
17183998Sbrooksint EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
17283998Sbrooks	{
17383998Sbrooks	EC_EXTRA_DATA *d;
17483998Sbrooks
17583998Sbrooks	if (dest->meth->group_copy == 0)
17683998Sbrooks		{
17783998Sbrooks		ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
17883998Sbrooks		return 0;
17983998Sbrooks		}
18083998Sbrooks	if (dest->meth != src->meth)
18183998Sbrooks		{
18283998Sbrooks		ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
18383998Sbrooks		return 0;
18483998Sbrooks		}
18583998Sbrooks	if (dest == src)
18683998Sbrooks		return 1;
18783998Sbrooks
18883998Sbrooks	EC_EX_DATA_free_all_data(&dest->extra_data);
18983998Sbrooks
19083998Sbrooks	for (d = src->extra_data; d != NULL; d = d->next)
19183998Sbrooks		{
19283998Sbrooks		void *t = d->dup_func(d->data);
19383998Sbrooks
19483998Sbrooks		if (t == NULL)
19583998Sbrooks			return 0;
19683998Sbrooks		if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func))
19783998Sbrooks			return 0;
19883998Sbrooks		}
19983998Sbrooks
20083998Sbrooks	if (src->generator != NULL)
20183998Sbrooks		{
20283998Sbrooks		if (dest->generator == NULL)
20383998Sbrooks			{
20483998Sbrooks			dest->generator = EC_POINT_new(dest);
20583998Sbrooks			if (dest->generator == NULL) return 0;
20683998Sbrooks			}
20783998Sbrooks		if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
20883998Sbrooks		}
20983998Sbrooks	else
21083998Sbrooks		{
21183998Sbrooks		/* src->generator == NULL */
21283998Sbrooks		if (dest->generator != NULL)
21383998Sbrooks			{
21483998Sbrooks			EC_POINT_clear_free(dest->generator);
21583998Sbrooks			dest->generator = NULL;
21683998Sbrooks			}
21783998Sbrooks		}
21883998Sbrooks
21983998Sbrooks	if (!BN_copy(&dest->order, &src->order)) return 0;
22083998Sbrooks	if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
22183998Sbrooks
22283998Sbrooks	dest->curve_name = src->curve_name;
22383998Sbrooks	dest->asn1_flag  = src->asn1_flag;
22483998Sbrooks	dest->asn1_form  = src->asn1_form;
22583998Sbrooks
22683998Sbrooks	if (src->seed)
22783998Sbrooks		{
22883998Sbrooks		if (dest->seed)
22983998Sbrooks			OPENSSL_free(dest->seed);
23083998Sbrooks		dest->seed = OPENSSL_malloc(src->seed_len);
23183998Sbrooks		if (dest->seed == NULL)
23283998Sbrooks			return 0;
23383998Sbrooks		if (!memcpy(dest->seed, src->seed, src->seed_len))
23487599Sobrien			return 0;
23583998Sbrooks		dest->seed_len = src->seed_len;
23683998Sbrooks		}
237121816Sbrooks	else
23883998Sbrooks		{
23983998Sbrooks		if (dest->seed)
24083998Sbrooks			OPENSSL_free(dest->seed);
24183998Sbrooks		dest->seed = NULL;
24283998Sbrooks		dest->seed_len = 0;
24383998Sbrooks		}
24483998Sbrooks
245121816Sbrooks
24683998Sbrooks	return dest->meth->group_copy(dest, src);
24783998Sbrooks	}
24883998Sbrooks
24983998Sbrooks
25083998SbrooksEC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
251132780Skan	{
25283998Sbrooks	EC_GROUP *t = NULL;
25383998Sbrooks	int ok = 0;
254121816Sbrooks
25583998Sbrooks	if (a == NULL) return NULL;
256121816Sbrooks
25783998Sbrooks	if ((t = EC_GROUP_new(a->meth)) == NULL) return(NULL);
25883998Sbrooks	if (!EC_GROUP_copy(t, a)) goto err;
25983998Sbrooks
26083998Sbrooks	ok = 1;
26184060Sbrooks
26283998Sbrooks  err:
26383998Sbrooks	if (!ok)
26483998Sbrooks		{
26583998Sbrooks		if (t) EC_GROUP_free(t);
26683998Sbrooks		return NULL;
26783998Sbrooks		}
268126203Sphk	else return t;
26983998Sbrooks	}
27083998Sbrooks
27183998Sbrooks
272126196Scpercivaconst EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
27383998Sbrooks	{
27483998Sbrooks	return group->meth;
27583998Sbrooks	}
27683998Sbrooks
27783998Sbrooks
27883998Sbrooksint EC_METHOD_get_field_type(const EC_METHOD *meth)
279132780Skan        {
28083998Sbrooks        return meth->field_type;
28183998Sbrooks        }
28283998Sbrooks
28383998Sbrooks
28483998Sbrooksint EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
28584060Sbrooks	{
28683998Sbrooks	if (generator == NULL)
28783998Sbrooks		{
28883998Sbrooks		ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
28983998Sbrooks		return 0   ;
29083998Sbrooks		}
29183998Sbrooks
29283998Sbrooks	if (group->generator == NULL)
29383998Sbrooks		{
29483998Sbrooks		group->generator = EC_POINT_new(group);
29583998Sbrooks		if (group->generator == NULL) return 0;
29683998Sbrooks		}
29783998Sbrooks	if (!EC_POINT_copy(group->generator, generator)) return 0;
29883998Sbrooks
29983998Sbrooks	if (order != NULL)
30083998Sbrooks		{ if (!BN_copy(&group->order, order)) return 0; }
30183998Sbrooks	else
30283998Sbrooks		BN_zero(&group->order);
30383998Sbrooks
30483998Sbrooks	if (cofactor != NULL)
30583998Sbrooks		{ if (!BN_copy(&group->cofactor, cofactor)) return 0; }
30683998Sbrooks	else
30783998Sbrooks		BN_zero(&group->cofactor);
30883998Sbrooks
30983998Sbrooks	return 1;
31083998Sbrooks	}
311111119Simp
31283998Sbrooks
31383998Sbrooksconst EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
31483998Sbrooks	{
31583998Sbrooks	return group->generator;
31683998Sbrooks	}
31783998Sbrooks
31883998Sbrooks
31983998Sbrooksint EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
32083998Sbrooks	{
32183998Sbrooks	if (!BN_copy(order, &group->order))
32283998Sbrooks		return 0;
32383998Sbrooks
32483998Sbrooks	return !BN_is_zero(order);
32583998Sbrooks	}
32683998Sbrooks
32783998Sbrooks
32883998Sbrooksint EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
32983998Sbrooks	{
33083998Sbrooks	if (!BN_copy(cofactor, &group->cofactor))
33183998Sbrooks		return 0;
33283998Sbrooks
33383998Sbrooks	return !BN_is_zero(&group->cofactor);
33483998Sbrooks	}
33583998Sbrooks
33683998Sbrooks
33783998Sbrooksvoid EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
33883998Sbrooks	{
33983998Sbrooks	group->curve_name = nid;
34083998Sbrooks	}
34183998Sbrooks
34283998Sbrooks
34383998Sbrooksint EC_GROUP_get_curve_name(const EC_GROUP *group)
34483998Sbrooks	{
34583998Sbrooks	return group->curve_name;
34683998Sbrooks	}
34783998Sbrooks
34883998Sbrooks
34983998Sbrooksvoid EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
35083998Sbrooks	{
35183998Sbrooks	group->asn1_flag = flag;
35283998Sbrooks	}
35383998Sbrooks
35483998Sbrooks
35583998Sbrooksint EC_GROUP_get_asn1_flag(const EC_GROUP *group)
35683998Sbrooks	{
35783998Sbrooks	return group->asn1_flag;
35883998Sbrooks	}
35983998Sbrooks
36083998Sbrooks
36183998Sbrooksvoid EC_GROUP_set_point_conversion_form(EC_GROUP *group,
36283998Sbrooks                                        point_conversion_form_t form)
36383998Sbrooks	{
36483998Sbrooks	group->asn1_form = form;
36583998Sbrooks	}
36683998Sbrooks
36783998Sbrooks
36883998Sbrookspoint_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group)
36983998Sbrooks	{
37083998Sbrooks	return group->asn1_form;
37183998Sbrooks	}
37283998Sbrooks
37383998Sbrooks
37483998Sbrookssize_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
37583998Sbrooks	{
37683998Sbrooks	if (group->seed)
37783998Sbrooks		{
37883998Sbrooks		OPENSSL_free(group->seed);
37983998Sbrooks		group->seed = NULL;
38083998Sbrooks		group->seed_len = 0;
38183998Sbrooks		}
38283998Sbrooks
38383998Sbrooks	if (!len || !p)
38483998Sbrooks		return 1;
38583998Sbrooks
38683998Sbrooks	if ((group->seed = OPENSSL_malloc(len)) == NULL)
38783998Sbrooks		return 0;
38883998Sbrooks	memcpy(group->seed, p, len);
38983998Sbrooks	group->seed_len = len;
39083998Sbrooks
39183998Sbrooks	return len;
39283998Sbrooks	}
39383998Sbrooks
39483998Sbrooks
39583998Sbrooksunsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
39683998Sbrooks	{
39783998Sbrooks	return group->seed;
39883998Sbrooks	}
39983998Sbrooks
40083998Sbrooks
40183998Sbrookssize_t EC_GROUP_get_seed_len(const EC_GROUP *group)
40283998Sbrooks	{
40383998Sbrooks	return group->seed_len;
40483998Sbrooks	}
40583998Sbrooks
40683998Sbrooks
40783998Sbrooksint EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
40883998Sbrooks	{
40983998Sbrooks	if (group->meth->group_set_curve == 0)
41083998Sbrooks		{
41183998Sbrooks		ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
412121816Sbrooks		return 0;
41383998Sbrooks		}
41483998Sbrooks	return group->meth->group_set_curve(group, p, a, b, ctx);
41583998Sbrooks	}
41683998Sbrooks
41783998Sbrooks
41883998Sbrooksint EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
41983998Sbrooks	{
42083998Sbrooks	if (group->meth->group_get_curve == 0)
42183998Sbrooks		{
42283998Sbrooks		ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
42383998Sbrooks		return 0;
42483998Sbrooks		}
42583998Sbrooks	return group->meth->group_get_curve(group, p, a, b, ctx);
42683998Sbrooks	}
42783998Sbrooks
42883998Sbrooks
42983998Sbrooksint EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
43083998Sbrooks	{
43183998Sbrooks	if (group->meth->group_set_curve == 0)
43283998Sbrooks		{
43383998Sbrooks		ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
43483998Sbrooks		return 0;
43583998Sbrooks		}
43683998Sbrooks	return group->meth->group_set_curve(group, p, a, b, ctx);
43783998Sbrooks	}
43883998Sbrooks
43983998Sbrooks
44083998Sbrooksint EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
44183998Sbrooks	{
44283998Sbrooks	if (group->meth->group_get_curve == 0)
44383998Sbrooks		{
44483998Sbrooks		ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
44583998Sbrooks		return 0;
44683998Sbrooks		}
44783998Sbrooks	return group->meth->group_get_curve(group, p, a, b, ctx);
448131155Sjulian	}
44983998Sbrooks
450131155Sjulian
45187599Sobrienint EC_GROUP_get_degree(const EC_GROUP *group)
45283998Sbrooks	{
45383998Sbrooks	if (group->meth->group_get_degree == 0)
45483998Sbrooks		{
45583998Sbrooks		ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
45683998Sbrooks		return 0;
45783998Sbrooks		}
458131155Sjulian	return group->meth->group_get_degree(group);
45983998Sbrooks	}
46083998Sbrooks
46183998Sbrooks
46283998Sbrooksint EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
46383998Sbrooks	{
46483998Sbrooks	if (group->meth->group_check_discriminant == 0)
46583998Sbrooks		{
46683998Sbrooks		ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
46783998Sbrooks		return 0;
46883998Sbrooks		}
46983998Sbrooks	return group->meth->group_check_discriminant(group, ctx);
47083998Sbrooks	}
47183998Sbrooks
47283998Sbrooks
47383998Sbrooksint EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
47483998Sbrooks	{
47583998Sbrooks	int    r = 0;
47683998Sbrooks	BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
47783998Sbrooks	BN_CTX *ctx_new = NULL;
47883998Sbrooks
47983998Sbrooks	/* compare the field types*/
48083998Sbrooks	if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
48183998Sbrooks	    EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
48283998Sbrooks		return 1;
48383998Sbrooks	/* compare the curve name (if present in both) */
48483998Sbrooks	if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
48583998Sbrooks	    EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
48683998Sbrooks		return 1;
48783998Sbrooks
48883998Sbrooks	if (!ctx)
48983998Sbrooks		ctx_new = ctx = BN_CTX_new();
49083998Sbrooks	if (!ctx)
49183998Sbrooks		return -1;
49283998Sbrooks
49383998Sbrooks	BN_CTX_start(ctx);
49483998Sbrooks	a1 = BN_CTX_get(ctx);
49583998Sbrooks	a2 = BN_CTX_get(ctx);
496132464Sjulian	a3 = BN_CTX_get(ctx);
49783998Sbrooks	b1 = BN_CTX_get(ctx);
49883998Sbrooks	b2 = BN_CTX_get(ctx);
49983998Sbrooks	b3 = BN_CTX_get(ctx);
50083998Sbrooks	if (!b3)
50183998Sbrooks		{
50283998Sbrooks		BN_CTX_end(ctx);
50383998Sbrooks		if (ctx_new)
50483998Sbrooks			BN_CTX_free(ctx);
50583998Sbrooks		return -1;
50683998Sbrooks		}
50783998Sbrooks
508132464Sjulian	/* XXX This approach assumes that the external representation
50983998Sbrooks	 * of curves over the same field type is the same.
51083998Sbrooks	 */
51183998Sbrooks	if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
51283998Sbrooks	    !b->meth->group_get_curve(b, b1, b2, b3, ctx))
51383998Sbrooks		r = 1;
51483998Sbrooks
51583998Sbrooks	if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
51683998Sbrooks		r = 1;
51783998Sbrooks
51883998Sbrooks	/* XXX EC_POINT_cmp() assumes that the methods are equal */
51983998Sbrooks	if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
52083998Sbrooks	    EC_GROUP_get0_generator(b), ctx))
52183998Sbrooks		r = 1;
52283998Sbrooks
52383998Sbrooks	if (!r)
52487599Sobrien		{
52583998Sbrooks		/* compare the order and cofactor */
52683998Sbrooks		if (!EC_GROUP_get_order(a, a1, ctx) ||
52783998Sbrooks		    !EC_GROUP_get_order(b, b1, ctx) ||
52883998Sbrooks		    !EC_GROUP_get_cofactor(a, a2, ctx) ||
52983998Sbrooks		    !EC_GROUP_get_cofactor(b, b2, ctx))
53083998Sbrooks			{
53183998Sbrooks			BN_CTX_end(ctx);
53283998Sbrooks			if (ctx_new)
53383998Sbrooks				BN_CTX_free(ctx);
53483998Sbrooks			return -1;
53583998Sbrooks			}
53683998Sbrooks		if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
53783998Sbrooks			r = 1;
53883998Sbrooks		}
53983998Sbrooks
54083998Sbrooks	BN_CTX_end(ctx);
54183998Sbrooks	if (ctx_new)
54283998Sbrooks		BN_CTX_free(ctx);
54383998Sbrooks
54483998Sbrooks	return r;
54583998Sbrooks	}
54683998Sbrooks
54783998Sbrooks
54883998Sbrooks/* this has 'package' visibility */
54983998Sbrooksint EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
55083998Sbrooks	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
55183998Sbrooks	{
55283998Sbrooks	EC_EXTRA_DATA *d;
55383998Sbrooks
55483998Sbrooks	if (ex_data == NULL)
55583998Sbrooks		return 0;
55683998Sbrooks
55783998Sbrooks	for (d = *ex_data; d != NULL; d = d->next)
55883998Sbrooks		{
55983998Sbrooks		if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
56083998Sbrooks			{
561108172Shsu			ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
56283998Sbrooks			return 0;
56383998Sbrooks			}
56483998Sbrooks		}
56583998Sbrooks
566108172Shsu	if (data == NULL)
56783998Sbrooks		/* no explicit entry needed */
56883998Sbrooks		return 1;
56983998Sbrooks
57083998Sbrooks	d = OPENSSL_malloc(sizeof *d);
57183998Sbrooks	if (d == NULL)
57283998Sbrooks		return 0;
57383998Sbrooks
57483998Sbrooks	d->data = data;
57583998Sbrooks	d->dup_func = dup_func;
57683998Sbrooks	d->free_func = free_func;
57783998Sbrooks	d->clear_free_func = clear_free_func;
57883998Sbrooks
57983998Sbrooks	d->next = *ex_data;
58083998Sbrooks	*ex_data = d;
58183998Sbrooks
58283998Sbrooks	return 1;
58383998Sbrooks	}
58483998Sbrooks
58583998Sbrooks/* this has 'package' visibility */
58683998Sbrooksvoid *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
58783998Sbrooks	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
58883998Sbrooks	{
58983998Sbrooks	const EC_EXTRA_DATA *d;
59083998Sbrooks
59183998Sbrooks	for (d = ex_data; d != NULL; d = d->next)
59283998Sbrooks		{
59383998Sbrooks		if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
59483998Sbrooks			return d->data;
59583998Sbrooks		}
596
597	return NULL;
598	}
599
600/* this has 'package' visibility */
601void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
602	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
603	{
604	EC_EXTRA_DATA **p;
605
606	if (ex_data == NULL)
607		return;
608
609	for (p = ex_data; *p != NULL; p = &((*p)->next))
610		{
611		if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
612			{
613			EC_EXTRA_DATA *next = (*p)->next;
614
615			(*p)->free_func((*p)->data);
616			OPENSSL_free(*p);
617
618			*p = next;
619			return;
620			}
621		}
622	}
623
624/* this has 'package' visibility */
625void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
626	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
627	{
628	EC_EXTRA_DATA **p;
629
630	if (ex_data == NULL)
631		return;
632
633	for (p = ex_data; *p != NULL; p = &((*p)->next))
634		{
635		if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
636			{
637			EC_EXTRA_DATA *next = (*p)->next;
638
639			(*p)->clear_free_func((*p)->data);
640			OPENSSL_free(*p);
641
642			*p = next;
643			return;
644			}
645		}
646	}
647
648/* this has 'package' visibility */
649void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
650	{
651	EC_EXTRA_DATA *d;
652
653	if (ex_data == NULL)
654		return;
655
656	d = *ex_data;
657	while (d)
658		{
659		EC_EXTRA_DATA *next = d->next;
660
661		d->free_func(d->data);
662		OPENSSL_free(d);
663
664		d = next;
665		}
666	*ex_data = NULL;
667	}
668
669/* this has 'package' visibility */
670void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
671	{
672	EC_EXTRA_DATA *d;
673
674	if (ex_data == NULL)
675		return;
676
677	d = *ex_data;
678	while (d)
679		{
680		EC_EXTRA_DATA *next = d->next;
681
682		d->clear_free_func(d->data);
683		OPENSSL_free(d);
684
685		d = next;
686		}
687	*ex_data = NULL;
688	}
689
690
691/* functions for EC_POINT objects */
692
693EC_POINT *EC_POINT_new(const EC_GROUP *group)
694	{
695	EC_POINT *ret;
696
697	if (group == NULL)
698		{
699		ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
700		return NULL;
701		}
702	if (group->meth->point_init == 0)
703		{
704		ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
705		return NULL;
706		}
707
708	ret = OPENSSL_malloc(sizeof *ret);
709	if (ret == NULL)
710		{
711		ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
712		return NULL;
713		}
714
715	ret->meth = group->meth;
716
717	if (!ret->meth->point_init(ret))
718		{
719		OPENSSL_free(ret);
720		return NULL;
721		}
722
723	return ret;
724	}
725
726
727void EC_POINT_free(EC_POINT *point)
728	{
729	if (!point) return;
730
731	if (point->meth->point_finish != 0)
732		point->meth->point_finish(point);
733	OPENSSL_free(point);
734	}
735
736
737void EC_POINT_clear_free(EC_POINT *point)
738	{
739	if (!point) return;
740
741	if (point->meth->point_clear_finish != 0)
742		point->meth->point_clear_finish(point);
743	else if (point->meth != NULL && point->meth->point_finish != 0)
744		point->meth->point_finish(point);
745	OPENSSL_cleanse(point, sizeof *point);
746	OPENSSL_free(point);
747	}
748
749
750int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
751	{
752	if (dest->meth->point_copy == 0)
753		{
754		ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
755		return 0;
756		}
757	if (dest->meth != src->meth)
758		{
759		ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
760		return 0;
761		}
762	if (dest == src)
763		return 1;
764	return dest->meth->point_copy(dest, src);
765	}
766
767
768EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
769	{
770	EC_POINT *t;
771	int r;
772
773	if (a == NULL) return NULL;
774
775	t = EC_POINT_new(group);
776	if (t == NULL) return(NULL);
777	r = EC_POINT_copy(t, a);
778	if (!r)
779		{
780		EC_POINT_free(t);
781		return NULL;
782		}
783	else return t;
784	}
785
786
787const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
788	{
789	return point->meth;
790	}
791
792
793int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
794	{
795	if (group->meth->point_set_to_infinity == 0)
796		{
797		ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
798		return 0;
799		}
800	if (group->meth != point->meth)
801		{
802		ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
803		return 0;
804		}
805	return group->meth->point_set_to_infinity(group, point);
806	}
807
808
809int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
810	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
811	{
812	if (group->meth->point_set_Jprojective_coordinates_GFp == 0)
813		{
814		ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
815		return 0;
816		}
817	if (group->meth != point->meth)
818		{
819		ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
820		return 0;
821		}
822	return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
823	}
824
825
826int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
827	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
828	{
829	if (group->meth->point_get_Jprojective_coordinates_GFp == 0)
830		{
831		ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
832		return 0;
833		}
834	if (group->meth != point->meth)
835		{
836		ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
837		return 0;
838		}
839	return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
840	}
841
842
843int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
844	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
845	{
846	if (group->meth->point_set_affine_coordinates == 0)
847		{
848		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
849		return 0;
850		}
851	if (group->meth != point->meth)
852		{
853		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
854		return 0;
855		}
856	return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
857	}
858
859
860int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
861	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
862	{
863	if (group->meth->point_set_affine_coordinates == 0)
864		{
865		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
866		return 0;
867		}
868	if (group->meth != point->meth)
869		{
870		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
871		return 0;
872		}
873	return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
874	}
875
876
877int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
878	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
879	{
880	if (group->meth->point_get_affine_coordinates == 0)
881		{
882		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
883		return 0;
884		}
885	if (group->meth != point->meth)
886		{
887		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
888		return 0;
889		}
890	return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
891	}
892
893
894int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,
895	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
896	{
897	if (group->meth->point_get_affine_coordinates == 0)
898		{
899		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
900		return 0;
901		}
902	if (group->meth != point->meth)
903		{
904		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
905		return 0;
906		}
907	return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
908	}
909
910
911int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
912	const BIGNUM *x, int y_bit, BN_CTX *ctx)
913	{
914	if (group->meth->point_set_compressed_coordinates == 0)
915		{
916		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
917		return 0;
918		}
919	if (group->meth != point->meth)
920		{
921		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
922		return 0;
923		}
924	return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
925	}
926
927
928int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
929	const BIGNUM *x, int y_bit, BN_CTX *ctx)
930	{
931	if (group->meth->point_set_compressed_coordinates == 0)
932		{
933		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
934		return 0;
935		}
936	if (group->meth != point->meth)
937		{
938		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
939		return 0;
940		}
941	return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
942	}
943
944
945size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
946        unsigned char *buf, size_t len, BN_CTX *ctx)
947	{
948	if (group->meth->point2oct == 0)
949		{
950		ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
951		return 0;
952		}
953	if (group->meth != point->meth)
954		{
955		ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
956		return 0;
957		}
958	return group->meth->point2oct(group, point, form, buf, len, ctx);
959	}
960
961
962int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
963        const unsigned char *buf, size_t len, BN_CTX *ctx)
964	{
965	if (group->meth->oct2point == 0)
966		{
967		ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
968		return 0;
969		}
970	if (group->meth != point->meth)
971		{
972		ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
973		return 0;
974		}
975	return group->meth->oct2point(group, point, buf, len, ctx);
976	}
977
978
979int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
980	{
981	if (group->meth->add == 0)
982		{
983		ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
984		return 0;
985		}
986	if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth))
987		{
988		ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
989		return 0;
990		}
991	return group->meth->add(group, r, a, b, ctx);
992	}
993
994
995int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
996	{
997	if (group->meth->dbl == 0)
998		{
999		ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1000		return 0;
1001		}
1002	if ((group->meth != r->meth) || (r->meth != a->meth))
1003		{
1004		ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
1005		return 0;
1006		}
1007	return group->meth->dbl(group, r, a, ctx);
1008	}
1009
1010
1011int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
1012	{
1013	if (group->meth->invert == 0)
1014		{
1015		ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1016		return 0;
1017		}
1018	if (group->meth != a->meth)
1019		{
1020		ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
1021		return 0;
1022		}
1023	return group->meth->invert(group, a, ctx);
1024	}
1025
1026
1027int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
1028	{
1029	if (group->meth->is_at_infinity == 0)
1030		{
1031		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1032		return 0;
1033		}
1034	if (group->meth != point->meth)
1035		{
1036		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
1037		return 0;
1038		}
1039	return group->meth->is_at_infinity(group, point);
1040	}
1041
1042
1043/*
1044 * Check whether an EC_POINT is on the curve or not. Note that the return
1045 * value for this function should NOT be treated as a boolean. Return values:
1046 *  1: The point is on the curve
1047 *  0: The point is not on the curve
1048 * -1: An error occurred
1049 */
1050int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
1051                         BN_CTX *ctx)
1052	{
1053	if (group->meth->is_on_curve == 0)
1054		{
1055		ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1056		return 0;
1057		}
1058	if (group->meth != point->meth)
1059		{
1060		ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
1061		return 0;
1062		}
1063	return group->meth->is_on_curve(group, point, ctx);
1064	}
1065
1066
1067int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
1068	{
1069	if (group->meth->point_cmp == 0)
1070		{
1071		ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1072		return -1;
1073		}
1074	if ((group->meth != a->meth) || (a->meth != b->meth))
1075		{
1076		ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
1077		return -1;
1078		}
1079	return group->meth->point_cmp(group, a, b, ctx);
1080	}
1081
1082
1083int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1084	{
1085	if (group->meth->make_affine == 0)
1086		{
1087		ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1088		return 0;
1089		}
1090	if (group->meth != point->meth)
1091		{
1092		ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1093		return 0;
1094		}
1095	return group->meth->make_affine(group, point, ctx);
1096	}
1097
1098
1099int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
1100	{
1101	size_t i;
1102
1103	if (group->meth->points_make_affine == 0)
1104		{
1105		ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1106		return 0;
1107		}
1108	for (i = 0; i < num; i++)
1109		{
1110		if (group->meth != points[i]->meth)
1111			{
1112			ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1113			return 0;
1114			}
1115		}
1116	return group->meth->points_make_affine(group, num, points, ctx);
1117	}
1118
1119
1120/* Functions for point multiplication.
1121 *
1122 * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c;
1123 * otherwise we dispatch through methods.
1124 */
1125
1126int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1127	size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
1128	{
1129	if (group->meth->mul == 0)
1130		/* use default */
1131		return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
1132
1133	return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
1134	}
1135
1136int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1137	const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
1138	{
1139	/* just a convenient interface to EC_POINTs_mul() */
1140
1141	const EC_POINT *points[1];
1142	const BIGNUM *scalars[1];
1143
1144	points[0] = point;
1145	scalars[0] = p_scalar;
1146
1147	return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx);
1148	}
1149
1150int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1151	{
1152	if (group->meth->mul == 0)
1153		/* use default */
1154		return ec_wNAF_precompute_mult(group, ctx);
1155
1156	if (group->meth->precompute_mult != 0)
1157		return group->meth->precompute_mult(group, ctx);
1158	else
1159		return 1; /* nothing to do, so report success */
1160	}
1161
1162int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
1163	{
1164	if (group->meth->mul == 0)
1165		/* use default */
1166		return ec_wNAF_have_precompute_mult(group);
1167
1168	if (group->meth->have_precompute_mult != 0)
1169		return group->meth->have_precompute_mult(group);
1170	else
1171		return 0; /* cannot tell whether precomputation has been performed */
1172	}
1173