1/* crypto/ec/ec_lib.c */
2/* ====================================================================
3 * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in
14 *    the documentation and/or other materials provided with the
15 *    distribution.
16 *
17 * 3. All advertising materials mentioning features or use of this
18 *    software must display the following acknowledgment:
19 *    "This product includes software developed by the OpenSSL Project
20 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21 *
22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23 *    endorse or promote products derived from this software without
24 *    prior written permission. For written permission, please contact
25 *    openssl-core@openssl.org.
26 *
27 * 5. Products derived from this software may not be called "OpenSSL"
28 *    nor may "OpenSSL" appear in their names without prior written
29 *    permission of the OpenSSL Project.
30 *
31 * 6. Redistributions of any form whatsoever must retain the following
32 *    acknowledgment:
33 *    "This product includes software developed by the OpenSSL Project
34 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 * OF THE POSSIBILITY OF SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This product includes cryptographic software written by Eric Young
51 * (eay@cryptsoft.com).  This product includes software written by Tim
52 * Hudson (tjh@cryptsoft.com).
53 *
54 */
55
56#include <string.h>
57
58#include <openssl/err.h>
59#include <openssl/opensslv.h>
60
61#include "ec_lcl.h"
62
63static const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
64
65
66/* functions for EC_GROUP objects */
67
68EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
69	{
70	EC_GROUP *ret;
71
72	if (meth == NULL)
73		{
74		ECerr(EC_F_EC_GROUP_NEW, ERR_R_PASSED_NULL_PARAMETER);
75		return NULL;
76		}
77	if (meth->group_init == 0)
78		{
79		ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
80		return NULL;
81		}
82
83	ret = OPENSSL_malloc(sizeof *ret);
84	if (ret == NULL)
85		{
86		ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
87		return NULL;
88		}
89
90	ret->meth = meth;
91
92	ret->extra_data = NULL;
93	ret->extra_data_dup_func = 0;
94	ret->extra_data_free_func = 0;
95	ret->extra_data_clear_free_func = 0;
96
97	if (!meth->group_init(ret))
98		{
99		OPENSSL_free(ret);
100		return NULL;
101		}
102
103	return ret;
104	}
105
106
107void EC_GROUP_free(EC_GROUP *group)
108	{
109	if (!group) return;
110
111	if (group->meth->group_finish != 0)
112		group->meth->group_finish(group);
113
114	EC_GROUP_free_extra_data(group);
115
116	OPENSSL_free(group);
117	}
118
119
120void EC_GROUP_clear_free(EC_GROUP *group)
121	{
122	if (!group) return;
123
124	if (group->meth->group_clear_finish != 0)
125		group->meth->group_clear_finish(group);
126	else if (group->meth != NULL && group->meth->group_finish != 0)
127		group->meth->group_finish(group);
128
129	EC_GROUP_clear_free_extra_data(group);
130
131	OPENSSL_cleanse(group, sizeof *group);
132	OPENSSL_free(group);
133	}
134
135
136int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
137	{
138	if (dest->meth->group_copy == 0)
139		{
140		ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
141		return 0;
142		}
143	if (dest->meth != src->meth)
144		{
145		ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
146		return 0;
147		}
148	if (dest == src)
149		return 1;
150
151	EC_GROUP_clear_free_extra_data(dest);
152	if (src->extra_data_dup_func)
153		{
154		if (src->extra_data != NULL)
155			{
156			dest->extra_data = src->extra_data_dup_func(src->extra_data);
157			if (dest->extra_data == NULL)
158				return 0;
159			}
160
161		dest->extra_data_dup_func = src->extra_data_dup_func;
162		dest->extra_data_free_func = src->extra_data_free_func;
163		dest->extra_data_clear_free_func = src->extra_data_clear_free_func;
164		}
165
166	return dest->meth->group_copy(dest, src);
167	}
168
169
170const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
171	{
172	return group->meth;
173	}
174
175
176int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
177	{
178	if (group->meth->group_set_curve_GFp == 0)
179		{
180		ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
181		return 0;
182		}
183	return group->meth->group_set_curve_GFp(group, p, a, b, ctx);
184	}
185
186
187int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
188	{
189	if (group->meth->group_get_curve_GFp == 0)
190		{
191		ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
192		return 0;
193		}
194	return group->meth->group_get_curve_GFp(group, p, a, b, ctx);
195	}
196
197
198int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
199	{
200	if (group->meth->group_set_generator == 0)
201		{
202		ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
203		return 0;
204		}
205	return group->meth->group_set_generator(group, generator, order, cofactor);
206	}
207
208
209EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
210	{
211	if (group->meth->group_get0_generator == 0)
212		{
213		ECerr(EC_F_EC_GROUP_GET0_GENERATOR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
214		return 0;
215		}
216	return group->meth->group_get0_generator(group);
217	}
218
219
220int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
221	{
222	if (group->meth->group_get_order == 0)
223		{
224		ECerr(EC_F_EC_GROUP_GET_ORDER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
225		return 0;
226		}
227	return group->meth->group_get_order(group, order, ctx);
228	}
229
230
231int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
232	{
233	if (group->meth->group_get_cofactor == 0)
234		{
235		ECerr(EC_F_EC_GROUP_GET_COFACTOR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
236		return 0;
237		}
238	return group->meth->group_get_cofactor(group, cofactor, ctx);
239	}
240
241
242/* this has 'package' visibility */
243int EC_GROUP_set_extra_data(EC_GROUP *group, void *extra_data, void *(*extra_data_dup_func)(void *),
244	void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *))
245	{
246	if ((group->extra_data != NULL)
247		|| (group->extra_data_dup_func != 0)
248		|| (group->extra_data_free_func != 0)
249		|| (group->extra_data_clear_free_func != 0))
250		{
251		ECerr(EC_F_EC_GROUP_SET_EXTRA_DATA, EC_R_SLOT_FULL);
252		return 0;
253		}
254
255	group->extra_data = extra_data;
256	group->extra_data_dup_func = extra_data_dup_func;
257	group->extra_data_free_func = extra_data_free_func;
258	group->extra_data_clear_free_func = extra_data_clear_free_func;
259	return 1;
260	}
261
262
263/* this has 'package' visibility */
264void *EC_GROUP_get_extra_data(const EC_GROUP *group, void *(*extra_data_dup_func)(void *),
265	void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *))
266	{
267	if ((group->extra_data_dup_func != extra_data_dup_func)
268		|| (group->extra_data_free_func != extra_data_free_func)
269		|| (group->extra_data_clear_free_func != extra_data_clear_free_func))
270		{
271#if 0 /* this was an error in 0.9.7, but that does not make a lot of sense */
272		ECerr(..._F_EC_GROUP_GET_EXTRA_DATA, ..._R_NO_SUCH_EXTRA_DATA);
273#endif
274		return NULL;
275		}
276
277	return group->extra_data;
278	}
279
280
281/* this has 'package' visibility */
282void EC_GROUP_free_extra_data(EC_GROUP *group)
283	{
284	if (group->extra_data_free_func)
285		group->extra_data_free_func(group->extra_data);
286	group->extra_data = NULL;
287	group->extra_data_dup_func = 0;
288	group->extra_data_free_func = 0;
289	group->extra_data_clear_free_func = 0;
290	}
291
292
293/* this has 'package' visibility */
294void EC_GROUP_clear_free_extra_data(EC_GROUP *group)
295	{
296	if (group->extra_data_clear_free_func)
297		group->extra_data_clear_free_func(group->extra_data);
298	else if (group->extra_data_free_func)
299		group->extra_data_free_func(group->extra_data);
300	group->extra_data = NULL;
301	group->extra_data_dup_func = 0;
302	group->extra_data_free_func = 0;
303	group->extra_data_clear_free_func = 0;
304	}
305
306
307
308/* functions for EC_POINT objects */
309
310EC_POINT *EC_POINT_new(const EC_GROUP *group)
311	{
312	EC_POINT *ret;
313
314	if (group == NULL)
315		{
316		ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
317		return NULL;
318		}
319	if (group->meth->point_init == 0)
320		{
321		ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
322		return NULL;
323		}
324
325	ret = OPENSSL_malloc(sizeof *ret);
326	if (ret == NULL)
327		{
328		ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
329		return NULL;
330		}
331
332	ret->meth = group->meth;
333
334	if (!ret->meth->point_init(ret))
335		{
336		OPENSSL_free(ret);
337		return NULL;
338		}
339
340	return ret;
341	}
342
343
344void EC_POINT_free(EC_POINT *point)
345	{
346	if (!point) return;
347
348	if (point->meth->point_finish != 0)
349		point->meth->point_finish(point);
350	OPENSSL_free(point);
351	}
352
353
354void EC_POINT_clear_free(EC_POINT *point)
355	{
356	if (!point) return;
357
358	if (point->meth->point_clear_finish != 0)
359		point->meth->point_clear_finish(point);
360	else if (point->meth != NULL && point->meth->point_finish != 0)
361		point->meth->point_finish(point);
362	OPENSSL_cleanse(point, sizeof *point);
363	OPENSSL_free(point);
364	}
365
366
367int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
368	{
369	if (dest->meth->point_copy == 0)
370		{
371		ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
372		return 0;
373		}
374	if (dest->meth != src->meth)
375		{
376		ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
377		return 0;
378		}
379	if (dest == src)
380		return 1;
381	return dest->meth->point_copy(dest, src);
382	}
383
384
385const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
386	{
387	return point->meth;
388	}
389
390
391int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
392	{
393	if (group->meth->point_set_to_infinity == 0)
394		{
395		ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
396		return 0;
397		}
398	if (group->meth != point->meth)
399		{
400		ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
401		return 0;
402		}
403	return group->meth->point_set_to_infinity(group, point);
404	}
405
406
407int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
408	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
409	{
410	if (group->meth->point_set_Jprojective_coordinates_GFp == 0)
411		{
412		ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
413		return 0;
414		}
415	if (group->meth != point->meth)
416		{
417		ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
418		return 0;
419		}
420	return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
421	}
422
423
424int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
425	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
426	{
427	if (group->meth->point_get_Jprojective_coordinates_GFp == 0)
428		{
429		ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
430		return 0;
431		}
432	if (group->meth != point->meth)
433		{
434		ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
435		return 0;
436		}
437	return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
438	}
439
440
441int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
442	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
443	{
444	if (group->meth->point_set_affine_coordinates_GFp == 0)
445		{
446		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
447		return 0;
448		}
449	if (group->meth != point->meth)
450		{
451		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
452		return 0;
453		}
454	return group->meth->point_set_affine_coordinates_GFp(group, point, x, y, ctx);
455	}
456
457
458int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
459	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
460	{
461	if (group->meth->point_get_affine_coordinates_GFp == 0)
462		{
463		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
464		return 0;
465		}
466	if (group->meth != point->meth)
467		{
468		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
469		return 0;
470		}
471	return group->meth->point_get_affine_coordinates_GFp(group, point, x, y, ctx);
472	}
473
474
475int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
476	const BIGNUM *x, int y_bit, BN_CTX *ctx)
477	{
478	if (group->meth->point_set_compressed_coordinates_GFp == 0)
479		{
480		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
481		return 0;
482		}
483	if (group->meth != point->meth)
484		{
485		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
486		return 0;
487		}
488	return group->meth->point_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx);
489	}
490
491
492size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
493        unsigned char *buf, size_t len, BN_CTX *ctx)
494	{
495	if (group->meth->point2oct == 0)
496		{
497		ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
498		return 0;
499		}
500	if (group->meth != point->meth)
501		{
502		ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
503		return 0;
504		}
505	return group->meth->point2oct(group, point, form, buf, len, ctx);
506	}
507
508
509int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
510        const unsigned char *buf, size_t len, BN_CTX *ctx)
511	{
512	if (group->meth->oct2point == 0)
513		{
514		ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
515		return 0;
516		}
517	if (group->meth != point->meth)
518		{
519		ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
520		return 0;
521		}
522	return group->meth->oct2point(group, point, buf, len, ctx);
523	}
524
525
526int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
527	{
528	if (group->meth->add == 0)
529		{
530		ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
531		return 0;
532		}
533	if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth))
534		{
535		ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
536		return 0;
537		}
538	return group->meth->add(group, r, a, b, ctx);
539	}
540
541
542int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
543	{
544	if (group->meth->dbl == 0)
545		{
546		ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
547		return 0;
548		}
549	if ((group->meth != r->meth) || (r->meth != a->meth))
550		{
551		ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
552		return 0;
553		}
554	return group->meth->dbl(group, r, a, ctx);
555	}
556
557
558int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
559	{
560	if (group->meth->dbl == 0)
561		{
562		ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
563		return 0;
564		}
565	if (group->meth != a->meth)
566		{
567		ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
568		return 0;
569		}
570	return group->meth->invert(group, a, ctx);
571	}
572
573
574int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
575	{
576	if (group->meth->is_at_infinity == 0)
577		{
578		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
579		return 0;
580		}
581	if (group->meth != point->meth)
582		{
583		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
584		return 0;
585		}
586	return group->meth->is_at_infinity(group, point);
587	}
588
589
590int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
591	{
592	if (group->meth->is_on_curve == 0)
593		{
594		ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
595		return 0;
596		}
597	if (group->meth != point->meth)
598		{
599		ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
600		return 0;
601		}
602	return group->meth->is_on_curve(group, point, ctx);
603	}
604
605
606int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
607	{
608	if (group->meth->point_cmp == 0)
609		{
610		ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
611		return 0;
612		}
613	if ((group->meth != a->meth) || (a->meth != b->meth))
614		{
615		ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
616		return 0;
617		}
618	return group->meth->point_cmp(group, a, b, ctx);
619	}
620
621
622int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
623	{
624	if (group->meth->make_affine == 0)
625		{
626		ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
627		return 0;
628		}
629	if (group->meth != point->meth)
630		{
631		ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
632		return 0;
633		}
634	return group->meth->make_affine(group, point, ctx);
635	}
636
637
638int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
639	{
640	size_t i;
641
642	if (group->meth->points_make_affine == 0)
643		{
644		ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
645		return 0;
646		}
647	for (i = 0; i < num; i++)
648		{
649		if (group->meth != points[i]->meth)
650			{
651			ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
652			return 0;
653			}
654		}
655	return group->meth->points_make_affine(group, num, points, ctx);
656	}
657