xref: /openbsd-src/lib/libcrypto/ec/ecp_methods.c (revision 6d90e0461cad04c6e59ca2c12100afa402bffed9)
1*6d90e046Stb /* $OpenBSD: ecp_methods.c,v 1.42 2025/01/25 13:15:21 tb Exp $ */
2cb3e3e66Stb /* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
3cb3e3e66Stb  * for the OpenSSL project.
4cb3e3e66Stb  * Includes code written by Bodo Moeller for the OpenSSL project.
5cb3e3e66Stb  */
6cb3e3e66Stb /* ====================================================================
7cb3e3e66Stb  * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
8cb3e3e66Stb  *
9cb3e3e66Stb  * Redistribution and use in source and binary forms, with or without
10cb3e3e66Stb  * modification, are permitted provided that the following conditions
11cb3e3e66Stb  * are met:
12cb3e3e66Stb  *
13cb3e3e66Stb  * 1. Redistributions of source code must retain the above copyright
14cb3e3e66Stb  *    notice, this list of conditions and the following disclaimer.
15cb3e3e66Stb  *
16cb3e3e66Stb  * 2. Redistributions in binary form must reproduce the above copyright
17cb3e3e66Stb  *    notice, this list of conditions and the following disclaimer in
18cb3e3e66Stb  *    the documentation and/or other materials provided with the
19cb3e3e66Stb  *    distribution.
20cb3e3e66Stb  *
21cb3e3e66Stb  * 3. All advertising materials mentioning features or use of this
22cb3e3e66Stb  *    software must display the following acknowledgment:
23cb3e3e66Stb  *    "This product includes software developed by the OpenSSL Project
24cb3e3e66Stb  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
25cb3e3e66Stb  *
26cb3e3e66Stb  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27cb3e3e66Stb  *    endorse or promote products derived from this software without
28cb3e3e66Stb  *    prior written permission. For written permission, please contact
29cb3e3e66Stb  *    openssl-core@openssl.org.
30cb3e3e66Stb  *
31cb3e3e66Stb  * 5. Products derived from this software may not be called "OpenSSL"
32cb3e3e66Stb  *    nor may "OpenSSL" appear in their names without prior written
33cb3e3e66Stb  *    permission of the OpenSSL Project.
34cb3e3e66Stb  *
35cb3e3e66Stb  * 6. Redistributions of any form whatsoever must retain the following
36cb3e3e66Stb  *    acknowledgment:
37cb3e3e66Stb  *    "This product includes software developed by the OpenSSL Project
38cb3e3e66Stb  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
39cb3e3e66Stb  *
40cb3e3e66Stb  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41cb3e3e66Stb  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42cb3e3e66Stb  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43cb3e3e66Stb  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44cb3e3e66Stb  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45cb3e3e66Stb  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46cb3e3e66Stb  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47cb3e3e66Stb  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48cb3e3e66Stb  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49cb3e3e66Stb  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50cb3e3e66Stb  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51cb3e3e66Stb  * OF THE POSSIBILITY OF SUCH DAMAGE.
52cb3e3e66Stb  * ====================================================================
53cb3e3e66Stb  *
54cb3e3e66Stb  * This product includes cryptographic software written by Eric Young
55cb3e3e66Stb  * (eay@cryptsoft.com).  This product includes software written by Tim
56cb3e3e66Stb  * Hudson (tjh@cryptsoft.com).
57cb3e3e66Stb  *
58cb3e3e66Stb  */
59cb3e3e66Stb /* ====================================================================
60cb3e3e66Stb  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
61cb3e3e66Stb  * Portions of this software developed by SUN MICROSYSTEMS, INC.,
62cb3e3e66Stb  * and contributed to the OpenSSL project.
63cb3e3e66Stb  */
64cb3e3e66Stb 
65cb3e3e66Stb #include <stdlib.h>
66cb3e3e66Stb 
67cb3e3e66Stb #include <openssl/bn.h>
68cb3e3e66Stb #include <openssl/ec.h>
69cb3e3e66Stb #include <openssl/err.h>
70cb3e3e66Stb #include <openssl/objects.h>
71cb3e3e66Stb 
72cb3e3e66Stb #include "bn_local.h"
73cb3e3e66Stb #include "ec_local.h"
74cb3e3e66Stb 
75cb3e3e66Stb /*
76bd66d9a3Stb  * Most method functions in this file are designed to work with non-trivial
77bd66d9a3Stb  * representations of field elements if necessary: while standard modular
78bd66d9a3Stb  * addition and subtraction are used, the field_mul and field_sqr methods will
79bd66d9a3Stb  * be used for multiplication, and field_encode and field_decode (if defined)
80cb3e3e66Stb  * will be used for converting between representations.
81cb3e3e66Stb  *
82bd66d9a3Stb  * The functions ec_points_make_affine() and ec_point_get_affine_coordinates()
833c24ce7eStb  * assume that if a non-trivial representation is used, it is a Montgomery
84cb3e3e66Stb  * representation (i.e. 'encoding' means multiplying by some factor R).
85cb3e3e66Stb  */
86cb3e3e66Stb 
87f6116716Stb static inline int
88f6116716Stb ec_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
89f6116716Stb     BN_CTX *ctx)
90f6116716Stb {
91f6116716Stb 	return group->meth->field_mul(group, r, a, b, ctx);
92f6116716Stb }
93f6116716Stb 
94f6116716Stb static inline int
95f6116716Stb ec_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
96f6116716Stb {
97f6116716Stb 	return group->meth->field_sqr(group, r, a, ctx);
98f6116716Stb }
99f6116716Stb 
100899705c2Stb static int
101cb3e3e66Stb ec_decode_scalar(const EC_GROUP *group, BIGNUM *bn, const BIGNUM *x, BN_CTX *ctx)
102cb3e3e66Stb {
103cb3e3e66Stb 	if (bn == NULL)
104cb3e3e66Stb 		return 1;
105cb3e3e66Stb 
106cb3e3e66Stb 	if (group->meth->field_decode != NULL)
107cb3e3e66Stb 		return group->meth->field_decode(group, bn, x, ctx);
108cb3e3e66Stb 
109cb3e3e66Stb 	return bn_copy(bn, x);
110cb3e3e66Stb }
111cb3e3e66Stb 
112cb3e3e66Stb static int
113cb3e3e66Stb ec_encode_scalar(const EC_GROUP *group, BIGNUM *bn, const BIGNUM *x, BN_CTX *ctx)
114cb3e3e66Stb {
1153c2cb882Stb 	if (!BN_nnmod(bn, x, group->p, ctx))
116cb3e3e66Stb 		return 0;
117cb3e3e66Stb 
118cb3e3e66Stb 	if (group->meth->field_encode != NULL)
119cb3e3e66Stb 		return group->meth->field_encode(group, bn, bn, ctx);
120cb3e3e66Stb 
121cb3e3e66Stb 	return 1;
122cb3e3e66Stb }
123cb3e3e66Stb 
124cb3e3e66Stb static int
125d9a83419Stb ec_group_set_curve(EC_GROUP *group,
126cb3e3e66Stb     const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
127cb3e3e66Stb {
128cb3e3e66Stb 	BIGNUM *a_plus_3;
129cb3e3e66Stb 	int ret = 0;
130cb3e3e66Stb 
131cb3e3e66Stb 	/* p must be a prime > 3 */
132cb3e3e66Stb 	if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) {
133cb3e3e66Stb 		ECerror(EC_R_INVALID_FIELD);
134cb3e3e66Stb 		return 0;
135cb3e3e66Stb 	}
136cb3e3e66Stb 
137cb3e3e66Stb 	BN_CTX_start(ctx);
138cb3e3e66Stb 
139cb3e3e66Stb 	if ((a_plus_3 = BN_CTX_get(ctx)) == NULL)
140cb3e3e66Stb 		goto err;
141cb3e3e66Stb 
1423c2cb882Stb 	if (!bn_copy(group->p, p))
143cb3e3e66Stb 		goto err;
1443c2cb882Stb 	BN_set_negative(group->p, 0);
145cb3e3e66Stb 
1463c2cb882Stb 	if (!ec_encode_scalar(group, group->a, a, ctx))
147cb3e3e66Stb 		goto err;
1483c2cb882Stb 	if (!ec_encode_scalar(group, group->b, b, ctx))
149cb3e3e66Stb 		goto err;
150cb3e3e66Stb 
151cb3e3e66Stb 	if (!BN_set_word(a_plus_3, 3))
152cb3e3e66Stb 		goto err;
1533c2cb882Stb 	if (!BN_mod_add(a_plus_3, a_plus_3, a, group->p, ctx))
154cb3e3e66Stb 		goto err;
155cb3e3e66Stb 
156cb3e3e66Stb 	group->a_is_minus3 = BN_is_zero(a_plus_3);
157cb3e3e66Stb 
158cb3e3e66Stb 	ret = 1;
159cb3e3e66Stb 
160cb3e3e66Stb  err:
161cb3e3e66Stb 	BN_CTX_end(ctx);
162cb3e3e66Stb 
163cb3e3e66Stb 	return ret;
164cb3e3e66Stb }
165cb3e3e66Stb 
166899705c2Stb static int
1673c24ce7eStb ec_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
1683c24ce7eStb     BN_CTX *ctx)
169cb3e3e66Stb {
170cb3e3e66Stb 	if (p != NULL) {
1713c2cb882Stb 		if (!bn_copy(p, group->p))
172cb3e3e66Stb 			return 0;
173cb3e3e66Stb 	}
1743c2cb882Stb 	if (!ec_decode_scalar(group, a, group->a, ctx))
175cb3e3e66Stb 		return 0;
1763c2cb882Stb 	if (!ec_decode_scalar(group, b, group->b, ctx))
177cb3e3e66Stb 		return 0;
178cb3e3e66Stb 
179cb3e3e66Stb 	return 1;
180cb3e3e66Stb }
181cb3e3e66Stb 
182899705c2Stb static int
1834fb59ff9Stb ec_point_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
184bbf457e4Stb {
185bbf457e4Stb 	BIGNUM *rh, *tmp, *Z4, *Z6;
186bbf457e4Stb 	int ret = -1;
187bbf457e4Stb 
188bbf457e4Stb 	if (EC_POINT_is_at_infinity(group, point))
189bbf457e4Stb 		return 1;
190bbf457e4Stb 
191bbf457e4Stb 	BN_CTX_start(ctx);
192bbf457e4Stb 
193bbf457e4Stb 	if ((rh = BN_CTX_get(ctx)) == NULL)
194bbf457e4Stb 		goto err;
195bbf457e4Stb 	if ((tmp = BN_CTX_get(ctx)) == NULL)
196bbf457e4Stb 		goto err;
197bbf457e4Stb 	if ((Z4 = BN_CTX_get(ctx)) == NULL)
198bbf457e4Stb 		goto err;
199bbf457e4Stb 	if ((Z6 = BN_CTX_get(ctx)) == NULL)
200bbf457e4Stb 		goto err;
201bbf457e4Stb 
202bbf457e4Stb 	/*
2037b995231Stb 	 * The curve is defined by a Weierstrass equation y^2 = x^3 + a*x + b.
2047b995231Stb 	 * The point is given in Jacobian projective coordinates where (X, Y, Z)
2057b995231Stb 	 * represents (x, y) = (X/Z^2, Y/Z^3). Substituting this and multiplying
2067b995231Stb 	 * by Z^6 transforms the above into Y^2 = X^3 + a*X*Z^4 + b*Z^6.
207bbf457e4Stb 	 */
208bbf457e4Stb 
209bbf457e4Stb 	/* rh := X^2 */
210f6116716Stb 	if (!ec_field_sqr(group, rh, point->X, ctx))
211bbf457e4Stb 		goto err;
212bbf457e4Stb 
213bbf457e4Stb 	if (!point->Z_is_one) {
214f6116716Stb 		if (!ec_field_sqr(group, tmp, point->Z, ctx))
215bbf457e4Stb 			goto err;
216f6116716Stb 		if (!ec_field_sqr(group, Z4, tmp, ctx))
217bbf457e4Stb 			goto err;
218f6116716Stb 		if (!ec_field_mul(group, Z6, Z4, tmp, ctx))
219bbf457e4Stb 			goto err;
220bbf457e4Stb 
221bbf457e4Stb 		/* rh := (rh + a*Z^4)*X */
222bbf457e4Stb 		if (group->a_is_minus3) {
223d6f80948Stb 			if (!BN_mod_lshift1_quick(tmp, Z4, group->p))
224bbf457e4Stb 				goto err;
225d6f80948Stb 			if (!BN_mod_add_quick(tmp, tmp, Z4, group->p))
226bbf457e4Stb 				goto err;
227d6f80948Stb 			if (!BN_mod_sub_quick(rh, rh, tmp, group->p))
228bbf457e4Stb 				goto err;
229f6116716Stb 			if (!ec_field_mul(group, rh, rh, point->X, ctx))
230bbf457e4Stb 				goto err;
231bbf457e4Stb 		} else {
232f6116716Stb 			if (!ec_field_mul(group, tmp, Z4, group->a, ctx))
233bbf457e4Stb 				goto err;
234d6f80948Stb 			if (!BN_mod_add_quick(rh, rh, tmp, group->p))
235bbf457e4Stb 				goto err;
236f6116716Stb 			if (!ec_field_mul(group, rh, rh, point->X, ctx))
237bbf457e4Stb 				goto err;
238bbf457e4Stb 		}
239bbf457e4Stb 
240bbf457e4Stb 		/* rh := rh + b*Z^6 */
241f6116716Stb 		if (!ec_field_mul(group, tmp, group->b, Z6, ctx))
242bbf457e4Stb 			goto err;
243d6f80948Stb 		if (!BN_mod_add_quick(rh, rh, tmp, group->p))
244bbf457e4Stb 			goto err;
245bbf457e4Stb 	} else {
246bbf457e4Stb 		/* point->Z_is_one */
247bbf457e4Stb 
248bbf457e4Stb 		/* rh := (rh + a)*X */
249d6f80948Stb 		if (!BN_mod_add_quick(rh, rh, group->a, group->p))
250bbf457e4Stb 			goto err;
251f6116716Stb 		if (!ec_field_mul(group, rh, rh, point->X, ctx))
252bbf457e4Stb 			goto err;
253bbf457e4Stb 		/* rh := rh + b */
254d6f80948Stb 		if (!BN_mod_add_quick(rh, rh, group->b, group->p))
255bbf457e4Stb 			goto err;
256bbf457e4Stb 	}
257bbf457e4Stb 
258bbf457e4Stb 	/* 'lh' := Y^2 */
259f6116716Stb 	if (!ec_field_sqr(group, tmp, point->Y, ctx))
260bbf457e4Stb 		goto err;
261bbf457e4Stb 
262bbf457e4Stb 	ret = (0 == BN_ucmp(tmp, rh));
263bbf457e4Stb 
264bbf457e4Stb  err:
265bbf457e4Stb 	BN_CTX_end(ctx);
266bbf457e4Stb 
267bbf457e4Stb 	return ret;
268bbf457e4Stb }
269bbf457e4Stb 
270bbf457e4Stb /*
271bbf457e4Stb  * Returns -1 on error, 0 if the points are equal, 1 if the points are distinct.
272bbf457e4Stb  */
273bbf457e4Stb 
274bbf457e4Stb static int
2754fb59ff9Stb ec_point_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
2764fb59ff9Stb     BN_CTX *ctx)
277bbf457e4Stb {
278bbf457e4Stb 	BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
279bbf457e4Stb 	const BIGNUM *tmp1_, *tmp2_;
280bbf457e4Stb 	int ret = -1;
281bbf457e4Stb 
282bbf457e4Stb 	if (EC_POINT_is_at_infinity(group, a) && EC_POINT_is_at_infinity(group, b))
283bbf457e4Stb 		return 0;
284bbf457e4Stb 	if (EC_POINT_is_at_infinity(group, a) || EC_POINT_is_at_infinity(group, b))
285bbf457e4Stb 		return 1;
286bbf457e4Stb 
287bbf457e4Stb 	if (a->Z_is_one && b->Z_is_one)
288bbf457e4Stb 		return BN_cmp(a->X, b->X) != 0 || BN_cmp(a->Y, b->Y) != 0;
289bbf457e4Stb 
290bbf457e4Stb 	BN_CTX_start(ctx);
291bbf457e4Stb 
292bbf457e4Stb 	if ((tmp1 = BN_CTX_get(ctx)) == NULL)
293bbf457e4Stb 		goto end;
294bbf457e4Stb 	if ((tmp2 = BN_CTX_get(ctx)) == NULL)
295bbf457e4Stb 		goto end;
296bbf457e4Stb 	if ((Za23 = BN_CTX_get(ctx)) == NULL)
297bbf457e4Stb 		goto end;
298bbf457e4Stb 	if ((Zb23 = BN_CTX_get(ctx)) == NULL)
299bbf457e4Stb 		goto end;
300bbf457e4Stb 
301bbf457e4Stb 	/*
302c852d338Stb 	 * Decide whether (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3), or
303c852d338Stb 	 * equivalently, (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
304bbf457e4Stb 	 */
305bbf457e4Stb 
306bbf457e4Stb 	if (!b->Z_is_one) {
307f6116716Stb 		if (!ec_field_sqr(group, Zb23, b->Z, ctx))
308bbf457e4Stb 			goto end;
309f6116716Stb 		if (!ec_field_mul(group, tmp1, a->X, Zb23, ctx))
310bbf457e4Stb 			goto end;
311bbf457e4Stb 		tmp1_ = tmp1;
312bbf457e4Stb 	} else
313bbf457e4Stb 		tmp1_ = a->X;
314bbf457e4Stb 	if (!a->Z_is_one) {
315f6116716Stb 		if (!ec_field_sqr(group, Za23, a->Z, ctx))
316bbf457e4Stb 			goto end;
317f6116716Stb 		if (!ec_field_mul(group, tmp2, b->X, Za23, ctx))
318bbf457e4Stb 			goto end;
319bbf457e4Stb 		tmp2_ = tmp2;
320bbf457e4Stb 	} else
321bbf457e4Stb 		tmp2_ = b->X;
322bbf457e4Stb 
323bbf457e4Stb 	/* compare  X_a*Z_b^2  with  X_b*Z_a^2 */
324bbf457e4Stb 	if (BN_cmp(tmp1_, tmp2_) != 0) {
325bbf457e4Stb 		ret = 1;	/* points differ */
326bbf457e4Stb 		goto end;
327bbf457e4Stb 	}
328bbf457e4Stb 	if (!b->Z_is_one) {
329f6116716Stb 		if (!ec_field_mul(group, Zb23, Zb23, b->Z, ctx))
330bbf457e4Stb 			goto end;
331f6116716Stb 		if (!ec_field_mul(group, tmp1, a->Y, Zb23, ctx))
332bbf457e4Stb 			goto end;
333bbf457e4Stb 		/* tmp1_ = tmp1 */
334bbf457e4Stb 	} else
335bbf457e4Stb 		tmp1_ = a->Y;
336bbf457e4Stb 	if (!a->Z_is_one) {
337f6116716Stb 		if (!ec_field_mul(group, Za23, Za23, a->Z, ctx))
338bbf457e4Stb 			goto end;
339f6116716Stb 		if (!ec_field_mul(group, tmp2, b->Y, Za23, ctx))
340bbf457e4Stb 			goto end;
341bbf457e4Stb 		/* tmp2_ = tmp2 */
342bbf457e4Stb 	} else
343bbf457e4Stb 		tmp2_ = b->Y;
344bbf457e4Stb 
345bbf457e4Stb 	/* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */
346bbf457e4Stb 	if (BN_cmp(tmp1_, tmp2_) != 0) {
347bbf457e4Stb 		ret = 1;	/* points differ */
348bbf457e4Stb 		goto end;
349bbf457e4Stb 	}
350bbf457e4Stb 	/* points are equal */
351bbf457e4Stb 	ret = 0;
352bbf457e4Stb 
353bbf457e4Stb  end:
354bbf457e4Stb 	BN_CTX_end(ctx);
355bbf457e4Stb 
356bbf457e4Stb 	return ret;
357bbf457e4Stb }
358bbf457e4Stb 
359bbf457e4Stb static int
360d9a83419Stb ec_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
361cb3e3e66Stb     const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
362cb3e3e66Stb {
363e2762cb6Stb 	int ret = 0;
364e2762cb6Stb 
365cb3e3e66Stb 	if (x == NULL || y == NULL) {
366cb3e3e66Stb 		ECerror(ERR_R_PASSED_NULL_PARAMETER);
367e2762cb6Stb 		goto err;
368cb3e3e66Stb 	}
369e2762cb6Stb 
370e2762cb6Stb 	if (!ec_encode_scalar(group, point->X, x, ctx))
371e2762cb6Stb 		goto err;
372e2762cb6Stb 	if (!ec_encode_scalar(group, point->Y, y, ctx))
373e2762cb6Stb 		goto err;
374e2762cb6Stb 	if (!ec_encode_scalar(group, point->Z, BN_value_one(), ctx))
375e2762cb6Stb 		goto err;
376e2762cb6Stb 	point->Z_is_one = 1;
377e2762cb6Stb 
378e2762cb6Stb 	ret = 1;
379e2762cb6Stb 
380e2762cb6Stb  err:
381e2762cb6Stb 	return ret;
382cb3e3e66Stb }
383cb3e3e66Stb 
384899705c2Stb static int
3853c24ce7eStb ec_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
3863c24ce7eStb     BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
387cb3e3e66Stb {
388cb3e3e66Stb 	BIGNUM *z, *Z, *Z_1, *Z_2, *Z_3;
389cb3e3e66Stb 	int ret = 0;
390cb3e3e66Stb 
391cb3e3e66Stb 	BN_CTX_start(ctx);
392cb3e3e66Stb 
393cb3e3e66Stb 	if ((z = BN_CTX_get(ctx)) == NULL)
394cb3e3e66Stb 		goto err;
395cb3e3e66Stb 	if ((Z = BN_CTX_get(ctx)) == NULL)
396cb3e3e66Stb 		goto err;
397cb3e3e66Stb 	if ((Z_1 = BN_CTX_get(ctx)) == NULL)
398cb3e3e66Stb 		goto err;
399cb3e3e66Stb 	if ((Z_2 = BN_CTX_get(ctx)) == NULL)
400cb3e3e66Stb 		goto err;
401cb3e3e66Stb 	if ((Z_3 = BN_CTX_get(ctx)) == NULL)
402cb3e3e66Stb 		goto err;
403cb3e3e66Stb 
4041cc088a1Sjsing 	/*
4051cc088a1Sjsing 	 * Convert from Jacobian projective coordinates (X, Y, Z) into
4061cc088a1Sjsing 	 * (X/Z^2, Y/Z^3).
4071cc088a1Sjsing 	 */
408cb3e3e66Stb 
4093c2cb882Stb 	if (!ec_decode_scalar(group, z, point->Z, ctx))
410cb3e3e66Stb 		goto err;
411cb3e3e66Stb 
412cb3e3e66Stb 	if (BN_is_one(z)) {
4133c2cb882Stb 		if (!ec_decode_scalar(group, x, point->X, ctx))
414cb3e3e66Stb 			goto err;
4153c2cb882Stb 		if (!ec_decode_scalar(group, y, point->Y, ctx))
416cb3e3e66Stb 			goto err;
417cb3e3e66Stb 		goto done;
418cb3e3e66Stb 	}
419cb3e3e66Stb 
4203c2cb882Stb 	if (BN_mod_inverse_ct(Z_1, z, group->p, ctx) == NULL) {
421cb3e3e66Stb 		ECerror(ERR_R_BN_LIB);
422cb3e3e66Stb 		goto err;
423cb3e3e66Stb 	}
424cb3e3e66Stb 	if (group->meth->field_encode == NULL) {
425cb3e3e66Stb 		/* field_sqr works on standard representation */
426728db599Stb 		if (!ec_field_sqr(group, Z_2, Z_1, ctx))
427cb3e3e66Stb 			goto err;
428cb3e3e66Stb 	} else {
4293c2cb882Stb 		if (!BN_mod_sqr(Z_2, Z_1, group->p, ctx))
430cb3e3e66Stb 			goto err;
431cb3e3e66Stb 	}
432cb3e3e66Stb 
433cb3e3e66Stb 	if (x != NULL) {
434cb3e3e66Stb 		/*
435cb3e3e66Stb 		 * in the Montgomery case, field_mul will cancel out
436cb3e3e66Stb 		 * Montgomery factor in X:
437cb3e3e66Stb 		 */
438728db599Stb 		if (!ec_field_mul(group, x, point->X, Z_2, ctx))
439cb3e3e66Stb 			goto err;
440cb3e3e66Stb 	}
441cb3e3e66Stb 	if (y != NULL) {
442cb3e3e66Stb 		if (group->meth->field_encode == NULL) {
443cb3e3e66Stb 			/* field_mul works on standard representation */
444728db599Stb 			if (!ec_field_mul(group, Z_3, Z_2, Z_1, ctx))
445cb3e3e66Stb 				goto err;
446cb3e3e66Stb 		} else {
4473c2cb882Stb 			if (!BN_mod_mul(Z_3, Z_2, Z_1, group->p, ctx))
448cb3e3e66Stb 				goto err;
449cb3e3e66Stb 		}
450cb3e3e66Stb 
451cb3e3e66Stb 		/*
452cb3e3e66Stb 		 * in the Montgomery case, field_mul will cancel out
453cb3e3e66Stb 		 * Montgomery factor in Y:
454cb3e3e66Stb 		 */
455728db599Stb 		if (!ec_field_mul(group, y, point->Y, Z_3, ctx))
456cb3e3e66Stb 			goto err;
457cb3e3e66Stb 	}
458cb3e3e66Stb 
459cb3e3e66Stb  done:
460cb3e3e66Stb 	ret = 1;
461cb3e3e66Stb 
462cb3e3e66Stb  err:
463cb3e3e66Stb 	BN_CTX_end(ctx);
464cb3e3e66Stb 
465cb3e3e66Stb 	return ret;
466cb3e3e66Stb }
467cb3e3e66Stb 
468899705c2Stb static int
46944d65b39Stb ec_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT **points,
47044d65b39Stb     BN_CTX *ctx)
47144d65b39Stb {
47244d65b39Stb 	BIGNUM **prod_Z = NULL;
47344d65b39Stb 	BIGNUM *one, *tmp, *tmp_Z;
47444d65b39Stb 	size_t i;
47544d65b39Stb 	int ret = 0;
47644d65b39Stb 
47744d65b39Stb 	if (num == 0)
47844d65b39Stb 		return 1;
47944d65b39Stb 
48044d65b39Stb 	BN_CTX_start(ctx);
48144d65b39Stb 
48244d65b39Stb 	if ((one = BN_CTX_get(ctx)) == NULL)
48344d65b39Stb 		goto err;
48444d65b39Stb 	if ((tmp = BN_CTX_get(ctx)) == NULL)
48544d65b39Stb 		goto err;
48644d65b39Stb 	if ((tmp_Z = BN_CTX_get(ctx)) == NULL)
48744d65b39Stb 		goto err;
48844d65b39Stb 
48944d65b39Stb 	if (!ec_encode_scalar(group, one, BN_value_one(), ctx))
49044d65b39Stb 		goto err;
49144d65b39Stb 
49244d65b39Stb 	if ((prod_Z = calloc(num, sizeof *prod_Z)) == NULL)
49344d65b39Stb 		goto err;
49444d65b39Stb 	for (i = 0; i < num; i++) {
49544d65b39Stb 		if ((prod_Z[i] = BN_CTX_get(ctx)) == NULL)
49644d65b39Stb 			goto err;
49744d65b39Stb 	}
49844d65b39Stb 
49944d65b39Stb 	/*
50044d65b39Stb 	 * Set prod_Z[i] to the product of points[0]->Z, ..., points[i]->Z,
50144d65b39Stb 	 * skipping any zero-valued inputs (pretend that they're 1).
50244d65b39Stb 	 */
50344d65b39Stb 
50444d65b39Stb 	if (!BN_is_zero(points[0]->Z)) {
50544d65b39Stb 		if (!bn_copy(prod_Z[0], points[0]->Z))
50644d65b39Stb 			goto err;
50744d65b39Stb 	} else {
50844d65b39Stb 		if (!bn_copy(prod_Z[0], one))
50944d65b39Stb 			goto err;
51044d65b39Stb 	}
51144d65b39Stb 
51244d65b39Stb 	for (i = 1; i < num; i++) {
51344d65b39Stb 		if (!BN_is_zero(points[i]->Z)) {
514728db599Stb 			if (!ec_field_mul(group, prod_Z[i],
51544d65b39Stb 			    prod_Z[i - 1], points[i]->Z, ctx))
51644d65b39Stb 				goto err;
51744d65b39Stb 		} else {
51844d65b39Stb 			if (!bn_copy(prod_Z[i], prod_Z[i - 1]))
51944d65b39Stb 				goto err;
52044d65b39Stb 		}
52144d65b39Stb 	}
52244d65b39Stb 
52344d65b39Stb 	/*
52444d65b39Stb 	 * Now use a single explicit inversion to replace every non-zero
52544d65b39Stb 	 * points[i]->Z by its inverse.
52644d65b39Stb 	 */
52744d65b39Stb 	if (!BN_mod_inverse_nonct(tmp, prod_Z[num - 1], group->p, ctx)) {
52844d65b39Stb 		ECerror(ERR_R_BN_LIB);
52944d65b39Stb 		goto err;
53044d65b39Stb 	}
53144d65b39Stb 
53244d65b39Stb 	if (group->meth->field_encode != NULL) {
53344d65b39Stb 		/*
53444d65b39Stb 		 * In the Montgomery case we just turned R*H (representing H)
53544d65b39Stb 		 * into 1/(R*H), but we need R*(1/H) (representing 1/H); i.e.,
53644d65b39Stb 		 * we need to multiply by the Montgomery factor twice.
53744d65b39Stb 		 */
53844d65b39Stb 		if (!group->meth->field_encode(group, tmp, tmp, ctx))
53944d65b39Stb 			goto err;
54044d65b39Stb 		if (!group->meth->field_encode(group, tmp, tmp, ctx))
54144d65b39Stb 			goto err;
54244d65b39Stb 	}
54344d65b39Stb 
54444d65b39Stb 	for (i = num - 1; i > 0; i--) {
54544d65b39Stb 		/*
54644d65b39Stb 		 * Loop invariant: tmp is the product of the inverses of
54744d65b39Stb 		 * points[0]->Z, ..., points[i]->Z (zero-valued inputs skipped).
54844d65b39Stb 		 */
54944d65b39Stb 		if (BN_is_zero(points[i]->Z))
55044d65b39Stb 			continue;
55144d65b39Stb 
55244d65b39Stb 		/* Set tmp_Z to the inverse of points[i]->Z. */
553728db599Stb 		if (!ec_field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx))
55444d65b39Stb 			goto err;
55544d65b39Stb 		/* Adjust tmp to satisfy loop invariant. */
556728db599Stb 		if (!ec_field_mul(group, tmp, tmp, points[i]->Z, ctx))
55744d65b39Stb 			goto err;
55844d65b39Stb 		/* Replace points[i]->Z by its inverse. */
55944d65b39Stb 		if (!bn_copy(points[i]->Z, tmp_Z))
56044d65b39Stb 			goto err;
56144d65b39Stb 	}
56244d65b39Stb 
56344d65b39Stb 	if (!BN_is_zero(points[0]->Z)) {
56444d65b39Stb 		/* Replace points[0]->Z by its inverse. */
56544d65b39Stb 		if (!bn_copy(points[0]->Z, tmp))
56644d65b39Stb 			goto err;
56744d65b39Stb 	}
56844d65b39Stb 
56944d65b39Stb 	/* Finally, fix up the X and Y coordinates for all points. */
57044d65b39Stb 	for (i = 0; i < num; i++) {
57144d65b39Stb 		EC_POINT *p = points[i];
57244d65b39Stb 
57344d65b39Stb 		if (BN_is_zero(p->Z))
57444d65b39Stb 			continue;
57544d65b39Stb 
57644d65b39Stb 		/* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */
57744d65b39Stb 
578728db599Stb 		if (!ec_field_sqr(group, tmp, p->Z, ctx))
57944d65b39Stb 			goto err;
580728db599Stb 		if (!ec_field_mul(group, p->X, p->X, tmp, ctx))
58144d65b39Stb 			goto err;
58244d65b39Stb 
583728db599Stb 		if (!ec_field_mul(group, tmp, tmp, p->Z, ctx))
58444d65b39Stb 			goto err;
585728db599Stb 		if (!ec_field_mul(group, p->Y, p->Y, tmp, ctx))
58644d65b39Stb 			goto err;
58744d65b39Stb 
58844d65b39Stb 		if (!bn_copy(p->Z, one))
58944d65b39Stb 			goto err;
59044d65b39Stb 		p->Z_is_one = 1;
59144d65b39Stb 	}
59244d65b39Stb 
59344d65b39Stb 	ret = 1;
59444d65b39Stb 
59544d65b39Stb  err:
59644d65b39Stb 	BN_CTX_end(ctx);
59744d65b39Stb 	free(prod_Z);
59844d65b39Stb 
59944d65b39Stb 	return ret;
60044d65b39Stb }
60144d65b39Stb 
60244d65b39Stb static int
6033c24ce7eStb ec_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b,
6043c24ce7eStb     BN_CTX *ctx)
605cb3e3e66Stb {
606cb3e3e66Stb 	BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
607cb3e3e66Stb 	int ret = 0;
608cb3e3e66Stb 
609cb3e3e66Stb 	if (a == b)
610cb3e3e66Stb 		return EC_POINT_dbl(group, r, a, ctx);
611cb3e3e66Stb 	if (EC_POINT_is_at_infinity(group, a))
612cb3e3e66Stb 		return EC_POINT_copy(r, b);
613cb3e3e66Stb 	if (EC_POINT_is_at_infinity(group, b))
614cb3e3e66Stb 		return EC_POINT_copy(r, a);
615cb3e3e66Stb 
616cb3e3e66Stb 	BN_CTX_start(ctx);
617cb3e3e66Stb 
618cb3e3e66Stb 	if ((n0 = BN_CTX_get(ctx)) == NULL)
619cb3e3e66Stb 		goto end;
620cb3e3e66Stb 	if ((n1 = BN_CTX_get(ctx)) == NULL)
621cb3e3e66Stb 		goto end;
622cb3e3e66Stb 	if ((n2 = BN_CTX_get(ctx)) == NULL)
623cb3e3e66Stb 		goto end;
624cb3e3e66Stb 	if ((n3 = BN_CTX_get(ctx)) == NULL)
625cb3e3e66Stb 		goto end;
626cb3e3e66Stb 	if ((n4 = BN_CTX_get(ctx)) == NULL)
627cb3e3e66Stb 		goto end;
628cb3e3e66Stb 	if ((n5 = BN_CTX_get(ctx)) == NULL)
629cb3e3e66Stb 		goto end;
630cb3e3e66Stb 	if ((n6 = BN_CTX_get(ctx)) == NULL)
631cb3e3e66Stb 		goto end;
632cb3e3e66Stb 
633cb3e3e66Stb 	/*
634cb3e3e66Stb 	 * Note that in this function we must not read components of 'a' or
635cb3e3e66Stb 	 * 'b' once we have written the corresponding components of 'r'. ('r'
636cb3e3e66Stb 	 * might be one of 'a' or 'b'.)
637cb3e3e66Stb 	 */
638cb3e3e66Stb 
639cb3e3e66Stb 	/* n1, n2 */
640cb3e3e66Stb 	if (b->Z_is_one) {
6413c2cb882Stb 		if (!bn_copy(n1, a->X))
642cb3e3e66Stb 			goto end;
6433c2cb882Stb 		if (!bn_copy(n2, a->Y))
644cb3e3e66Stb 			goto end;
645cb3e3e66Stb 		/* n1 = X_a */
646cb3e3e66Stb 		/* n2 = Y_a */
647cb3e3e66Stb 	} else {
648f6116716Stb 		if (!ec_field_sqr(group, n0, b->Z, ctx))
649cb3e3e66Stb 			goto end;
650f6116716Stb 		if (!ec_field_mul(group, n1, a->X, n0, ctx))
651cb3e3e66Stb 			goto end;
652cb3e3e66Stb 		/* n1 = X_a * Z_b^2 */
653cb3e3e66Stb 
654f6116716Stb 		if (!ec_field_mul(group, n0, n0, b->Z, ctx))
655cb3e3e66Stb 			goto end;
656f6116716Stb 		if (!ec_field_mul(group, n2, a->Y, n0, ctx))
657cb3e3e66Stb 			goto end;
658cb3e3e66Stb 		/* n2 = Y_a * Z_b^3 */
659cb3e3e66Stb 	}
660cb3e3e66Stb 
661cb3e3e66Stb 	/* n3, n4 */
662cb3e3e66Stb 	if (a->Z_is_one) {
6633c2cb882Stb 		if (!bn_copy(n3, b->X))
664cb3e3e66Stb 			goto end;
6653c2cb882Stb 		if (!bn_copy(n4, b->Y))
666cb3e3e66Stb 			goto end;
667cb3e3e66Stb 		/* n3 = X_b */
668cb3e3e66Stb 		/* n4 = Y_b */
669cb3e3e66Stb 	} else {
670f6116716Stb 		if (!ec_field_sqr(group, n0, a->Z, ctx))
671cb3e3e66Stb 			goto end;
672f6116716Stb 		if (!ec_field_mul(group, n3, b->X, n0, ctx))
673cb3e3e66Stb 			goto end;
674cb3e3e66Stb 		/* n3 = X_b * Z_a^2 */
675cb3e3e66Stb 
676f6116716Stb 		if (!ec_field_mul(group, n0, n0, a->Z, ctx))
677cb3e3e66Stb 			goto end;
678f6116716Stb 		if (!ec_field_mul(group, n4, b->Y, n0, ctx))
679cb3e3e66Stb 			goto end;
680cb3e3e66Stb 		/* n4 = Y_b * Z_a^3 */
681cb3e3e66Stb 	}
682cb3e3e66Stb 
683cb3e3e66Stb 	/* n5, n6 */
684d6f80948Stb 	if (!BN_mod_sub_quick(n5, n1, n3, group->p))
685cb3e3e66Stb 		goto end;
686d6f80948Stb 	if (!BN_mod_sub_quick(n6, n2, n4, group->p))
687cb3e3e66Stb 		goto end;
688cb3e3e66Stb 	/* n5 = n1 - n3 */
689cb3e3e66Stb 	/* n6 = n2 - n4 */
690cb3e3e66Stb 
691cb3e3e66Stb 	if (BN_is_zero(n5)) {
692cb3e3e66Stb 		if (BN_is_zero(n6)) {
693cb3e3e66Stb 			/* a is the same point as b */
694cb3e3e66Stb 			BN_CTX_end(ctx);
695cb3e3e66Stb 			ret = EC_POINT_dbl(group, r, a, ctx);
696cb3e3e66Stb 			ctx = NULL;
697cb3e3e66Stb 			goto end;
698cb3e3e66Stb 		} else {
699cb3e3e66Stb 			/* a is the inverse of b */
7003c2cb882Stb 			BN_zero(r->Z);
701cb3e3e66Stb 			r->Z_is_one = 0;
702cb3e3e66Stb 			ret = 1;
703cb3e3e66Stb 			goto end;
704cb3e3e66Stb 		}
705cb3e3e66Stb 	}
706cb3e3e66Stb 	/* 'n7', 'n8' */
707d6f80948Stb 	if (!BN_mod_add_quick(n1, n1, n3, group->p))
708cb3e3e66Stb 		goto end;
709d6f80948Stb 	if (!BN_mod_add_quick(n2, n2, n4, group->p))
710cb3e3e66Stb 		goto end;
711cb3e3e66Stb 	/* 'n7' = n1 + n3 */
712cb3e3e66Stb 	/* 'n8' = n2 + n4 */
713cb3e3e66Stb 
714cb3e3e66Stb 	/* Z_r */
715cb3e3e66Stb 	if (a->Z_is_one && b->Z_is_one) {
7163c2cb882Stb 		if (!bn_copy(r->Z, n5))
717cb3e3e66Stb 			goto end;
718cb3e3e66Stb 	} else {
719cb3e3e66Stb 		if (a->Z_is_one) {
7203c2cb882Stb 			if (!bn_copy(n0, b->Z))
721cb3e3e66Stb 				goto end;
722cb3e3e66Stb 		} else if (b->Z_is_one) {
7233c2cb882Stb 			if (!bn_copy(n0, a->Z))
724cb3e3e66Stb 				goto end;
725cb3e3e66Stb 		} else {
726f6116716Stb 			if (!ec_field_mul(group, n0, a->Z, b->Z, ctx))
727cb3e3e66Stb 				goto end;
728cb3e3e66Stb 		}
729f6116716Stb 		if (!ec_field_mul(group, r->Z, n0, n5, ctx))
730cb3e3e66Stb 			goto end;
731cb3e3e66Stb 	}
732cb3e3e66Stb 	r->Z_is_one = 0;
733cb3e3e66Stb 	/* Z_r = Z_a * Z_b * n5 */
734cb3e3e66Stb 
735cb3e3e66Stb 	/* X_r */
736f6116716Stb 	if (!ec_field_sqr(group, n0, n6, ctx))
737cb3e3e66Stb 		goto end;
738f6116716Stb 	if (!ec_field_sqr(group, n4, n5, ctx))
739cb3e3e66Stb 		goto end;
740f6116716Stb 	if (!ec_field_mul(group, n3, n1, n4, ctx))
741cb3e3e66Stb 		goto end;
742d6f80948Stb 	if (!BN_mod_sub_quick(r->X, n0, n3, group->p))
743cb3e3e66Stb 		goto end;
744cb3e3e66Stb 	/* X_r = n6^2 - n5^2 * 'n7' */
745cb3e3e66Stb 
746cb3e3e66Stb 	/* 'n9' */
747d6f80948Stb 	if (!BN_mod_lshift1_quick(n0, r->X, group->p))
748cb3e3e66Stb 		goto end;
749d6f80948Stb 	if (!BN_mod_sub_quick(n0, n3, n0, group->p))
750cb3e3e66Stb 		goto end;
751cb3e3e66Stb 	/* n9 = n5^2 * 'n7' - 2 * X_r */
752cb3e3e66Stb 
753cb3e3e66Stb 	/* Y_r */
754f6116716Stb 	if (!ec_field_mul(group, n0, n0, n6, ctx))
755cb3e3e66Stb 		goto end;
756f6116716Stb 	if (!ec_field_mul(group, n5, n4, n5, ctx))
757cb3e3e66Stb 		goto end;	/* now n5 is n5^3 */
758f6116716Stb 	if (!ec_field_mul(group, n1, n2, n5, ctx))
759cb3e3e66Stb 		goto end;
760d6f80948Stb 	if (!BN_mod_sub_quick(n0, n0, n1, group->p))
761cb3e3e66Stb 		goto end;
762cb3e3e66Stb 	if (BN_is_odd(n0))
763d6f80948Stb 		if (!BN_add(n0, n0, group->p))
764cb3e3e66Stb 			goto end;
765cb3e3e66Stb 	/* now  0 <= n0 < 2*p,  and n0 is even */
7663c2cb882Stb 	if (!BN_rshift1(r->Y, n0))
767cb3e3e66Stb 		goto end;
768cb3e3e66Stb 	/* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
769cb3e3e66Stb 
770cb3e3e66Stb 	ret = 1;
771cb3e3e66Stb 
772cb3e3e66Stb  end:
773cb3e3e66Stb 	BN_CTX_end(ctx);
774cb3e3e66Stb 
775cb3e3e66Stb 	return ret;
776cb3e3e66Stb }
777cb3e3e66Stb 
778899705c2Stb static int
779d9a83419Stb ec_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
780cb3e3e66Stb {
781cb3e3e66Stb 	BIGNUM *n0, *n1, *n2, *n3;
782cb3e3e66Stb 	int ret = 0;
783cb3e3e66Stb 
784cb3e3e66Stb 	if (EC_POINT_is_at_infinity(group, a))
785cb3e3e66Stb 		return EC_POINT_set_to_infinity(group, r);
786cb3e3e66Stb 
787cb3e3e66Stb 	BN_CTX_start(ctx);
788cb3e3e66Stb 
789cb3e3e66Stb 	if ((n0 = BN_CTX_get(ctx)) == NULL)
790cb3e3e66Stb 		goto err;
791cb3e3e66Stb 	if ((n1 = BN_CTX_get(ctx)) == NULL)
792cb3e3e66Stb 		goto err;
793cb3e3e66Stb 	if ((n2 = BN_CTX_get(ctx)) == NULL)
794cb3e3e66Stb 		goto err;
795cb3e3e66Stb 	if ((n3 = BN_CTX_get(ctx)) == NULL)
796cb3e3e66Stb 		goto err;
797cb3e3e66Stb 
798cb3e3e66Stb 	/*
799cb3e3e66Stb 	 * Note that in this function we must not read components of 'a' once
800cb3e3e66Stb 	 * we have written the corresponding components of 'r'. ('r' might
801cb3e3e66Stb 	 * the same as 'a'.)
802cb3e3e66Stb 	 */
803cb3e3e66Stb 
804cb3e3e66Stb 	/* n1 */
805cb3e3e66Stb 	if (a->Z_is_one) {
806f6116716Stb 		if (!ec_field_sqr(group, n0, a->X, ctx))
807cb3e3e66Stb 			goto err;
808d6f80948Stb 		if (!BN_mod_lshift1_quick(n1, n0, group->p))
809cb3e3e66Stb 			goto err;
810d6f80948Stb 		if (!BN_mod_add_quick(n0, n0, n1, group->p))
811cb3e3e66Stb 			goto err;
812d6f80948Stb 		if (!BN_mod_add_quick(n1, n0, group->a, group->p))
813cb3e3e66Stb 			goto err;
814cb3e3e66Stb 		/* n1 = 3 * X_a^2 + a_curve */
815cb3e3e66Stb 	} else if (group->a_is_minus3) {
816f6116716Stb 		if (!ec_field_sqr(group, n1, a->Z, ctx))
817cb3e3e66Stb 			goto err;
818d6f80948Stb 		if (!BN_mod_add_quick(n0, a->X, n1, group->p))
819cb3e3e66Stb 			goto err;
820d6f80948Stb 		if (!BN_mod_sub_quick(n2, a->X, n1, group->p))
821cb3e3e66Stb 			goto err;
822f6116716Stb 		if (!ec_field_mul(group, n1, n0, n2, ctx))
823cb3e3e66Stb 			goto err;
824d6f80948Stb 		if (!BN_mod_lshift1_quick(n0, n1, group->p))
825cb3e3e66Stb 			goto err;
826d6f80948Stb 		if (!BN_mod_add_quick(n1, n0, n1, group->p))
827cb3e3e66Stb 			goto err;
828cb3e3e66Stb 		/*
829cb3e3e66Stb 		 * n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) = 3 * X_a^2 - 3 *
830cb3e3e66Stb 		 * Z_a^4
831cb3e3e66Stb 		 */
832cb3e3e66Stb 	} else {
833f6116716Stb 		if (!ec_field_sqr(group, n0, a->X, ctx))
834cb3e3e66Stb 			goto err;
835d6f80948Stb 		if (!BN_mod_lshift1_quick(n1, n0, group->p))
836cb3e3e66Stb 			goto err;
837d6f80948Stb 		if (!BN_mod_add_quick(n0, n0, n1, group->p))
838cb3e3e66Stb 			goto err;
839f6116716Stb 		if (!ec_field_sqr(group, n1, a->Z, ctx))
840cb3e3e66Stb 			goto err;
841f6116716Stb 		if (!ec_field_sqr(group, n1, n1, ctx))
842cb3e3e66Stb 			goto err;
843f6116716Stb 		if (!ec_field_mul(group, n1, n1, group->a, ctx))
844cb3e3e66Stb 			goto err;
845d6f80948Stb 		if (!BN_mod_add_quick(n1, n1, n0, group->p))
846cb3e3e66Stb 			goto err;
847cb3e3e66Stb 		/* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
848cb3e3e66Stb 	}
849cb3e3e66Stb 
850cb3e3e66Stb 	/* Z_r */
851cb3e3e66Stb 	if (a->Z_is_one) {
8523c2cb882Stb 		if (!bn_copy(n0, a->Y))
853cb3e3e66Stb 			goto err;
854cb3e3e66Stb 	} else {
855f6116716Stb 		if (!ec_field_mul(group, n0, a->Y, a->Z, ctx))
856cb3e3e66Stb 			goto err;
857cb3e3e66Stb 	}
858d6f80948Stb 	if (!BN_mod_lshift1_quick(r->Z, n0, group->p))
859cb3e3e66Stb 		goto err;
860cb3e3e66Stb 	r->Z_is_one = 0;
861cb3e3e66Stb 	/* Z_r = 2 * Y_a * Z_a */
862cb3e3e66Stb 
863cb3e3e66Stb 	/* n2 */
864f6116716Stb 	if (!ec_field_sqr(group, n3, a->Y, ctx))
865cb3e3e66Stb 		goto err;
866f6116716Stb 	if (!ec_field_mul(group, n2, a->X, n3, ctx))
867cb3e3e66Stb 		goto err;
868d6f80948Stb 	if (!BN_mod_lshift_quick(n2, n2, 2, group->p))
869cb3e3e66Stb 		goto err;
870cb3e3e66Stb 	/* n2 = 4 * X_a * Y_a^2 */
871cb3e3e66Stb 
872cb3e3e66Stb 	/* X_r */
873d6f80948Stb 	if (!BN_mod_lshift1_quick(n0, n2, group->p))
874cb3e3e66Stb 		goto err;
875f6116716Stb 	if (!ec_field_sqr(group, r->X, n1, ctx))
876cb3e3e66Stb 		goto err;
877d6f80948Stb 	if (!BN_mod_sub_quick(r->X, r->X, n0, group->p))
878cb3e3e66Stb 		goto err;
879cb3e3e66Stb 	/* X_r = n1^2 - 2 * n2 */
880cb3e3e66Stb 
881cb3e3e66Stb 	/* n3 */
882f6116716Stb 	if (!ec_field_sqr(group, n0, n3, ctx))
883cb3e3e66Stb 		goto err;
884d6f80948Stb 	if (!BN_mod_lshift_quick(n3, n0, 3, group->p))
885cb3e3e66Stb 		goto err;
886cb3e3e66Stb 	/* n3 = 8 * Y_a^4 */
887cb3e3e66Stb 
888cb3e3e66Stb 	/* Y_r */
889d6f80948Stb 	if (!BN_mod_sub_quick(n0, n2, r->X, group->p))
890cb3e3e66Stb 		goto err;
891f6116716Stb 	if (!ec_field_mul(group, n0, n1, n0, ctx))
892cb3e3e66Stb 		goto err;
893d6f80948Stb 	if (!BN_mod_sub_quick(r->Y, n0, n3, group->p))
894cb3e3e66Stb 		goto err;
895cb3e3e66Stb 	/* Y_r = n1 * (n2 - X_r) - n3 */
896cb3e3e66Stb 
897cb3e3e66Stb 	ret = 1;
898cb3e3e66Stb 
899cb3e3e66Stb  err:
900cb3e3e66Stb 	BN_CTX_end(ctx);
901cb3e3e66Stb 
902cb3e3e66Stb 	return ret;
903cb3e3e66Stb }
904cb3e3e66Stb 
905899705c2Stb static int
906d9a83419Stb ec_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
907cb3e3e66Stb {
9083c2cb882Stb 	if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y))
909cb3e3e66Stb 		/* point is its own inverse */
910cb3e3e66Stb 		return 1;
911cb3e3e66Stb 
9123c2cb882Stb 	return BN_usub(point->Y, group->p, point->Y);
913cb3e3e66Stb }
914cb3e3e66Stb 
915cb3e3e66Stb /*
9161cc088a1Sjsing  * Apply randomization of EC point Jacobian projective coordinates:
917cb3e3e66Stb  *
918cb3e3e66Stb  *	(X, Y, Z) = (lambda^2 * X, lambda^3 * Y, lambda * Z)
919cb3e3e66Stb  *
9203fd2f05cStb  * where lambda is in the interval [1, p).
921cb3e3e66Stb  */
922899705c2Stb static int
923d9a83419Stb ec_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx)
924cb3e3e66Stb {
925cb3e3e66Stb 	BIGNUM *lambda = NULL;
926cb3e3e66Stb 	BIGNUM *tmp = NULL;
927cb3e3e66Stb 	int ret = 0;
928cb3e3e66Stb 
929cb3e3e66Stb 	BN_CTX_start(ctx);
930cb3e3e66Stb 	if ((lambda = BN_CTX_get(ctx)) == NULL)
931cb3e3e66Stb 		goto err;
932cb3e3e66Stb 	if ((tmp = BN_CTX_get(ctx)) == NULL)
933cb3e3e66Stb 		goto err;
934cb3e3e66Stb 
9353fd2f05cStb 	/* Generate lambda in [1, p). */
9363c2cb882Stb 	if (!bn_rand_interval(lambda, 1, group->p))
937cb3e3e66Stb 		goto err;
938cb3e3e66Stb 
939cb3e3e66Stb 	if (group->meth->field_encode != NULL &&
940cb3e3e66Stb 	    !group->meth->field_encode(group, lambda, lambda, ctx))
941cb3e3e66Stb 		goto err;
942cb3e3e66Stb 
943cb3e3e66Stb 	/* Z = lambda * Z */
944f6116716Stb 	if (!ec_field_mul(group, p->Z, lambda, p->Z, ctx))
945cb3e3e66Stb 		goto err;
946cb3e3e66Stb 
947cb3e3e66Stb 	/* tmp = lambda^2 */
948728db599Stb 	if (!ec_field_sqr(group, tmp, lambda, ctx))
949cb3e3e66Stb 		goto err;
950cb3e3e66Stb 
951cb3e3e66Stb 	/* X = lambda^2 * X */
952f6116716Stb 	if (!ec_field_mul(group, p->X, tmp, p->X, ctx))
953cb3e3e66Stb 		goto err;
954cb3e3e66Stb 
955cb3e3e66Stb 	/* tmp = lambda^3 */
956f6116716Stb 	if (!ec_field_mul(group, tmp, tmp, lambda, ctx))
957cb3e3e66Stb 		goto err;
958cb3e3e66Stb 
959cb3e3e66Stb 	/* Y = lambda^3 * Y */
960f6116716Stb 	if (!ec_field_mul(group, p->Y, tmp, p->Y, ctx))
961cb3e3e66Stb 		goto err;
962cb3e3e66Stb 
963cb3e3e66Stb 	/* Disable optimized arithmetics after replacing Z by lambda * Z. */
964cb3e3e66Stb 	p->Z_is_one = 0;
965cb3e3e66Stb 
966cb3e3e66Stb 	ret = 1;
967cb3e3e66Stb 
968cb3e3e66Stb  err:
969cb3e3e66Stb 	BN_CTX_end(ctx);
970cb3e3e66Stb 	return ret;
971cb3e3e66Stb }
972cb3e3e66Stb 
973cb3e3e66Stb #define EC_POINT_BN_set_flags(P, flags) do {				\
9743c2cb882Stb 	BN_set_flags((P)->X, (flags));					\
9753c2cb882Stb 	BN_set_flags((P)->Y, (flags));					\
9763c2cb882Stb 	BN_set_flags((P)->Z, (flags));					\
977cb3e3e66Stb } while(0)
978cb3e3e66Stb 
979cb3e3e66Stb #define EC_POINT_CSWAP(c, a, b, w, t) do {				\
9803c2cb882Stb 	if (!BN_swap_ct(c, (a)->X, (b)->X, w)	||			\
9813c2cb882Stb 	    !BN_swap_ct(c, (a)->Y, (b)->Y, w)	||			\
9823c2cb882Stb 	    !BN_swap_ct(c, (a)->Z, (b)->Z, w))				\
983cb3e3e66Stb 		goto err;						\
984cb3e3e66Stb 	t = ((a)->Z_is_one ^ (b)->Z_is_one) & (c);			\
985cb3e3e66Stb 	(a)->Z_is_one ^= (t);						\
986cb3e3e66Stb 	(b)->Z_is_one ^= (t);						\
987cb3e3e66Stb } while(0)
988cb3e3e66Stb 
989cb3e3e66Stb /*
990cb3e3e66Stb  * This function computes (in constant time) a point multiplication over the
991cb3e3e66Stb  * EC group.
992cb3e3e66Stb  *
993cb3e3e66Stb  * At a high level, it is Montgomery ladder with conditional swaps.
994cb3e3e66Stb  *
995cb3e3e66Stb  * It performs either a fixed point multiplication
996cb3e3e66Stb  *          (scalar * generator)
997cb3e3e66Stb  * when point is NULL, or a variable point multiplication
998cb3e3e66Stb  *          (scalar * point)
999cb3e3e66Stb  * when point is not NULL.
1000cb3e3e66Stb  *
1001cb3e3e66Stb  * scalar should be in the range [0,n) otherwise all constant time bets are off.
1002cb3e3e66Stb  *
1003cb3e3e66Stb  * NB: This says nothing about EC_POINT_add and EC_POINT_dbl,
1004cb3e3e66Stb  * which of course are not constant time themselves.
1005cb3e3e66Stb  *
1006cb3e3e66Stb  * The product is stored in r.
1007cb3e3e66Stb  *
1008cb3e3e66Stb  * Returns 1 on success, 0 otherwise.
1009cb3e3e66Stb  */
1010cb3e3e66Stb static int
1011d9a83419Stb ec_mul_ct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1012cb3e3e66Stb     const EC_POINT *point, BN_CTX *ctx)
1013cb3e3e66Stb {
1014cb3e3e66Stb 	int i, cardinality_bits, group_top, kbit, pbit, Z_is_one;
1015cb3e3e66Stb 	EC_POINT *s = NULL;
1016cb3e3e66Stb 	BIGNUM *k = NULL;
1017cb3e3e66Stb 	BIGNUM *lambda = NULL;
1018cb3e3e66Stb 	BIGNUM *cardinality = NULL;
1019cb3e3e66Stb 	int ret = 0;
1020cb3e3e66Stb 
1021cb3e3e66Stb 	BN_CTX_start(ctx);
1022cb3e3e66Stb 
1023c383f79cStb 	if ((s = EC_POINT_dup(point, group)) == NULL)
1024cb3e3e66Stb 		goto err;
1025cb3e3e66Stb 
1026cb3e3e66Stb 	EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME);
1027cb3e3e66Stb 
1028cb3e3e66Stb 	if ((cardinality = BN_CTX_get(ctx)) == NULL)
1029cb3e3e66Stb 		goto err;
1030cb3e3e66Stb 	if ((lambda = BN_CTX_get(ctx)) == NULL)
1031cb3e3e66Stb 		goto err;
1032cb3e3e66Stb 	if ((k = BN_CTX_get(ctx)) == NULL)
1033cb3e3e66Stb 		goto err;
10343c2cb882Stb 	if (!BN_mul(cardinality, group->order, group->cofactor, ctx))
1035cb3e3e66Stb 		goto err;
1036cb3e3e66Stb 
1037cb3e3e66Stb 	/*
1038cb3e3e66Stb 	 * Group cardinalities are often on a word boundary.
1039cb3e3e66Stb 	 * So when we pad the scalar, some timing diff might
1040cb3e3e66Stb 	 * pop if it needs to be expanded due to carries.
1041cb3e3e66Stb 	 * So expand ahead of time.
1042cb3e3e66Stb 	 */
1043cb3e3e66Stb 	cardinality_bits = BN_num_bits(cardinality);
1044cb3e3e66Stb 	group_top = cardinality->top;
1045cb3e3e66Stb 	if (!bn_wexpand(k, group_top + 2) ||
1046cb3e3e66Stb 	    !bn_wexpand(lambda, group_top + 2))
1047cb3e3e66Stb 		goto err;
1048cb3e3e66Stb 
1049cb3e3e66Stb 	if (!bn_copy(k, scalar))
1050cb3e3e66Stb 		goto err;
1051cb3e3e66Stb 
1052cb3e3e66Stb 	BN_set_flags(k, BN_FLG_CONSTTIME);
1053cb3e3e66Stb 
1054cb3e3e66Stb 	if (BN_num_bits(k) > cardinality_bits || BN_is_negative(k)) {
1055cb3e3e66Stb 		/*
1056cb3e3e66Stb 		 * This is an unusual input, and we don't guarantee
1057cb3e3e66Stb 		 * constant-timeness
1058cb3e3e66Stb 		 */
1059cb3e3e66Stb 		if (!BN_nnmod(k, k, cardinality, ctx))
1060cb3e3e66Stb 			goto err;
1061cb3e3e66Stb 	}
1062cb3e3e66Stb 
1063cb3e3e66Stb 	if (!BN_add(lambda, k, cardinality))
1064cb3e3e66Stb 		goto err;
1065cb3e3e66Stb 	BN_set_flags(lambda, BN_FLG_CONSTTIME);
1066cb3e3e66Stb 	if (!BN_add(k, lambda, cardinality))
1067cb3e3e66Stb 		goto err;
1068cb3e3e66Stb 	/*
1069cb3e3e66Stb 	 * lambda := scalar + cardinality
1070cb3e3e66Stb 	 * k := scalar + 2*cardinality
1071cb3e3e66Stb 	 */
1072cb3e3e66Stb 	kbit = BN_is_bit_set(lambda, cardinality_bits);
1073cb3e3e66Stb 	if (!BN_swap_ct(kbit, k, lambda, group_top + 2))
1074cb3e3e66Stb 		goto err;
1075cb3e3e66Stb 
10763c2cb882Stb 	group_top = group->p->top;
10773c2cb882Stb 	if (!bn_wexpand(s->X, group_top) ||
10783c2cb882Stb 	    !bn_wexpand(s->Y, group_top) ||
10793c2cb882Stb 	    !bn_wexpand(s->Z, group_top) ||
10803c2cb882Stb 	    !bn_wexpand(r->X, group_top) ||
10813c2cb882Stb 	    !bn_wexpand(r->Y, group_top) ||
10823c2cb882Stb 	    !bn_wexpand(r->Z, group_top))
1083cb3e3e66Stb 		goto err;
1084cb3e3e66Stb 
1085cb3e3e66Stb 	/*
1086cb3e3e66Stb 	 * Apply coordinate blinding for EC_POINT if the underlying EC_METHOD
1087cb3e3e66Stb 	 * implements it.
1088cb3e3e66Stb 	 */
1089a680ff0cSjsing 	if (!ec_blind_coordinates(group, s, ctx))
1090cb3e3e66Stb 		goto err;
1091cb3e3e66Stb 
1092cb3e3e66Stb 	/* top bit is a 1, in a fixed pos */
1093cb3e3e66Stb 	if (!EC_POINT_copy(r, s))
1094cb3e3e66Stb 		goto err;
1095cb3e3e66Stb 
1096cb3e3e66Stb 	EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME);
1097cb3e3e66Stb 
1098cb3e3e66Stb 	if (!EC_POINT_dbl(group, s, s, ctx))
1099cb3e3e66Stb 		goto err;
1100cb3e3e66Stb 
1101cb3e3e66Stb 	pbit = 0;
1102cb3e3e66Stb 
1103cb3e3e66Stb 	/*
1104cb3e3e66Stb 	 * The ladder step, with branches, is
1105cb3e3e66Stb 	 *
1106cb3e3e66Stb 	 * k[i] == 0: S = add(R, S), R = dbl(R)
1107cb3e3e66Stb 	 * k[i] == 1: R = add(S, R), S = dbl(S)
1108cb3e3e66Stb 	 *
1109cb3e3e66Stb 	 * Swapping R, S conditionally on k[i] leaves you with state
1110cb3e3e66Stb 	 *
1111cb3e3e66Stb 	 * k[i] == 0: T, U = R, S
1112cb3e3e66Stb 	 * k[i] == 1: T, U = S, R
1113cb3e3e66Stb 	 *
1114cb3e3e66Stb 	 * Then perform the ECC ops.
1115cb3e3e66Stb 	 *
1116cb3e3e66Stb 	 * U = add(T, U)
1117cb3e3e66Stb 	 * T = dbl(T)
1118cb3e3e66Stb 	 *
1119cb3e3e66Stb 	 * Which leaves you with state
1120cb3e3e66Stb 	 *
1121cb3e3e66Stb 	 * k[i] == 0: U = add(R, S), T = dbl(R)
1122cb3e3e66Stb 	 * k[i] == 1: U = add(S, R), T = dbl(S)
1123cb3e3e66Stb 	 *
1124cb3e3e66Stb 	 * Swapping T, U conditionally on k[i] leaves you with state
1125cb3e3e66Stb 	 *
1126cb3e3e66Stb 	 * k[i] == 0: R, S = T, U
1127cb3e3e66Stb 	 * k[i] == 1: R, S = U, T
1128cb3e3e66Stb 	 *
1129cb3e3e66Stb 	 * Which leaves you with state
1130cb3e3e66Stb 	 *
1131cb3e3e66Stb 	 * k[i] == 0: S = add(R, S), R = dbl(R)
1132cb3e3e66Stb 	 * k[i] == 1: R = add(S, R), S = dbl(S)
1133cb3e3e66Stb 	 *
1134cb3e3e66Stb 	 * So we get the same logic, but instead of a branch it's a
1135cb3e3e66Stb 	 * conditional swap, followed by ECC ops, then another conditional swap.
1136cb3e3e66Stb 	 *
1137cb3e3e66Stb 	 * Optimization: The end of iteration i and start of i-1 looks like
1138cb3e3e66Stb 	 *
1139cb3e3e66Stb 	 * ...
1140cb3e3e66Stb 	 * CSWAP(k[i], R, S)
1141cb3e3e66Stb 	 * ECC
1142cb3e3e66Stb 	 * CSWAP(k[i], R, S)
1143cb3e3e66Stb 	 * (next iteration)
1144cb3e3e66Stb 	 * CSWAP(k[i-1], R, S)
1145cb3e3e66Stb 	 * ECC
1146cb3e3e66Stb 	 * CSWAP(k[i-1], R, S)
1147cb3e3e66Stb 	 * ...
1148cb3e3e66Stb 	 *
1149cb3e3e66Stb 	 * So instead of two contiguous swaps, you can merge the condition
1150cb3e3e66Stb 	 * bits and do a single swap.
1151cb3e3e66Stb 	 *
1152cb3e3e66Stb 	 * k[i]   k[i-1]    Outcome
1153cb3e3e66Stb 	 * 0      0         No Swap
1154cb3e3e66Stb 	 * 0      1         Swap
1155cb3e3e66Stb 	 * 1      0         Swap
1156cb3e3e66Stb 	 * 1      1         No Swap
1157cb3e3e66Stb 	 *
1158cb3e3e66Stb 	 * This is XOR. pbit tracks the previous bit of k.
1159cb3e3e66Stb 	 */
1160cb3e3e66Stb 
1161cb3e3e66Stb 	for (i = cardinality_bits - 1; i >= 0; i--) {
1162cb3e3e66Stb 		kbit = BN_is_bit_set(k, i) ^ pbit;
1163cb3e3e66Stb 		EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one);
1164cb3e3e66Stb 		if (!EC_POINT_add(group, s, r, s, ctx))
1165cb3e3e66Stb 			goto err;
1166cb3e3e66Stb 		if (!EC_POINT_dbl(group, r, r, ctx))
1167cb3e3e66Stb 			goto err;
1168cb3e3e66Stb 		/*
1169cb3e3e66Stb 		 * pbit logic merges this cswap with that of the
1170cb3e3e66Stb 		 * next iteration
1171cb3e3e66Stb 		 */
1172cb3e3e66Stb 		pbit ^= kbit;
1173cb3e3e66Stb 	}
1174cb3e3e66Stb 	/* one final cswap to move the right value into r */
1175cb3e3e66Stb 	EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one);
1176cb3e3e66Stb 
1177cb3e3e66Stb 	ret = 1;
1178cb3e3e66Stb 
1179cb3e3e66Stb  err:
1180cb3e3e66Stb 	EC_POINT_free(s);
1181cb3e3e66Stb 	BN_CTX_end(ctx);
1182cb3e3e66Stb 
1183cb3e3e66Stb 	return ret;
1184cb3e3e66Stb }
1185cb3e3e66Stb 
1186cb3e3e66Stb #undef EC_POINT_BN_set_flags
1187cb3e3e66Stb #undef EC_POINT_CSWAP
1188cb3e3e66Stb 
1189899705c2Stb static int
11903c24ce7eStb ec_mul_single_ct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
11913c24ce7eStb     const EC_POINT *point, BN_CTX *ctx)
1192cb3e3e66Stb {
1193d9a83419Stb 	return ec_mul_ct(group, r, scalar, point, ctx);
1194cb3e3e66Stb }
1195cb3e3e66Stb 
1196899705c2Stb static int
11973c24ce7eStb ec_mul_double_nonct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
11983c24ce7eStb     const BIGNUM *p_scalar, const EC_POINT *point, BN_CTX *ctx)
1199cb3e3e66Stb {
12009d4c47a8Stb 	return ec_wnaf_mul(group, r, g_scalar, point, p_scalar, ctx);
1201cb3e3e66Stb }
1202cb3e3e66Stb 
1203107480a9Stb static int
1204f6116716Stb ec_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
1205f6116716Stb     const BIGNUM *b, BN_CTX *ctx)
1206f6116716Stb {
1207f6116716Stb 	return BN_mod_mul(r, a, b, group->p, ctx);
1208f6116716Stb }
1209f6116716Stb 
1210f6116716Stb static int
1211f6116716Stb ec_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
1212f6116716Stb {
1213f6116716Stb 	return BN_mod_sqr(r, a, group->p, ctx);
1214f6116716Stb }
1215f6116716Stb 
1216f6116716Stb static int
1217d9a83419Stb ec_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
1218107480a9Stb     const BIGNUM *b, BN_CTX *ctx)
1219107480a9Stb {
1220107480a9Stb 	BN_MONT_CTX *mont = NULL;
1221107480a9Stb 	int ret = 0;
1222107480a9Stb 
1223de420f14Stb 	BN_MONT_CTX_free(group->mont_ctx);
1224de420f14Stb 	group->mont_ctx = NULL;
1225107480a9Stb 
1226de420f14Stb 	if ((mont = BN_MONT_CTX_new()) == NULL)
1227107480a9Stb 		goto err;
1228107480a9Stb 	if (!BN_MONT_CTX_set(mont, p, ctx)) {
1229107480a9Stb 		ECerror(ERR_R_BN_LIB);
1230107480a9Stb 		goto err;
1231107480a9Stb 	}
1232107480a9Stb 	group->mont_ctx = mont;
1233107480a9Stb 	mont = NULL;
1234107480a9Stb 
1235de420f14Stb 	if (!ec_group_set_curve(group, p, a, b, ctx)) {
1236de420f14Stb 		BN_MONT_CTX_free(group->mont_ctx);
1237de420f14Stb 		group->mont_ctx = NULL;
1238de420f14Stb 		goto err;
1239de420f14Stb 	}
1240de420f14Stb 
1241de420f14Stb 	ret = 1;
1242107480a9Stb 
1243107480a9Stb  err:
1244107480a9Stb 	BN_MONT_CTX_free(mont);
1245107480a9Stb 
1246107480a9Stb 	return ret;
1247107480a9Stb }
1248107480a9Stb 
1249107480a9Stb static int
1250d9a83419Stb ec_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
1251107480a9Stb     const BIGNUM *b, BN_CTX *ctx)
1252107480a9Stb {
1253107480a9Stb 	if (group->mont_ctx == NULL) {
1254107480a9Stb 		ECerror(EC_R_NOT_INITIALIZED);
1255107480a9Stb 		return 0;
1256107480a9Stb 	}
1257107480a9Stb 	return BN_mod_mul_montgomery(r, a, b, group->mont_ctx, ctx);
1258107480a9Stb }
1259107480a9Stb 
1260107480a9Stb static int
1261d9a83419Stb ec_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
1262107480a9Stb     BN_CTX *ctx)
1263107480a9Stb {
1264107480a9Stb 	if (group->mont_ctx == NULL) {
1265107480a9Stb 		ECerror(EC_R_NOT_INITIALIZED);
1266107480a9Stb 		return 0;
1267107480a9Stb 	}
1268107480a9Stb 	return BN_mod_mul_montgomery(r, a, a, group->mont_ctx, ctx);
1269107480a9Stb }
1270107480a9Stb 
1271107480a9Stb static int
1272d9a83419Stb ec_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
1273107480a9Stb     BN_CTX *ctx)
1274107480a9Stb {
1275107480a9Stb 	if (group->mont_ctx == NULL) {
1276107480a9Stb 		ECerror(EC_R_NOT_INITIALIZED);
1277107480a9Stb 		return 0;
1278107480a9Stb 	}
1279107480a9Stb 	return BN_to_montgomery(r, a, group->mont_ctx, ctx);
1280107480a9Stb }
1281107480a9Stb 
1282107480a9Stb static int
1283d9a83419Stb ec_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
1284107480a9Stb     BN_CTX *ctx)
1285107480a9Stb {
1286107480a9Stb 	if (group->mont_ctx == NULL) {
1287107480a9Stb 		ECerror(EC_R_NOT_INITIALIZED);
1288107480a9Stb 		return 0;
1289107480a9Stb 	}
1290107480a9Stb 	return BN_from_montgomery(r, a, group->mont_ctx, ctx);
1291107480a9Stb }
1292107480a9Stb 
1293cb3e3e66Stb static const EC_METHOD ec_GFp_simple_method = {
1294d9a83419Stb 	.group_set_curve = ec_group_set_curve,
1295d9a83419Stb 	.group_get_curve = ec_group_get_curve,
12964fb59ff9Stb 	.point_is_on_curve = ec_point_is_on_curve,
12974fb59ff9Stb 	.point_cmp = ec_point_cmp,
1298d9a83419Stb 	.point_set_affine_coordinates = ec_point_set_affine_coordinates,
1299d9a83419Stb 	.point_get_affine_coordinates = ec_point_get_affine_coordinates,
13009581610fStb 	.points_make_affine = ec_points_make_affine,
1301d9a83419Stb 	.add = ec_add,
1302d9a83419Stb 	.dbl = ec_dbl,
1303d9a83419Stb 	.invert = ec_invert,
1304d9a83419Stb 	.mul_single_ct = ec_mul_single_ct,
1305d9a83419Stb 	.mul_double_nonct = ec_mul_double_nonct,
1306f6116716Stb 	.field_mul = ec_simple_field_mul,
1307f6116716Stb 	.field_sqr = ec_simple_field_sqr,
1308cb3e3e66Stb };
1309cb3e3e66Stb 
1310cb3e3e66Stb const EC_METHOD *
1311cb3e3e66Stb EC_GFp_simple_method(void)
1312cb3e3e66Stb {
1313cb3e3e66Stb 	return &ec_GFp_simple_method;
1314cb3e3e66Stb }
1315cb3e3e66Stb LCRYPTO_ALIAS(EC_GFp_simple_method);
1316107480a9Stb 
1317107480a9Stb static const EC_METHOD ec_GFp_mont_method = {
1318d9a83419Stb 	.group_set_curve = ec_mont_group_set_curve,
1319d9a83419Stb 	.group_get_curve = ec_group_get_curve,
13204fb59ff9Stb 	.point_is_on_curve = ec_point_is_on_curve,
13214fb59ff9Stb 	.point_cmp = ec_point_cmp,
1322d9a83419Stb 	.point_set_affine_coordinates = ec_point_set_affine_coordinates,
1323d9a83419Stb 	.point_get_affine_coordinates = ec_point_get_affine_coordinates,
13249581610fStb 	.points_make_affine = ec_points_make_affine,
1325d9a83419Stb 	.add = ec_add,
1326d9a83419Stb 	.dbl = ec_dbl,
1327d9a83419Stb 	.invert = ec_invert,
1328d9a83419Stb 	.mul_single_ct = ec_mul_single_ct,
1329d9a83419Stb 	.mul_double_nonct = ec_mul_double_nonct,
1330d9a83419Stb 	.field_mul = ec_mont_field_mul,
1331d9a83419Stb 	.field_sqr = ec_mont_field_sqr,
1332d9a83419Stb 	.field_encode = ec_mont_field_encode,
1333d9a83419Stb 	.field_decode = ec_mont_field_decode,
1334107480a9Stb };
1335107480a9Stb 
1336107480a9Stb const EC_METHOD *
1337107480a9Stb EC_GFp_mont_method(void)
1338107480a9Stb {
1339107480a9Stb 	return &ec_GFp_mont_method;
1340107480a9Stb }
1341107480a9Stb LCRYPTO_ALIAS(EC_GFp_mont_method);
1342