1/* crypto/ec/ec_lib.c */
2/*
3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in
17 *    the documentation and/or other materials provided with the
18 *    distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 *    software must display the following acknowledgment:
22 *    "This product includes software developed by the OpenSSL Project
23 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 *    endorse or promote products derived from this software without
27 *    prior written permission. For written permission, please contact
28 *    openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 *    nor may "OpenSSL" appear in their names without prior written
32 *    permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 *    acknowledgment:
36 *    "This product includes software developed by the OpenSSL Project
37 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com).  This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Binary polynomial ECC support in OpenSSL originally developed by
61 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
62 */
63
64#include <string.h>
65
66#include <openssl/err.h>
67#include <openssl/opensslv.h>
68
69#include "ec_lcl.h"
70
71static const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
72
73
74/* functions for EC_GROUP objects */
75
76EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
77	{
78	EC_GROUP *ret;
79
80	if (meth == NULL)
81		{
82		ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
83		return NULL;
84		}
85	if (meth->group_init == 0)
86		{
87		ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
88		return NULL;
89		}
90
91	ret = OPENSSL_malloc(sizeof *ret);
92	if (ret == NULL)
93		{
94		ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
95		return NULL;
96		}
97
98	ret->meth = meth;
99
100	ret->extra_data = NULL;
101
102	ret->generator = NULL;
103	BN_init(&ret->order);
104	BN_init(&ret->cofactor);
105
106	ret->curve_name = 0;
107	ret->asn1_flag  = 0;
108	ret->asn1_form  = POINT_CONVERSION_UNCOMPRESSED;
109
110	ret->seed = NULL;
111	ret->seed_len = 0;
112
113	if (!meth->group_init(ret))
114		{
115		OPENSSL_free(ret);
116		return NULL;
117		}
118
119	return ret;
120	}
121
122
123void EC_GROUP_free(EC_GROUP *group)
124	{
125	if (!group) return;
126
127	if (group->meth->group_finish != 0)
128		group->meth->group_finish(group);
129
130	EC_EX_DATA_free_all_data(&group->extra_data);
131
132	if (group->generator != NULL)
133		EC_POINT_free(group->generator);
134	BN_free(&group->order);
135	BN_free(&group->cofactor);
136
137	if (group->seed)
138		OPENSSL_free(group->seed);
139
140	OPENSSL_free(group);
141	}
142
143
144void EC_GROUP_clear_free(EC_GROUP *group)
145	{
146	if (!group) return;
147
148	if (group->meth->group_clear_finish != 0)
149		group->meth->group_clear_finish(group);
150	else if (group->meth->group_finish != 0)
151		group->meth->group_finish(group);
152
153	EC_EX_DATA_clear_free_all_data(&group->extra_data);
154
155	if (group->generator != NULL)
156		EC_POINT_clear_free(group->generator);
157	BN_clear_free(&group->order);
158	BN_clear_free(&group->cofactor);
159
160	if (group->seed)
161		{
162		OPENSSL_cleanse(group->seed, group->seed_len);
163		OPENSSL_free(group->seed);
164		}
165
166	OPENSSL_cleanse(group, sizeof *group);
167	OPENSSL_free(group);
168	}
169
170
171int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
172	{
173	EC_EXTRA_DATA *d;
174
175	if (dest->meth->group_copy == 0)
176		{
177		ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
178		return 0;
179		}
180	if (dest->meth != src->meth)
181		{
182		ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
183		return 0;
184		}
185	if (dest == src)
186		return 1;
187
188	EC_EX_DATA_free_all_data(&dest->extra_data);
189
190	for (d = src->extra_data; d != NULL; d = d->next)
191		{
192		void *t = d->dup_func(d->data);
193
194		if (t == NULL)
195			return 0;
196		if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func))
197			return 0;
198		}
199
200	if (src->generator != NULL)
201		{
202		if (dest->generator == NULL)
203			{
204			dest->generator = EC_POINT_new(dest);
205			if (dest->generator == NULL) return 0;
206			}
207		if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
208		}
209	else
210		{
211		/* src->generator == NULL */
212		if (dest->generator != NULL)
213			{
214			EC_POINT_clear_free(dest->generator);
215			dest->generator = NULL;
216			}
217		}
218
219	if (!BN_copy(&dest->order, &src->order)) return 0;
220	if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
221
222	dest->curve_name = src->curve_name;
223	dest->asn1_flag  = src->asn1_flag;
224	dest->asn1_form  = src->asn1_form;
225
226	if (src->seed)
227		{
228		if (dest->seed)
229			OPENSSL_free(dest->seed);
230		dest->seed = OPENSSL_malloc(src->seed_len);
231		if (dest->seed == NULL)
232			return 0;
233		if (!memcpy(dest->seed, src->seed, src->seed_len))
234			return 0;
235		dest->seed_len = src->seed_len;
236		}
237	else
238		{
239		if (dest->seed)
240			OPENSSL_free(dest->seed);
241		dest->seed = NULL;
242		dest->seed_len = 0;
243		}
244
245
246	return dest->meth->group_copy(dest, src);
247	}
248
249
250EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
251	{
252	EC_GROUP *t = NULL;
253	int ok = 0;
254
255	if (a == NULL) return NULL;
256
257	if ((t = EC_GROUP_new(a->meth)) == NULL) return(NULL);
258	if (!EC_GROUP_copy(t, a)) goto err;
259
260	ok = 1;
261
262  err:
263	if (!ok)
264		{
265		if (t) EC_GROUP_free(t);
266		return NULL;
267		}
268	else return t;
269	}
270
271
272const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
273	{
274	return group->meth;
275	}
276
277
278int EC_METHOD_get_field_type(const EC_METHOD *meth)
279        {
280        return meth->field_type;
281        }
282
283
284int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
285	{
286	if (generator == NULL)
287		{
288		ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
289		return 0   ;
290		}
291
292	if (group->generator == NULL)
293		{
294		group->generator = EC_POINT_new(group);
295		if (group->generator == NULL) return 0;
296		}
297	if (!EC_POINT_copy(group->generator, generator)) return 0;
298
299	if (order != NULL)
300		{ if (!BN_copy(&group->order, order)) return 0; }
301	else
302		BN_zero(&group->order);
303
304	if (cofactor != NULL)
305		{ if (!BN_copy(&group->cofactor, cofactor)) return 0; }
306	else
307		BN_zero(&group->cofactor);
308
309	return 1;
310	}
311
312
313const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
314	{
315	return group->generator;
316	}
317
318
319int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
320	{
321	if (!BN_copy(order, &group->order))
322		return 0;
323
324	return !BN_is_zero(order);
325	}
326
327
328int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
329	{
330	if (!BN_copy(cofactor, &group->cofactor))
331		return 0;
332
333	return !BN_is_zero(&group->cofactor);
334	}
335
336
337void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
338	{
339	group->curve_name = nid;
340	}
341
342
343int EC_GROUP_get_curve_name(const EC_GROUP *group)
344	{
345	return group->curve_name;
346	}
347
348
349void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
350	{
351	group->asn1_flag = flag;
352	}
353
354
355int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
356	{
357	return group->asn1_flag;
358	}
359
360
361void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
362                                        point_conversion_form_t form)
363	{
364	group->asn1_form = form;
365	}
366
367
368point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group)
369	{
370	return group->asn1_form;
371	}
372
373
374size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
375	{
376	if (group->seed)
377		{
378		OPENSSL_free(group->seed);
379		group->seed = NULL;
380		group->seed_len = 0;
381		}
382
383	if (!len || !p)
384		return 1;
385
386	if ((group->seed = OPENSSL_malloc(len)) == NULL)
387		return 0;
388	memcpy(group->seed, p, len);
389	group->seed_len = len;
390
391	return len;
392	}
393
394
395unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
396	{
397	return group->seed;
398	}
399
400
401size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
402	{
403	return group->seed_len;
404	}
405
406
407int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
408	{
409	if (group->meth->group_set_curve == 0)
410		{
411		ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
412		return 0;
413		}
414	return group->meth->group_set_curve(group, p, a, b, ctx);
415	}
416
417
418int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
419	{
420	if (group->meth->group_get_curve == 0)
421		{
422		ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
423		return 0;
424		}
425	return group->meth->group_get_curve(group, p, a, b, ctx);
426	}
427
428
429int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
430	{
431	if (group->meth->group_set_curve == 0)
432		{
433		ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
434		return 0;
435		}
436	return group->meth->group_set_curve(group, p, a, b, ctx);
437	}
438
439
440int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
441	{
442	if (group->meth->group_get_curve == 0)
443		{
444		ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
445		return 0;
446		}
447	return group->meth->group_get_curve(group, p, a, b, ctx);
448	}
449
450
451int EC_GROUP_get_degree(const EC_GROUP *group)
452	{
453	if (group->meth->group_get_degree == 0)
454		{
455		ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
456		return 0;
457		}
458	return group->meth->group_get_degree(group);
459	}
460
461
462int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
463	{
464	if (group->meth->group_check_discriminant == 0)
465		{
466		ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
467		return 0;
468		}
469	return group->meth->group_check_discriminant(group, ctx);
470	}
471
472
473int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
474	{
475	int    r = 0;
476	BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
477	BN_CTX *ctx_new = NULL;
478
479	/* compare the field types*/
480	if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
481	    EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
482		return 1;
483	/* compare the curve name (if present) */
484	if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
485	    EC_GROUP_get_curve_name(a) == EC_GROUP_get_curve_name(b))
486		return 0;
487
488	if (!ctx)
489		ctx_new = ctx = BN_CTX_new();
490	if (!ctx)
491		return -1;
492
493	BN_CTX_start(ctx);
494	a1 = BN_CTX_get(ctx);
495	a2 = BN_CTX_get(ctx);
496	a3 = BN_CTX_get(ctx);
497	b1 = BN_CTX_get(ctx);
498	b2 = BN_CTX_get(ctx);
499	b3 = BN_CTX_get(ctx);
500	if (!b3)
501		{
502		BN_CTX_end(ctx);
503		if (ctx_new)
504			BN_CTX_free(ctx);
505		return -1;
506		}
507
508	/* XXX This approach assumes that the external representation
509	 * of curves over the same field type is the same.
510	 */
511	if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
512	    !b->meth->group_get_curve(b, b1, b2, b3, ctx))
513		r = 1;
514
515	if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
516		r = 1;
517
518	/* XXX EC_POINT_cmp() assumes that the methods are equal */
519	if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
520	    EC_GROUP_get0_generator(b), ctx))
521		r = 1;
522
523	if (!r)
524		{
525		/* compare the order and cofactor */
526		if (!EC_GROUP_get_order(a, a1, ctx) ||
527		    !EC_GROUP_get_order(b, b1, ctx) ||
528		    !EC_GROUP_get_cofactor(a, a2, ctx) ||
529		    !EC_GROUP_get_cofactor(b, b2, ctx))
530			{
531			BN_CTX_end(ctx);
532			if (ctx_new)
533				BN_CTX_free(ctx);
534			return -1;
535			}
536		if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
537			r = 1;
538		}
539
540	BN_CTX_end(ctx);
541	if (ctx_new)
542		BN_CTX_free(ctx);
543
544	return r;
545	}
546
547
548/* this has 'package' visibility */
549int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
550	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
551	{
552	EC_EXTRA_DATA *d;
553
554	if (ex_data == NULL)
555		return 0;
556
557	for (d = *ex_data; d != NULL; d = d->next)
558		{
559		if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
560			{
561			ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
562			return 0;
563			}
564		}
565
566	if (data == NULL)
567		/* no explicit entry needed */
568		return 1;
569
570	d = OPENSSL_malloc(sizeof *d);
571	if (d == NULL)
572		return 0;
573
574	d->data = data;
575	d->dup_func = dup_func;
576	d->free_func = free_func;
577	d->clear_free_func = clear_free_func;
578
579	d->next = *ex_data;
580	*ex_data = d;
581
582	return 1;
583	}
584
585/* this has 'package' visibility */
586void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
587	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
588	{
589	const EC_EXTRA_DATA *d;
590
591	for (d = ex_data; d != NULL; d = d->next)
592		{
593		if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
594			return d->data;
595		}
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->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->dbl == 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
1043int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
1044	{
1045	if (group->meth->is_on_curve == 0)
1046		{
1047		ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1048		return 0;
1049		}
1050	if (group->meth != point->meth)
1051		{
1052		ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
1053		return 0;
1054		}
1055	return group->meth->is_on_curve(group, point, ctx);
1056	}
1057
1058
1059int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
1060	{
1061	if (group->meth->point_cmp == 0)
1062		{
1063		ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1064		return 0;
1065		}
1066	if ((group->meth != a->meth) || (a->meth != b->meth))
1067		{
1068		ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
1069		return 0;
1070		}
1071	return group->meth->point_cmp(group, a, b, ctx);
1072	}
1073
1074
1075int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1076	{
1077	if (group->meth->make_affine == 0)
1078		{
1079		ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1080		return 0;
1081		}
1082	if (group->meth != point->meth)
1083		{
1084		ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1085		return 0;
1086		}
1087	return group->meth->make_affine(group, point, ctx);
1088	}
1089
1090
1091int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
1092	{
1093	size_t i;
1094
1095	if (group->meth->points_make_affine == 0)
1096		{
1097		ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1098		return 0;
1099		}
1100	for (i = 0; i < num; i++)
1101		{
1102		if (group->meth != points[i]->meth)
1103			{
1104			ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1105			return 0;
1106			}
1107		}
1108	return group->meth->points_make_affine(group, num, points, ctx);
1109	}
1110
1111
1112/* Functions for point multiplication.
1113 *
1114 * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c;
1115 * otherwise we dispatch through methods.
1116 */
1117
1118int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1119	size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
1120	{
1121	if (group->meth->mul == 0)
1122		/* use default */
1123		return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
1124
1125	return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
1126	}
1127
1128int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1129	const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
1130	{
1131	/* just a convenient interface to EC_POINTs_mul() */
1132
1133	const EC_POINT *points[1];
1134	const BIGNUM *scalars[1];
1135
1136	points[0] = point;
1137	scalars[0] = p_scalar;
1138
1139	return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx);
1140	}
1141
1142int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1143	{
1144	if (group->meth->mul == 0)
1145		/* use default */
1146		return ec_wNAF_precompute_mult(group, ctx);
1147
1148	if (group->meth->precompute_mult != 0)
1149		return group->meth->precompute_mult(group, ctx);
1150	else
1151		return 1; /* nothing to do, so report success */
1152	}
1153
1154int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
1155	{
1156	if (group->meth->mul == 0)
1157		/* use default */
1158		return ec_wNAF_have_precompute_mult(group);
1159
1160	if (group->meth->have_precompute_mult != 0)
1161		return group->meth->have_precompute_mult(group);
1162	else
1163		return 0; /* cannot tell whether precomputation has been performed */
1164	}
1165