• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
71  static const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
72  
73  
74  /* functions for EC_GROUP objects */
75  
EC_GROUP_new(const EC_METHOD * meth)76  EC_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  
EC_GROUP_free(EC_GROUP * group)123  void 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  
EC_GROUP_clear_free(EC_GROUP * group)144  void 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  
EC_GROUP_copy(EC_GROUP * dest,const EC_GROUP * src)171  int 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  
EC_GROUP_dup(const EC_GROUP * a)250  EC_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  
EC_GROUP_method_of(const EC_GROUP * group)272  const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
273  	{
274  	return group->meth;
275  	}
276  
277  
EC_METHOD_get_field_type(const EC_METHOD * meth)278  int EC_METHOD_get_field_type(const EC_METHOD *meth)
279          {
280          return meth->field_type;
281          }
282  
283  
EC_GROUP_set_generator(EC_GROUP * group,const EC_POINT * generator,const BIGNUM * order,const BIGNUM * cofactor)284  int 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  
EC_GROUP_get0_generator(const EC_GROUP * group)313  const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
314  	{
315  	return group->generator;
316  	}
317  
318  
EC_GROUP_get_order(const EC_GROUP * group,BIGNUM * order,BN_CTX * ctx)319  int 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  
EC_GROUP_get_cofactor(const EC_GROUP * group,BIGNUM * cofactor,BN_CTX * ctx)328  int 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  
EC_GROUP_set_curve_name(EC_GROUP * group,int nid)337  void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
338  	{
339  	group->curve_name = nid;
340  	}
341  
342  
EC_GROUP_get_curve_name(const EC_GROUP * group)343  int EC_GROUP_get_curve_name(const EC_GROUP *group)
344  	{
345  	return group->curve_name;
346  	}
347  
348  
EC_GROUP_set_asn1_flag(EC_GROUP * group,int flag)349  void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
350  	{
351  	group->asn1_flag = flag;
352  	}
353  
354  
EC_GROUP_get_asn1_flag(const EC_GROUP * group)355  int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
356  	{
357  	return group->asn1_flag;
358  	}
359  
360  
EC_GROUP_set_point_conversion_form(EC_GROUP * group,point_conversion_form_t form)361  void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
362                                          point_conversion_form_t form)
363  	{
364  	group->asn1_form = form;
365  	}
366  
367  
EC_GROUP_get_point_conversion_form(const EC_GROUP * group)368  point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group)
369  	{
370  	return group->asn1_form;
371  	}
372  
373  
EC_GROUP_set_seed(EC_GROUP * group,const unsigned char * p,size_t len)374  size_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  
EC_GROUP_get0_seed(const EC_GROUP * group)395  unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
396  	{
397  	return group->seed;
398  	}
399  
400  
EC_GROUP_get_seed_len(const EC_GROUP * group)401  size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
402  	{
403  	return group->seed_len;
404  	}
405  
406  
EC_GROUP_set_curve_GFp(EC_GROUP * group,const BIGNUM * p,const BIGNUM * a,const BIGNUM * b,BN_CTX * ctx)407  int 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  
EC_GROUP_get_curve_GFp(const EC_GROUP * group,BIGNUM * p,BIGNUM * a,BIGNUM * b,BN_CTX * ctx)418  int 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  
EC_GROUP_set_curve_GF2m(EC_GROUP * group,const BIGNUM * p,const BIGNUM * a,const BIGNUM * b,BN_CTX * ctx)429  int 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  
EC_GROUP_get_curve_GF2m(const EC_GROUP * group,BIGNUM * p,BIGNUM * a,BIGNUM * b,BN_CTX * ctx)440  int 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  
EC_GROUP_get_degree(const EC_GROUP * group)451  int 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  
EC_GROUP_check_discriminant(const EC_GROUP * group,BN_CTX * ctx)462  int 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  
EC_GROUP_cmp(const EC_GROUP * a,const EC_GROUP * b,BN_CTX * ctx)473  int 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 */
EC_EX_DATA_set_data(EC_EXTRA_DATA ** ex_data,void * data,void * (* dup_func)(void *),void (* free_func)(void *),void (* clear_free_func)(void *))549  int 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 */
EC_EX_DATA_get_data(const EC_EXTRA_DATA * ex_data,void * (* dup_func)(void *),void (* free_func)(void *),void (* clear_free_func)(void *))586  void *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 */
EC_EX_DATA_free_data(EC_EXTRA_DATA ** ex_data,void * (* dup_func)(void *),void (* free_func)(void *),void (* clear_free_func)(void *))601  void 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 */
EC_EX_DATA_clear_free_data(EC_EXTRA_DATA ** ex_data,void * (* dup_func)(void *),void (* free_func)(void *),void (* clear_free_func)(void *))625  void 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 */
EC_EX_DATA_free_all_data(EC_EXTRA_DATA ** ex_data)649  void 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 */
EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA ** ex_data)670  void 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  
EC_POINT_new(const EC_GROUP * group)693  EC_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  
EC_POINT_free(EC_POINT * point)727  void 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  
EC_POINT_clear_free(EC_POINT * point)737  void 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  
EC_POINT_copy(EC_POINT * dest,const EC_POINT * src)750  int 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  
EC_POINT_dup(const EC_POINT * a,const EC_GROUP * group)768  EC_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  
EC_POINT_method_of(const EC_POINT * point)787  const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
788  	{
789  	return point->meth;
790  	}
791  
792  
EC_POINT_set_to_infinity(const EC_GROUP * group,EC_POINT * point)793  int 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  
EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,const BIGNUM * z,BN_CTX * ctx)809  int 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  
EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BIGNUM * z,BN_CTX * ctx)826  int 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  
EC_POINT_set_affine_coordinates_GFp(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,BN_CTX * ctx)843  int 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  
EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,BN_CTX * ctx)860  int 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  
EC_POINT_get_affine_coordinates_GFp(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BN_CTX * ctx)877  int 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  
EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BN_CTX * ctx)894  int 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  
EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,int y_bit,BN_CTX * ctx)911  int 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  
EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,int y_bit,BN_CTX * ctx)928  int 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  
EC_POINT_point2oct(const EC_GROUP * group,const EC_POINT * point,point_conversion_form_t form,unsigned char * buf,size_t len,BN_CTX * ctx)945  size_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  
EC_POINT_oct2point(const EC_GROUP * group,EC_POINT * point,const unsigned char * buf,size_t len,BN_CTX * ctx)962  int 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  
EC_POINT_add(const EC_GROUP * group,EC_POINT * r,const EC_POINT * a,const EC_POINT * b,BN_CTX * ctx)979  int 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  
EC_POINT_dbl(const EC_GROUP * group,EC_POINT * r,const EC_POINT * a,BN_CTX * ctx)995  int 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  
EC_POINT_invert(const EC_GROUP * group,EC_POINT * a,BN_CTX * ctx)1011  int 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  
EC_POINT_is_at_infinity(const EC_GROUP * group,const EC_POINT * point)1027  int 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  
EC_POINT_is_on_curve(const EC_GROUP * group,const EC_POINT * point,BN_CTX * ctx)1043  int 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  
EC_POINT_cmp(const EC_GROUP * group,const EC_POINT * a,const EC_POINT * b,BN_CTX * ctx)1059  int 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  
EC_POINT_make_affine(const EC_GROUP * group,EC_POINT * point,BN_CTX * ctx)1075  int 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  
EC_POINTs_make_affine(const EC_GROUP * group,size_t num,EC_POINT * points[],BN_CTX * ctx)1091  int 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  
EC_POINTs_mul(const EC_GROUP * group,EC_POINT * r,const BIGNUM * scalar,size_t num,const EC_POINT * points[],const BIGNUM * scalars[],BN_CTX * ctx)1118  int 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  
EC_POINT_mul(const EC_GROUP * group,EC_POINT * r,const BIGNUM * g_scalar,const EC_POINT * point,const BIGNUM * p_scalar,BN_CTX * ctx)1128  int 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  
EC_GROUP_precompute_mult(EC_GROUP * group,BN_CTX * ctx)1142  int 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  
EC_GROUP_have_precompute_mult(const EC_GROUP * group)1154  int 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