xref: /freebsd/crypto/libecc/src/curves/prj_pt.c (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
1*f0865ec9SKyle Evans /*
2*f0865ec9SKyle Evans  *  Copyright (C) 2017 - This file is part of libecc project
3*f0865ec9SKyle Evans  *
4*f0865ec9SKyle Evans  *  Authors:
5*f0865ec9SKyle Evans  *      Ryad BENADJILA <ryadbenadjila@gmail.com>
6*f0865ec9SKyle Evans  *      Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7*f0865ec9SKyle Evans  *      Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8*f0865ec9SKyle Evans  *
9*f0865ec9SKyle Evans  *  Contributors:
10*f0865ec9SKyle Evans  *      Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11*f0865ec9SKyle Evans  *      Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
12*f0865ec9SKyle Evans  *
13*f0865ec9SKyle Evans  *  This software is licensed under a dual BSD and GPL v2 license.
14*f0865ec9SKyle Evans  *  See LICENSE file at the root folder of the project.
15*f0865ec9SKyle Evans  */
16*f0865ec9SKyle Evans #include <libecc/curves/ec_shortw.h>
17*f0865ec9SKyle Evans #include <libecc/curves/prj_pt.h>
18*f0865ec9SKyle Evans #include <libecc/nn/nn_logical.h>
19*f0865ec9SKyle Evans #include <libecc/nn/nn_add.h>
20*f0865ec9SKyle Evans #include <libecc/nn/nn_rand.h>
21*f0865ec9SKyle Evans #include <libecc/fp/fp_add.h>
22*f0865ec9SKyle Evans #include <libecc/fp/fp_mul.h>
23*f0865ec9SKyle Evans #include <libecc/fp/fp_montgomery.h>
24*f0865ec9SKyle Evans #include <libecc/fp/fp_rand.h>
25*f0865ec9SKyle Evans 
26*f0865ec9SKyle Evans #define PRJ_PT_MAGIC ((word_t)(0xe1cd70babb1d5afeULL))
27*f0865ec9SKyle Evans 
28*f0865ec9SKyle Evans /*
29*f0865ec9SKyle Evans  * Check given projective point has been correctly initialized (using
30*f0865ec9SKyle Evans  * prj_pt_init()). Returns 0 on success, -1 on error.
31*f0865ec9SKyle Evans  */
prj_pt_check_initialized(prj_pt_src_t in)32*f0865ec9SKyle Evans int prj_pt_check_initialized(prj_pt_src_t in)
33*f0865ec9SKyle Evans {
34*f0865ec9SKyle Evans 	int ret;
35*f0865ec9SKyle Evans 
36*f0865ec9SKyle Evans 	MUST_HAVE(((in != NULL) && (in->magic == PRJ_PT_MAGIC)), ret, err);
37*f0865ec9SKyle Evans 	ret = ec_shortw_crv_check_initialized(in->crv);
38*f0865ec9SKyle Evans 
39*f0865ec9SKyle Evans err:
40*f0865ec9SKyle Evans 	return ret;
41*f0865ec9SKyle Evans }
42*f0865ec9SKyle Evans 
43*f0865ec9SKyle Evans /*
44*f0865ec9SKyle Evans  * Initialize the projective point structure on given curve as the point at
45*f0865ec9SKyle Evans  * infinity. The function returns 0 on success, -1 on error.
46*f0865ec9SKyle Evans  */
prj_pt_init(prj_pt_t in,ec_shortw_crv_src_t curve)47*f0865ec9SKyle Evans int prj_pt_init(prj_pt_t in, ec_shortw_crv_src_t curve)
48*f0865ec9SKyle Evans {
49*f0865ec9SKyle Evans 	int ret;
50*f0865ec9SKyle Evans 
51*f0865ec9SKyle Evans 	ret = ec_shortw_crv_check_initialized(curve); EG(ret, err);
52*f0865ec9SKyle Evans 
53*f0865ec9SKyle Evans 	MUST_HAVE((in != NULL), ret, err);
54*f0865ec9SKyle Evans 
55*f0865ec9SKyle Evans 	ret = fp_init(&(in->X), curve->a.ctx); EG(ret, err);
56*f0865ec9SKyle Evans 	ret = fp_init(&(in->Y), curve->a.ctx); EG(ret, err);
57*f0865ec9SKyle Evans 	ret = fp_init(&(in->Z), curve->a.ctx); EG(ret, err);
58*f0865ec9SKyle Evans 	in->crv = curve;
59*f0865ec9SKyle Evans 	in->magic = PRJ_PT_MAGIC;
60*f0865ec9SKyle Evans 
61*f0865ec9SKyle Evans err:
62*f0865ec9SKyle Evans 	return ret;
63*f0865ec9SKyle Evans }
64*f0865ec9SKyle Evans 
65*f0865ec9SKyle Evans /*
66*f0865ec9SKyle Evans  * Initialize the projective point structure on given curve using given
67*f0865ec9SKyle Evans  * coordinates. The function returns 0 on success, -1 on error.
68*f0865ec9SKyle Evans  */
prj_pt_init_from_coords(prj_pt_t in,ec_shortw_crv_src_t curve,fp_src_t xcoord,fp_src_t ycoord,fp_src_t zcoord)69*f0865ec9SKyle Evans int prj_pt_init_from_coords(prj_pt_t in,
70*f0865ec9SKyle Evans 			     ec_shortw_crv_src_t curve,
71*f0865ec9SKyle Evans 			     fp_src_t xcoord, fp_src_t ycoord, fp_src_t zcoord)
72*f0865ec9SKyle Evans {
73*f0865ec9SKyle Evans 	int ret;
74*f0865ec9SKyle Evans 
75*f0865ec9SKyle Evans 	ret = prj_pt_init(in, curve); EG(ret, err);
76*f0865ec9SKyle Evans 	ret = fp_copy(&(in->X), xcoord); EG(ret, err);
77*f0865ec9SKyle Evans 	ret = fp_copy(&(in->Y), ycoord); EG(ret, err);
78*f0865ec9SKyle Evans 	ret = fp_copy(&(in->Z), zcoord);
79*f0865ec9SKyle Evans 
80*f0865ec9SKyle Evans err:
81*f0865ec9SKyle Evans 	return ret;
82*f0865ec9SKyle Evans }
83*f0865ec9SKyle Evans 
84*f0865ec9SKyle Evans /*
85*f0865ec9SKyle Evans  * Uninit given projective point structure. The function returns 0 on success,
86*f0865ec9SKyle Evans  * -1 on error. This is an error if passed point has not already been
87*f0865ec9SKyle Evans  * initialized first.
88*f0865ec9SKyle Evans  */
prj_pt_uninit(prj_pt_t in)89*f0865ec9SKyle Evans void prj_pt_uninit(prj_pt_t in)
90*f0865ec9SKyle Evans {
91*f0865ec9SKyle Evans 	if((in != NULL) && (in->magic == PRJ_PT_MAGIC) && (in->crv != NULL)){
92*f0865ec9SKyle Evans 		in->crv = NULL;
93*f0865ec9SKyle Evans 		in->magic = WORD(0);
94*f0865ec9SKyle Evans 
95*f0865ec9SKyle Evans 		fp_uninit(&(in->X));
96*f0865ec9SKyle Evans 		fp_uninit(&(in->Y));
97*f0865ec9SKyle Evans 		fp_uninit(&(in->Z));
98*f0865ec9SKyle Evans 	}
99*f0865ec9SKyle Evans 
100*f0865ec9SKyle Evans 	return;
101*f0865ec9SKyle Evans }
102*f0865ec9SKyle Evans 
103*f0865ec9SKyle Evans /*
104*f0865ec9SKyle Evans  * Checks if projective point is the point at infinity (last coordinate is 0).
105*f0865ec9SKyle Evans  * In that case, 'iszero' out parameter is set to 1. It is set to 0 if the
106*f0865ec9SKyle Evans  * point is not the point at infinity. The function returns 0 on success, -1 on
107*f0865ec9SKyle Evans  * error. On error, 'iszero' is not meaningful.
108*f0865ec9SKyle Evans  */
prj_pt_iszero(prj_pt_src_t in,int * iszero)109*f0865ec9SKyle Evans int prj_pt_iszero(prj_pt_src_t in, int *iszero)
110*f0865ec9SKyle Evans {
111*f0865ec9SKyle Evans 	int ret;
112*f0865ec9SKyle Evans 
113*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in); EG(ret, err);
114*f0865ec9SKyle Evans 	ret = fp_iszero(&(in->Z), iszero);
115*f0865ec9SKyle Evans 
116*f0865ec9SKyle Evans err:
117*f0865ec9SKyle Evans 	return ret;
118*f0865ec9SKyle Evans }
119*f0865ec9SKyle Evans 
120*f0865ec9SKyle Evans /*
121*f0865ec9SKyle Evans  * Set given projective point 'out' to the point at infinity. The functions
122*f0865ec9SKyle Evans  * returns 0 on success, -1 on error.
123*f0865ec9SKyle Evans  */
prj_pt_zero(prj_pt_t out)124*f0865ec9SKyle Evans int prj_pt_zero(prj_pt_t out)
125*f0865ec9SKyle Evans {
126*f0865ec9SKyle Evans 	int ret;
127*f0865ec9SKyle Evans 
128*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(out); EG(ret, err);
129*f0865ec9SKyle Evans 
130*f0865ec9SKyle Evans 	ret = fp_zero(&(out->X)); EG(ret, err);
131*f0865ec9SKyle Evans 	ret = fp_one(&(out->Y)); EG(ret, err);
132*f0865ec9SKyle Evans 	ret = fp_zero(&(out->Z));
133*f0865ec9SKyle Evans 
134*f0865ec9SKyle Evans err:
135*f0865ec9SKyle Evans 	return ret;
136*f0865ec9SKyle Evans }
137*f0865ec9SKyle Evans 
138*f0865ec9SKyle Evans /*
139*f0865ec9SKyle Evans  * Check if a projective point is indeed on its curve. The function sets
140*f0865ec9SKyle Evans  * 'on_curve' out parameter to 1 if the point is on the curve, 0 if not.
141*f0865ec9SKyle Evans  * The function returns 0 on success, -1 on error. 'on_curve' is not
142*f0865ec9SKyle Evans  * meaningful on error.
143*f0865ec9SKyle Evans  */
prj_pt_is_on_curve(prj_pt_src_t in,int * on_curve)144*f0865ec9SKyle Evans int prj_pt_is_on_curve(prj_pt_src_t in,  int *on_curve)
145*f0865ec9SKyle Evans {
146*f0865ec9SKyle Evans 	int ret, cmp;
147*f0865ec9SKyle Evans 
148*f0865ec9SKyle Evans 	/* In order to check that we are on the curve, we
149*f0865ec9SKyle Evans 	 * use the projective formula of the curve:
150*f0865ec9SKyle Evans 	 *
151*f0865ec9SKyle Evans 	 *   Y**2 * Z = X**3 + a * X * Z**2 + b * Z**3
152*f0865ec9SKyle Evans 	 *
153*f0865ec9SKyle Evans 	 */
154*f0865ec9SKyle Evans 	fp X, Y, Z;
155*f0865ec9SKyle Evans 	X.magic = Y.magic = Z.magic = WORD(0);
156*f0865ec9SKyle Evans 
157*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in); EG(ret, err);
158*f0865ec9SKyle Evans 	ret = ec_shortw_crv_check_initialized(in->crv); EG(ret, err);
159*f0865ec9SKyle Evans 	MUST_HAVE((on_curve != NULL), ret, err);
160*f0865ec9SKyle Evans 
161*f0865ec9SKyle Evans 	ret = fp_init(&X, in->X.ctx); EG(ret, err);
162*f0865ec9SKyle Evans 	ret = fp_init(&Y, in->X.ctx); EG(ret, err);
163*f0865ec9SKyle Evans 	ret = fp_init(&Z, in->X.ctx); EG(ret, err);
164*f0865ec9SKyle Evans 
165*f0865ec9SKyle Evans 	/* Compute X**3 + a * X * Z**2 + b * Z**3 on one side */
166*f0865ec9SKyle Evans 	ret = fp_sqr(&X, &(in->X)); EG(ret, err);
167*f0865ec9SKyle Evans 	ret = fp_mul(&X, &X, &(in->X)); EG(ret, err);
168*f0865ec9SKyle Evans 	ret = fp_mul(&Z, &(in->X), &(in->crv->a)); EG(ret, err);
169*f0865ec9SKyle Evans 	ret = fp_mul(&Y, &(in->crv->b), &(in->Z)); EG(ret, err);
170*f0865ec9SKyle Evans 	ret = fp_add(&Z, &Z, &Y); EG(ret, err);
171*f0865ec9SKyle Evans 	ret = fp_mul(&Z, &Z, &(in->Z)); EG(ret, err);
172*f0865ec9SKyle Evans 	ret = fp_mul(&Z, &Z, &(in->Z)); EG(ret, err);
173*f0865ec9SKyle Evans 	ret = fp_add(&X, &X, &Z); EG(ret, err);
174*f0865ec9SKyle Evans 
175*f0865ec9SKyle Evans 	/* Compute Y**2 * Z on the other side */
176*f0865ec9SKyle Evans 	ret = fp_sqr(&Y, &(in->Y)); EG(ret, err);
177*f0865ec9SKyle Evans 	ret = fp_mul(&Y, &Y, &(in->Z)); EG(ret, err);
178*f0865ec9SKyle Evans 
179*f0865ec9SKyle Evans 	/* Compare the two values */
180*f0865ec9SKyle Evans 	ret = fp_cmp(&X, &Y, &cmp); EG(ret, err);
181*f0865ec9SKyle Evans 
182*f0865ec9SKyle Evans 	(*on_curve) = (!cmp);
183*f0865ec9SKyle Evans 
184*f0865ec9SKyle Evans err:
185*f0865ec9SKyle Evans 	fp_uninit(&X);
186*f0865ec9SKyle Evans 	fp_uninit(&Y);
187*f0865ec9SKyle Evans 	fp_uninit(&Z);
188*f0865ec9SKyle Evans 
189*f0865ec9SKyle Evans 	return ret;
190*f0865ec9SKyle Evans }
191*f0865ec9SKyle Evans 
192*f0865ec9SKyle Evans /*
193*f0865ec9SKyle Evans  * The function copies 'in' projective point to 'out'. 'out' is initialized by
194*f0865ec9SKyle Evans  * the function. The function returns 0 on sucess, -1 on error.
195*f0865ec9SKyle Evans  */
prj_pt_copy(prj_pt_t out,prj_pt_src_t in)196*f0865ec9SKyle Evans int prj_pt_copy(prj_pt_t out, prj_pt_src_t in)
197*f0865ec9SKyle Evans {
198*f0865ec9SKyle Evans 	int ret;
199*f0865ec9SKyle Evans 
200*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in); EG(ret, err);
201*f0865ec9SKyle Evans 
202*f0865ec9SKyle Evans 	ret = prj_pt_init(out, in->crv); EG(ret, err);
203*f0865ec9SKyle Evans 
204*f0865ec9SKyle Evans 	ret = fp_copy(&(out->X), &(in->X)); EG(ret, err);
205*f0865ec9SKyle Evans 	ret = fp_copy(&(out->Y), &(in->Y)); EG(ret, err);
206*f0865ec9SKyle Evans 	ret = fp_copy(&(out->Z), &(in->Z));
207*f0865ec9SKyle Evans 
208*f0865ec9SKyle Evans err:
209*f0865ec9SKyle Evans 	return ret;
210*f0865ec9SKyle Evans }
211*f0865ec9SKyle Evans 
212*f0865ec9SKyle Evans /*
213*f0865ec9SKyle Evans  * Convert given projective point 'in' to affine representation in 'out'. 'out'
214*f0865ec9SKyle Evans  * is initialized by the function. The function returns 0 on success, -1 on
215*f0865ec9SKyle Evans  * error. Passing the point at infinty to the function is considered as an
216*f0865ec9SKyle Evans  * error.
217*f0865ec9SKyle Evans  */
prj_pt_to_aff(aff_pt_t out,prj_pt_src_t in)218*f0865ec9SKyle Evans int prj_pt_to_aff(aff_pt_t out, prj_pt_src_t in)
219*f0865ec9SKyle Evans {
220*f0865ec9SKyle Evans 	int ret, iszero;
221*f0865ec9SKyle Evans 
222*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in); EG(ret, err);
223*f0865ec9SKyle Evans 
224*f0865ec9SKyle Evans 	ret = prj_pt_iszero(in, &iszero); EG(ret, err);
225*f0865ec9SKyle Evans 	MUST_HAVE((!iszero), ret, err);
226*f0865ec9SKyle Evans 
227*f0865ec9SKyle Evans 	ret = aff_pt_init(out, in->crv); EG(ret, err);
228*f0865ec9SKyle Evans 
229*f0865ec9SKyle Evans 	ret = fp_inv(&(out->x), &(in->Z)); EG(ret, err);
230*f0865ec9SKyle Evans 	ret = fp_mul(&(out->y), &(in->Y), &(out->x)); EG(ret, err);
231*f0865ec9SKyle Evans 	ret = fp_mul(&(out->x), &(in->X), &(out->x));
232*f0865ec9SKyle Evans 
233*f0865ec9SKyle Evans err:
234*f0865ec9SKyle Evans 	return ret;
235*f0865ec9SKyle Evans }
236*f0865ec9SKyle Evans 
237*f0865ec9SKyle Evans /*
238*f0865ec9SKyle Evans  * Get the unique Z = 1 projective point representation ("equivalent" to affine
239*f0865ec9SKyle Evans  * point). The function returns 0 on success, -1 on error.
240*f0865ec9SKyle Evans  */
prj_pt_unique(prj_pt_t out,prj_pt_src_t in)241*f0865ec9SKyle Evans int prj_pt_unique(prj_pt_t out, prj_pt_src_t in)
242*f0865ec9SKyle Evans {
243*f0865ec9SKyle Evans 	int ret, iszero;
244*f0865ec9SKyle Evans 
245*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in); EG(ret, err);
246*f0865ec9SKyle Evans 	ret = prj_pt_iszero(in, &iszero); EG(ret, err);
247*f0865ec9SKyle Evans 	MUST_HAVE((!iszero), ret, err);
248*f0865ec9SKyle Evans 
249*f0865ec9SKyle Evans 	if(out == in){
250*f0865ec9SKyle Evans 		/* Aliasing case */
251*f0865ec9SKyle Evans 		fp tmp;
252*f0865ec9SKyle Evans 		tmp.magic = WORD(0);
253*f0865ec9SKyle Evans 
254*f0865ec9SKyle Evans 		ret = fp_init(&tmp, (in->Z).ctx); EG(ret, err);
255*f0865ec9SKyle Evans 		ret = fp_inv(&tmp, &(in->Z)); EG(ret, err1);
256*f0865ec9SKyle Evans 		ret = fp_mul(&(out->Y), &(in->Y), &tmp); EG(ret, err1);
257*f0865ec9SKyle Evans 		ret = fp_mul(&(out->X), &(in->X), &tmp); EG(ret, err1);
258*f0865ec9SKyle Evans 		ret = fp_one(&(out->Z)); EG(ret, err1);
259*f0865ec9SKyle Evans err1:
260*f0865ec9SKyle Evans 		fp_uninit(&tmp); EG(ret, err);
261*f0865ec9SKyle Evans 	}
262*f0865ec9SKyle Evans 	else{
263*f0865ec9SKyle Evans 	        ret = prj_pt_init(out, in->crv); EG(ret, err);
264*f0865ec9SKyle Evans 		ret = fp_inv(&(out->X), &(in->Z)); EG(ret, err);
265*f0865ec9SKyle Evans 		ret = fp_mul(&(out->Y), &(in->Y), &(out->X)); EG(ret, err);
266*f0865ec9SKyle Evans 		ret = fp_mul(&(out->X), &(in->X), &(out->X)); EG(ret, err);
267*f0865ec9SKyle Evans 		ret = fp_one(&(out->Z)); EG(ret, err);
268*f0865ec9SKyle Evans 	}
269*f0865ec9SKyle Evans 
270*f0865ec9SKyle Evans 
271*f0865ec9SKyle Evans err:
272*f0865ec9SKyle Evans 	return ret;
273*f0865ec9SKyle Evans }
274*f0865ec9SKyle Evans 
275*f0865ec9SKyle Evans /*
276*f0865ec9SKyle Evans  * Converts affine point 'in' to projective representation in 'out'. 'out' is
277*f0865ec9SKyle Evans  * initialized by the function. The function returns 0 on success, -1 on error.
278*f0865ec9SKyle Evans  */
ec_shortw_aff_to_prj(prj_pt_t out,aff_pt_src_t in)279*f0865ec9SKyle Evans int ec_shortw_aff_to_prj(prj_pt_t out, aff_pt_src_t in)
280*f0865ec9SKyle Evans {
281*f0865ec9SKyle Evans 	int ret, on_curve;
282*f0865ec9SKyle Evans 
283*f0865ec9SKyle Evans 	ret = aff_pt_check_initialized(in); EG(ret, err);
284*f0865ec9SKyle Evans 
285*f0865ec9SKyle Evans 	/* The input affine point must be on the curve */
286*f0865ec9SKyle Evans 	ret = aff_pt_is_on_curve(in, &on_curve); EG(ret, err);
287*f0865ec9SKyle Evans 	MUST_HAVE(on_curve, ret, err);
288*f0865ec9SKyle Evans 
289*f0865ec9SKyle Evans 	ret = prj_pt_init(out, in->crv); EG(ret, err);
290*f0865ec9SKyle Evans 	ret = fp_copy(&(out->X), &(in->x)); EG(ret, err);
291*f0865ec9SKyle Evans 	ret = fp_copy(&(out->Y), &(in->y)); EG(ret, err);
292*f0865ec9SKyle Evans 	ret = nn_one(&(out->Z).fp_val); /* Z = 1 */
293*f0865ec9SKyle Evans 
294*f0865ec9SKyle Evans err:
295*f0865ec9SKyle Evans 	return ret;
296*f0865ec9SKyle Evans }
297*f0865ec9SKyle Evans 
298*f0865ec9SKyle Evans /*
299*f0865ec9SKyle Evans  * Compare projective points 'in1' and 'in2'. On success, 'cmp' is set to
300*f0865ec9SKyle Evans  * the result of the comparison (0 if in1 == in2, !0 if in1 != in2). The
301*f0865ec9SKyle Evans  * function returns 0 on success, -1 on error.
302*f0865ec9SKyle Evans  */
prj_pt_cmp(prj_pt_src_t in1,prj_pt_src_t in2,int * cmp)303*f0865ec9SKyle Evans int prj_pt_cmp(prj_pt_src_t in1, prj_pt_src_t in2, int *cmp)
304*f0865ec9SKyle Evans {
305*f0865ec9SKyle Evans 	fp X1, X2, Y1, Y2;
306*f0865ec9SKyle Evans 	int ret, x_cmp, y_cmp;
307*f0865ec9SKyle Evans 	X1.magic = X2.magic = Y1.magic = Y2.magic = WORD(0);
308*f0865ec9SKyle Evans 
309*f0865ec9SKyle Evans 	MUST_HAVE((cmp != NULL), ret, err);
310*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in1); EG(ret, err);
311*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in2); EG(ret, err);
312*f0865ec9SKyle Evans 
313*f0865ec9SKyle Evans 	MUST_HAVE((in1->crv == in2->crv), ret, err);
314*f0865ec9SKyle Evans 
315*f0865ec9SKyle Evans 	ret = fp_init(&X1, (in1->X).ctx); EG(ret, err);
316*f0865ec9SKyle Evans 	ret = fp_init(&X2, (in2->X).ctx); EG(ret, err);
317*f0865ec9SKyle Evans 	ret = fp_init(&Y1, (in1->Y).ctx); EG(ret, err);
318*f0865ec9SKyle Evans 	ret = fp_init(&Y2, (in2->Y).ctx); EG(ret, err);
319*f0865ec9SKyle Evans 
320*f0865ec9SKyle Evans 	/*
321*f0865ec9SKyle Evans 	 * Montgomery multiplication is used as it is faster than
322*f0865ec9SKyle Evans 	 * usual multiplication and the spurious multiplicative
323*f0865ec9SKyle Evans 	 * factor does not matter.
324*f0865ec9SKyle Evans 	 */
325*f0865ec9SKyle Evans 	ret = fp_mul_monty(&X1, &(in1->X), &(in2->Z)); EG(ret, err);
326*f0865ec9SKyle Evans 	ret = fp_mul_monty(&X2, &(in2->X), &(in1->Z)); EG(ret, err);
327*f0865ec9SKyle Evans 	ret = fp_mul_monty(&Y1, &(in1->Y), &(in2->Z)); EG(ret, err);
328*f0865ec9SKyle Evans 	ret = fp_mul_monty(&Y2, &(in2->Y), &(in1->Z)); EG(ret, err);
329*f0865ec9SKyle Evans 
330*f0865ec9SKyle Evans 	ret = fp_mul_monty(&X1, &(in1->X), &(in2->Z)); EG(ret, err);
331*f0865ec9SKyle Evans 	ret = fp_mul_monty(&X2, &(in2->X), &(in1->Z)); EG(ret, err);
332*f0865ec9SKyle Evans 	ret = fp_mul_monty(&Y1, &(in1->Y), &(in2->Z)); EG(ret, err);
333*f0865ec9SKyle Evans 	ret = fp_mul_monty(&Y2, &(in2->Y), &(in1->Z)); EG(ret, err);
334*f0865ec9SKyle Evans 	ret = fp_cmp(&X1, &X2, &x_cmp); EG(ret, err);
335*f0865ec9SKyle Evans 	ret = fp_cmp(&Y1, &Y2, &y_cmp);
336*f0865ec9SKyle Evans 
337*f0865ec9SKyle Evans 	if (!ret) {
338*f0865ec9SKyle Evans 		(*cmp) = (x_cmp | y_cmp);
339*f0865ec9SKyle Evans 	}
340*f0865ec9SKyle Evans 
341*f0865ec9SKyle Evans err:
342*f0865ec9SKyle Evans 	fp_uninit(&Y2);
343*f0865ec9SKyle Evans 	fp_uninit(&Y1);
344*f0865ec9SKyle Evans 	fp_uninit(&X2);
345*f0865ec9SKyle Evans 	fp_uninit(&X1);
346*f0865ec9SKyle Evans 
347*f0865ec9SKyle Evans 	return ret;
348*f0865ec9SKyle Evans }
349*f0865ec9SKyle Evans 
350*f0865ec9SKyle Evans /*
351*f0865ec9SKyle Evans  * NOTE: this internal functions assumes that upper layer have checked that in1 and in2
352*f0865ec9SKyle Evans  * are initialized, and that cmp is not NULL.
353*f0865ec9SKyle Evans  */
_prj_pt_eq_or_opp_X(prj_pt_src_t in1,prj_pt_src_t in2,int * cmp)354*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static inline int _prj_pt_eq_or_opp_X(prj_pt_src_t in1, prj_pt_src_t in2, int *cmp)
355*f0865ec9SKyle Evans {
356*f0865ec9SKyle Evans 	int ret;
357*f0865ec9SKyle Evans 	fp X1, X2;
358*f0865ec9SKyle Evans 	X1.magic = X2.magic = WORD(0);
359*f0865ec9SKyle Evans 
360*f0865ec9SKyle Evans 	/*
361*f0865ec9SKyle Evans 	 * Montgomery multiplication is used as it is faster than
362*f0865ec9SKyle Evans 	 * usual multiplication and the spurious multiplicative
363*f0865ec9SKyle Evans 	 * factor does not matter.
364*f0865ec9SKyle Evans 	 */
365*f0865ec9SKyle Evans 	ret = fp_init(&X1, (in1->X).ctx); EG(ret, err);
366*f0865ec9SKyle Evans 	ret = fp_init(&X2, (in2->X).ctx); EG(ret, err);
367*f0865ec9SKyle Evans 	ret = fp_mul_monty(&X1, &(in1->X), &(in2->Z)); EG(ret, err);
368*f0865ec9SKyle Evans 	ret = fp_mul_monty(&X2, &(in2->X), &(in1->Z)); EG(ret, err);
369*f0865ec9SKyle Evans 	ret = fp_cmp(&X1, &X2, cmp);
370*f0865ec9SKyle Evans 
371*f0865ec9SKyle Evans err:
372*f0865ec9SKyle Evans 	fp_uninit(&X1);
373*f0865ec9SKyle Evans 	fp_uninit(&X2);
374*f0865ec9SKyle Evans 
375*f0865ec9SKyle Evans 	return ret;
376*f0865ec9SKyle Evans }
377*f0865ec9SKyle Evans 
378*f0865ec9SKyle Evans /*
379*f0865ec9SKyle Evans  * NOTE: this internal functions assumes that upper layer have checked that in1 and in2
380*f0865ec9SKyle Evans  * are initialized, and that eq_or_opp is not NULL.
381*f0865ec9SKyle Evans  */
_prj_pt_eq_or_opp_Y(prj_pt_src_t in1,prj_pt_src_t in2,int * eq_or_opp)382*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static inline int _prj_pt_eq_or_opp_Y(prj_pt_src_t in1, prj_pt_src_t in2, int *eq_or_opp)
383*f0865ec9SKyle Evans {
384*f0865ec9SKyle Evans 	int ret;
385*f0865ec9SKyle Evans 	fp Y1, Y2;
386*f0865ec9SKyle Evans 	Y1.magic = Y2.magic = WORD(0);
387*f0865ec9SKyle Evans 
388*f0865ec9SKyle Evans 	/*
389*f0865ec9SKyle Evans 	 * Montgomery multiplication is used as it is faster than
390*f0865ec9SKyle Evans 	 * usual multiplication and the spurious multiplicative
391*f0865ec9SKyle Evans 	 * factor does not matter.
392*f0865ec9SKyle Evans 	 */
393*f0865ec9SKyle Evans 	ret = fp_init(&Y1, (in1->Y).ctx); EG(ret, err);
394*f0865ec9SKyle Evans 	ret = fp_init(&Y2, (in2->Y).ctx); EG(ret, err);
395*f0865ec9SKyle Evans 	ret = fp_mul_monty(&Y1, &(in1->Y), &(in2->Z)); EG(ret, err);
396*f0865ec9SKyle Evans 	ret = fp_mul_monty(&Y2, &(in2->Y), &(in1->Z)); EG(ret, err);
397*f0865ec9SKyle Evans 	ret = fp_eq_or_opp(&Y1, &Y2, eq_or_opp);
398*f0865ec9SKyle Evans 
399*f0865ec9SKyle Evans err:
400*f0865ec9SKyle Evans 	fp_uninit(&Y1);
401*f0865ec9SKyle Evans 	fp_uninit(&Y2);
402*f0865ec9SKyle Evans 
403*f0865ec9SKyle Evans 	return ret;
404*f0865ec9SKyle Evans }
405*f0865ec9SKyle Evans 
406*f0865ec9SKyle Evans  /*
407*f0865ec9SKyle Evans  * The functions tests if given projective points 'in1' and 'in2' are equal or
408*f0865ec9SKyle Evans  * opposite. On success, the result of the comparison is given via 'eq_or_opp'
409*f0865ec9SKyle Evans  * out parameter (1 if equal or opposite, 0 otherwise). The function returns
410*f0865ec9SKyle Evans  * 0 on succes, -1 on error.
411*f0865ec9SKyle Evans  */
prj_pt_eq_or_opp(prj_pt_src_t in1,prj_pt_src_t in2,int * eq_or_opp)412*f0865ec9SKyle Evans int prj_pt_eq_or_opp(prj_pt_src_t in1, prj_pt_src_t in2, int *eq_or_opp)
413*f0865ec9SKyle Evans {
414*f0865ec9SKyle Evans 	int ret, cmp, _eq_or_opp;
415*f0865ec9SKyle Evans 
416*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in1); EG(ret, err);
417*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in2); EG(ret, err);
418*f0865ec9SKyle Evans 	MUST_HAVE((in1->crv == in2->crv), ret, err);
419*f0865ec9SKyle Evans 	MUST_HAVE((eq_or_opp != NULL), ret, err);
420*f0865ec9SKyle Evans 
421*f0865ec9SKyle Evans 	ret = _prj_pt_eq_or_opp_X(in1, in2, &cmp); EG(ret, err);
422*f0865ec9SKyle Evans 	ret = _prj_pt_eq_or_opp_Y(in1, in2, &_eq_or_opp);
423*f0865ec9SKyle Evans 
424*f0865ec9SKyle Evans 	if (!ret) {
425*f0865ec9SKyle Evans 		(*eq_or_opp) = ((cmp == 0) & _eq_or_opp);
426*f0865ec9SKyle Evans 	}
427*f0865ec9SKyle Evans 
428*f0865ec9SKyle Evans err:
429*f0865ec9SKyle Evans 	return ret;
430*f0865ec9SKyle Evans }
431*f0865ec9SKyle Evans 
432*f0865ec9SKyle Evans /* Compute the opposite of a projective point. Supports aliasing.
433*f0865ec9SKyle Evans  * Returns 0 on success, -1 on failure.
434*f0865ec9SKyle Evans  */
prj_pt_neg(prj_pt_t out,prj_pt_src_t in)435*f0865ec9SKyle Evans int prj_pt_neg(prj_pt_t out, prj_pt_src_t in)
436*f0865ec9SKyle Evans {
437*f0865ec9SKyle Evans 	int ret;
438*f0865ec9SKyle Evans 
439*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in); EG(ret, err);
440*f0865ec9SKyle Evans 
441*f0865ec9SKyle Evans 	if (out != in) { /* Copy point if not aliased */
442*f0865ec9SKyle Evans 		ret = prj_pt_init(out, in->crv); EG(ret, err);
443*f0865ec9SKyle Evans 		ret = prj_pt_copy(out, in); EG(ret, err);
444*f0865ec9SKyle Evans 	}
445*f0865ec9SKyle Evans 
446*f0865ec9SKyle Evans 	/* Then, negate Y */
447*f0865ec9SKyle Evans 	ret = fp_neg(&(out->Y), &(out->Y));
448*f0865ec9SKyle Evans 
449*f0865ec9SKyle Evans err:
450*f0865ec9SKyle Evans 	return ret;
451*f0865ec9SKyle Evans }
452*f0865ec9SKyle Evans 
453*f0865ec9SKyle Evans /*
454*f0865ec9SKyle Evans  * Import a projective point from a buffer with the following layout; the 3
455*f0865ec9SKyle Evans  * coordinates (elements of Fp) are each encoded on p_len bytes, where p_len
456*f0865ec9SKyle Evans  * is the size of p in bytes (e.g. 66 for a prime p of 521 bits). Each
457*f0865ec9SKyle Evans  * coordinate is encoded in big endian. Size of buffer must exactly match
458*f0865ec9SKyle Evans  * 3 * p_len. The projective point is initialized by the function.
459*f0865ec9SKyle Evans  *
460*f0865ec9SKyle Evans  * The function returns 0 on success, -1 on error.
461*f0865ec9SKyle Evans  */
prj_pt_import_from_buf(prj_pt_t pt,const u8 * pt_buf,u16 pt_buf_len,ec_shortw_crv_src_t crv)462*f0865ec9SKyle Evans int prj_pt_import_from_buf(prj_pt_t pt,
463*f0865ec9SKyle Evans 			   const u8 *pt_buf,
464*f0865ec9SKyle Evans 			   u16 pt_buf_len, ec_shortw_crv_src_t crv)
465*f0865ec9SKyle Evans {
466*f0865ec9SKyle Evans 	int on_curve, ret;
467*f0865ec9SKyle Evans 	fp_ctx_src_t ctx;
468*f0865ec9SKyle Evans 	u16 coord_len;
469*f0865ec9SKyle Evans 
470*f0865ec9SKyle Evans 	ret = ec_shortw_crv_check_initialized(crv); EG(ret, err);
471*f0865ec9SKyle Evans 	MUST_HAVE((pt_buf != NULL) && (pt != NULL), ret, err);
472*f0865ec9SKyle Evans 
473*f0865ec9SKyle Evans 	ctx = crv->a.ctx;
474*f0865ec9SKyle Evans 	coord_len = (u16)BYTECEIL(ctx->p_bitlen);
475*f0865ec9SKyle Evans 	MUST_HAVE((pt_buf_len == (3 * coord_len)), ret, err);
476*f0865ec9SKyle Evans 
477*f0865ec9SKyle Evans 	ret = fp_init_from_buf(&(pt->X), ctx, pt_buf, coord_len); EG(ret, err);
478*f0865ec9SKyle Evans 	ret = fp_init_from_buf(&(pt->Y), ctx, pt_buf + coord_len, coord_len); EG(ret, err);
479*f0865ec9SKyle Evans 	ret = fp_init_from_buf(&(pt->Z), ctx, pt_buf + (2 * coord_len), coord_len); EG(ret, err);
480*f0865ec9SKyle Evans 
481*f0865ec9SKyle Evans 	/* Set the curve */
482*f0865ec9SKyle Evans 	pt->crv = crv;
483*f0865ec9SKyle Evans 
484*f0865ec9SKyle Evans 	/* Mark the point as initialized */
485*f0865ec9SKyle Evans 	pt->magic = PRJ_PT_MAGIC;
486*f0865ec9SKyle Evans 
487*f0865ec9SKyle Evans 	/* Check that the point is indeed on the provided curve, uninitialize it
488*f0865ec9SKyle Evans 	 * if this is not the case.
489*f0865ec9SKyle Evans 	 */
490*f0865ec9SKyle Evans 	ret = prj_pt_is_on_curve(pt, &on_curve); EG(ret, err);
491*f0865ec9SKyle Evans 	if (!on_curve){
492*f0865ec9SKyle Evans 		prj_pt_uninit(pt);
493*f0865ec9SKyle Evans 		ret = -1;
494*f0865ec9SKyle Evans 	}
495*f0865ec9SKyle Evans 
496*f0865ec9SKyle Evans err:
497*f0865ec9SKyle Evans 	PTR_NULLIFY(ctx);
498*f0865ec9SKyle Evans 
499*f0865ec9SKyle Evans 	return ret;
500*f0865ec9SKyle Evans }
501*f0865ec9SKyle Evans 
502*f0865ec9SKyle Evans /*
503*f0865ec9SKyle Evans  * Import a projective point from an affine point buffer with the following layout; the 2
504*f0865ec9SKyle Evans  * coordinates (elements of Fp) are each encoded on p_len bytes, where p_len
505*f0865ec9SKyle Evans  * is the size of p in bytes (e.g. 66 for a prime p of 521 bits). Each
506*f0865ec9SKyle Evans  * coordinate is encoded in big endian. Size of buffer must exactly match
507*f0865ec9SKyle Evans  * 2 * p_len. The projective point is initialized by the function.
508*f0865ec9SKyle Evans  *
509*f0865ec9SKyle Evans  * The function returns 0 on success, -1 on error.
510*f0865ec9SKyle Evans  */
prj_pt_import_from_aff_buf(prj_pt_t pt,const u8 * pt_buf,u16 pt_buf_len,ec_shortw_crv_src_t crv)511*f0865ec9SKyle Evans int prj_pt_import_from_aff_buf(prj_pt_t pt,
512*f0865ec9SKyle Evans 			   const u8 *pt_buf,
513*f0865ec9SKyle Evans 			   u16 pt_buf_len, ec_shortw_crv_src_t crv)
514*f0865ec9SKyle Evans {
515*f0865ec9SKyle Evans 	int ret, on_curve;
516*f0865ec9SKyle Evans 	fp_ctx_src_t ctx;
517*f0865ec9SKyle Evans 	u16 coord_len;
518*f0865ec9SKyle Evans 
519*f0865ec9SKyle Evans 	ret = ec_shortw_crv_check_initialized(crv); EG(ret, err);
520*f0865ec9SKyle Evans 	MUST_HAVE((pt_buf != NULL) && (pt != NULL), ret, err);
521*f0865ec9SKyle Evans 
522*f0865ec9SKyle Evans 	ctx = crv->a.ctx;
523*f0865ec9SKyle Evans 	coord_len = (u16)BYTECEIL(ctx->p_bitlen);
524*f0865ec9SKyle Evans 	MUST_HAVE((pt_buf_len == (2 * coord_len)), ret, err);
525*f0865ec9SKyle Evans 
526*f0865ec9SKyle Evans 	ret = fp_init_from_buf(&(pt->X), ctx, pt_buf, coord_len); EG(ret, err);
527*f0865ec9SKyle Evans 	ret = fp_init_from_buf(&(pt->Y), ctx, pt_buf + coord_len, coord_len); EG(ret, err);
528*f0865ec9SKyle Evans 	/* Z coordinate is set to 1 */
529*f0865ec9SKyle Evans 	ret = fp_init(&(pt->Z), ctx); EG(ret, err);
530*f0865ec9SKyle Evans 	ret = fp_one(&(pt->Z)); EG(ret, err);
531*f0865ec9SKyle Evans 
532*f0865ec9SKyle Evans 	/* Set the curve */
533*f0865ec9SKyle Evans 	pt->crv = crv;
534*f0865ec9SKyle Evans 
535*f0865ec9SKyle Evans 	/* Mark the point as initialized */
536*f0865ec9SKyle Evans 	pt->magic = PRJ_PT_MAGIC;
537*f0865ec9SKyle Evans 
538*f0865ec9SKyle Evans 	/* Check that the point is indeed on the provided curve, uninitialize it
539*f0865ec9SKyle Evans 	 * if this is not the case.
540*f0865ec9SKyle Evans 	 */
541*f0865ec9SKyle Evans 	ret = prj_pt_is_on_curve(pt, &on_curve); EG(ret, err);
542*f0865ec9SKyle Evans 	if (!on_curve){
543*f0865ec9SKyle Evans 		prj_pt_uninit(pt);
544*f0865ec9SKyle Evans 		ret = -1;
545*f0865ec9SKyle Evans 	}
546*f0865ec9SKyle Evans 
547*f0865ec9SKyle Evans err:
548*f0865ec9SKyle Evans 	PTR_NULLIFY(ctx);
549*f0865ec9SKyle Evans 
550*f0865ec9SKyle Evans 	return ret;
551*f0865ec9SKyle Evans }
552*f0865ec9SKyle Evans 
553*f0865ec9SKyle Evans 
554*f0865ec9SKyle Evans /* Export a projective point to a buffer with the following layout; the 3
555*f0865ec9SKyle Evans  * coordinates (elements of Fp) are each encoded on p_len bytes, where p_len
556*f0865ec9SKyle Evans  * is the size of p in bytes (e.g. 66 for a prime p of 521 bits). Each
557*f0865ec9SKyle Evans  * coordinate is encoded in big endian. Size of buffer must exactly match
558*f0865ec9SKyle Evans  * 3 * p_len.
559*f0865ec9SKyle Evans  *
560*f0865ec9SKyle Evans  * The function returns 0 on success, -1 on error.
561*f0865ec9SKyle Evans  */
prj_pt_export_to_buf(prj_pt_src_t pt,u8 * pt_buf,u32 pt_buf_len)562*f0865ec9SKyle Evans int prj_pt_export_to_buf(prj_pt_src_t pt, u8 *pt_buf, u32 pt_buf_len)
563*f0865ec9SKyle Evans {
564*f0865ec9SKyle Evans 	fp_ctx_src_t ctx;
565*f0865ec9SKyle Evans 	u16 coord_len;
566*f0865ec9SKyle Evans 	int ret, on_curve;
567*f0865ec9SKyle Evans 
568*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(pt); EG(ret, err);
569*f0865ec9SKyle Evans 
570*f0865ec9SKyle Evans 	MUST_HAVE((pt_buf != NULL), ret, err);
571*f0865ec9SKyle Evans 
572*f0865ec9SKyle Evans 	/* The point to be exported must be on the curve */
573*f0865ec9SKyle Evans 	ret = prj_pt_is_on_curve(pt, &on_curve); EG(ret, err);
574*f0865ec9SKyle Evans 	MUST_HAVE((on_curve), ret, err);
575*f0865ec9SKyle Evans 
576*f0865ec9SKyle Evans 	ctx = pt->crv->a.ctx;
577*f0865ec9SKyle Evans 	coord_len = (u16)BYTECEIL(ctx->p_bitlen);
578*f0865ec9SKyle Evans 	MUST_HAVE((pt_buf_len == (3 * coord_len)), ret, err);
579*f0865ec9SKyle Evans 
580*f0865ec9SKyle Evans 	/* Export the three coordinates */
581*f0865ec9SKyle Evans 	ret = fp_export_to_buf(pt_buf, coord_len, &(pt->X)); EG(ret, err);
582*f0865ec9SKyle Evans 	ret = fp_export_to_buf(pt_buf + coord_len, coord_len, &(pt->Y)); EG(ret, err);
583*f0865ec9SKyle Evans 	ret = fp_export_to_buf(pt_buf + (2 * coord_len), coord_len, &(pt->Z));
584*f0865ec9SKyle Evans 
585*f0865ec9SKyle Evans err:
586*f0865ec9SKyle Evans 	PTR_NULLIFY(ctx);
587*f0865ec9SKyle Evans 
588*f0865ec9SKyle Evans 	return ret;
589*f0865ec9SKyle Evans }
590*f0865ec9SKyle Evans 
591*f0865ec9SKyle Evans /*
592*f0865ec9SKyle Evans  * Export a projective point to an affine point buffer with the following
593*f0865ec9SKyle Evans  * layout; the 2 coordinates (elements of Fp) are each encoded on p_len bytes,
594*f0865ec9SKyle Evans  * where p_len is the size of p in bytes (e.g. 66 for a prime p of 521 bits).
595*f0865ec9SKyle Evans  * Each coordinate is encoded in big endian. Size of buffer must exactly match
596*f0865ec9SKyle Evans  * 2 * p_len.
597*f0865ec9SKyle Evans  *
598*f0865ec9SKyle Evans  * The function returns 0 on success, -1 on error.
599*f0865ec9SKyle Evans  */
prj_pt_export_to_aff_buf(prj_pt_src_t pt,u8 * pt_buf,u32 pt_buf_len)600*f0865ec9SKyle Evans int prj_pt_export_to_aff_buf(prj_pt_src_t pt, u8 *pt_buf, u32 pt_buf_len)
601*f0865ec9SKyle Evans {
602*f0865ec9SKyle Evans 	int ret, on_curve;
603*f0865ec9SKyle Evans 	aff_pt tmp_aff;
604*f0865ec9SKyle Evans 	tmp_aff.magic = WORD(0);
605*f0865ec9SKyle Evans 
606*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(pt); EG(ret, err);
607*f0865ec9SKyle Evans 
608*f0865ec9SKyle Evans 	MUST_HAVE((pt_buf != NULL), ret, err);
609*f0865ec9SKyle Evans 
610*f0865ec9SKyle Evans 	/* The point to be exported must be on the curve */
611*f0865ec9SKyle Evans 	ret = prj_pt_is_on_curve(pt, &on_curve); EG(ret, err);
612*f0865ec9SKyle Evans 	MUST_HAVE((on_curve), ret, err);
613*f0865ec9SKyle Evans 
614*f0865ec9SKyle Evans 	/* Move to the affine unique representation */
615*f0865ec9SKyle Evans 	ret = prj_pt_to_aff(&tmp_aff, pt); EG(ret, err);
616*f0865ec9SKyle Evans 
617*f0865ec9SKyle Evans 	/* Export the affine point to the buffer */
618*f0865ec9SKyle Evans 	ret = aff_pt_export_to_buf(&tmp_aff, pt_buf, pt_buf_len);
619*f0865ec9SKyle Evans 
620*f0865ec9SKyle Evans err:
621*f0865ec9SKyle Evans 	aff_pt_uninit(&tmp_aff);
622*f0865ec9SKyle Evans 
623*f0865ec9SKyle Evans 	return ret;
624*f0865ec9SKyle Evans }
625*f0865ec9SKyle Evans 
626*f0865ec9SKyle Evans 
627*f0865ec9SKyle Evans #ifdef NO_USE_COMPLETE_FORMULAS
628*f0865ec9SKyle Evans 
629*f0865ec9SKyle Evans /*
630*f0865ec9SKyle Evans  * The function is an internal one: no check is performed on parameters,
631*f0865ec9SKyle Evans  * this MUST be done by the caller:
632*f0865ec9SKyle Evans  *
633*f0865ec9SKyle Evans  *  - in is initialized
634*f0865ec9SKyle Evans  *  - in and out must not be aliased
635*f0865ec9SKyle Evans  *
636*f0865ec9SKyle Evans  * The function will initialize 'out'. The function returns 0 on success, -1
637*f0865ec9SKyle Evans  * on error.
638*f0865ec9SKyle Evans  */
__prj_pt_dbl_monty_no_cf(prj_pt_t out,prj_pt_src_t in)639*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int __prj_pt_dbl_monty_no_cf(prj_pt_t out, prj_pt_src_t in)
640*f0865ec9SKyle Evans {
641*f0865ec9SKyle Evans 	fp XX, ZZ, w, s, ss, sss, R, RR, B, h;
642*f0865ec9SKyle Evans 	int ret;
643*f0865ec9SKyle Evans 	XX.magic = ZZ.magic = w.magic = s.magic = WORD(0);
644*f0865ec9SKyle Evans 	ss.magic = sss.magic = R.magic = WORD(0);
645*f0865ec9SKyle Evans 	RR.magic = B.magic = h.magic = WORD(0);
646*f0865ec9SKyle Evans 
647*f0865ec9SKyle Evans 	ret = prj_pt_init(out, in->crv); EG(ret, err);
648*f0865ec9SKyle Evans 
649*f0865ec9SKyle Evans 	ret = fp_init(&XX, out->crv->a.ctx); EG(ret, err);
650*f0865ec9SKyle Evans 	ret = fp_init(&ZZ, out->crv->a.ctx); EG(ret, err);
651*f0865ec9SKyle Evans 	ret = fp_init(&w, out->crv->a.ctx); EG(ret, err);
652*f0865ec9SKyle Evans 	ret = fp_init(&s, out->crv->a.ctx); EG(ret, err);
653*f0865ec9SKyle Evans 	ret = fp_init(&ss, out->crv->a.ctx); EG(ret, err);
654*f0865ec9SKyle Evans 	ret = fp_init(&sss, out->crv->a.ctx); EG(ret, err);
655*f0865ec9SKyle Evans 	ret = fp_init(&R, out->crv->a.ctx); EG(ret, err);
656*f0865ec9SKyle Evans 	ret = fp_init(&RR, out->crv->a.ctx); EG(ret, err);
657*f0865ec9SKyle Evans 	ret = fp_init(&B, out->crv->a.ctx); EG(ret, err);
658*f0865ec9SKyle Evans 	ret = fp_init(&h, out->crv->a.ctx); EG(ret, err);
659*f0865ec9SKyle Evans 
660*f0865ec9SKyle Evans 	/* XX = X1² */
661*f0865ec9SKyle Evans 	ret = fp_sqr_monty(&XX, &(in->X)); EG(ret, err);
662*f0865ec9SKyle Evans 
663*f0865ec9SKyle Evans 	/* ZZ = Z1² */
664*f0865ec9SKyle Evans 	ret = fp_sqr_monty(&ZZ, &(in->Z)); EG(ret, err);
665*f0865ec9SKyle Evans 
666*f0865ec9SKyle Evans 	/* w = a*ZZ+3*XX */
667*f0865ec9SKyle Evans 	ret = fp_mul_monty(&w, &(in->crv->a_monty), &ZZ); EG(ret, err);
668*f0865ec9SKyle Evans 	ret = fp_add_monty(&w, &w, &XX); EG(ret, err);
669*f0865ec9SKyle Evans 	ret = fp_add_monty(&w, &w, &XX); EG(ret, err);
670*f0865ec9SKyle Evans 	ret = fp_add_monty(&w, &w, &XX); EG(ret, err);
671*f0865ec9SKyle Evans 
672*f0865ec9SKyle Evans 	/* s = 2*Y1*Z1 */
673*f0865ec9SKyle Evans 	ret = fp_mul_monty(&s, &(in->Y), &(in->Z)); EG(ret, err);
674*f0865ec9SKyle Evans 	ret = fp_add_monty(&s, &s, &s); EG(ret, err);
675*f0865ec9SKyle Evans 
676*f0865ec9SKyle Evans 	/* ss = s² */
677*f0865ec9SKyle Evans 	ret = fp_sqr_monty(&ss, &s); EG(ret, err);
678*f0865ec9SKyle Evans 
679*f0865ec9SKyle Evans 	/* sss = s*ss */
680*f0865ec9SKyle Evans 	ret = fp_mul_monty(&sss, &s, &ss); EG(ret, err);
681*f0865ec9SKyle Evans 
682*f0865ec9SKyle Evans 	/* R = Y1*s */
683*f0865ec9SKyle Evans 	ret = fp_mul_monty(&R, &(in->Y), &s); EG(ret, err);
684*f0865ec9SKyle Evans 
685*f0865ec9SKyle Evans 	/* RR = R² */
686*f0865ec9SKyle Evans 	ret = fp_sqr_monty(&RR, &R); EG(ret, err);
687*f0865ec9SKyle Evans 
688*f0865ec9SKyle Evans 	/* B = (X1+R)²-XX-RR */
689*f0865ec9SKyle Evans 	ret = fp_add_monty(&R, &R, &(in->X)); EG(ret, err);
690*f0865ec9SKyle Evans 	ret = fp_sqr_monty(&B, &R); EG(ret, err);
691*f0865ec9SKyle Evans 	ret = fp_sub_monty(&B, &B, &XX); EG(ret, err);
692*f0865ec9SKyle Evans 	ret = fp_sub_monty(&B, &B, &RR); EG(ret, err);
693*f0865ec9SKyle Evans 
694*f0865ec9SKyle Evans 	/* h = w²-2*B */
695*f0865ec9SKyle Evans 	ret = fp_sqr_monty(&h, &w); EG(ret, err);
696*f0865ec9SKyle Evans 	ret = fp_sub_monty(&h, &h, &B); EG(ret, err);
697*f0865ec9SKyle Evans 	ret = fp_sub_monty(&h, &h, &B); EG(ret, err);
698*f0865ec9SKyle Evans 
699*f0865ec9SKyle Evans 	/* X3 = h*s */
700*f0865ec9SKyle Evans 	ret = fp_mul_monty(&(out->X), &h, &s); EG(ret, err);
701*f0865ec9SKyle Evans 
702*f0865ec9SKyle Evans 	/* Y3 = w*(B-h)-2*RR */
703*f0865ec9SKyle Evans 	ret = fp_sub_monty(&B, &B, &h); EG(ret, err);
704*f0865ec9SKyle Evans 	ret = fp_mul_monty(&(out->Y), &w, &B); EG(ret, err);
705*f0865ec9SKyle Evans 	ret = fp_sub_monty(&(out->Y), &(out->Y), &RR); EG(ret, err);
706*f0865ec9SKyle Evans 	ret = fp_sub_monty(&(out->Y), &(out->Y), &RR); EG(ret, err);
707*f0865ec9SKyle Evans 
708*f0865ec9SKyle Evans 	/* Z3 = sss */
709*f0865ec9SKyle Evans 	ret = fp_copy(&(out->Z), &sss);
710*f0865ec9SKyle Evans 
711*f0865ec9SKyle Evans err:
712*f0865ec9SKyle Evans 	fp_uninit(&XX);
713*f0865ec9SKyle Evans 	fp_uninit(&ZZ);
714*f0865ec9SKyle Evans 	fp_uninit(&w);
715*f0865ec9SKyle Evans 	fp_uninit(&s);
716*f0865ec9SKyle Evans 	fp_uninit(&ss);
717*f0865ec9SKyle Evans 	fp_uninit(&sss);
718*f0865ec9SKyle Evans 	fp_uninit(&R);
719*f0865ec9SKyle Evans 	fp_uninit(&RR);
720*f0865ec9SKyle Evans 	fp_uninit(&B);
721*f0865ec9SKyle Evans 	fp_uninit(&h);
722*f0865ec9SKyle Evans 
723*f0865ec9SKyle Evans 	return ret;
724*f0865ec9SKyle Evans }
725*f0865ec9SKyle Evans 
726*f0865ec9SKyle Evans /*
727*f0865ec9SKyle Evans  * The function is an internal one: no check is performed on parameters,
728*f0865ec9SKyle Evans  * this MUST be done by the caller:
729*f0865ec9SKyle Evans  *
730*f0865ec9SKyle Evans  *  - in1 and in2 are initialized
731*f0865ec9SKyle Evans  *  - in1 and in2 are on the same curve
732*f0865ec9SKyle Evans  *  - in1/in2 and out must not be aliased
733*f0865ec9SKyle Evans  *  - in1 and in2 must not be equal, opposite or have identical value
734*f0865ec9SKyle Evans  *
735*f0865ec9SKyle Evans  * The function will initialize 'out'. The function returns 0 on success, -1
736*f0865ec9SKyle Evans  * on error.
737*f0865ec9SKyle Evans  */
___prj_pt_add_monty_no_cf(prj_pt_t out,prj_pt_src_t in1,prj_pt_src_t in2)738*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int ___prj_pt_add_monty_no_cf(prj_pt_t out,
739*f0865ec9SKyle Evans 							       prj_pt_src_t in1,
740*f0865ec9SKyle Evans 							       prj_pt_src_t in2)
741*f0865ec9SKyle Evans {
742*f0865ec9SKyle Evans 	fp Y1Z2, X1Z2, Z1Z2, u, uu, v, vv, vvv, R, A;
743*f0865ec9SKyle Evans 	int ret;
744*f0865ec9SKyle Evans 	Y1Z2.magic = X1Z2.magic = Z1Z2.magic = u.magic = uu.magic = v.magic = WORD(0);
745*f0865ec9SKyle Evans 	vv.magic = vvv.magic = R.magic = A.magic = WORD(0);
746*f0865ec9SKyle Evans 
747*f0865ec9SKyle Evans 	ret = prj_pt_init(out, in1->crv); EG(ret, err);
748*f0865ec9SKyle Evans 
749*f0865ec9SKyle Evans 	ret = fp_init(&Y1Z2, out->crv->a.ctx); EG(ret, err);
750*f0865ec9SKyle Evans 	ret = fp_init(&X1Z2, out->crv->a.ctx); EG(ret, err);
751*f0865ec9SKyle Evans 	ret = fp_init(&Z1Z2, out->crv->a.ctx); EG(ret, err);
752*f0865ec9SKyle Evans 	ret = fp_init(&u, out->crv->a.ctx); EG(ret, err);
753*f0865ec9SKyle Evans 	ret = fp_init(&uu, out->crv->a.ctx); EG(ret, err);
754*f0865ec9SKyle Evans 	ret = fp_init(&v, out->crv->a.ctx); EG(ret, err);
755*f0865ec9SKyle Evans 	ret = fp_init(&vv, out->crv->a.ctx); EG(ret, err);
756*f0865ec9SKyle Evans 	ret = fp_init(&vvv, out->crv->a.ctx); EG(ret, err);
757*f0865ec9SKyle Evans 	ret = fp_init(&R, out->crv->a.ctx); EG(ret, err);
758*f0865ec9SKyle Evans 	ret = fp_init(&A, out->crv->a.ctx); EG(ret, err);
759*f0865ec9SKyle Evans 
760*f0865ec9SKyle Evans 	/* Y1Z2 = Y1*Z2 */
761*f0865ec9SKyle Evans 	ret = fp_mul_monty(&Y1Z2, &(in1->Y), &(in2->Z)); EG(ret, err);
762*f0865ec9SKyle Evans 
763*f0865ec9SKyle Evans 	/* X1Z2 = X1*Z2 */
764*f0865ec9SKyle Evans 	ret = fp_mul_monty(&X1Z2, &(in1->X), &(in2->Z)); EG(ret, err);
765*f0865ec9SKyle Evans 
766*f0865ec9SKyle Evans 	/* Z1Z2 = Z1*Z2 */
767*f0865ec9SKyle Evans 	ret = fp_mul_monty(&Z1Z2, &(in1->Z), &(in2->Z)); EG(ret, err);
768*f0865ec9SKyle Evans 
769*f0865ec9SKyle Evans 	/* u = Y2*Z1-Y1Z2 */
770*f0865ec9SKyle Evans 	ret = fp_mul_monty(&u, &(in2->Y), &(in1->Z)); EG(ret, err);
771*f0865ec9SKyle Evans 	ret = fp_sub_monty(&u, &u, &Y1Z2); EG(ret, err);
772*f0865ec9SKyle Evans 
773*f0865ec9SKyle Evans 	/* uu = u² */
774*f0865ec9SKyle Evans 	ret = fp_sqr_monty(&uu, &u); EG(ret, err);
775*f0865ec9SKyle Evans 
776*f0865ec9SKyle Evans 	/* v = X2*Z1-X1Z2 */
777*f0865ec9SKyle Evans 	ret = fp_mul_monty(&v, &(in2->X), &(in1->Z)); EG(ret, err);
778*f0865ec9SKyle Evans 	ret = fp_sub_monty(&v, &v, &X1Z2); EG(ret, err);
779*f0865ec9SKyle Evans 
780*f0865ec9SKyle Evans 	/* vv = v² */
781*f0865ec9SKyle Evans 	ret = fp_sqr_monty(&vv, &v); EG(ret, err);
782*f0865ec9SKyle Evans 
783*f0865ec9SKyle Evans 	/* vvv = v*vv */
784*f0865ec9SKyle Evans 	ret = fp_mul_monty(&vvv, &v, &vv); EG(ret, err);
785*f0865ec9SKyle Evans 
786*f0865ec9SKyle Evans 	/* R = vv*X1Z2 */
787*f0865ec9SKyle Evans 	ret = fp_mul_monty(&R, &vv, &X1Z2); EG(ret, err);
788*f0865ec9SKyle Evans 
789*f0865ec9SKyle Evans 	/* A = uu*Z1Z2-vvv-2*R */
790*f0865ec9SKyle Evans 	ret = fp_mul_monty(&A, &uu, &Z1Z2); EG(ret, err);
791*f0865ec9SKyle Evans 	ret = fp_sub_monty(&A, &A, &vvv); EG(ret, err);
792*f0865ec9SKyle Evans 	ret = fp_sub_monty(&A, &A, &R); EG(ret, err);
793*f0865ec9SKyle Evans 	ret = fp_sub_monty(&A, &A, &R); EG(ret, err);
794*f0865ec9SKyle Evans 
795*f0865ec9SKyle Evans 	/* X3 = v*A */
796*f0865ec9SKyle Evans 	ret = fp_mul_monty(&(out->X), &v, &A); EG(ret, err);
797*f0865ec9SKyle Evans 
798*f0865ec9SKyle Evans 	/* Y3 = u*(R-A)-vvv*Y1Z2 */
799*f0865ec9SKyle Evans 	ret = fp_sub_monty(&R, &R, &A); EG(ret, err);
800*f0865ec9SKyle Evans 	ret = fp_mul_monty(&(out->Y), &u, &R); EG(ret, err);
801*f0865ec9SKyle Evans 	ret = fp_mul_monty(&R, &vvv, &Y1Z2); EG(ret, err);
802*f0865ec9SKyle Evans 	ret = fp_sub_monty(&(out->Y), &(out->Y), &R); EG(ret, err);
803*f0865ec9SKyle Evans 
804*f0865ec9SKyle Evans 	/* Z3 = vvv*Z1Z2 */
805*f0865ec9SKyle Evans 	ret = fp_mul_monty(&(out->Z), &vvv, &Z1Z2);
806*f0865ec9SKyle Evans 
807*f0865ec9SKyle Evans err:
808*f0865ec9SKyle Evans 	fp_uninit(&Y1Z2);
809*f0865ec9SKyle Evans 	fp_uninit(&X1Z2);
810*f0865ec9SKyle Evans 	fp_uninit(&Z1Z2);
811*f0865ec9SKyle Evans 	fp_uninit(&u);
812*f0865ec9SKyle Evans 	fp_uninit(&uu);
813*f0865ec9SKyle Evans 	fp_uninit(&v);
814*f0865ec9SKyle Evans 	fp_uninit(&vv);
815*f0865ec9SKyle Evans 	fp_uninit(&vvv);
816*f0865ec9SKyle Evans 	fp_uninit(&R);
817*f0865ec9SKyle Evans 	fp_uninit(&A);
818*f0865ec9SKyle Evans 
819*f0865ec9SKyle Evans 	return ret;
820*f0865ec9SKyle Evans }
821*f0865ec9SKyle Evans 
822*f0865ec9SKyle Evans /*
823*f0865ec9SKyle Evans  * Public version of the addition w/o complete formulas to handle the case
824*f0865ec9SKyle Evans  * where the inputs are zero or opposite. Returns 0 on success, -1 on error.
825*f0865ec9SKyle Evans  */
__prj_pt_add_monty_no_cf(prj_pt_t out,prj_pt_src_t in1,prj_pt_src_t in2)826*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int __prj_pt_add_monty_no_cf(prj_pt_t out, prj_pt_src_t in1, prj_pt_src_t in2)
827*f0865ec9SKyle Evans {
828*f0865ec9SKyle Evans 	int ret, iszero, eq_or_opp, cmp;
829*f0865ec9SKyle Evans 
830*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in1); EG(ret, err);
831*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in2); EG(ret, err);
832*f0865ec9SKyle Evans 	MUST_HAVE((in1->crv == in2->crv), ret, err);
833*f0865ec9SKyle Evans 
834*f0865ec9SKyle Evans 	ret = prj_pt_iszero(in1, &iszero); EG(ret, err);
835*f0865ec9SKyle Evans 	if (iszero) {
836*f0865ec9SKyle Evans 		/* in1 at infinity, output in2 in all cases */
837*f0865ec9SKyle Evans 		ret = prj_pt_init(out, in2->crv); EG(ret, err);
838*f0865ec9SKyle Evans 		ret = prj_pt_copy(out, in2); EG(ret, err);
839*f0865ec9SKyle Evans 	} else {
840*f0865ec9SKyle Evans 		/* in1 not at infinity, output in2 */
841*f0865ec9SKyle Evans 		ret = prj_pt_iszero(in2, &iszero); EG(ret, err);
842*f0865ec9SKyle Evans 		if (iszero) {
843*f0865ec9SKyle Evans 			/* in2 at infinity, output in1 */
844*f0865ec9SKyle Evans 			ret = prj_pt_init(out, in1->crv); EG(ret, err);
845*f0865ec9SKyle Evans 			ret = prj_pt_copy(out, in1); EG(ret, err);
846*f0865ec9SKyle Evans 		} else {
847*f0865ec9SKyle Evans 			/* enither in1, nor in2 at infinity */
848*f0865ec9SKyle Evans 
849*f0865ec9SKyle Evans 			/*
850*f0865ec9SKyle Evans 			 * The following test which guarantees in1 and in2 are not
851*f0865ec9SKyle Evans 			 * equal or opposite needs to be rewritten because it
852*f0865ec9SKyle Evans 			 * has a *HUGE* impact on perf (ec_self_tests run on
853*f0865ec9SKyle Evans 			 * all test vectors takes 24 times as long with this
854*f0865ec9SKyle Evans 			 * enabled). The same exists in non monty version.
855*f0865ec9SKyle Evans 			 */
856*f0865ec9SKyle Evans 			ret = prj_pt_eq_or_opp(in1, in2, &eq_or_opp); EG(ret, err);
857*f0865ec9SKyle Evans 			if (eq_or_opp) {
858*f0865ec9SKyle Evans 				/* in1 and in2 are either equal or opposite */
859*f0865ec9SKyle Evans 				ret = prj_pt_cmp(in1, in2, &cmp); EG(ret, err);
860*f0865ec9SKyle Evans 				if (cmp == 0) {
861*f0865ec9SKyle Evans 					/* in1 == in2 => doubling w/o cf */
862*f0865ec9SKyle Evans 					ret = __prj_pt_dbl_monty_no_cf(out, in1); EG(ret, err);
863*f0865ec9SKyle Evans 				} else {
864*f0865ec9SKyle Evans 					/* in1 == -in2 => output zero (point at infinity) */
865*f0865ec9SKyle Evans 					ret = prj_pt_init(out, in1->crv); EG(ret, err);
866*f0865ec9SKyle Evans 					ret = prj_pt_zero(out); EG(ret, err);
867*f0865ec9SKyle Evans 				}
868*f0865ec9SKyle Evans 			} else {
869*f0865ec9SKyle Evans 				/*
870*f0865ec9SKyle Evans 				 * in1 and in2 are neither 0, nor equal or
871*f0865ec9SKyle Evans 				 * opposite. Use the basic monty addition
872*f0865ec9SKyle Evans 				 * implementation w/o complete formulas.
873*f0865ec9SKyle Evans 				 */
874*f0865ec9SKyle Evans 				ret = ___prj_pt_add_monty_no_cf(out, in1, in2); EG(ret, err);
875*f0865ec9SKyle Evans 			}
876*f0865ec9SKyle Evans 		}
877*f0865ec9SKyle Evans 	}
878*f0865ec9SKyle Evans 
879*f0865ec9SKyle Evans err:
880*f0865ec9SKyle Evans 	return ret;
881*f0865ec9SKyle Evans }
882*f0865ec9SKyle Evans 
883*f0865ec9SKyle Evans 
884*f0865ec9SKyle Evans #else /* NO_USE_COMPLETE_FORMULAS */
885*f0865ec9SKyle Evans 
886*f0865ec9SKyle Evans 
887*f0865ec9SKyle Evans /*
888*f0865ec9SKyle Evans  * If NO_USE_COMPLETE_FORMULAS flag is not defined addition formulas from Algorithm 3
889*f0865ec9SKyle Evans  * of https://joostrenes.nl/publications/complete.pdf are used, otherwise
890*f0865ec9SKyle Evans  * http://www.hyperelliptic.org/EFD/g1p/auto-shortw-projective.html#doubling-dbl-2007-bl
891*f0865ec9SKyle Evans  */
__prj_pt_dbl_monty_cf(prj_pt_t out,prj_pt_src_t in)892*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int __prj_pt_dbl_monty_cf(prj_pt_t out, prj_pt_src_t in)
893*f0865ec9SKyle Evans {
894*f0865ec9SKyle Evans 	fp t0, t1, t2, t3;
895*f0865ec9SKyle Evans 	int ret;
896*f0865ec9SKyle Evans 	t0.magic = t1.magic = t2.magic = t3.magic = WORD(0);
897*f0865ec9SKyle Evans 
898*f0865ec9SKyle Evans 	ret = prj_pt_init(out, in->crv); EG(ret, err);
899*f0865ec9SKyle Evans 
900*f0865ec9SKyle Evans 	ret = fp_init(&t0, out->crv->a.ctx); EG(ret, err);
901*f0865ec9SKyle Evans 	ret = fp_init(&t1, out->crv->a.ctx); EG(ret, err);
902*f0865ec9SKyle Evans 	ret = fp_init(&t2, out->crv->a.ctx); EG(ret, err);
903*f0865ec9SKyle Evans 	ret = fp_init(&t3, out->crv->a.ctx); EG(ret, err);
904*f0865ec9SKyle Evans 
905*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t0, &in->X, &in->X); EG(ret, err);
906*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t1, &in->Y, &in->Y); EG(ret, err);
907*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t2, &in->Z, &in->Z); EG(ret, err);
908*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t3, &in->X, &in->Y); EG(ret, err);
909*f0865ec9SKyle Evans 	ret = fp_add_monty(&t3, &t3, &t3); EG(ret, err);
910*f0865ec9SKyle Evans 
911*f0865ec9SKyle Evans 	ret = fp_mul_monty(&out->Z, &in->X, &in->Z); EG(ret, err);
912*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->Z, &out->Z, &out->Z); EG(ret, err);
913*f0865ec9SKyle Evans 	ret = fp_mul_monty(&out->X, &in->crv->a_monty, &out->Z); EG(ret, err);
914*f0865ec9SKyle Evans 	ret = fp_mul_monty(&out->Y, &in->crv->b3_monty, &t2); EG(ret, err);
915*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->Y, &out->X, &out->Y); EG(ret, err);
916*f0865ec9SKyle Evans 
917*f0865ec9SKyle Evans 	ret = fp_sub_monty(&out->X, &t1, &out->Y); EG(ret, err);
918*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->Y, &t1, &out->Y); EG(ret, err);
919*f0865ec9SKyle Evans 	ret = fp_mul_monty(&out->Y, &out->X, &out->Y); EG(ret, err);
920*f0865ec9SKyle Evans 	ret = fp_mul_monty(&out->X, &t3, &out->X); EG(ret, err);
921*f0865ec9SKyle Evans 	ret = fp_mul_monty(&out->Z, &in->crv->b3_monty, &out->Z); EG(ret, err);
922*f0865ec9SKyle Evans 
923*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t2, &in->crv->a_monty, &t2); EG(ret, err);
924*f0865ec9SKyle Evans 	ret = fp_sub_monty(&t3, &t0, &t2); EG(ret, err);
925*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t3, &in->crv->a_monty, &t3); EG(ret, err);
926*f0865ec9SKyle Evans 	ret = fp_add_monty(&t3, &t3, &out->Z); EG(ret, err);
927*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->Z, &t0, &t0); EG(ret, err);
928*f0865ec9SKyle Evans 
929*f0865ec9SKyle Evans 	ret = fp_add_monty(&t0, &out->Z, &t0); EG(ret, err);
930*f0865ec9SKyle Evans 	ret = fp_add_monty(&t0, &t0, &t2); EG(ret, err);
931*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t0, &t0, &t3); EG(ret, err);
932*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->Y, &out->Y, &t0); EG(ret, err);
933*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t2, &in->Y, &in->Z); EG(ret, err);
934*f0865ec9SKyle Evans 
935*f0865ec9SKyle Evans 	ret = fp_add_monty(&t2, &t2, &t2); EG(ret, err);
936*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t0, &t2, &t3); EG(ret, err);
937*f0865ec9SKyle Evans 	ret = fp_sub_monty(&out->X, &out->X, &t0); EG(ret, err);
938*f0865ec9SKyle Evans 	ret = fp_mul_monty(&out->Z, &t2, &t1); EG(ret, err);
939*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->Z, &out->Z, &out->Z); EG(ret, err);
940*f0865ec9SKyle Evans 
941*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->Z, &out->Z, &out->Z);
942*f0865ec9SKyle Evans 
943*f0865ec9SKyle Evans err:
944*f0865ec9SKyle Evans 	fp_uninit(&t0);
945*f0865ec9SKyle Evans 	fp_uninit(&t1);
946*f0865ec9SKyle Evans 	fp_uninit(&t2);
947*f0865ec9SKyle Evans 	fp_uninit(&t3);
948*f0865ec9SKyle Evans 
949*f0865ec9SKyle Evans 	return ret;
950*f0865ec9SKyle Evans }
951*f0865ec9SKyle Evans 
952*f0865ec9SKyle Evans /*
953*f0865ec9SKyle Evans  * If NO_USE_COMPLETE_FORMULAS flag is not defined addition formulas from Algorithm 1
954*f0865ec9SKyle Evans  * of https://joostrenes.nl/publications/complete.pdf are used, otherwise
955*f0865ec9SKyle Evans  * http://www.hyperelliptic.org/EFD/g1p/auto-shortw-projective.html#addition-add-1998-cmo-2
956*f0865ec9SKyle Evans  */
957*f0865ec9SKyle Evans 
958*f0865ec9SKyle Evans /*
959*f0865ec9SKyle Evans  * The function is an internal one: no check is performed on parameters,
960*f0865ec9SKyle Evans  * this MUST be done by the caller:
961*f0865ec9SKyle Evans  *
962*f0865ec9SKyle Evans  *  - in1 and in2 are initialized
963*f0865ec9SKyle Evans  *  - in1 and in2 are on the same curve
964*f0865ec9SKyle Evans  *  - in1/in2 and out must not be aliased
965*f0865ec9SKyle Evans  *  - in1 and in2 must not be an "exceptional" pair, i.e. (in1-in2) is not a point
966*f0865ec9SKyle Evans  *  of order exactly 2
967*f0865ec9SKyle Evans  *
968*f0865ec9SKyle Evans  * The function will initialize 'out'. The function returns 0 on success, -1
969*f0865ec9SKyle Evans  * on error.
970*f0865ec9SKyle Evans  */
__prj_pt_add_monty_cf(prj_pt_t out,prj_pt_src_t in1,prj_pt_src_t in2)971*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int __prj_pt_add_monty_cf(prj_pt_t out,
972*f0865ec9SKyle Evans 							   prj_pt_src_t in1,
973*f0865ec9SKyle Evans 							   prj_pt_src_t in2)
974*f0865ec9SKyle Evans {
975*f0865ec9SKyle Evans 	int cmp1, cmp2;
976*f0865ec9SKyle Evans 	fp t0, t1, t2, t3, t4, t5;
977*f0865ec9SKyle Evans 	int ret;
978*f0865ec9SKyle Evans 	t0.magic = t1.magic = t2.magic = WORD(0);
979*f0865ec9SKyle Evans 	t3.magic = t4.magic = t5.magic = WORD(0);
980*f0865ec9SKyle Evans 
981*f0865ec9SKyle Evans 	ret = prj_pt_init(out, in1->crv); EG(ret, err);
982*f0865ec9SKyle Evans 
983*f0865ec9SKyle Evans 	ret = fp_init(&t0, out->crv->a.ctx); EG(ret, err);
984*f0865ec9SKyle Evans 	ret = fp_init(&t1, out->crv->a.ctx); EG(ret, err);
985*f0865ec9SKyle Evans 	ret = fp_init(&t2, out->crv->a.ctx); EG(ret, err);
986*f0865ec9SKyle Evans 	ret = fp_init(&t3, out->crv->a.ctx); EG(ret, err);
987*f0865ec9SKyle Evans 	ret = fp_init(&t4, out->crv->a.ctx); EG(ret, err);
988*f0865ec9SKyle Evans 	ret = fp_init(&t5, out->crv->a.ctx); EG(ret, err);
989*f0865ec9SKyle Evans 
990*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t0, &in1->X, &in2->X); EG(ret, err);
991*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t1, &in1->Y, &in2->Y); EG(ret, err);
992*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t2, &in1->Z, &in2->Z); EG(ret, err);
993*f0865ec9SKyle Evans 	ret = fp_add_monty(&t3, &in1->X, &in1->Y); EG(ret, err);
994*f0865ec9SKyle Evans 	ret = fp_add_monty(&t4, &in2->X, &in2->Y); EG(ret, err);
995*f0865ec9SKyle Evans 
996*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t3, &t3, &t4); EG(ret, err);
997*f0865ec9SKyle Evans 	ret = fp_add_monty(&t4, &t0, &t1); EG(ret, err);
998*f0865ec9SKyle Evans 	ret = fp_sub_monty(&t3, &t3, &t4); EG(ret, err);
999*f0865ec9SKyle Evans 	ret = fp_add_monty(&t4, &in1->X, &in1->Z); EG(ret, err);
1000*f0865ec9SKyle Evans 	ret = fp_add_monty(&t5, &in2->X, &in2->Z); EG(ret, err);
1001*f0865ec9SKyle Evans 
1002*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t4, &t4, &t5); EG(ret, err);
1003*f0865ec9SKyle Evans 	ret = fp_add_monty(&t5, &t0, &t2); EG(ret, err);
1004*f0865ec9SKyle Evans 	ret = fp_sub_monty(&t4, &t4, &t5); EG(ret, err);
1005*f0865ec9SKyle Evans 	ret = fp_add_monty(&t5, &in1->Y, &in1->Z); EG(ret, err);
1006*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->X, &in2->Y, &in2->Z); EG(ret, err);
1007*f0865ec9SKyle Evans 
1008*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t5, &t5, &out->X); EG(ret, err);
1009*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->X, &t1, &t2); EG(ret, err);
1010*f0865ec9SKyle Evans 	ret = fp_sub_monty(&t5, &t5, &out->X); EG(ret, err);
1011*f0865ec9SKyle Evans 	ret = fp_mul_monty(&out->Z, &in1->crv->a_monty, &t4); EG(ret, err);
1012*f0865ec9SKyle Evans 	ret = fp_mul_monty(&out->X, &in1->crv->b3_monty, &t2); EG(ret, err);
1013*f0865ec9SKyle Evans 
1014*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->Z, &out->X, &out->Z); EG(ret, err);
1015*f0865ec9SKyle Evans 	ret = fp_sub_monty(&out->X, &t1, &out->Z); EG(ret, err);
1016*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->Z, &t1, &out->Z); EG(ret, err);
1017*f0865ec9SKyle Evans 	ret = fp_mul_monty(&out->Y, &out->X, &out->Z); EG(ret, err);
1018*f0865ec9SKyle Evans 	ret = fp_add_monty(&t1, &t0, &t0); EG(ret, err);
1019*f0865ec9SKyle Evans 
1020*f0865ec9SKyle Evans 	ret = fp_add_monty(&t1, &t1, &t0); EG(ret, err);
1021*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t2, &in1->crv->a_monty, &t2); EG(ret, err);
1022*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t4, &in1->crv->b3_monty, &t4); EG(ret, err);
1023*f0865ec9SKyle Evans 	ret = fp_add_monty(&t1, &t1, &t2); EG(ret, err);
1024*f0865ec9SKyle Evans 	ret = fp_sub_monty(&t2, &t0, &t2); EG(ret, err);
1025*f0865ec9SKyle Evans 
1026*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t2, &in1->crv->a_monty, &t2); EG(ret, err);
1027*f0865ec9SKyle Evans 	ret = fp_add_monty(&t4, &t4, &t2); EG(ret, err);
1028*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t0, &t1, &t4); EG(ret, err);
1029*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->Y, &out->Y, &t0); EG(ret, err);
1030*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t0, &t5, &t4); EG(ret, err);
1031*f0865ec9SKyle Evans 
1032*f0865ec9SKyle Evans 	ret = fp_mul_monty(&out->X, &t3, &out->X); EG(ret, err);
1033*f0865ec9SKyle Evans 	ret = fp_sub_monty(&out->X, &out->X, &t0); EG(ret, err);
1034*f0865ec9SKyle Evans 	ret = fp_mul_monty(&t0, &t3, &t1); EG(ret, err);
1035*f0865ec9SKyle Evans 	ret = fp_mul_monty(&out->Z, &t5, &out->Z); EG(ret, err);
1036*f0865ec9SKyle Evans 	ret = fp_add_monty(&out->Z, &out->Z, &t0);
1037*f0865ec9SKyle Evans 
1038*f0865ec9SKyle Evans 	/* Check for "exceptional" pairs of input points with
1039*f0865ec9SKyle Evans 	 * checking if Y = Z = 0 as output (see the Bosma-Lenstra
1040*f0865ec9SKyle Evans 	 * article "Complete Systems of Two Addition Laws for
1041*f0865ec9SKyle Evans 	 * Elliptic Curves"). This should only happen on composite
1042*f0865ec9SKyle Evans 	 * order curves (i.e. not on prime order curves).
1043*f0865ec9SKyle Evans 	 *
1044*f0865ec9SKyle Evans 	 * In this case, we raise an error as the result is
1045*f0865ec9SKyle Evans 	 * not sound. This should not happen in our nominal
1046*f0865ec9SKyle Evans 	 * cases with regular signature and protocols, and if
1047*f0865ec9SKyle Evans 	 * it happens this usually means that bad points have
1048*f0865ec9SKyle Evans 	 * been injected.
1049*f0865ec9SKyle Evans 	 *
1050*f0865ec9SKyle Evans 	 * NOTE: if for some reasons you need to deal with
1051*f0865ec9SKyle Evans 	 * all the possible pairs of points including these
1052*f0865ec9SKyle Evans 	 * exceptional pairs of inputs with an order 2 difference,
1053*f0865ec9SKyle Evans 	 * you should fallback to the incomplete formulas using the
1054*f0865ec9SKyle Evans 	 * COMPLETE=0 compilation toggle. Beware that in this
1055*f0865ec9SKyle Evans 	 * case, the library will be more sensitive to
1056*f0865ec9SKyle Evans 	 * side-channel attacks.
1057*f0865ec9SKyle Evans 	 */
1058*f0865ec9SKyle Evans 	ret = fp_iszero(&(out->Z), &cmp1); EG(ret, err);
1059*f0865ec9SKyle Evans 	ret = fp_iszero(&(out->Y), &cmp2); EG(ret, err);
1060*f0865ec9SKyle Evans 	MUST_HAVE(!((cmp1) && (cmp2)), ret, err);
1061*f0865ec9SKyle Evans 
1062*f0865ec9SKyle Evans err:
1063*f0865ec9SKyle Evans 	fp_uninit(&t0);
1064*f0865ec9SKyle Evans 	fp_uninit(&t1);
1065*f0865ec9SKyle Evans 	fp_uninit(&t2);
1066*f0865ec9SKyle Evans 	fp_uninit(&t3);
1067*f0865ec9SKyle Evans 	fp_uninit(&t4);
1068*f0865ec9SKyle Evans 	fp_uninit(&t5);
1069*f0865ec9SKyle Evans 
1070*f0865ec9SKyle Evans 	return ret;
1071*f0865ec9SKyle Evans }
1072*f0865ec9SKyle Evans #endif  /* NO_USE_COMPLETE_FORMULAS */
1073*f0865ec9SKyle Evans 
1074*f0865ec9SKyle Evans /*
1075*f0865ec9SKyle Evans  * Internal function:
1076*f0865ec9SKyle Evans  *
1077*f0865ec9SKyle Evans  *  - not supporting aliasing,
1078*f0865ec9SKyle Evans  *  - requiring caller to check in parameter is initialized
1079*f0865ec9SKyle Evans  *
1080*f0865ec9SKyle Evans  * Based on library configuration, the function either use complete formulas
1081*f0865ec9SKyle Evans  * or not.
1082*f0865ec9SKyle Evans  */
_prj_pt_dbl_monty(prj_pt_t out,prj_pt_src_t in)1083*f0865ec9SKyle Evans static int _prj_pt_dbl_monty(prj_pt_t out, prj_pt_src_t in)
1084*f0865ec9SKyle Evans {
1085*f0865ec9SKyle Evans 	int ret;
1086*f0865ec9SKyle Evans 
1087*f0865ec9SKyle Evans #ifdef NO_USE_COMPLETE_FORMULAS
1088*f0865ec9SKyle Evans 	int iszero;
1089*f0865ec9SKyle Evans 	ret = prj_pt_iszero(in, &iszero); EG(ret, err);
1090*f0865ec9SKyle Evans 	if (iszero) {
1091*f0865ec9SKyle Evans 		ret = prj_pt_init(out, in->crv); EG(ret, err);
1092*f0865ec9SKyle Evans 		ret = prj_pt_zero(out);
1093*f0865ec9SKyle Evans 	} else {
1094*f0865ec9SKyle Evans 		ret = __prj_pt_dbl_monty_no_cf(out, in);
1095*f0865ec9SKyle Evans 	}
1096*f0865ec9SKyle Evans #else
1097*f0865ec9SKyle Evans 	ret = __prj_pt_dbl_monty_cf(out, in); EG(ret, err);
1098*f0865ec9SKyle Evans #endif
1099*f0865ec9SKyle Evans 
1100*f0865ec9SKyle Evans err:
1101*f0865ec9SKyle Evans 	return ret;
1102*f0865ec9SKyle Evans }
1103*f0865ec9SKyle Evans 
1104*f0865ec9SKyle Evans /*
1105*f0865ec9SKyle Evans  * Internal version that peform in place doubling of given val,
1106*f0865ec9SKyle Evans  * by using a temporary copy. Sanity checks on parameters must
1107*f0865ec9SKyle Evans  * be done by caller.
1108*f0865ec9SKyle Evans  */
_prj_pt_dbl_monty_aliased(prj_pt_t val)1109*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_dbl_monty_aliased(prj_pt_t val)
1110*f0865ec9SKyle Evans {
1111*f0865ec9SKyle Evans 	prj_pt out_cpy;
1112*f0865ec9SKyle Evans 	int ret;
1113*f0865ec9SKyle Evans 	out_cpy.magic = WORD(0);
1114*f0865ec9SKyle Evans 
1115*f0865ec9SKyle Evans 	ret = _prj_pt_dbl_monty(&out_cpy, val); EG(ret, err);
1116*f0865ec9SKyle Evans 	ret = prj_pt_copy(val, &out_cpy);
1117*f0865ec9SKyle Evans 
1118*f0865ec9SKyle Evans err:
1119*f0865ec9SKyle Evans 	prj_pt_uninit(&out_cpy);
1120*f0865ec9SKyle Evans 
1121*f0865ec9SKyle Evans 	return ret;
1122*f0865ec9SKyle Evans }
1123*f0865ec9SKyle Evans 
1124*f0865ec9SKyle Evans /*
1125*f0865ec9SKyle Evans  * Public function for projective point doubling. The function handles the init
1126*f0865ec9SKyle Evans  * check of 'in' parameter which must be guaranteed for internal functions.
1127*f0865ec9SKyle Evans  * 'out' parameter need not be initialized and can be aliased with 'in'
1128*f0865ec9SKyle Evans  * parameter.
1129*f0865ec9SKyle Evans  *
1130*f0865ec9SKyle Evans  * The function returns 0 on success, -1 on error.
1131*f0865ec9SKyle Evans  */
prj_pt_dbl(prj_pt_t out,prj_pt_src_t in)1132*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET int prj_pt_dbl(prj_pt_t out, prj_pt_src_t in)
1133*f0865ec9SKyle Evans {
1134*f0865ec9SKyle Evans 	int ret;
1135*f0865ec9SKyle Evans 
1136*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in); EG(ret, err);
1137*f0865ec9SKyle Evans 
1138*f0865ec9SKyle Evans 	if (out == in) {
1139*f0865ec9SKyle Evans 		ret = _prj_pt_dbl_monty_aliased(out);
1140*f0865ec9SKyle Evans 	} else {
1141*f0865ec9SKyle Evans 		ret = _prj_pt_dbl_monty(out, in);
1142*f0865ec9SKyle Evans 	}
1143*f0865ec9SKyle Evans 
1144*f0865ec9SKyle Evans err:
1145*f0865ec9SKyle Evans 	return ret;
1146*f0865ec9SKyle Evans }
1147*f0865ec9SKyle Evans 
1148*f0865ec9SKyle Evans /*
1149*f0865ec9SKyle Evans  * Internal function:
1150*f0865ec9SKyle Evans  *
1151*f0865ec9SKyle Evans  *  - not supporting aliasing,
1152*f0865ec9SKyle Evans  *  - requiring caller to check in1 and in2 parameter
1153*f0865ec9SKyle Evans  *
1154*f0865ec9SKyle Evans  * Based on library configuration, the function either use complete formulas
1155*f0865ec9SKyle Evans  * or not.
1156*f0865ec9SKyle Evans  */
_prj_pt_add_monty(prj_pt_t out,prj_pt_src_t in1,prj_pt_src_t in2)1157*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static inline int _prj_pt_add_monty(prj_pt_t out,
1158*f0865ec9SKyle Evans 							      prj_pt_src_t in1,
1159*f0865ec9SKyle Evans 							      prj_pt_src_t in2)
1160*f0865ec9SKyle Evans {
1161*f0865ec9SKyle Evans #ifndef NO_USE_COMPLETE_FORMULAS
1162*f0865ec9SKyle Evans 	return __prj_pt_add_monty_cf(out, in1, in2);
1163*f0865ec9SKyle Evans #else
1164*f0865ec9SKyle Evans 	return __prj_pt_add_monty_no_cf(out, in1, in2);
1165*f0865ec9SKyle Evans #endif
1166*f0865ec9SKyle Evans }
1167*f0865ec9SKyle Evans 
1168*f0865ec9SKyle Evans /*
1169*f0865ec9SKyle Evans  * The function is an internal one that specifically handles aliasing. No check
1170*f0865ec9SKyle Evans  * is performed on parameters, this MUST be done by the caller:
1171*f0865ec9SKyle Evans  *
1172*f0865ec9SKyle Evans  *  - in1 and in2 are initialized
1173*f0865ec9SKyle Evans  *  - in1 and in2 are on the same curve
1174*f0865ec9SKyle Evans  *
1175*f0865ec9SKyle Evans  * The function will initialize 'out'. The function returns 0 on success, -1
1176*f0865ec9SKyle Evans  * on error.
1177*f0865ec9SKyle Evans  */
_prj_pt_add_monty_aliased(prj_pt_t out,prj_pt_src_t in1,prj_pt_src_t in2)1178*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_add_monty_aliased(prj_pt_t out,
1179*f0865ec9SKyle Evans 								prj_pt_src_t in1,
1180*f0865ec9SKyle Evans 								prj_pt_src_t in2)
1181*f0865ec9SKyle Evans {
1182*f0865ec9SKyle Evans 	int ret;
1183*f0865ec9SKyle Evans 	prj_pt out_cpy;
1184*f0865ec9SKyle Evans 	out_cpy.magic = WORD(0);
1185*f0865ec9SKyle Evans 
1186*f0865ec9SKyle Evans 	ret = _prj_pt_add_monty(&out_cpy, in1, in2); EG(ret, err);
1187*f0865ec9SKyle Evans 	ret = prj_pt_copy(out, &out_cpy); EG(ret, err);
1188*f0865ec9SKyle Evans 
1189*f0865ec9SKyle Evans err:
1190*f0865ec9SKyle Evans 	prj_pt_uninit(&out_cpy);
1191*f0865ec9SKyle Evans 
1192*f0865ec9SKyle Evans 	return ret;
1193*f0865ec9SKyle Evans }
1194*f0865ec9SKyle Evans 
1195*f0865ec9SKyle Evans /*
1196*f0865ec9SKyle Evans  * Public function for projective point addition. The function handles the
1197*f0865ec9SKyle Evans  * init checks of 'in1' and 'in2' parameters, along with the check they
1198*f0865ec9SKyle Evans  * use the same curve. This must be guaranteed for internal functions.
1199*f0865ec9SKyle Evans  * 'out' parameter need not be initialized and can be aliased with either
1200*f0865ec9SKyle Evans  * 'in1' or 'in2' parameter.
1201*f0865ec9SKyle Evans  *
1202*f0865ec9SKyle Evans  * The function returns 0 on success, -1 on error.
1203*f0865ec9SKyle Evans  */
prj_pt_add(prj_pt_t out,prj_pt_src_t in1,prj_pt_src_t in2)1204*f0865ec9SKyle Evans int prj_pt_add(prj_pt_t out, prj_pt_src_t in1, prj_pt_src_t in2)
1205*f0865ec9SKyle Evans {
1206*f0865ec9SKyle Evans 	int ret;
1207*f0865ec9SKyle Evans 
1208*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in1); EG(ret, err);
1209*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in2); EG(ret, err);
1210*f0865ec9SKyle Evans 	MUST_HAVE((in1->crv == in2->crv), ret, err);
1211*f0865ec9SKyle Evans 
1212*f0865ec9SKyle Evans 	if ((out == in1) || (out == in2)) {
1213*f0865ec9SKyle Evans 		ret = _prj_pt_add_monty_aliased(out, in1, in2);
1214*f0865ec9SKyle Evans 	} else {
1215*f0865ec9SKyle Evans 		ret = _prj_pt_add_monty(out, in1, in2);
1216*f0865ec9SKyle Evans 	}
1217*f0865ec9SKyle Evans 
1218*f0865ec9SKyle Evans err:
1219*f0865ec9SKyle Evans 	return ret;
1220*f0865ec9SKyle Evans }
1221*f0865ec9SKyle Evans 
1222*f0865ec9SKyle Evans /*******************************************************************************/
1223*f0865ec9SKyle Evans /****** Scalar multiplication algorithms ***************************************/
1224*f0865ec9SKyle Evans /***********/
1225*f0865ec9SKyle Evans /*
1226*f0865ec9SKyle Evans  * The description below summarizes the following algorithms.
1227*f0865ec9SKyle Evans  *
1228*f0865ec9SKyle Evans  * Double-and-Add-Always and Montgomery Ladder masked using Itoh et al. anti-ADPA
1229*f0865ec9SKyle Evans  * (Address-bit DPA) countermeasure.
1230*f0865ec9SKyle Evans  * See "A Practical Countermeasure against Address-Bit Differential Power Analysis"
1231*f0865ec9SKyle Evans  * by Itoh, Izu and Takenaka for more information.
1232*f0865ec9SKyle Evans  *
1233*f0865ec9SKyle Evans  * NOTE: these masked variants of the Double-and-Add-Always and Montgomery Ladder algorithms
1234*f0865ec9SKyle Evans  * are used by default as Itoh et al. countermeasure has a very small impact on performance
1235*f0865ec9SKyle Evans  * and is inherently more robust againt DPA. The only case where we use another variant is
1236*f0865ec9SKyle Evans  * for devices with low memory as Itoh requires many temporary variables that consume many
1237*f0865ec9SKyle Evans  * temporary stack space.
1238*f0865ec9SKyle Evans  *
1239*f0865ec9SKyle Evans  * NOTE: the algorithms inherently depend on the MSB of the
1240*f0865ec9SKyle Evans  * scalar. In order to avoid leaking this MSB and fall into HNP (Hidden Number
1241*f0865ec9SKyle Evans  * Problem) issues, we use the trick described in https://eprint.iacr.org/2011/232.pdf
1242*f0865ec9SKyle Evans  * to have the MSB always set. However, since the scalar m might be less or bigger than
1243*f0865ec9SKyle Evans  * the order q of the curve, we distinguish three situations:
1244*f0865ec9SKyle Evans  *     - The scalar m is < q (the order), in this case we compute:
1245*f0865ec9SKyle Evans  *         -
1246*f0865ec9SKyle Evans  *        | m' = m + (2 * q) if [log(k + q)] == [log(q)],
1247*f0865ec9SKyle Evans  *        | m' = m + q otherwise.
1248*f0865ec9SKyle Evans  *         -
1249*f0865ec9SKyle Evans  *     - The scalar m is >= q and < q**2, in this case we compute:
1250*f0865ec9SKyle Evans  *         -
1251*f0865ec9SKyle Evans  *        | m' = m + (2 * (q**2)) if [log(k + (q**2))] == [log(q**2)],
1252*f0865ec9SKyle Evans  *        | m' = m + (q**2) otherwise.
1253*f0865ec9SKyle Evans  *         -
1254*f0865ec9SKyle Evans  *     - The scalar m is >= (q**2), in this case m == m'
1255*f0865ec9SKyle Evans  *
1256*f0865ec9SKyle Evans  *   => We only deal with 0 <= m < (q**2) using the countermeasure. When m >= (q**2),
1257*f0865ec9SKyle Evans  *      we stick with m' = m, accepting MSB issues (not much can be done in this case
1258*f0865ec9SKyle Evans  *      anyways). In the two first cases, Double-and-Add-Always and Montgomery Ladder are
1259*f0865ec9SKyle Evans  *      performed in constant time wrt the size of the scalar m.
1260*f0865ec9SKyle Evans  */
1261*f0865ec9SKyle Evans /***********/
1262*f0865ec9SKyle Evans /*
1263*f0865ec9SKyle Evans  * Internal point blinding function: as it is internal, in is supposed to be initialized and
1264*f0865ec9SKyle Evans  * aliasing is NOT supported.
1265*f0865ec9SKyle Evans  */
_blind_projective_point(prj_pt_t out,prj_pt_src_t in)1266*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _blind_projective_point(prj_pt_t out, prj_pt_src_t in)
1267*f0865ec9SKyle Evans {
1268*f0865ec9SKyle Evans 	int ret;
1269*f0865ec9SKyle Evans 
1270*f0865ec9SKyle Evans 	/* Random for projective coordinates masking */
1271*f0865ec9SKyle Evans 	/* NOTE: to limit stack usage, we reuse out->Z as a temporary
1272*f0865ec9SKyle Evans 	 * variable. This does not work if in == out, hence the check.
1273*f0865ec9SKyle Evans 	 */
1274*f0865ec9SKyle Evans 	MUST_HAVE((in != out), ret, err);
1275*f0865ec9SKyle Evans 
1276*f0865ec9SKyle Evans 	ret = prj_pt_init(out, in->crv); EG(ret, err);
1277*f0865ec9SKyle Evans 
1278*f0865ec9SKyle Evans 	/* Get a random value l in Fp */
1279*f0865ec9SKyle Evans 	ret = fp_get_random(&(out->Z), in->X.ctx); EG(ret, err);
1280*f0865ec9SKyle Evans 
1281*f0865ec9SKyle Evans 	/*
1282*f0865ec9SKyle Evans 	 * Blind the point with projective coordinates
1283*f0865ec9SKyle Evans 	 * (X, Y, Z) => (l*X, l*Y, l*Z)
1284*f0865ec9SKyle Evans 	 */
1285*f0865ec9SKyle Evans 	ret = fp_mul_monty(&(out->X), &(in->X), &(out->Z)); EG(ret, err);
1286*f0865ec9SKyle Evans 	ret = fp_mul_monty(&(out->Y), &(in->Y), &(out->Z)); EG(ret, err);
1287*f0865ec9SKyle Evans 	ret = fp_mul_monty(&(out->Z), &(in->Z), &(out->Z));
1288*f0865ec9SKyle Evans 
1289*f0865ec9SKyle Evans err:
1290*f0865ec9SKyle Evans 	return ret;
1291*f0865ec9SKyle Evans }
1292*f0865ec9SKyle Evans 
1293*f0865ec9SKyle Evans /* If nothing is specified regarding the scalar multiplication algorithm, we use
1294*f0865ec9SKyle Evans  * the Montgomery Ladder. For the specific case of small stack devices, we release
1295*f0865ec9SKyle Evans  * some pressure on the stack by explicitly using double and always WITHOUT the Itoh
1296*f0865ec9SKyle Evans  * et al. countermeasure against A-DPA as it is quite consuming.
1297*f0865ec9SKyle Evans  */
1298*f0865ec9SKyle Evans #if defined(USE_SMALL_STACK) && defined(USE_MONTY_LADDER)
1299*f0865ec9SKyle Evans #error "Small stack is only compatible with USE_DOUBLE_ADD_ALWAYS while USE_MONTY_LADDER has been explicitly asked!"
1300*f0865ec9SKyle Evans #endif
1301*f0865ec9SKyle Evans 
1302*f0865ec9SKyle Evans #if defined(USE_SMALL_STACK)
1303*f0865ec9SKyle Evans #ifndef USE_DOUBLE_ADD_ALWAYS
1304*f0865ec9SKyle Evans #define USE_DOUBLE_ADD_ALWAYS
1305*f0865ec9SKyle Evans #endif
1306*f0865ec9SKyle Evans #endif
1307*f0865ec9SKyle Evans 
1308*f0865ec9SKyle Evans #if !defined(USE_DOUBLE_ADD_ALWAYS) && !defined(USE_MONTY_LADDER)
1309*f0865ec9SKyle Evans #define USE_MONTY_LADDER
1310*f0865ec9SKyle Evans #endif
1311*f0865ec9SKyle Evans 
1312*f0865ec9SKyle Evans #if defined(USE_DOUBLE_ADD_ALWAYS) && defined(USE_MONTY_LADDER)
1313*f0865ec9SKyle Evans #error "You can either choose USE_DOUBLE_ADD_ALWAYS or USE_MONTY_LADDER, not both!"
1314*f0865ec9SKyle Evans #endif
1315*f0865ec9SKyle Evans 
1316*f0865ec9SKyle Evans #if defined(USE_DOUBLE_ADD_ALWAYS) && !defined(USE_SMALL_STACK)
_prj_pt_mul_ltr_monty_dbl_add_always(prj_pt_t out,nn_src_t m,prj_pt_src_t in)1317*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_mul_ltr_monty_dbl_add_always(prj_pt_t out, nn_src_t m, prj_pt_src_t in)
1318*f0865ec9SKyle Evans {
1319*f0865ec9SKyle Evans 	/* We use Itoh et al. notations here for T and the random r */
1320*f0865ec9SKyle Evans 	prj_pt T[3];
1321*f0865ec9SKyle Evans 	bitcnt_t mlen;
1322*f0865ec9SKyle Evans 	u8 mbit, rbit;
1323*f0865ec9SKyle Evans 	/* Random for masking the Double and Add Always algorithm */
1324*f0865ec9SKyle Evans 	nn r;
1325*f0865ec9SKyle Evans 	/* The new scalar we will use with MSB fixed to 1 (noted m' above).
1326*f0865ec9SKyle Evans 	 * This helps dealing with constant time.
1327*f0865ec9SKyle Evans 	 */
1328*f0865ec9SKyle Evans 	nn m_msb_fixed;
1329*f0865ec9SKyle Evans 	nn_src_t curve_order;
1330*f0865ec9SKyle Evans 	nn curve_order_square;
1331*f0865ec9SKyle Evans 	int ret, ret_ops, cmp;
1332*f0865ec9SKyle Evans 	r.magic = m_msb_fixed.magic = curve_order_square.magic = WORD(0);
1333*f0865ec9SKyle Evans 	T[0].magic = T[1].magic = T[2].magic = WORD(0);
1334*f0865ec9SKyle Evans 
1335*f0865ec9SKyle Evans 	/* Compute m' from m depending on the rule described above */
1336*f0865ec9SKyle Evans 	curve_order = &(in->crv->order);
1337*f0865ec9SKyle Evans 	/* First compute q**2 */
1338*f0865ec9SKyle Evans 	ret = nn_sqr(&curve_order_square, curve_order); EG(ret, err);
1339*f0865ec9SKyle Evans 	/* Then compute m' depending on m size */
1340*f0865ec9SKyle Evans 	ret = nn_cmp(m, curve_order, &cmp); EG(ret, err);
1341*f0865ec9SKyle Evans 	if (cmp < 0){
1342*f0865ec9SKyle Evans 		bitcnt_t msb_bit_len, order_bitlen;
1343*f0865ec9SKyle Evans 
1344*f0865ec9SKyle Evans 		/* Case where m < q */
1345*f0865ec9SKyle Evans 		ret = nn_add(&m_msb_fixed, m, curve_order); EG(ret, err);
1346*f0865ec9SKyle Evans 		ret = nn_bitlen(&m_msb_fixed, &msb_bit_len); EG(ret, err);
1347*f0865ec9SKyle Evans 		ret = nn_bitlen(curve_order, &order_bitlen); EG(ret, err);
1348*f0865ec9SKyle Evans 		ret = nn_cnd_add((msb_bit_len == order_bitlen), &m_msb_fixed,
1349*f0865ec9SKyle Evans 				  &m_msb_fixed, curve_order); EG(ret, err);
1350*f0865ec9SKyle Evans 	} else {
1351*f0865ec9SKyle Evans 		ret = nn_cmp(m, &curve_order_square, &cmp); EG(ret, err);
1352*f0865ec9SKyle Evans 		if (cmp < 0) {
1353*f0865ec9SKyle Evans 			bitcnt_t msb_bit_len, curve_order_square_bitlen;
1354*f0865ec9SKyle Evans 
1355*f0865ec9SKyle Evans 			/* Case where m >= q and m < (q**2) */
1356*f0865ec9SKyle Evans 			ret = nn_add(&m_msb_fixed, m, &curve_order_square); EG(ret, err);
1357*f0865ec9SKyle Evans 			ret = nn_bitlen(&m_msb_fixed, &msb_bit_len); EG(ret, err);
1358*f0865ec9SKyle Evans 			ret = nn_bitlen(&curve_order_square, &curve_order_square_bitlen); EG(ret, err);
1359*f0865ec9SKyle Evans 			ret = nn_cnd_add((msb_bit_len == curve_order_square_bitlen),
1360*f0865ec9SKyle Evans 					&m_msb_fixed, &m_msb_fixed, &curve_order_square); EG(ret, err);
1361*f0865ec9SKyle Evans 		} else {
1362*f0865ec9SKyle Evans 			/* Case where m >= (q**2) */
1363*f0865ec9SKyle Evans 			ret = nn_copy(&m_msb_fixed, m); EG(ret, err);
1364*f0865ec9SKyle Evans 		}
1365*f0865ec9SKyle Evans 	}
1366*f0865ec9SKyle Evans 	ret = nn_bitlen(&m_msb_fixed, &mlen); EG(ret, err);
1367*f0865ec9SKyle Evans 	MUST_HAVE(mlen != 0, ret, err);
1368*f0865ec9SKyle Evans 	mlen--;
1369*f0865ec9SKyle Evans 
1370*f0865ec9SKyle Evans 	/* Hide possible internal failures for double and add
1371*f0865ec9SKyle Evans 	 * operations and perform the operation in constant time.
1372*f0865ec9SKyle Evans 	 */
1373*f0865ec9SKyle Evans 	ret_ops = 0;
1374*f0865ec9SKyle Evans 
1375*f0865ec9SKyle Evans 	/* Get a random r with the same size of m_msb_fixed */
1376*f0865ec9SKyle Evans 	ret = nn_get_random_len(&r, m_msb_fixed.wlen * WORD_BYTES); EG(ret, err);
1377*f0865ec9SKyle Evans 
1378*f0865ec9SKyle Evans 	ret = nn_getbit(&r, mlen, &rbit); EG(ret, err);
1379*f0865ec9SKyle Evans 
1380*f0865ec9SKyle Evans 	/* Initialize points */
1381*f0865ec9SKyle Evans 	ret = prj_pt_init(&T[0], in->crv); EG(ret, err);
1382*f0865ec9SKyle Evans 	ret = prj_pt_init(&T[1], in->crv); EG(ret, err);
1383*f0865ec9SKyle Evans 
1384*f0865ec9SKyle Evans 	/*
1385*f0865ec9SKyle Evans 	 * T[2] = R(P)
1386*f0865ec9SKyle Evans 	 * Blind the point with projective coordinates
1387*f0865ec9SKyle Evans 	 * (X, Y, Z) => (l*X, l*Y, l*Z)
1388*f0865ec9SKyle Evans 	 */
1389*f0865ec9SKyle Evans 	ret = _blind_projective_point(&T[2], in); EG(ret, err);
1390*f0865ec9SKyle Evans 
1391*f0865ec9SKyle Evans 	/*  T[r[n-1]] = T[2] */
1392*f0865ec9SKyle Evans 	ret = prj_pt_copy(&T[rbit], &T[2]); EG(ret, err);
1393*f0865ec9SKyle Evans 
1394*f0865ec9SKyle Evans 	/* Main loop of Double and Add Always */
1395*f0865ec9SKyle Evans 	while (mlen > 0) {
1396*f0865ec9SKyle Evans 		u8 rbit_next;
1397*f0865ec9SKyle Evans 		--mlen;
1398*f0865ec9SKyle Evans 		/* rbit is r[i+1], and rbit_next is r[i] */
1399*f0865ec9SKyle Evans 		ret = nn_getbit(&r, mlen, &rbit_next); EG(ret, err);
1400*f0865ec9SKyle Evans 
1401*f0865ec9SKyle Evans 		/* mbit is m[i] */
1402*f0865ec9SKyle Evans 		ret = nn_getbit(&m_msb_fixed, mlen, &mbit); EG(ret, err);
1403*f0865ec9SKyle Evans 
1404*f0865ec9SKyle Evans 		/* Double: T[r[i+1]] = ECDBL(T[r[i+1]]) */
1405*f0865ec9SKyle Evans #ifndef NO_USE_COMPLETE_FORMULAS
1406*f0865ec9SKyle Evans 		/*
1407*f0865ec9SKyle Evans 		 * NOTE: in case of complete formulas, we use the
1408*f0865ec9SKyle Evans 		 * addition for doubling, incurring a small performance hit
1409*f0865ec9SKyle Evans 		 * for better SCA resistance.
1410*f0865ec9SKyle Evans 		 */
1411*f0865ec9SKyle Evans 		ret_ops |= prj_pt_add(&T[rbit], &T[rbit], &T[rbit]);
1412*f0865ec9SKyle Evans #else
1413*f0865ec9SKyle Evans 		ret_ops |= prj_pt_dbl(&T[rbit], &T[rbit]);
1414*f0865ec9SKyle Evans #endif
1415*f0865ec9SKyle Evans 		/* Add:  T[1-r[i+1]] = ECADD(T[r[i+1]],T[2]) */
1416*f0865ec9SKyle Evans 		ret_ops |= prj_pt_add(&T[1-rbit], &T[rbit], &T[2]);
1417*f0865ec9SKyle Evans 
1418*f0865ec9SKyle Evans 		/*
1419*f0865ec9SKyle Evans 		 * T[r[i]] = T[d[i] ^ r[i+1]]
1420*f0865ec9SKyle Evans 		 * NOTE: we use the low level nn_copy function here to avoid
1421*f0865ec9SKyle Evans 		 * any possible leakage on operands with prj_pt_copy
1422*f0865ec9SKyle Evans 		 */
1423*f0865ec9SKyle Evans 		ret = nn_copy(&(T[rbit_next].X.fp_val), &(T[mbit ^ rbit].X.fp_val)); EG(ret, err);
1424*f0865ec9SKyle Evans 		ret = nn_copy(&(T[rbit_next].Y.fp_val), &(T[mbit ^ rbit].Y.fp_val)); EG(ret, err);
1425*f0865ec9SKyle Evans 		ret = nn_copy(&(T[rbit_next].Z.fp_val), &(T[mbit ^ rbit].Z.fp_val)); EG(ret, err);
1426*f0865ec9SKyle Evans 
1427*f0865ec9SKyle Evans 		/* Update rbit */
1428*f0865ec9SKyle Evans 		rbit = rbit_next;
1429*f0865ec9SKyle Evans 	}
1430*f0865ec9SKyle Evans 	/* Output: T[r[0]] */
1431*f0865ec9SKyle Evans 	ret = prj_pt_copy(out, &T[rbit]); EG(ret, err);
1432*f0865ec9SKyle Evans 
1433*f0865ec9SKyle Evans 	/* Take into consideration our double and add errors */
1434*f0865ec9SKyle Evans 	ret |= ret_ops;
1435*f0865ec9SKyle Evans 
1436*f0865ec9SKyle Evans err:
1437*f0865ec9SKyle Evans 	prj_pt_uninit(&T[0]);
1438*f0865ec9SKyle Evans 	prj_pt_uninit(&T[1]);
1439*f0865ec9SKyle Evans 	prj_pt_uninit(&T[2]);
1440*f0865ec9SKyle Evans 	nn_uninit(&r);
1441*f0865ec9SKyle Evans 	nn_uninit(&m_msb_fixed);
1442*f0865ec9SKyle Evans 	nn_uninit(&curve_order_square);
1443*f0865ec9SKyle Evans 
1444*f0865ec9SKyle Evans 	PTR_NULLIFY(curve_order);
1445*f0865ec9SKyle Evans 
1446*f0865ec9SKyle Evans 	return ret;
1447*f0865ec9SKyle Evans }
1448*f0865ec9SKyle Evans #endif
1449*f0865ec9SKyle Evans 
1450*f0865ec9SKyle Evans #if defined(USE_DOUBLE_ADD_ALWAYS) && defined(USE_SMALL_STACK)
1451*f0865ec9SKyle Evans /* NOTE: in small stack case where we compile for low memory devices, we do not use Itoh et al. countermeasure
1452*f0865ec9SKyle Evans  * as it requires too much temporary space on the stack.
1453*f0865ec9SKyle Evans  */
_prj_pt_mul_ltr_monty_dbl_add_always(prj_pt_t out,nn_src_t m,prj_pt_src_t in)1454*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_mul_ltr_monty_dbl_add_always(prj_pt_t out, nn_src_t m, prj_pt_src_t in)
1455*f0865ec9SKyle Evans {
1456*f0865ec9SKyle Evans 	int ret, ret_ops;
1457*f0865ec9SKyle Evans 
1458*f0865ec9SKyle Evans 	/* Hide possible internal failures for double and add
1459*f0865ec9SKyle Evans 	 * operations and perform the operation in constant time.
1460*f0865ec9SKyle Evans 	 */
1461*f0865ec9SKyle Evans 	ret_ops = 0;
1462*f0865ec9SKyle Evans 
1463*f0865ec9SKyle Evans 	/* Blind the input point projective coordinates */
1464*f0865ec9SKyle Evans 	ret = _blind_projective_point(out, in); EG(ret, err);
1465*f0865ec9SKyle Evans 
1466*f0865ec9SKyle Evans 	/*******************/
1467*f0865ec9SKyle Evans 	{
1468*f0865ec9SKyle Evans 		bitcnt_t mlen;
1469*f0865ec9SKyle Evans 		u8 mbit;
1470*f0865ec9SKyle Evans 		/* The new scalar we will use with MSB fixed to 1 (noted m' above).
1471*f0865ec9SKyle Evans 		 * This helps dealing with constant time.
1472*f0865ec9SKyle Evans 		 */
1473*f0865ec9SKyle Evans 		nn m_msb_fixed;
1474*f0865ec9SKyle Evans 		nn_src_t curve_order;
1475*f0865ec9SKyle Evans 		int cmp;
1476*f0865ec9SKyle Evans 		m_msb_fixed.magic = WORD(0);
1477*f0865ec9SKyle Evans 
1478*f0865ec9SKyle Evans 		{
1479*f0865ec9SKyle Evans 			nn curve_order_square;
1480*f0865ec9SKyle Evans 			curve_order_square.magic = WORD(0);
1481*f0865ec9SKyle Evans 
1482*f0865ec9SKyle Evans 			/* Compute m' from m depending on the rule described above */
1483*f0865ec9SKyle Evans 			curve_order = &(in->crv->order);
1484*f0865ec9SKyle Evans 			/* First compute q**2 */
1485*f0865ec9SKyle Evans 			ret = nn_sqr(&curve_order_square, curve_order); EG(ret, err1);
1486*f0865ec9SKyle Evans 			/* Then compute m' depending on m size */
1487*f0865ec9SKyle Evans 			ret = nn_cmp(m, curve_order, &cmp); EG(ret, err1);
1488*f0865ec9SKyle Evans 			if (cmp < 0){
1489*f0865ec9SKyle Evans 				bitcnt_t msb_bit_len, order_bitlen;
1490*f0865ec9SKyle Evans 
1491*f0865ec9SKyle Evans 				/* Case where m < q */
1492*f0865ec9SKyle Evans 				ret = nn_add(&m_msb_fixed, m, curve_order); EG(ret, err1);
1493*f0865ec9SKyle Evans 				ret = nn_bitlen(&m_msb_fixed, &msb_bit_len); EG(ret, err1);
1494*f0865ec9SKyle Evans 				ret = nn_bitlen(curve_order, &order_bitlen); EG(ret, err1);
1495*f0865ec9SKyle Evans 				ret = nn_cnd_add((msb_bit_len == order_bitlen), &m_msb_fixed,
1496*f0865ec9SKyle Evans 					  &m_msb_fixed, curve_order); EG(ret, err1);
1497*f0865ec9SKyle Evans 			} else {
1498*f0865ec9SKyle Evans 				ret = nn_cmp(m, &curve_order_square, &cmp); EG(ret, err1);
1499*f0865ec9SKyle Evans 				if (cmp < 0) {
1500*f0865ec9SKyle Evans 					bitcnt_t msb_bit_len, curve_order_square_bitlen;
1501*f0865ec9SKyle Evans 
1502*f0865ec9SKyle Evans 					/* Case where m >= q and m < (q**2) */
1503*f0865ec9SKyle Evans 					ret = nn_add(&m_msb_fixed, m, &curve_order_square); EG(ret, err1);
1504*f0865ec9SKyle Evans 					ret = nn_bitlen(&m_msb_fixed, &msb_bit_len); EG(ret, err1);
1505*f0865ec9SKyle Evans 					ret = nn_bitlen(&curve_order_square, &curve_order_square_bitlen); EG(ret, err1);
1506*f0865ec9SKyle Evans 					ret = nn_cnd_add((msb_bit_len == curve_order_square_bitlen),
1507*f0865ec9SKyle Evans 							&m_msb_fixed, &m_msb_fixed, &curve_order_square); EG(ret, err1);
1508*f0865ec9SKyle Evans 				} else {
1509*f0865ec9SKyle Evans 					/* Case where m >= (q**2) */
1510*f0865ec9SKyle Evans 					ret = nn_copy(&m_msb_fixed, m); EG(ret, err1);
1511*f0865ec9SKyle Evans 				}
1512*f0865ec9SKyle Evans 			}
1513*f0865ec9SKyle Evans err1:
1514*f0865ec9SKyle Evans 			nn_uninit(&curve_order_square); EG(ret, err);
1515*f0865ec9SKyle Evans 		}
1516*f0865ec9SKyle Evans 
1517*f0865ec9SKyle Evans 		ret = nn_bitlen(&m_msb_fixed, &mlen); EG(ret, err);
1518*f0865ec9SKyle Evans 		MUST_HAVE((mlen != 0), ret, err);
1519*f0865ec9SKyle Evans 		mlen--;
1520*f0865ec9SKyle Evans 
1521*f0865ec9SKyle Evans 		{
1522*f0865ec9SKyle Evans 			prj_pt dbl;
1523*f0865ec9SKyle Evans 			dbl.magic = WORD(0);
1524*f0865ec9SKyle Evans 
1525*f0865ec9SKyle Evans 			/* Initialize temporary point */
1526*f0865ec9SKyle Evans 			ret = prj_pt_init(&dbl, in->crv); EG(ret, err2);
1527*f0865ec9SKyle Evans 
1528*f0865ec9SKyle Evans 			/* Main loop of Double and Add Always */
1529*f0865ec9SKyle Evans 			while (mlen > 0) {
1530*f0865ec9SKyle Evans 				--mlen;
1531*f0865ec9SKyle Evans 				/* mbit is m[i] */
1532*f0865ec9SKyle Evans 				ret = nn_getbit(&m_msb_fixed, mlen, &mbit); EG(ret, err2);
1533*f0865ec9SKyle Evans 
1534*f0865ec9SKyle Evans #ifndef NO_USE_COMPLETE_FORMULAS
1535*f0865ec9SKyle Evans 				/*
1536*f0865ec9SKyle Evans 				 * NOTE: in case of complete formulas, we use the
1537*f0865ec9SKyle Evans 				 * addition for doubling, incurring a small performance hit
1538*f0865ec9SKyle Evans 				 * for better SCA resistance.
1539*f0865ec9SKyle Evans 				 */
1540*f0865ec9SKyle Evans 				ret_ops |= prj_pt_add(&dbl, out, out);
1541*f0865ec9SKyle Evans #else
1542*f0865ec9SKyle Evans 				ret_ops |= prj_pt_dbl(&dbl, out);
1543*f0865ec9SKyle Evans #endif
1544*f0865ec9SKyle Evans 				ret_ops |= prj_pt_add(out, &dbl, in);
1545*f0865ec9SKyle Evans 				/* Swap */
1546*f0865ec9SKyle Evans 				ret = nn_cnd_swap(!mbit, &(out->X.fp_val), &(dbl.X.fp_val)); EG(ret, err2);
1547*f0865ec9SKyle Evans 				ret = nn_cnd_swap(!mbit, &(out->Y.fp_val), &(dbl.Y.fp_val)); EG(ret, err2);
1548*f0865ec9SKyle Evans 				ret = nn_cnd_swap(!mbit, &(out->Z.fp_val), &(dbl.Z.fp_val)); EG(ret, err2);
1549*f0865ec9SKyle Evans 			}
1550*f0865ec9SKyle Evans err2:
1551*f0865ec9SKyle Evans 			prj_pt_uninit(&dbl); EG(ret, err);
1552*f0865ec9SKyle Evans 		}
1553*f0865ec9SKyle Evans 
1554*f0865ec9SKyle Evans err:
1555*f0865ec9SKyle Evans 		nn_uninit(&m_msb_fixed);
1556*f0865ec9SKyle Evans 
1557*f0865ec9SKyle Evans 		PTR_NULLIFY(curve_order);
1558*f0865ec9SKyle Evans 	}
1559*f0865ec9SKyle Evans 
1560*f0865ec9SKyle Evans 	/* Take into consideration our double and add errors */
1561*f0865ec9SKyle Evans 	ret |= ret_ops;
1562*f0865ec9SKyle Evans 
1563*f0865ec9SKyle Evans 	return ret;
1564*f0865ec9SKyle Evans }
1565*f0865ec9SKyle Evans #endif
1566*f0865ec9SKyle Evans 
1567*f0865ec9SKyle Evans 
1568*f0865ec9SKyle Evans #ifdef USE_MONTY_LADDER
_prj_pt_mul_ltr_monty_ladder(prj_pt_t out,nn_src_t m,prj_pt_src_t in)1569*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_mul_ltr_monty_ladder(prj_pt_t out, nn_src_t m, prj_pt_src_t in)
1570*f0865ec9SKyle Evans {
1571*f0865ec9SKyle Evans 	/* We use Itoh et al. notations here for T and the random r */
1572*f0865ec9SKyle Evans 	prj_pt T[3];
1573*f0865ec9SKyle Evans 	bitcnt_t mlen;
1574*f0865ec9SKyle Evans 	u8 mbit, rbit;
1575*f0865ec9SKyle Evans 	/* Random for masking the Montgomery Ladder algorithm */
1576*f0865ec9SKyle Evans 	nn r;
1577*f0865ec9SKyle Evans 	/* The new scalar we will use with MSB fixed to 1 (noted m' above).
1578*f0865ec9SKyle Evans 	 * This helps dealing with constant time.
1579*f0865ec9SKyle Evans 	 */
1580*f0865ec9SKyle Evans 	nn m_msb_fixed;
1581*f0865ec9SKyle Evans 	nn_src_t curve_order;
1582*f0865ec9SKyle Evans 	nn curve_order_square;
1583*f0865ec9SKyle Evans 	int ret, ret_ops, cmp;
1584*f0865ec9SKyle Evans 	r.magic = m_msb_fixed.magic = curve_order_square.magic = WORD(0);
1585*f0865ec9SKyle Evans 	T[0].magic = T[1].magic = T[2].magic = WORD(0);
1586*f0865ec9SKyle Evans 
1587*f0865ec9SKyle Evans 	/* Compute m' from m depending on the rule described above */
1588*f0865ec9SKyle Evans 	curve_order = &(in->crv->order);
1589*f0865ec9SKyle Evans 
1590*f0865ec9SKyle Evans 	/* First compute q**2 */
1591*f0865ec9SKyle Evans 	ret = nn_sqr(&curve_order_square, curve_order); EG(ret, err);
1592*f0865ec9SKyle Evans 
1593*f0865ec9SKyle Evans 	/* Then compute m' depending on m size */
1594*f0865ec9SKyle Evans 	ret = nn_cmp(m, curve_order, &cmp); EG(ret, err);
1595*f0865ec9SKyle Evans 	if (cmp < 0) {
1596*f0865ec9SKyle Evans 		bitcnt_t msb_bit_len, order_bitlen;
1597*f0865ec9SKyle Evans 
1598*f0865ec9SKyle Evans 		/* Case where m < q */
1599*f0865ec9SKyle Evans 		ret = nn_add(&m_msb_fixed, m, curve_order); EG(ret, err);
1600*f0865ec9SKyle Evans 		ret = nn_bitlen(&m_msb_fixed, &msb_bit_len); EG(ret, err);
1601*f0865ec9SKyle Evans 		ret = nn_bitlen(curve_order, &order_bitlen); EG(ret, err);
1602*f0865ec9SKyle Evans 		ret = nn_cnd_add((msb_bit_len == order_bitlen), &m_msb_fixed,
1603*f0865ec9SKyle Evans 				&m_msb_fixed, curve_order); EG(ret, err);
1604*f0865ec9SKyle Evans 	} else {
1605*f0865ec9SKyle Evans 		ret = nn_cmp(m, &curve_order_square, &cmp); EG(ret, err);
1606*f0865ec9SKyle Evans 		if (cmp < 0) {
1607*f0865ec9SKyle Evans 			bitcnt_t msb_bit_len, curve_order_square_bitlen;
1608*f0865ec9SKyle Evans 
1609*f0865ec9SKyle Evans 			/* Case where m >= q and m < (q**2) */
1610*f0865ec9SKyle Evans 			ret = nn_add(&m_msb_fixed, m, &curve_order_square); EG(ret, err);
1611*f0865ec9SKyle Evans 			ret = nn_bitlen(&m_msb_fixed, &msb_bit_len); EG(ret, err);
1612*f0865ec9SKyle Evans 			ret = nn_bitlen(&curve_order_square, &curve_order_square_bitlen); EG(ret, err);
1613*f0865ec9SKyle Evans 			ret = nn_cnd_add((msb_bit_len == curve_order_square_bitlen),
1614*f0865ec9SKyle Evans 					 &m_msb_fixed, &m_msb_fixed, &curve_order_square); EG(ret, err);
1615*f0865ec9SKyle Evans 		} else {
1616*f0865ec9SKyle Evans 			/* Case where m >= (q**2) */
1617*f0865ec9SKyle Evans 			ret = nn_copy(&m_msb_fixed, m); EG(ret, err);
1618*f0865ec9SKyle Evans 		}
1619*f0865ec9SKyle Evans 	}
1620*f0865ec9SKyle Evans 
1621*f0865ec9SKyle Evans 	ret = nn_bitlen(&m_msb_fixed, &mlen); EG(ret, err);
1622*f0865ec9SKyle Evans 	MUST_HAVE((mlen != 0), ret, err);
1623*f0865ec9SKyle Evans 	mlen--;
1624*f0865ec9SKyle Evans 
1625*f0865ec9SKyle Evans 	/* Hide possible internal failures for double and add
1626*f0865ec9SKyle Evans 	 * operations and perform the operation in constant time.
1627*f0865ec9SKyle Evans 	 */
1628*f0865ec9SKyle Evans 	ret_ops = 0;
1629*f0865ec9SKyle Evans 
1630*f0865ec9SKyle Evans 	/* Get a random r with the same size of m_msb_fixed */
1631*f0865ec9SKyle Evans 	ret = nn_get_random_len(&r, (u16)(m_msb_fixed.wlen * WORD_BYTES)); EG(ret, err);
1632*f0865ec9SKyle Evans 
1633*f0865ec9SKyle Evans 	ret = nn_getbit(&r, mlen, &rbit); EG(ret, err);
1634*f0865ec9SKyle Evans 
1635*f0865ec9SKyle Evans 	/* Initialize points */
1636*f0865ec9SKyle Evans 	ret = prj_pt_init(&T[0], in->crv); EG(ret, err);
1637*f0865ec9SKyle Evans 	ret = prj_pt_init(&T[1], in->crv); EG(ret, err);
1638*f0865ec9SKyle Evans 	ret = prj_pt_init(&T[2], in->crv); EG(ret, err);
1639*f0865ec9SKyle Evans 
1640*f0865ec9SKyle Evans 	/* Initialize T[r[n-1]] to input point */
1641*f0865ec9SKyle Evans 	/*
1642*f0865ec9SKyle Evans 	 * Blind the point with projective coordinates
1643*f0865ec9SKyle Evans 	 * (X, Y, Z) => (l*X, l*Y, l*Z)
1644*f0865ec9SKyle Evans 	 */
1645*f0865ec9SKyle Evans 	ret = _blind_projective_point(&T[rbit], in); EG(ret, err);
1646*f0865ec9SKyle Evans 
1647*f0865ec9SKyle Evans 	/* Initialize T[1-r[n-1]] with ECDBL(T[r[n-1]])) */
1648*f0865ec9SKyle Evans #ifndef NO_USE_COMPLETE_FORMULAS
1649*f0865ec9SKyle Evans 	/*
1650*f0865ec9SKyle Evans 	 * NOTE: in case of complete formulas, we use the
1651*f0865ec9SKyle Evans 	 * addition for doubling, incurring a small performance hit
1652*f0865ec9SKyle Evans 	 * for better SCA resistance.
1653*f0865ec9SKyle Evans 	 */
1654*f0865ec9SKyle Evans 	ret_ops |= prj_pt_add(&T[1-rbit], &T[rbit], &T[rbit]);
1655*f0865ec9SKyle Evans #else
1656*f0865ec9SKyle Evans 	ret_ops |= prj_pt_dbl(&T[1-rbit], &T[rbit]);
1657*f0865ec9SKyle Evans #endif
1658*f0865ec9SKyle Evans 
1659*f0865ec9SKyle Evans 	/* Main loop of the Montgomery Ladder */
1660*f0865ec9SKyle Evans 	while (mlen > 0) {
1661*f0865ec9SKyle Evans 		u8 rbit_next;
1662*f0865ec9SKyle Evans 		--mlen;
1663*f0865ec9SKyle Evans 		/* rbit is r[i+1], and rbit_next is r[i] */
1664*f0865ec9SKyle Evans 		ret = nn_getbit(&r, mlen, &rbit_next); EG(ret, err);
1665*f0865ec9SKyle Evans 
1666*f0865ec9SKyle Evans 		/* mbit is m[i] */
1667*f0865ec9SKyle Evans 		ret = nn_getbit(&m_msb_fixed, mlen, &mbit); EG(ret, err);
1668*f0865ec9SKyle Evans 		/* Double: T[2] = ECDBL(T[d[i] ^ r[i+1]]) */
1669*f0865ec9SKyle Evans 
1670*f0865ec9SKyle Evans #ifndef NO_USE_COMPLETE_FORMULAS
1671*f0865ec9SKyle Evans 		/* NOTE: in case of complete formulas, we use the
1672*f0865ec9SKyle Evans 		 * addition for doubling, incurring a small performance hit
1673*f0865ec9SKyle Evans 		 * for better SCA resistance.
1674*f0865ec9SKyle Evans 		 */
1675*f0865ec9SKyle Evans 		ret_ops |= prj_pt_add(&T[2], &T[mbit ^ rbit], &T[mbit ^ rbit]);
1676*f0865ec9SKyle Evans #else
1677*f0865ec9SKyle Evans 		ret_ops |= prj_pt_dbl(&T[2], &T[mbit ^ rbit]);
1678*f0865ec9SKyle Evans #endif
1679*f0865ec9SKyle Evans 
1680*f0865ec9SKyle Evans 		/* Add: T[1] = ECADD(T[0],T[1]) */
1681*f0865ec9SKyle Evans 		ret_ops |= prj_pt_add(&T[1], &T[0], &T[1]);
1682*f0865ec9SKyle Evans 
1683*f0865ec9SKyle Evans 		/* T[0] = T[2-(d[i] ^ r[i])] */
1684*f0865ec9SKyle Evans 		/*
1685*f0865ec9SKyle Evans 		 * NOTE: we use the low level nn_copy function here to avoid
1686*f0865ec9SKyle Evans 		 * any possible leakage on operands with prj_pt_copy
1687*f0865ec9SKyle Evans 		 */
1688*f0865ec9SKyle Evans 		ret = nn_copy(&(T[0].X.fp_val), &(T[2-(mbit ^ rbit_next)].X.fp_val)); EG(ret, err);
1689*f0865ec9SKyle Evans 		ret = nn_copy(&(T[0].Y.fp_val), &(T[2-(mbit ^ rbit_next)].Y.fp_val)); EG(ret, err);
1690*f0865ec9SKyle Evans 		ret = nn_copy(&(T[0].Z.fp_val), &(T[2-(mbit ^ rbit_next)].Z.fp_val)); EG(ret, err);
1691*f0865ec9SKyle Evans 
1692*f0865ec9SKyle Evans 		/* T[1] = T[1+(d[i] ^ r[i])] */
1693*f0865ec9SKyle Evans 		/* NOTE: we use the low level nn_copy function here to avoid
1694*f0865ec9SKyle Evans 		 * any possible leakage on operands with prj_pt_copy
1695*f0865ec9SKyle Evans 		 */
1696*f0865ec9SKyle Evans 		ret = nn_copy(&(T[1].X.fp_val), &(T[1+(mbit ^ rbit_next)].X.fp_val)); EG(ret, err);
1697*f0865ec9SKyle Evans 		ret = nn_copy(&(T[1].Y.fp_val), &(T[1+(mbit ^ rbit_next)].Y.fp_val)); EG(ret, err);
1698*f0865ec9SKyle Evans 		ret = nn_copy(&(T[1].Z.fp_val), &(T[1+(mbit ^ rbit_next)].Z.fp_val)); EG(ret, err);
1699*f0865ec9SKyle Evans 
1700*f0865ec9SKyle Evans 		/* Update rbit */
1701*f0865ec9SKyle Evans 		rbit = rbit_next;
1702*f0865ec9SKyle Evans 	}
1703*f0865ec9SKyle Evans 	/* Output: T[r[0]] */
1704*f0865ec9SKyle Evans 	ret = prj_pt_copy(out, &T[rbit]); EG(ret, err);
1705*f0865ec9SKyle Evans 
1706*f0865ec9SKyle Evans 	/* Take into consideration our double and add errors */
1707*f0865ec9SKyle Evans 	ret |= ret_ops;
1708*f0865ec9SKyle Evans 
1709*f0865ec9SKyle Evans err:
1710*f0865ec9SKyle Evans 	prj_pt_uninit(&T[0]);
1711*f0865ec9SKyle Evans 	prj_pt_uninit(&T[1]);
1712*f0865ec9SKyle Evans 	prj_pt_uninit(&T[2]);
1713*f0865ec9SKyle Evans 	nn_uninit(&r);
1714*f0865ec9SKyle Evans 	nn_uninit(&m_msb_fixed);
1715*f0865ec9SKyle Evans 	nn_uninit(&curve_order_square);
1716*f0865ec9SKyle Evans 
1717*f0865ec9SKyle Evans 	PTR_NULLIFY(curve_order);
1718*f0865ec9SKyle Evans 
1719*f0865ec9SKyle Evans 	return ret;
1720*f0865ec9SKyle Evans }
1721*f0865ec9SKyle Evans #endif
1722*f0865ec9SKyle Evans 
1723*f0865ec9SKyle Evans /* Main projective scalar multiplication function.
1724*f0865ec9SKyle Evans  * Depending on the preprocessing options, we use either the
1725*f0865ec9SKyle Evans  * Double and Add Always algorithm, or the Montgomery Ladder one.
1726*f0865ec9SKyle Evans  */
_prj_pt_mul_ltr_monty(prj_pt_t out,nn_src_t m,prj_pt_src_t in)1727*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_mul_ltr_monty(prj_pt_t out, nn_src_t m, prj_pt_src_t in){
1728*f0865ec9SKyle Evans #if defined(USE_DOUBLE_ADD_ALWAYS)
1729*f0865ec9SKyle Evans 	return _prj_pt_mul_ltr_monty_dbl_add_always(out, m, in);
1730*f0865ec9SKyle Evans #elif defined(USE_MONTY_LADDER)
1731*f0865ec9SKyle Evans 	return _prj_pt_mul_ltr_monty_ladder(out, m, in);
1732*f0865ec9SKyle Evans #else
1733*f0865ec9SKyle Evans #error "Error: neither Double and Add Always nor Montgomery Ladder has been selected!"
1734*f0865ec9SKyle Evans #endif
1735*f0865ec9SKyle Evans }
1736*f0865ec9SKyle Evans 
1737*f0865ec9SKyle Evans /* version with 'm' passed via 'out'. */
_prj_pt_mul_ltr_monty_aliased(prj_pt_t out,nn_src_t m,prj_pt_src_t in)1738*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_mul_ltr_monty_aliased(prj_pt_t out, nn_src_t m, prj_pt_src_t in)
1739*f0865ec9SKyle Evans {
1740*f0865ec9SKyle Evans 	prj_pt out_cpy;
1741*f0865ec9SKyle Evans 	int ret;
1742*f0865ec9SKyle Evans 	out_cpy.magic = WORD(0);
1743*f0865ec9SKyle Evans 
1744*f0865ec9SKyle Evans 	ret = prj_pt_init(&out_cpy, in->crv); EG(ret, err);
1745*f0865ec9SKyle Evans 	ret = _prj_pt_mul_ltr_monty(&out_cpy, m, in); EG(ret, err);
1746*f0865ec9SKyle Evans 	ret = prj_pt_copy(out, &out_cpy);
1747*f0865ec9SKyle Evans 
1748*f0865ec9SKyle Evans err:
1749*f0865ec9SKyle Evans 	prj_pt_uninit(&out_cpy);
1750*f0865ec9SKyle Evans 	return ret;
1751*f0865ec9SKyle Evans }
1752*f0865ec9SKyle Evans 
1753*f0865ec9SKyle Evans /* Aliased version. This is the public main interface of our
1754*f0865ec9SKyle Evans  * scalar multiplication algorithm. Checks that the input point
1755*f0865ec9SKyle Evans  * and that the output point are on the curve are performed here
1756*f0865ec9SKyle Evans  * (before and after calling the core algorithm, albeit Double and
1757*f0865ec9SKyle Evans  * Add Always or Montgomery Ladder).
1758*f0865ec9SKyle Evans  */
prj_pt_mul(prj_pt_t out,nn_src_t m,prj_pt_src_t in)1759*f0865ec9SKyle Evans int prj_pt_mul(prj_pt_t out, nn_src_t m, prj_pt_src_t in)
1760*f0865ec9SKyle Evans {
1761*f0865ec9SKyle Evans 	int ret, on_curve;
1762*f0865ec9SKyle Evans 
1763*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in); EG(ret, err);
1764*f0865ec9SKyle Evans 	ret = nn_check_initialized(m); EG(ret, err);
1765*f0865ec9SKyle Evans 
1766*f0865ec9SKyle Evans 	/* Check that the input is on the curve */
1767*f0865ec9SKyle Evans 	MUST_HAVE((!prj_pt_is_on_curve(in, &on_curve)) && on_curve, ret, err);
1768*f0865ec9SKyle Evans 
1769*f0865ec9SKyle Evans 	if (out == in) {
1770*f0865ec9SKyle Evans 		ret = _prj_pt_mul_ltr_monty_aliased(out, m, in); EG(ret, err);
1771*f0865ec9SKyle Evans 	} else {
1772*f0865ec9SKyle Evans 		ret = _prj_pt_mul_ltr_monty(out, m, in); EG(ret, err);
1773*f0865ec9SKyle Evans 	}
1774*f0865ec9SKyle Evans 
1775*f0865ec9SKyle Evans 	/* Check that the output is on the curve */
1776*f0865ec9SKyle Evans 	MUST_HAVE((!prj_pt_is_on_curve(out, &on_curve)) && on_curve, ret, err);
1777*f0865ec9SKyle Evans 
1778*f0865ec9SKyle Evans err:
1779*f0865ec9SKyle Evans 	return ret;
1780*f0865ec9SKyle Evans }
1781*f0865ec9SKyle Evans 
prj_pt_mul_blind(prj_pt_t out,nn_src_t m,prj_pt_src_t in)1782*f0865ec9SKyle Evans int prj_pt_mul_blind(prj_pt_t out, nn_src_t m, prj_pt_src_t in)
1783*f0865ec9SKyle Evans {
1784*f0865ec9SKyle Evans 	/* Blind the scalar m with (b*q) where q is the curve order.
1785*f0865ec9SKyle Evans 	 * NOTE: the curve order and the "generator" order are
1786*f0865ec9SKyle Evans 	 * usually the same (i.e. cofactor = 1) for the classical
1787*f0865ec9SKyle Evans 	 * prime fields curves. However some exceptions exist
1788*f0865ec9SKyle Evans 	 * (e.g. Wei25519 and Wei448), and in this case it is
1789*f0865ec9SKyle Evans 	 * curcial to use the curve order for a generic blinding
1790*f0865ec9SKyle Evans 	 * working on any point on the curve.
1791*f0865ec9SKyle Evans 	 */
1792*f0865ec9SKyle Evans 	nn b;
1793*f0865ec9SKyle Evans 	nn_src_t q;
1794*f0865ec9SKyle Evans 	int ret;
1795*f0865ec9SKyle Evans 	b.magic = WORD(0);
1796*f0865ec9SKyle Evans 
1797*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in); EG(ret, err);
1798*f0865ec9SKyle Evans 
1799*f0865ec9SKyle Evans 	q = &(in->crv->order);
1800*f0865ec9SKyle Evans 
1801*f0865ec9SKyle Evans 	ret = nn_init(&b, 0); EG(ret, err);
1802*f0865ec9SKyle Evans 
1803*f0865ec9SKyle Evans 	ret = nn_get_random_mod(&b, q); EG(ret, err);
1804*f0865ec9SKyle Evans 
1805*f0865ec9SKyle Evans 	ret = nn_mul(&b, &b, q); EG(ret, err);
1806*f0865ec9SKyle Evans 	ret = nn_add(&b, &b, m); EG(ret, err);
1807*f0865ec9SKyle Evans 
1808*f0865ec9SKyle Evans 	/* NOTE: point blinding is performed in the lower functions */
1809*f0865ec9SKyle Evans 	/* NOTE: check that input and output points are on the curve are
1810*f0865ec9SKyle Evans 	 * performed in the lower functions.
1811*f0865ec9SKyle Evans 	 */
1812*f0865ec9SKyle Evans 
1813*f0865ec9SKyle Evans 	/* Perform the scalar multiplication */
1814*f0865ec9SKyle Evans 	ret = prj_pt_mul(out, &b, in);
1815*f0865ec9SKyle Evans 
1816*f0865ec9SKyle Evans err:
1817*f0865ec9SKyle Evans 	nn_uninit(&b);
1818*f0865ec9SKyle Evans 
1819*f0865ec9SKyle Evans 	PTR_NULLIFY(q);
1820*f0865ec9SKyle Evans 
1821*f0865ec9SKyle Evans 	return ret;
1822*f0865ec9SKyle Evans }
1823*f0865ec9SKyle Evans 
1824*f0865ec9SKyle Evans /* Naive double and add scalar multiplication.
1825*f0865ec9SKyle Evans  *
1826*f0865ec9SKyle Evans  * This scalar multiplication is used on public values and is optimized with no
1827*f0865ec9SKyle Evans  * countermeasures, and it is usually faster as scalar can be small with few bits
1828*f0865ec9SKyle Evans  * to process (e.g. cofactors, etc.).
1829*f0865ec9SKyle Evans  *
1830*f0865ec9SKyle Evans  * out is initialized by the function.
1831*f0865ec9SKyle Evans  *
1832*f0865ec9SKyle Evans  * XXX: WARNING: this function must only be used on public points!
1833*f0865ec9SKyle Evans  *
1834*f0865ec9SKyle Evans  */
__prj_pt_unprotected_mult(prj_pt_t out,nn_src_t scalar,prj_pt_src_t public_in)1835*f0865ec9SKyle Evans static int __prj_pt_unprotected_mult(prj_pt_t out, nn_src_t scalar, prj_pt_src_t public_in)
1836*f0865ec9SKyle Evans {
1837*f0865ec9SKyle Evans         u8 expbit;
1838*f0865ec9SKyle Evans         bitcnt_t explen;
1839*f0865ec9SKyle Evans         int ret, iszero, on_curve;
1840*f0865ec9SKyle Evans 
1841*f0865ec9SKyle Evans         ret = prj_pt_check_initialized(public_in); EG(ret, err);
1842*f0865ec9SKyle Evans         ret = nn_check_initialized(scalar); EG(ret, err);
1843*f0865ec9SKyle Evans 
1844*f0865ec9SKyle Evans 	/* This function does not support aliasing */
1845*f0865ec9SKyle Evans 	MUST_HAVE((out != public_in), ret, err);
1846*f0865ec9SKyle Evans 
1847*f0865ec9SKyle Evans 	/* Check that the input is on the curve */
1848*f0865ec9SKyle Evans 	MUST_HAVE((!prj_pt_is_on_curve(public_in, &on_curve)) && on_curve, ret, err);
1849*f0865ec9SKyle Evans 
1850*f0865ec9SKyle Evans         ret = nn_iszero(scalar, &iszero); EG(ret, err);
1851*f0865ec9SKyle Evans 	/* Multiplication by zero is the point at infinity */
1852*f0865ec9SKyle Evans 	if(iszero){
1853*f0865ec9SKyle Evans 		ret = prj_pt_zero(out); EG(ret, err);
1854*f0865ec9SKyle Evans 		goto err;
1855*f0865ec9SKyle Evans 	}
1856*f0865ec9SKyle Evans 
1857*f0865ec9SKyle Evans         ret = nn_bitlen(scalar, &explen); EG(ret, err);
1858*f0865ec9SKyle Evans         /* Sanity check */
1859*f0865ec9SKyle Evans         MUST_HAVE((explen > 0), ret, err);
1860*f0865ec9SKyle Evans         explen = (bitcnt_t)(explen - 1);
1861*f0865ec9SKyle Evans 	ret = prj_pt_copy(out, public_in); EG(ret, err);
1862*f0865ec9SKyle Evans 
1863*f0865ec9SKyle Evans         while (explen > 0) {
1864*f0865ec9SKyle Evans                 explen = (bitcnt_t)(explen - 1);
1865*f0865ec9SKyle Evans                 ret = nn_getbit(scalar, explen, &expbit); EG(ret, err);
1866*f0865ec9SKyle Evans                 ret = prj_pt_dbl(out, out); EG(ret, err);
1867*f0865ec9SKyle Evans                 if(expbit){
1868*f0865ec9SKyle Evans                         ret = prj_pt_add(out, out, public_in); EG(ret, err);
1869*f0865ec9SKyle Evans                 }
1870*f0865ec9SKyle Evans         }
1871*f0865ec9SKyle Evans 
1872*f0865ec9SKyle Evans 	/* Check that the output is on the curve */
1873*f0865ec9SKyle Evans 	MUST_HAVE((!prj_pt_is_on_curve(out, &on_curve)) && on_curve, ret, err);
1874*f0865ec9SKyle Evans 
1875*f0865ec9SKyle Evans err:
1876*f0865ec9SKyle Evans         VAR_ZEROIFY(expbit);
1877*f0865ec9SKyle Evans         VAR_ZEROIFY(explen);
1878*f0865ec9SKyle Evans 
1879*f0865ec9SKyle Evans         return ret;
1880*f0865ec9SKyle Evans }
1881*f0865ec9SKyle Evans 
1882*f0865ec9SKyle Evans /* Aliased version of __prj_pt_unprotected_mult */
_prj_pt_unprotected_mult(prj_pt_t out,nn_src_t scalar,prj_pt_src_t public_in)1883*f0865ec9SKyle Evans int _prj_pt_unprotected_mult(prj_pt_t out, nn_src_t scalar, prj_pt_src_t public_in)
1884*f0865ec9SKyle Evans {
1885*f0865ec9SKyle Evans 	int ret;
1886*f0865ec9SKyle Evans 
1887*f0865ec9SKyle Evans 	if(out == public_in){
1888*f0865ec9SKyle Evans                 prj_pt A;
1889*f0865ec9SKyle Evans                 A.magic = WORD(0);
1890*f0865ec9SKyle Evans 
1891*f0865ec9SKyle Evans                 ret = prj_pt_copy(&A, public_in); EG(ret, err1);
1892*f0865ec9SKyle Evans 		ret = __prj_pt_unprotected_mult(out, scalar, &A);
1893*f0865ec9SKyle Evans err1:
1894*f0865ec9SKyle Evans 		prj_pt_uninit(&A);
1895*f0865ec9SKyle Evans 		goto err;
1896*f0865ec9SKyle Evans 	}
1897*f0865ec9SKyle Evans 	else{
1898*f0865ec9SKyle Evans 		ret = __prj_pt_unprotected_mult(out, scalar, public_in);
1899*f0865ec9SKyle Evans 	}
1900*f0865ec9SKyle Evans err:
1901*f0865ec9SKyle Evans 	return ret;
1902*f0865ec9SKyle Evans }
1903*f0865ec9SKyle Evans /*
1904*f0865ec9SKyle Evans  * Check if an integer is (a multiple of) a projective point order.
1905*f0865ec9SKyle Evans  *
1906*f0865ec9SKyle Evans  * The function returns 0 on success, -1 on error. The value check is set to 1 if the projective
1907*f0865ec9SKyle Evans  * point has order in_isorder, 0 otherwise. The value is meaningless on error.
1908*f0865ec9SKyle Evans  */
check_prj_pt_order(prj_pt_src_t in_shortw,nn_src_t in_isorder,prj_pt_sensitivity s,int * check)1909*f0865ec9SKyle Evans int check_prj_pt_order(prj_pt_src_t in_shortw, nn_src_t in_isorder, prj_pt_sensitivity s, int *check)
1910*f0865ec9SKyle Evans {
1911*f0865ec9SKyle Evans 	int ret, iszero;
1912*f0865ec9SKyle Evans 	prj_pt res;
1913*f0865ec9SKyle Evans 	res.magic = WORD(0);
1914*f0865ec9SKyle Evans 
1915*f0865ec9SKyle Evans 	/* First sanity checks */
1916*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in_shortw); EG(ret, err);
1917*f0865ec9SKyle Evans 	ret = nn_check_initialized(in_isorder); EG(ret, err);
1918*f0865ec9SKyle Evans 	MUST_HAVE((check != NULL), ret, err);
1919*f0865ec9SKyle Evans 
1920*f0865ec9SKyle Evans 	/* Then, perform the scalar multiplication */
1921*f0865ec9SKyle Evans 	if(s == PUBLIC_PT){
1922*f0865ec9SKyle Evans 		/* If this is a public point, we can use the naive scalar multiplication */
1923*f0865ec9SKyle Evans 		ret = _prj_pt_unprotected_mult(&res, in_isorder, in_shortw); EG(ret, err);
1924*f0865ec9SKyle Evans 	}
1925*f0865ec9SKyle Evans 	else{
1926*f0865ec9SKyle Evans 		/* If the point is private, it is sensitive and we proceed with the secure
1927*f0865ec9SKyle Evans 		 * scalar blind multiplication.
1928*f0865ec9SKyle Evans 		 */
1929*f0865ec9SKyle Evans 		ret = prj_pt_mul_blind(&res, in_isorder, in_shortw); EG(ret, err);
1930*f0865ec9SKyle Evans 	}
1931*f0865ec9SKyle Evans 
1932*f0865ec9SKyle Evans 	/* Check if we have the point at infinity */
1933*f0865ec9SKyle Evans 	ret = prj_pt_iszero(&res, &iszero); EG(ret, err);
1934*f0865ec9SKyle Evans 	(*check) = iszero;
1935*f0865ec9SKyle Evans 
1936*f0865ec9SKyle Evans err:
1937*f0865ec9SKyle Evans 	prj_pt_uninit(&res);
1938*f0865ec9SKyle Evans 
1939*f0865ec9SKyle Evans 	return ret;
1940*f0865ec9SKyle Evans }
1941*f0865ec9SKyle Evans 
1942*f0865ec9SKyle Evans /*****************************************************************************/
1943*f0865ec9SKyle Evans 
1944*f0865ec9SKyle Evans /*
1945*f0865ec9SKyle Evans  * Map points from Edwards to short Weierstrass projective points through Montgomery (composition mapping).
1946*f0865ec9SKyle Evans  *     Point at infinity (0, 1) -> (0, 1, 0) is treated as an exception, which is trivially not constant time.
1947*f0865ec9SKyle Evans  *     This is OK since our mapping functions should be used at the non sensitive input and output
1948*f0865ec9SKyle Evans  *     interfaces.
1949*f0865ec9SKyle Evans  *
1950*f0865ec9SKyle Evans  * The function returns 0 on success, -1 on error.
1951*f0865ec9SKyle Evans  */
aff_pt_edwards_to_prj_pt_shortw(aff_pt_edwards_src_t in_edwards,ec_shortw_crv_src_t shortw_crv,prj_pt_t out_shortw,fp_src_t alpha_edwards)1952*f0865ec9SKyle Evans int aff_pt_edwards_to_prj_pt_shortw(aff_pt_edwards_src_t in_edwards,
1953*f0865ec9SKyle Evans 				    ec_shortw_crv_src_t shortw_crv,
1954*f0865ec9SKyle Evans 				    prj_pt_t out_shortw,
1955*f0865ec9SKyle Evans 				    fp_src_t alpha_edwards)
1956*f0865ec9SKyle Evans {
1957*f0865ec9SKyle Evans 	int ret, iszero, cmp;
1958*f0865ec9SKyle Evans 	aff_pt out_shortw_aff;
1959*f0865ec9SKyle Evans 	fp one;
1960*f0865ec9SKyle Evans 	out_shortw_aff.magic = one.magic = WORD(0);
1961*f0865ec9SKyle Evans 
1962*f0865ec9SKyle Evans 	/* Check the curves compatibility */
1963*f0865ec9SKyle Evans 	ret = aff_pt_edwards_check_initialized(in_edwards); EG(ret, err);
1964*f0865ec9SKyle Evans 	ret = curve_edwards_shortw_check(in_edwards->crv, shortw_crv, alpha_edwards); EG(ret, err);
1965*f0865ec9SKyle Evans 
1966*f0865ec9SKyle Evans 	/* Initialize output point with curve */
1967*f0865ec9SKyle Evans 	ret = prj_pt_init(out_shortw, shortw_crv); EG(ret, err);
1968*f0865ec9SKyle Evans 
1969*f0865ec9SKyle Evans 	ret = fp_init(&one, in_edwards->x.ctx); EG(ret, err);
1970*f0865ec9SKyle Evans 	ret = fp_one(&one); EG(ret, err);
1971*f0865ec9SKyle Evans 
1972*f0865ec9SKyle Evans 	/* Check if we are the point at infinity
1973*f0865ec9SKyle Evans 	 * This check induces a non consant time exception, but the current function must be called on
1974*f0865ec9SKyle Evans 	 * public data anyways.
1975*f0865ec9SKyle Evans 	 */
1976*f0865ec9SKyle Evans 	ret = fp_iszero(&(in_edwards->x), &iszero); EG(ret, err);
1977*f0865ec9SKyle Evans 	ret = fp_cmp(&(in_edwards->y), &one, &cmp); EG(ret, err);
1978*f0865ec9SKyle Evans 	if(iszero && (cmp == 0)){
1979*f0865ec9SKyle Evans 		ret = prj_pt_zero(out_shortw); EG(ret, err);
1980*f0865ec9SKyle Evans 		ret = 0;
1981*f0865ec9SKyle Evans 		goto err;
1982*f0865ec9SKyle Evans 	}
1983*f0865ec9SKyle Evans 
1984*f0865ec9SKyle Evans 	/* Use the affine mapping */
1985*f0865ec9SKyle Evans 	ret = aff_pt_edwards_to_shortw(in_edwards, shortw_crv, &out_shortw_aff, alpha_edwards); EG(ret, err);
1986*f0865ec9SKyle Evans 	/* And then map the short Weierstrass affine to projective coordinates */
1987*f0865ec9SKyle Evans 	ret = ec_shortw_aff_to_prj(out_shortw, &out_shortw_aff);
1988*f0865ec9SKyle Evans 
1989*f0865ec9SKyle Evans err:
1990*f0865ec9SKyle Evans 	fp_uninit(&one);
1991*f0865ec9SKyle Evans 	aff_pt_uninit(&out_shortw_aff);
1992*f0865ec9SKyle Evans 
1993*f0865ec9SKyle Evans 	return ret;
1994*f0865ec9SKyle Evans }
1995*f0865ec9SKyle Evans 
1996*f0865ec9SKyle Evans /*
1997*f0865ec9SKyle Evans  * Map points from short Weierstrass projective points to Edwards through Montgomery (composition mapping).
1998*f0865ec9SKyle Evans  *     Point at infinity with Z=0 (in projective coordinates) -> (0, 1) is treated as an exception, which is trivially not constant time.
1999*f0865ec9SKyle Evans  *     This is OK since our mapping functions should be used at the non sensitive input and output
2000*f0865ec9SKyle Evans  *     interfaces.
2001*f0865ec9SKyle Evans  *
2002*f0865ec9SKyle Evans  * The function returns 0 on success, -1 on error.
2003*f0865ec9SKyle Evans  */
prj_pt_shortw_to_aff_pt_edwards(prj_pt_src_t in_shortw,ec_edwards_crv_src_t edwards_crv,aff_pt_edwards_t out_edwards,fp_src_t alpha_edwards)2004*f0865ec9SKyle Evans int prj_pt_shortw_to_aff_pt_edwards(prj_pt_src_t in_shortw,
2005*f0865ec9SKyle Evans 				    ec_edwards_crv_src_t edwards_crv,
2006*f0865ec9SKyle Evans 				    aff_pt_edwards_t out_edwards,
2007*f0865ec9SKyle Evans 				    fp_src_t alpha_edwards)
2008*f0865ec9SKyle Evans {
2009*f0865ec9SKyle Evans 	int ret, iszero;
2010*f0865ec9SKyle Evans 	aff_pt in_shortw_aff;
2011*f0865ec9SKyle Evans 	in_shortw_aff.magic = WORD(0);
2012*f0865ec9SKyle Evans 
2013*f0865ec9SKyle Evans 	/* Check the curves compatibility */
2014*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in_shortw); EG(ret, err);
2015*f0865ec9SKyle Evans 	ret = curve_edwards_shortw_check(edwards_crv, in_shortw->crv, alpha_edwards); EG(ret, err);
2016*f0865ec9SKyle Evans 
2017*f0865ec9SKyle Evans 	/* Initialize output point with curve */
2018*f0865ec9SKyle Evans 	ret = aff_pt_init(&in_shortw_aff, in_shortw->crv); EG(ret, err);
2019*f0865ec9SKyle Evans 
2020*f0865ec9SKyle Evans 	/* Check if we are the point at infinity
2021*f0865ec9SKyle Evans 	 * This check induces a non consant time exception, but the current function must be called on
2022*f0865ec9SKyle Evans 	 * public data anyways.
2023*f0865ec9SKyle Evans 	 */
2024*f0865ec9SKyle Evans 	ret = prj_pt_iszero(in_shortw, &iszero); EG(ret, err);
2025*f0865ec9SKyle Evans 	if(iszero){
2026*f0865ec9SKyle Evans 		fp zero, one;
2027*f0865ec9SKyle Evans 		zero.magic = one.magic = WORD(0);
2028*f0865ec9SKyle Evans 
2029*f0865ec9SKyle Evans 		ret = fp_init(&zero, in_shortw->X.ctx); EG(ret, err1);
2030*f0865ec9SKyle Evans 		ret = fp_init(&one, in_shortw->X.ctx); EG(ret, err1);
2031*f0865ec9SKyle Evans 
2032*f0865ec9SKyle Evans 		ret = fp_zero(&zero); EG(ret, err1);
2033*f0865ec9SKyle Evans 		ret = fp_one(&one); EG(ret, err1);
2034*f0865ec9SKyle Evans 
2035*f0865ec9SKyle Evans 		ret = aff_pt_edwards_init_from_coords(out_edwards, edwards_crv, &zero, &one);
2036*f0865ec9SKyle Evans 
2037*f0865ec9SKyle Evans err1:
2038*f0865ec9SKyle Evans 		fp_uninit(&zero);
2039*f0865ec9SKyle Evans 		fp_uninit(&one);
2040*f0865ec9SKyle Evans 
2041*f0865ec9SKyle Evans 		goto err;
2042*f0865ec9SKyle Evans 	}
2043*f0865ec9SKyle Evans 
2044*f0865ec9SKyle Evans 	/* Map projective to affine on the short Weierstrass */
2045*f0865ec9SKyle Evans 	ret = prj_pt_to_aff(&in_shortw_aff, in_shortw); EG(ret, err);
2046*f0865ec9SKyle Evans 	/* Use the affine mapping */
2047*f0865ec9SKyle Evans 	ret = aff_pt_shortw_to_edwards(&in_shortw_aff, edwards_crv, out_edwards, alpha_edwards);
2048*f0865ec9SKyle Evans 
2049*f0865ec9SKyle Evans err:
2050*f0865ec9SKyle Evans 	aff_pt_uninit(&in_shortw_aff);
2051*f0865ec9SKyle Evans 
2052*f0865ec9SKyle Evans 	return ret;
2053*f0865ec9SKyle Evans }
2054*f0865ec9SKyle Evans 
2055*f0865ec9SKyle Evans /*
2056*f0865ec9SKyle Evans  * Map points from Montgomery to short Weierstrass projective points.
2057*f0865ec9SKyle Evans  *
2058*f0865ec9SKyle Evans  * The function returns 0 on success, -1 on error.
2059*f0865ec9SKyle Evans  */
aff_pt_montgomery_to_prj_pt_shortw(aff_pt_montgomery_src_t in_montgomery,ec_shortw_crv_src_t shortw_crv,prj_pt_t out_shortw)2060*f0865ec9SKyle Evans int aff_pt_montgomery_to_prj_pt_shortw(aff_pt_montgomery_src_t in_montgomery,
2061*f0865ec9SKyle Evans 				       ec_shortw_crv_src_t shortw_crv,
2062*f0865ec9SKyle Evans 				       prj_pt_t out_shortw)
2063*f0865ec9SKyle Evans {
2064*f0865ec9SKyle Evans 	int ret;
2065*f0865ec9SKyle Evans 	aff_pt out_shortw_aff;
2066*f0865ec9SKyle Evans 	out_shortw_aff.magic = WORD(0);
2067*f0865ec9SKyle Evans 
2068*f0865ec9SKyle Evans 	/* Check the curves compatibility */
2069*f0865ec9SKyle Evans 	ret = aff_pt_montgomery_check_initialized(in_montgomery); EG(ret, err);
2070*f0865ec9SKyle Evans 	ret = curve_montgomery_shortw_check(in_montgomery->crv, shortw_crv); EG(ret, err);
2071*f0865ec9SKyle Evans 
2072*f0865ec9SKyle Evans 	/* Initialize output point with curve */
2073*f0865ec9SKyle Evans 	ret = prj_pt_init(out_shortw, shortw_crv); EG(ret, err);
2074*f0865ec9SKyle Evans 
2075*f0865ec9SKyle Evans 	/* Use the affine mapping */
2076*f0865ec9SKyle Evans 	ret = aff_pt_montgomery_to_shortw(in_montgomery, shortw_crv, &out_shortw_aff); EG(ret, err);
2077*f0865ec9SKyle Evans 	/* And then map the short Weierstrass affine to projective coordinates */
2078*f0865ec9SKyle Evans 	ret = ec_shortw_aff_to_prj(out_shortw, &out_shortw_aff);
2079*f0865ec9SKyle Evans 
2080*f0865ec9SKyle Evans err:
2081*f0865ec9SKyle Evans 	aff_pt_uninit(&out_shortw_aff);
2082*f0865ec9SKyle Evans 
2083*f0865ec9SKyle Evans 	return ret;
2084*f0865ec9SKyle Evans }
2085*f0865ec9SKyle Evans 
2086*f0865ec9SKyle Evans /*
2087*f0865ec9SKyle Evans  * Map points from short Weierstrass projective points to Montgomery.
2088*f0865ec9SKyle Evans  *
2089*f0865ec9SKyle Evans  * The function returns 0 on success, -1 on error.
2090*f0865ec9SKyle Evans  */
prj_pt_shortw_to_aff_pt_montgomery(prj_pt_src_t in_shortw,ec_montgomery_crv_src_t montgomery_crv,aff_pt_montgomery_t out_montgomery)2091*f0865ec9SKyle Evans int prj_pt_shortw_to_aff_pt_montgomery(prj_pt_src_t in_shortw, ec_montgomery_crv_src_t montgomery_crv, aff_pt_montgomery_t out_montgomery)
2092*f0865ec9SKyle Evans {
2093*f0865ec9SKyle Evans 	int ret;
2094*f0865ec9SKyle Evans 	aff_pt in_shortw_aff;
2095*f0865ec9SKyle Evans 	in_shortw_aff.magic = WORD(0);
2096*f0865ec9SKyle Evans 
2097*f0865ec9SKyle Evans 	/* Check the curves compatibility */
2098*f0865ec9SKyle Evans 	ret = prj_pt_check_initialized(in_shortw); EG(ret, err);
2099*f0865ec9SKyle Evans 	ret = curve_montgomery_shortw_check(montgomery_crv, in_shortw->crv); EG(ret, err);
2100*f0865ec9SKyle Evans 
2101*f0865ec9SKyle Evans 	/* Initialize output point with curve */
2102*f0865ec9SKyle Evans 	ret = aff_pt_init(&in_shortw_aff, in_shortw->crv); EG(ret, err);
2103*f0865ec9SKyle Evans 
2104*f0865ec9SKyle Evans 	/* Map projective to affine on the short Weierstrass */
2105*f0865ec9SKyle Evans 	ret = prj_pt_to_aff(&in_shortw_aff, in_shortw); EG(ret, err);
2106*f0865ec9SKyle Evans 	/* Use the affine mapping */
2107*f0865ec9SKyle Evans 	ret = aff_pt_shortw_to_montgomery(&in_shortw_aff, montgomery_crv, out_montgomery);
2108*f0865ec9SKyle Evans 
2109*f0865ec9SKyle Evans err:
2110*f0865ec9SKyle Evans 	aff_pt_uninit(&in_shortw_aff);
2111*f0865ec9SKyle Evans 
2112*f0865ec9SKyle Evans 	return ret;
2113*f0865ec9SKyle Evans }
2114