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#ifndef OPENSSL_NO_EC2M
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#endif
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#ifndef OPENSSL_NO_EC2M
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#endif
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#ifndef OPENSSL_NO_EC2M
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#endif
910
911int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
912	{
913	if (group->meth->add == 0)
914		{
915		ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
916		return 0;
917		}
918	if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth))
919		{
920		ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
921		return 0;
922		}
923	return group->meth->add(group, r, a, b, ctx);
924	}
925
926
927int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
928	{
929	if (group->meth->dbl == 0)
930		{
931		ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
932		return 0;
933		}
934	if ((group->meth != r->meth) || (r->meth != a->meth))
935		{
936		ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
937		return 0;
938		}
939	return group->meth->dbl(group, r, a, ctx);
940	}
941
942
943int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
944	{
945	if (group->meth->dbl == 0)
946		{
947		ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
948		return 0;
949		}
950	if (group->meth != a->meth)
951		{
952		ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
953		return 0;
954		}
955	return group->meth->invert(group, a, ctx);
956	}
957
958
959int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
960	{
961	if (group->meth->is_at_infinity == 0)
962		{
963		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
964		return 0;
965		}
966	if (group->meth != point->meth)
967		{
968		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
969		return 0;
970		}
971	return group->meth->is_at_infinity(group, point);
972	}
973
974
975int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
976	{
977	if (group->meth->is_on_curve == 0)
978		{
979		ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
980		return 0;
981		}
982	if (group->meth != point->meth)
983		{
984		ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
985		return 0;
986		}
987	return group->meth->is_on_curve(group, point, ctx);
988	}
989
990
991int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
992	{
993	if (group->meth->point_cmp == 0)
994		{
995		ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
996		return 0;
997		}
998	if ((group->meth != a->meth) || (a->meth != b->meth))
999		{
1000		ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
1001		return 0;
1002		}
1003	return group->meth->point_cmp(group, a, b, ctx);
1004	}
1005
1006
1007int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1008	{
1009	if (group->meth->make_affine == 0)
1010		{
1011		ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1012		return 0;
1013		}
1014	if (group->meth != point->meth)
1015		{
1016		ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1017		return 0;
1018		}
1019	return group->meth->make_affine(group, point, ctx);
1020	}
1021
1022
1023int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
1024	{
1025	size_t i;
1026
1027	if (group->meth->points_make_affine == 0)
1028		{
1029		ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1030		return 0;
1031		}
1032	for (i = 0; i < num; i++)
1033		{
1034		if (group->meth != points[i]->meth)
1035			{
1036			ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1037			return 0;
1038			}
1039		}
1040	return group->meth->points_make_affine(group, num, points, ctx);
1041	}
1042
1043
1044/* Functions for point multiplication.
1045 *
1046 * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c;
1047 * otherwise we dispatch through methods.
1048 */
1049
1050int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1051	size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
1052	{
1053	if (group->meth->mul == 0)
1054		/* use default */
1055		return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
1056
1057	return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
1058	}
1059
1060int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1061	const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
1062	{
1063	/* just a convenient interface to EC_POINTs_mul() */
1064
1065	const EC_POINT *points[1];
1066	const BIGNUM *scalars[1];
1067
1068	points[0] = point;
1069	scalars[0] = p_scalar;
1070
1071	return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx);
1072	}
1073
1074int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1075	{
1076	if (group->meth->mul == 0)
1077		/* use default */
1078		return ec_wNAF_precompute_mult(group, ctx);
1079
1080	if (group->meth->precompute_mult != 0)
1081		return group->meth->precompute_mult(group, ctx);
1082	else
1083		return 1; /* nothing to do, so report success */
1084	}
1085
1086int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
1087	{
1088	if (group->meth->mul == 0)
1089		/* use default */
1090		return ec_wNAF_have_precompute_mult(group);
1091
1092	if (group->meth->have_precompute_mult != 0)
1093		return group->meth->have_precompute_mult(group);
1094	else
1095		return 0; /* cannot tell whether precomputation has been performed */
1096	}
1097