xref: /freebsd/crypto/libecc/src/examples/basic/curve_basic_examples.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/libec.h>
17*f0865ec9SKyle Evans /* We include the printf external dependency for printf output */
18*f0865ec9SKyle Evans #include <libecc/external_deps/print.h>
19*f0865ec9SKyle Evans /* We include the time external dependency for performance measurement */
20*f0865ec9SKyle Evans #include <libecc/external_deps/time.h>
21*f0865ec9SKyle Evans 
22*f0865ec9SKyle Evans /* The followin function picks a random Fp element x, where Fp is the
23*f0865ec9SKyle Evans  * curve underlying prime field, and computes y in Fp such that:
24*f0865ec9SKyle Evans  *   y^2 = x^3 + ax + b, where a and b are the input elliptic
25*f0865ec9SKyle Evans  * curve parameters.
26*f0865ec9SKyle Evans  *
27*f0865ec9SKyle Evans  * This means that (x, y) are the affine coordinates of a "random"
28*f0865ec9SKyle Evans  * point on our curve. The function then outputs the projective
29*f0865ec9SKyle Evans  * coordinates of (x, y), i.e. the triplet (x, y, 1).
30*f0865ec9SKyle Evans  * PS: all our operations on points are done with projective coordinates.
31*f0865ec9SKyle Evans  *
32*f0865ec9SKyle Evans  * Computing y means computing a quadratic residue in Fp, for which we
33*f0865ec9SKyle Evans  * use the Tonelli-Shanks algorithm implemented in the Fp source example
34*f0865ec9SKyle Evans  * (fp_square_residue.c).
35*f0865ec9SKyle Evans  */
36*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET int get_random_point_on_curve(ec_params *curve_params, prj_pt *out_point);
get_random_point_on_curve(ec_params * curve_params,prj_pt * out_point)37*f0865ec9SKyle Evans int get_random_point_on_curve(ec_params *curve_params, prj_pt *out_point)
38*f0865ec9SKyle Evans {
39*f0865ec9SKyle Evans 	nn nn_tmp;
40*f0865ec9SKyle Evans 	int ret, is_oncurve;
41*f0865ec9SKyle Evans 
42*f0865ec9SKyle Evans 	/* Inside our internal representation, curve_params->ec_curve
43*f0865ec9SKyle Evans 	 * contains the curve coefficients a and b.
44*f0865ec9SKyle Evans 	 * curve_params->ec_fp is the Fp context of the curve.
45*f0865ec9SKyle Evans 	 */
46*f0865ec9SKyle Evans 	fp x, y, fp_tmp1, fp_tmp2;
47*f0865ec9SKyle Evans 	fp_ctx_src_t ctx;
48*f0865ec9SKyle Evans 
49*f0865ec9SKyle Evans 	MUST_HAVE((curve_params != NULL), ret, err);
50*f0865ec9SKyle Evans 
51*f0865ec9SKyle Evans 	nn_tmp.magic = WORD(0);
52*f0865ec9SKyle Evans 	x.magic = y.magic = fp_tmp1.magic = fp_tmp2.magic = WORD(0);
53*f0865ec9SKyle Evans 
54*f0865ec9SKyle Evans 	/* Initialize our x value with the curve Fp context */
55*f0865ec9SKyle Evans 	ctx = &(curve_params->ec_fp);
56*f0865ec9SKyle Evans 
57*f0865ec9SKyle Evans 	ret = fp_init(&x, ctx); EG(ret, err);
58*f0865ec9SKyle Evans 	ret = fp_init(&y, ctx); EG(ret, err);
59*f0865ec9SKyle Evans 	ret = fp_init(&fp_tmp1, ctx); EG(ret, err);
60*f0865ec9SKyle Evans 	ret = fp_init(&fp_tmp2, ctx); EG(ret, err);
61*f0865ec9SKyle Evans 
62*f0865ec9SKyle Evans 	ret = nn_init(&nn_tmp, 0); EG(ret, err);
63*f0865ec9SKyle Evans 	ret = nn_set_word_value(&nn_tmp, WORD(3)); EG(ret, err);
64*f0865ec9SKyle Evans 	while (1) {
65*f0865ec9SKyle Evans 		/* Get a random Fp */
66*f0865ec9SKyle Evans 		ret = fp_get_random(&x, ctx); EG(ret, err);
67*f0865ec9SKyle Evans 		ret = fp_copy(&fp_tmp1, &x); EG(ret, err);
68*f0865ec9SKyle Evans 		ret = fp_copy(&fp_tmp2, &x); EG(ret, err);
69*f0865ec9SKyle Evans 		/* Compute x^3 + ax + b */
70*f0865ec9SKyle Evans 		ret = fp_pow(&fp_tmp1, &fp_tmp1, &nn_tmp); EG(ret, err);
71*f0865ec9SKyle Evans 		ret = fp_mul(&fp_tmp2, &fp_tmp2, &(curve_params->ec_curve.a)); EG(ret, err);
72*f0865ec9SKyle Evans 		ret = fp_add(&fp_tmp1, &fp_tmp1, &fp_tmp2); EG(ret, err);
73*f0865ec9SKyle Evans 		ret = fp_add(&fp_tmp1, &fp_tmp1, &(curve_params->ec_curve.b)); EG(ret, err);
74*f0865ec9SKyle Evans 		/*
75*f0865ec9SKyle Evans 		 * Get any of the two square roots, corresponding to (x, y)
76*f0865ec9SKyle Evans 		 * and (x, -y) both on the curve. If no square root exist,
77*f0865ec9SKyle Evans 		 * go to next random Fp.
78*f0865ec9SKyle Evans 		 */
79*f0865ec9SKyle Evans 		if (fp_sqrt(&y, &fp_tmp2, &fp_tmp1) == 0) {
80*f0865ec9SKyle Evans 			/* Check that we indeed satisfy the curve equation */
81*f0865ec9SKyle Evans 			ret = is_on_shortw_curve(&x, &y, &(curve_params->ec_curve), &is_oncurve); EG(ret, err);
82*f0865ec9SKyle Evans 			if (!is_oncurve) {
83*f0865ec9SKyle Evans 				/* This should not happen ... */
84*f0865ec9SKyle Evans 				ext_printf("Error: Tonelli-Shanks found a bad "
85*f0865ec9SKyle Evans 					   "solution to curve equation ...\n");
86*f0865ec9SKyle Evans 				continue;
87*f0865ec9SKyle Evans 			}
88*f0865ec9SKyle Evans 			break;
89*f0865ec9SKyle Evans 		}
90*f0865ec9SKyle Evans 	}
91*f0865ec9SKyle Evans 	/* Now initialize our point with the coordinates (x, y, 1) */
92*f0865ec9SKyle Evans 	ret = fp_one(&fp_tmp1); EG(ret, err);
93*f0865ec9SKyle Evans 	ret = prj_pt_init_from_coords(out_point, &(curve_params->ec_curve), &x, &y,
94*f0865ec9SKyle Evans 				&fp_tmp1); EG(ret, err);
95*f0865ec9SKyle Evans 
96*f0865ec9SKyle Evans err:
97*f0865ec9SKyle Evans 	fp_uninit(&x);
98*f0865ec9SKyle Evans 	fp_uninit(&y);
99*f0865ec9SKyle Evans 	fp_uninit(&fp_tmp1);
100*f0865ec9SKyle Evans 	fp_uninit(&fp_tmp2);
101*f0865ec9SKyle Evans 	nn_uninit(&nn_tmp);
102*f0865ec9SKyle Evans 
103*f0865ec9SKyle Evans 	return ret;
104*f0865ec9SKyle Evans }
105*f0865ec9SKyle Evans 
106*f0865ec9SKyle Evans #define PERF_SCALAR_MUL 40
107*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET int check_curve(const u8 *curve_name);
check_curve(const u8 * curve_name)108*f0865ec9SKyle Evans int check_curve(const u8 *curve_name)
109*f0865ec9SKyle Evans {
110*f0865ec9SKyle Evans 	unsigned int i;
111*f0865ec9SKyle Evans 	u64 t1, t2;
112*f0865ec9SKyle Evans 	int ret, is_oncurve, isone, iszero;
113*f0865ec9SKyle Evans 
114*f0865ec9SKyle Evans 	nn nn_k;
115*f0865ec9SKyle Evans 	/* libecc internal structure holding the curve parameters */
116*f0865ec9SKyle Evans 	ec_params curve_params;
117*f0865ec9SKyle Evans 	/* libecc internal structure holding projective points on curves */
118*f0865ec9SKyle Evans 	prj_pt A, B, C, D;
119*f0865ec9SKyle Evans 	prj_pt TMP;
120*f0865ec9SKyle Evans 	aff_pt T;
121*f0865ec9SKyle Evans 	u32 len;
122*f0865ec9SKyle Evans 
123*f0865ec9SKyle Evans 	/* Importing a specific curve parameters from the constant static
124*f0865ec9SKyle Evans 	 * buffers describing it:
125*f0865ec9SKyle Evans 	 * It is possible to import a curves parameters by its name.
126*f0865ec9SKyle Evans 	 */
127*f0865ec9SKyle Evans 	const ec_str_params *the_curve_const_parameters;
128*f0865ec9SKyle Evans 
129*f0865ec9SKyle Evans 	nn_k.magic = WORD(0);
130*f0865ec9SKyle Evans 	A.magic = B.magic = C.magic = D.magic = WORD(0);
131*f0865ec9SKyle Evans 	TMP.magic = T.magic = WORD(0);
132*f0865ec9SKyle Evans 
133*f0865ec9SKyle Evans 	MUST_HAVE((curve_name != NULL), ret, err);
134*f0865ec9SKyle Evans 
135*f0865ec9SKyle Evans 	ret = local_strnlen((const char *)curve_name, MAX_CURVE_NAME_LEN, &len); EG(ret, err);
136*f0865ec9SKyle Evans 	len += 1;
137*f0865ec9SKyle Evans 	MUST_HAVE((len < 256), ret, err);
138*f0865ec9SKyle Evans 	ret = ec_get_curve_params_by_name(curve_name,
139*f0865ec9SKyle Evans 					    (u8)len, &the_curve_const_parameters); EG(ret, err);
140*f0865ec9SKyle Evans 
141*f0865ec9SKyle Evans 
142*f0865ec9SKyle Evans 	/* Get out if getting the parameters went wrong */
143*f0865ec9SKyle Evans 	if (the_curve_const_parameters == NULL) {
144*f0865ec9SKyle Evans 		ext_printf("Error: error when importing curve %s "
145*f0865ec9SKyle Evans 			   "parameters ...\n", curve_name);
146*f0865ec9SKyle Evans 		ret = -1;
147*f0865ec9SKyle Evans 		goto err;
148*f0865ec9SKyle Evans 	}
149*f0865ec9SKyle Evans 	/* Now map the curve parameters to our libecc internal representation */
150*f0865ec9SKyle Evans 	ret = import_params(&curve_params, the_curve_const_parameters); EG(ret, err);
151*f0865ec9SKyle Evans 	/* Get two random points on the curve */
152*f0865ec9SKyle Evans 	ret = get_random_point_on_curve(&curve_params, &A); EG(ret, err);
153*f0865ec9SKyle Evans 	ret = get_random_point_on_curve(&curve_params, &B); EG(ret, err);
154*f0865ec9SKyle Evans 
155*f0865ec9SKyle Evans 	/*
156*f0865ec9SKyle Evans 	 * Let's add the two points
157*f0865ec9SKyle Evans 	 * C = A + B with regular point addition
158*f0865ec9SKyle Evans 	 */
159*f0865ec9SKyle Evans 	ret = prj_pt_add(&C, &A, &B); EG(ret, err);
160*f0865ec9SKyle Evans 
161*f0865ec9SKyle Evans 	/*
162*f0865ec9SKyle Evans 	 * Check that the resulting additive point C = A+B is indeed on the
163*f0865ec9SKyle Evans 	 * curve.
164*f0865ec9SKyle Evans 	 */
165*f0865ec9SKyle Evans 	ret = prj_pt_to_aff(&T, &C); EG(ret, err);
166*f0865ec9SKyle Evans 	ret = prj_pt_is_on_curve(&C, &is_oncurve); EG(ret, err);
167*f0865ec9SKyle Evans 	if (!is_oncurve) {
168*f0865ec9SKyle Evans 		ext_printf("Error: C = A+B is not on the %s curve!\n",
169*f0865ec9SKyle Evans 			   curve_params.curve_name);
170*f0865ec9SKyle Evans 		ret = -1;
171*f0865ec9SKyle Evans 		goto err;
172*f0865ec9SKyle Evans 	}
173*f0865ec9SKyle Evans 	ret = aff_pt_is_on_curve(&T, &is_oncurve); EG(ret, err);
174*f0865ec9SKyle Evans 	if (!is_oncurve) {
175*f0865ec9SKyle Evans 		ext_printf("Error: C = A+B is not on the %s curve!\n",
176*f0865ec9SKyle Evans 			   curve_params.curve_name);
177*f0865ec9SKyle Evans 		ret = -1;
178*f0865ec9SKyle Evans 		goto err;
179*f0865ec9SKyle Evans 	}
180*f0865ec9SKyle Evans 	/* Same check with doubling
181*f0865ec9SKyle Evans 	 * C = 2A = A+A
182*f0865ec9SKyle Evans 	 */
183*f0865ec9SKyle Evans 	ret = prj_pt_dbl(&C, &A); EG(ret, err);
184*f0865ec9SKyle Evans 
185*f0865ec9SKyle Evans 	/* Check that the resulting point C = 2A is indeed on the curve.
186*f0865ec9SKyle Evans 	 *
187*f0865ec9SKyle Evans 	 */
188*f0865ec9SKyle Evans 	ret = prj_pt_to_aff(&T, &C); EG(ret, err);
189*f0865ec9SKyle Evans 	ret = prj_pt_is_on_curve(&C, &is_oncurve); EG(ret, err);
190*f0865ec9SKyle Evans 	if (!is_oncurve) {
191*f0865ec9SKyle Evans 		ext_printf("Error: C = A+B is not on the %s curve!\n",
192*f0865ec9SKyle Evans 			   curve_params.curve_name);
193*f0865ec9SKyle Evans 		ret = -1;
194*f0865ec9SKyle Evans 		goto err;
195*f0865ec9SKyle Evans 	}
196*f0865ec9SKyle Evans 	ret = aff_pt_is_on_curve(&T, &is_oncurve); EG(ret, err);
197*f0865ec9SKyle Evans 	if (!is_oncurve) {
198*f0865ec9SKyle Evans 		ext_printf("Error: C = A+B is not on the %s curve!\n",
199*f0865ec9SKyle Evans 			   curve_params.curve_name);
200*f0865ec9SKyle Evans 		ret = -1;
201*f0865ec9SKyle Evans 		goto err;
202*f0865ec9SKyle Evans 	}
203*f0865ec9SKyle Evans 	/*
204*f0865ec9SKyle Evans 	 * If the cofactor of the curve is 1, this means that the order of the
205*f0865ec9SKyle Evans 	 * generator is the cardinal of the curve (and hence the order of the
206*f0865ec9SKyle Evans 	 * curve points group). This means that for any point P on the curve,
207*f0865ec9SKyle Evans 	 * we should have qP = 0 (the inifinity point, i.e. the zero neutral
208*f0865ec9SKyle Evans 	 * element of the curve additive group).
209*f0865ec9SKyle Evans 	 */
210*f0865ec9SKyle Evans 	ret = prj_pt_add(&C, &A, &B); EG(ret, err);
211*f0865ec9SKyle Evans 	ret = prj_pt_dbl(&D, &A); EG(ret, err);
212*f0865ec9SKyle Evans 	ret = nn_isone(&(curve_params.ec_gen_cofactor), &isone); EG(ret, err);
213*f0865ec9SKyle Evans 	if (isone) {
214*f0865ec9SKyle Evans 		ret = prj_pt_mul(&TMP, &(curve_params.ec_gen_order), &A); EG(ret, err);
215*f0865ec9SKyle Evans 		ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
216*f0865ec9SKyle Evans 		if (!iszero) {
217*f0865ec9SKyle Evans 			ext_printf("Error: qA is not 0! (regular mul)\n");
218*f0865ec9SKyle Evans 			ret = -1;
219*f0865ec9SKyle Evans 			goto err;
220*f0865ec9SKyle Evans 		}
221*f0865ec9SKyle Evans 		/**/
222*f0865ec9SKyle Evans 		ret = prj_pt_mul_blind(&TMP, &(curve_params.ec_gen_order), &A); EG(ret, err);
223*f0865ec9SKyle Evans 		ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
224*f0865ec9SKyle Evans 		if (!iszero) {
225*f0865ec9SKyle Evans 			ext_printf("Error: qA is not 0! (regular blind mul)\n");
226*f0865ec9SKyle Evans 			ret = -1;
227*f0865ec9SKyle Evans 			goto err;
228*f0865ec9SKyle Evans 		}
229*f0865ec9SKyle Evans 		/**/
230*f0865ec9SKyle Evans 		ret = prj_pt_mul(&TMP, &(curve_params.ec_gen_order), &B); EG(ret, err);
231*f0865ec9SKyle Evans 		ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
232*f0865ec9SKyle Evans 		if (!iszero) {
233*f0865ec9SKyle Evans 			ext_printf("Error: qB is not 0! (regular mul)\n");
234*f0865ec9SKyle Evans 			ret = -1;
235*f0865ec9SKyle Evans 			goto err;
236*f0865ec9SKyle Evans 		}
237*f0865ec9SKyle Evans 		/**/
238*f0865ec9SKyle Evans 		ret = prj_pt_mul_blind(&TMP, &(curve_params.ec_gen_order), &B); EG(ret, err);
239*f0865ec9SKyle Evans 		ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
240*f0865ec9SKyle Evans 		if (!iszero) {
241*f0865ec9SKyle Evans 			ext_printf("Error: qB is not 0! (regular blind mul)\n");
242*f0865ec9SKyle Evans 			ret = -1;
243*f0865ec9SKyle Evans 			goto err;
244*f0865ec9SKyle Evans 		}
245*f0865ec9SKyle Evans 		/**/
246*f0865ec9SKyle Evans 		ret = prj_pt_mul(&TMP, &(curve_params.ec_gen_order), &C); EG(ret, err);
247*f0865ec9SKyle Evans 		ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
248*f0865ec9SKyle Evans 		if (!iszero) {
249*f0865ec9SKyle Evans 			ext_printf("Error: qC is not 0! (regular mul)\n");
250*f0865ec9SKyle Evans 			ret = -1;
251*f0865ec9SKyle Evans 			goto err;
252*f0865ec9SKyle Evans 		}
253*f0865ec9SKyle Evans 		/**/
254*f0865ec9SKyle Evans 		ret = prj_pt_mul_blind(&TMP, &(curve_params.ec_gen_order), &C); EG(ret, err);
255*f0865ec9SKyle Evans 		ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
256*f0865ec9SKyle Evans 		if (!iszero) {
257*f0865ec9SKyle Evans 			ext_printf("Error: qC is not 0! (regular bind mul)\n");
258*f0865ec9SKyle Evans 			ret = -1;
259*f0865ec9SKyle Evans 			goto err;
260*f0865ec9SKyle Evans 		}
261*f0865ec9SKyle Evans 		/**/
262*f0865ec9SKyle Evans 		ret = prj_pt_mul(&TMP, &(curve_params.ec_gen_order), &D); EG(ret, err);
263*f0865ec9SKyle Evans 		ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
264*f0865ec9SKyle Evans 		if (!iszero) {
265*f0865ec9SKyle Evans 			ext_printf("Error: qD is not 0! (regular mul)\n");
266*f0865ec9SKyle Evans 			ret = -1;
267*f0865ec9SKyle Evans 			goto err;
268*f0865ec9SKyle Evans 		}
269*f0865ec9SKyle Evans 		/**/
270*f0865ec9SKyle Evans 		ret = prj_pt_mul_blind(&TMP, &(curve_params.ec_gen_order), &D); EG(ret, err);
271*f0865ec9SKyle Evans 		ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
272*f0865ec9SKyle Evans 		if (!iszero) {
273*f0865ec9SKyle Evans 			ext_printf("Error: qD is not 0! (regular blind mul)\n");
274*f0865ec9SKyle Evans 			ret = -1;
275*f0865ec9SKyle Evans 			goto err;
276*f0865ec9SKyle Evans 		}
277*f0865ec9SKyle Evans 	}
278*f0865ec9SKyle Evans 	/* Let's do some performance tests for point addition and doubling!
279*f0865ec9SKyle Evans 	 * We compute kA many times to have a decent performance measurement,
280*f0865ec9SKyle Evans 	 * where k is chose random at each iteration. We also check that kA
281*f0865ec9SKyle Evans 	 * is indeed on the curve.
282*f0865ec9SKyle Evans 	 */
283*f0865ec9SKyle Evans 	ret = nn_init(&nn_k, 0); EG(ret, err);
284*f0865ec9SKyle Evans 	/**/
285*f0865ec9SKyle Evans 	if (get_ms_time(&t1)) {
286*f0865ec9SKyle Evans 		ext_printf("Error: cannot get time with get_ms_time\n");
287*f0865ec9SKyle Evans 		ret = -1;
288*f0865ec9SKyle Evans 		goto err;
289*f0865ec9SKyle Evans 	}
290*f0865ec9SKyle Evans 	for (i = 0; i < PERF_SCALAR_MUL; i++) {
291*f0865ec9SKyle Evans 		/* k = random mod (q) */
292*f0865ec9SKyle Evans 		ret = nn_get_random_mod(&nn_k, &(curve_params.ec_gen_order)); EG(ret, err);
293*f0865ec9SKyle Evans 		/* Compute kA with montgomery implementation w/o blinding */
294*f0865ec9SKyle Evans 		ret = prj_pt_mul(&TMP, &nn_k, &A); EG(ret, err);
295*f0865ec9SKyle Evans 		ret = prj_pt_to_aff(&T, &TMP); EG(ret, err);
296*f0865ec9SKyle Evans 		ret = prj_pt_is_on_curve(&TMP, &is_oncurve); EG(ret, err);
297*f0865ec9SKyle Evans 		if (!is_oncurve) {
298*f0865ec9SKyle Evans 			ext_printf("Error: kA is not on the %s curve!\n",
299*f0865ec9SKyle Evans 				   curve_params.curve_name);
300*f0865ec9SKyle Evans 			nn_print("k=", &nn_k);
301*f0865ec9SKyle Evans 			ret = -1;
302*f0865ec9SKyle Evans 			goto err;
303*f0865ec9SKyle Evans 		}
304*f0865ec9SKyle Evans 		ret = aff_pt_is_on_curve(&T, &is_oncurve); EG(ret, err);
305*f0865ec9SKyle Evans 		if (!is_oncurve) {
306*f0865ec9SKyle Evans 			ext_printf("Error: kA is not on the %s curve!\n",
307*f0865ec9SKyle Evans 				   curve_params.curve_name);
308*f0865ec9SKyle Evans 			nn_print("k=", &nn_k);
309*f0865ec9SKyle Evans 			ret = -1;
310*f0865ec9SKyle Evans 			goto err;
311*f0865ec9SKyle Evans 		}
312*f0865ec9SKyle Evans 	}
313*f0865ec9SKyle Evans 	if (get_ms_time(&t2)) {
314*f0865ec9SKyle Evans 		ext_printf("Error: cannot get time with get_ms_time\n");
315*f0865ec9SKyle Evans 		ret = -1;
316*f0865ec9SKyle Evans 		goto err;
317*f0865ec9SKyle Evans 	}
318*f0865ec9SKyle Evans 	ext_printf("  [*] Regular EC scalar multiplication took %f seconds "
319*f0865ec9SKyle Evans 		   "on average\n",
320*f0865ec9SKyle Evans 		   (double)(t2 - t1) / (double)(PERF_SCALAR_MUL * 1000ULL));
321*f0865ec9SKyle Evans 	/**/
322*f0865ec9SKyle Evans 	if (get_ms_time(&t1)) {
323*f0865ec9SKyle Evans 		ext_printf("Error: cannot get time with get_ms_time\n");
324*f0865ec9SKyle Evans 		ret = -1;
325*f0865ec9SKyle Evans 		goto err;
326*f0865ec9SKyle Evans 	}
327*f0865ec9SKyle Evans 	for (i = 0; i < PERF_SCALAR_MUL; i++) {
328*f0865ec9SKyle Evans 		/* k = random mod (q) */
329*f0865ec9SKyle Evans 		ret = nn_get_random_mod(&nn_k, &(curve_params.ec_gen_order)); EG(ret, err);
330*f0865ec9SKyle Evans 		/* Compute kA using montgomery implementation w/ blinding */
331*f0865ec9SKyle Evans 		ret = prj_pt_mul_blind(&TMP, &nn_k, &A); EG(ret, err);
332*f0865ec9SKyle Evans 		ret = prj_pt_to_aff(&T, &TMP); EG(ret, err);
333*f0865ec9SKyle Evans 		ret = prj_pt_is_on_curve(&TMP, &is_oncurve); EG(ret, err);
334*f0865ec9SKyle Evans 		if (!is_oncurve) {
335*f0865ec9SKyle Evans 			ext_printf("Error: kA is not on the %s curve!\n",
336*f0865ec9SKyle Evans 				   curve_params.curve_name);
337*f0865ec9SKyle Evans 			nn_print("k=", &nn_k);
338*f0865ec9SKyle Evans 			ret = -1;
339*f0865ec9SKyle Evans 			goto err;
340*f0865ec9SKyle Evans 		}
341*f0865ec9SKyle Evans 		ret = aff_pt_is_on_curve(&T, &is_oncurve); EG(ret, err);
342*f0865ec9SKyle Evans 		if (!is_oncurve) {
343*f0865ec9SKyle Evans 			ext_printf("Error: kA is not on the %s curve!\n",
344*f0865ec9SKyle Evans 				   curve_params.curve_name);
345*f0865ec9SKyle Evans 			nn_print("k=", &nn_k);
346*f0865ec9SKyle Evans 			ret = -1;
347*f0865ec9SKyle Evans 			goto err;
348*f0865ec9SKyle Evans 		}
349*f0865ec9SKyle Evans 	}
350*f0865ec9SKyle Evans 	if (get_ms_time(&t2)) {
351*f0865ec9SKyle Evans 		ext_printf("Error: cannot get time with get_ms_time\n");
352*f0865ec9SKyle Evans 		ret = -1;
353*f0865ec9SKyle Evans 		goto err;
354*f0865ec9SKyle Evans 	}
355*f0865ec9SKyle Evans 	ext_printf("  [*] Regular blind EC scalar multiplication took %f seconds "
356*f0865ec9SKyle Evans 		   "on average\n",
357*f0865ec9SKyle Evans 		   (double)(t2 - t1) / (double)(PERF_SCALAR_MUL * 1000ULL));
358*f0865ec9SKyle Evans 
359*f0865ec9SKyle Evans err:
360*f0865ec9SKyle Evans 	prj_pt_uninit(&A);
361*f0865ec9SKyle Evans 	prj_pt_uninit(&B);
362*f0865ec9SKyle Evans 	prj_pt_uninit(&C);
363*f0865ec9SKyle Evans 	prj_pt_uninit(&D);
364*f0865ec9SKyle Evans 	prj_pt_uninit(&TMP);
365*f0865ec9SKyle Evans 	aff_pt_uninit(&T);
366*f0865ec9SKyle Evans 	nn_uninit(&nn_k);
367*f0865ec9SKyle Evans 
368*f0865ec9SKyle Evans 	return ret;
369*f0865ec9SKyle Evans }
370*f0865ec9SKyle Evans 
371*f0865ec9SKyle Evans #ifdef CURVE_BASIC_EXAMPLES
main(int argc,char * argv[])372*f0865ec9SKyle Evans int main(int argc, char *argv[])
373*f0865ec9SKyle Evans {
374*f0865ec9SKyle Evans 	unsigned int i;
375*f0865ec9SKyle Evans 	u8 curve_name[MAX_CURVE_NAME_LEN] = { 0 };
376*f0865ec9SKyle Evans 	FORCE_USED_VAR(argc);
377*f0865ec9SKyle Evans 	FORCE_USED_VAR(argv);
378*f0865ec9SKyle Evans 
379*f0865ec9SKyle Evans 	/* Traverse all the possible curves we have at our disposal (known curves and
380*f0865ec9SKyle Evans 	 * user defined curves).
381*f0865ec9SKyle Evans 	 */
382*f0865ec9SKyle Evans 	for (i = 0; i < EC_CURVES_NUM; i++) {
383*f0865ec9SKyle Evans 		/* All our possible curves are in ../curves/curves_list.h
384*f0865ec9SKyle Evans 		 * We can get the curve name from its internal type.
385*f0865ec9SKyle Evans 		 */
386*f0865ec9SKyle Evans 		if(ec_get_curve_name_by_type(ec_maps[i].type, curve_name,
387*f0865ec9SKyle Evans 					  sizeof(curve_name))){
388*f0865ec9SKyle Evans 			ext_printf("Error when treating %s\n", curve_name);
389*f0865ec9SKyle Evans 			return -1;
390*f0865ec9SKyle Evans 		}
391*f0865ec9SKyle Evans 		/* Check our curve! */
392*f0865ec9SKyle Evans 		ext_printf("[+] Checking curve %s\n", curve_name);
393*f0865ec9SKyle Evans 		if (check_curve(curve_name)) {
394*f0865ec9SKyle Evans 			ext_printf("Error: error performing check on "
395*f0865ec9SKyle Evans 				   "curve %s\n", curve_name);
396*f0865ec9SKyle Evans 			return -1;
397*f0865ec9SKyle Evans 		}
398*f0865ec9SKyle Evans 	}
399*f0865ec9SKyle Evans 	return 0;
400*f0865ec9SKyle Evans }
401*f0865ec9SKyle Evans #endif
402