xref: /freebsd/crypto/libecc/src/curves/aff_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/aff_pt.h>
17*f0865ec9SKyle Evans 
18*f0865ec9SKyle Evans #define AFF_PT_MAGIC ((word_t)(0x4c82a9bcd0d9ffabULL))
19*f0865ec9SKyle Evans 
20*f0865ec9SKyle Evans /*
21*f0865ec9SKyle Evans  * Verify that an affine point has already been initialized. Return 0 on
22*f0865ec9SKyle Evans  * success, -1 otherwise.
23*f0865ec9SKyle Evans  */
aff_pt_check_initialized(aff_pt_src_t in)24*f0865ec9SKyle Evans int aff_pt_check_initialized(aff_pt_src_t in)
25*f0865ec9SKyle Evans {
26*f0865ec9SKyle Evans 	int ret;
27*f0865ec9SKyle Evans 
28*f0865ec9SKyle Evans 	MUST_HAVE(((in != NULL) && (in->magic == AFF_PT_MAGIC)), ret, err);
29*f0865ec9SKyle Evans 	ret = ec_shortw_crv_check_initialized(in->crv);
30*f0865ec9SKyle Evans 
31*f0865ec9SKyle Evans err:
32*f0865ec9SKyle Evans 	return ret;
33*f0865ec9SKyle Evans }
34*f0865ec9SKyle Evans 
35*f0865ec9SKyle Evans /*
36*f0865ec9SKyle Evans  * Initialize pointed aff_pt structure to make it usable by library
37*f0865ec9SKyle Evans  * function on given curve. Return 0 on success, -1 on error.
38*f0865ec9SKyle Evans  */
aff_pt_init(aff_pt_t in,ec_shortw_crv_src_t curve)39*f0865ec9SKyle Evans int aff_pt_init(aff_pt_t in, ec_shortw_crv_src_t curve)
40*f0865ec9SKyle Evans {
41*f0865ec9SKyle Evans 	int ret;
42*f0865ec9SKyle Evans 
43*f0865ec9SKyle Evans 	MUST_HAVE((in != NULL), ret, err);
44*f0865ec9SKyle Evans 	MUST_HAVE((curve != NULL), ret, err);
45*f0865ec9SKyle Evans 
46*f0865ec9SKyle Evans 	ret = ec_shortw_crv_check_initialized(curve); EG(ret, err);
47*f0865ec9SKyle Evans 	ret = fp_init(&(in->x), curve->a.ctx); EG(ret, err);
48*f0865ec9SKyle Evans 	ret = fp_init(&(in->y), curve->a.ctx); EG(ret, err);
49*f0865ec9SKyle Evans 
50*f0865ec9SKyle Evans 	in->crv = curve;
51*f0865ec9SKyle Evans 	in->magic = AFF_PT_MAGIC;
52*f0865ec9SKyle Evans 
53*f0865ec9SKyle Evans err:
54*f0865ec9SKyle Evans 	return ret;
55*f0865ec9SKyle Evans }
56*f0865ec9SKyle Evans 
57*f0865ec9SKyle Evans /*
58*f0865ec9SKyle Evans  * Initialize given point 'in' on given curve 'curve' and set its coordinates to
59*f0865ec9SKyle Evans  * 'xcoord' and 'ycoord'. Return 0 on success, -1 on error.
60*f0865ec9SKyle Evans  */
aff_pt_init_from_coords(aff_pt_t in,ec_shortw_crv_src_t curve,fp_src_t xcoord,fp_src_t ycoord)61*f0865ec9SKyle Evans int aff_pt_init_from_coords(aff_pt_t in,
62*f0865ec9SKyle Evans 			    ec_shortw_crv_src_t curve,
63*f0865ec9SKyle Evans 			    fp_src_t xcoord, fp_src_t ycoord)
64*f0865ec9SKyle Evans {
65*f0865ec9SKyle Evans 	int ret;
66*f0865ec9SKyle Evans 
67*f0865ec9SKyle Evans 	ret = aff_pt_init(in, curve); EG(ret, err);
68*f0865ec9SKyle Evans 	ret = fp_copy(&(in->x), xcoord); EG(ret, err);
69*f0865ec9SKyle Evans 	ret = fp_copy(&(in->y), ycoord);
70*f0865ec9SKyle Evans 
71*f0865ec9SKyle Evans err:
72*f0865ec9SKyle Evans 	return ret;
73*f0865ec9SKyle Evans }
74*f0865ec9SKyle Evans 
75*f0865ec9SKyle Evans /*
76*f0865ec9SKyle Evans  * Uninitialize pointed affine point 'in' to prevent further use (magic field
77*f0865ec9SKyle Evans  * in the structure is zeroized) and zeroize associated storage space. Note
78*f0865ec9SKyle Evans  * that the curve context pointed to by the point element (passed during init)
79*f0865ec9SKyle Evans  * is left untouched.
80*f0865ec9SKyle Evans  */
aff_pt_uninit(aff_pt_t in)81*f0865ec9SKyle Evans void aff_pt_uninit(aff_pt_t in)
82*f0865ec9SKyle Evans {
83*f0865ec9SKyle Evans 	if((in != NULL) && (in->magic == AFF_PT_MAGIC) && (in->crv != NULL)){
84*f0865ec9SKyle Evans 		in->crv = NULL;
85*f0865ec9SKyle Evans 		in->magic = WORD(0);
86*f0865ec9SKyle Evans 
87*f0865ec9SKyle Evans 		fp_uninit(&(in->x));
88*f0865ec9SKyle Evans 		fp_uninit(&(in->y));
89*f0865ec9SKyle Evans 	}
90*f0865ec9SKyle Evans 
91*f0865ec9SKyle Evans 	return;
92*f0865ec9SKyle Evans }
93*f0865ec9SKyle Evans 
94*f0865ec9SKyle Evans /*
95*f0865ec9SKyle Evans  * Recover the two possible y coordinates from one x on a given
96*f0865ec9SKyle Evans  * curve.
97*f0865ec9SKyle Evans  * The two outputs y1 and y2 are initialized in the function.
98*f0865ec9SKyle Evans  *
99*f0865ec9SKyle Evans  * The function returns -1 on error, 0 on success.
100*f0865ec9SKyle Evans  *
101*f0865ec9SKyle Evans  */
aff_pt_y_from_x(fp_t y1,fp_t y2,fp_src_t x,ec_shortw_crv_src_t curve)102*f0865ec9SKyle Evans int aff_pt_y_from_x(fp_t y1, fp_t y2, fp_src_t x, ec_shortw_crv_src_t curve)
103*f0865ec9SKyle Evans {
104*f0865ec9SKyle Evans 	int ret;
105*f0865ec9SKyle Evans 
106*f0865ec9SKyle Evans 	MUST_HAVE((y1 != NULL) && (y2 != NULL), ret, err);
107*f0865ec9SKyle Evans 	ret = ec_shortw_crv_check_initialized(curve); EG(ret, err);
108*f0865ec9SKyle Evans 	ret = fp_check_initialized(x);  EG(ret, err);
109*f0865ec9SKyle Evans 	/* Aliasing is not supported */
110*f0865ec9SKyle Evans 	MUST_HAVE((y1 != y2) && (y1 != x), ret, err);
111*f0865ec9SKyle Evans 
112*f0865ec9SKyle Evans 
113*f0865ec9SKyle Evans 	/* Initialize our elements */
114*f0865ec9SKyle Evans 	ret = fp_copy(y1, x); EG(ret, err);
115*f0865ec9SKyle Evans 	ret = fp_copy(y2, x); EG(ret, err);
116*f0865ec9SKyle Evans 
117*f0865ec9SKyle Evans 	/* Compute x^3 + ax + b */
118*f0865ec9SKyle Evans 	ret = fp_sqr(y1, y1); EG(ret, err);
119*f0865ec9SKyle Evans 	ret = fp_mul(y1, y1, x); EG(ret, err);
120*f0865ec9SKyle Evans 	ret = fp_mul(y2, y2, &(curve->a)); EG(ret, err);
121*f0865ec9SKyle Evans 	ret = fp_add(y1, y1, y2); EG(ret, err);
122*f0865ec9SKyle Evans 	ret = fp_add(y1, y1,  &(curve->b)); EG(ret, err);
123*f0865ec9SKyle Evans 
124*f0865ec9SKyle Evans 	/* Now compute the two possible square roots
125*f0865ec9SKyle Evans 	 * realizing y^2 = x^3 + ax + b
126*f0865ec9SKyle Evans 	 */
127*f0865ec9SKyle Evans 	ret = fp_sqrt(y1, y2, y1);
128*f0865ec9SKyle Evans 
129*f0865ec9SKyle Evans err:
130*f0865ec9SKyle Evans 	return ret;
131*f0865ec9SKyle Evans }
132*f0865ec9SKyle Evans 
133*f0865ec9SKyle Evans /*
134*f0865ec9SKyle Evans  * Check if given point of coordinate ('x', 'y') is on given curve 'curve' (i.e.
135*f0865ec9SKyle Evans  * if it verifies curve equation y^2 = x^3 + ax + b). On success, the verdict is
136*f0865ec9SKyle Evans  * given using 'on_curve' out parameter (1 if on curve, 0 if not). On error,
137*f0865ec9SKyle Evans  * the function returns -1 and 'on_curve' is left unmodified.
138*f0865ec9SKyle Evans  */
is_on_shortw_curve(fp_src_t x,fp_src_t y,ec_shortw_crv_src_t curve,int * on_curve)139*f0865ec9SKyle Evans int is_on_shortw_curve(fp_src_t x, fp_src_t y, ec_shortw_crv_src_t curve, int *on_curve)
140*f0865ec9SKyle Evans {
141*f0865ec9SKyle Evans 	fp tmp1, tmp2;
142*f0865ec9SKyle Evans 	int ret, cmp;
143*f0865ec9SKyle Evans 	tmp1.magic = tmp2.magic = WORD(0);
144*f0865ec9SKyle Evans 
145*f0865ec9SKyle Evans 	ret = ec_shortw_crv_check_initialized(curve); EG(ret, err);
146*f0865ec9SKyle Evans 	ret = fp_check_initialized(x);  EG(ret, err);
147*f0865ec9SKyle Evans 	ret = fp_check_initialized(y);  EG(ret, err);
148*f0865ec9SKyle Evans 	MUST_HAVE((on_curve != NULL), ret, err);
149*f0865ec9SKyle Evans 
150*f0865ec9SKyle Evans 	MUST_HAVE((x->ctx == y->ctx), ret, err);
151*f0865ec9SKyle Evans 	MUST_HAVE((x->ctx == curve->a.ctx), ret, err);
152*f0865ec9SKyle Evans 
153*f0865ec9SKyle Evans 	/* Note: to optimize local variables, we instead check that
154*f0865ec9SKyle Evans 	 * (y^2 - b) = (x^2 + a) * x
155*f0865ec9SKyle Evans 	 */
156*f0865ec9SKyle Evans 
157*f0865ec9SKyle Evans 	/* Compute y^2 - b */
158*f0865ec9SKyle Evans 	ret = fp_init(&tmp1, x->ctx); EG(ret, err);
159*f0865ec9SKyle Evans 	ret = fp_sqr(&tmp1, y); EG(ret, err);
160*f0865ec9SKyle Evans 	ret = fp_sub(&tmp1, &tmp1, &(curve->b)); EG(ret, err);
161*f0865ec9SKyle Evans 
162*f0865ec9SKyle Evans 	/* Compute (x^2 + a) * x */
163*f0865ec9SKyle Evans 	ret = fp_init(&tmp2, x->ctx); EG(ret, err);
164*f0865ec9SKyle Evans 	ret = fp_sqr(&tmp2, x); EG(ret, err);
165*f0865ec9SKyle Evans 	ret = fp_add(&tmp2, &tmp2, &(curve->a)); EG(ret, err);
166*f0865ec9SKyle Evans 	ret = fp_mul(&tmp2, &tmp2, x); EG(ret, err);
167*f0865ec9SKyle Evans 
168*f0865ec9SKyle Evans 	/* Now check*/
169*f0865ec9SKyle Evans 	ret = fp_cmp(&tmp1, &tmp2, &cmp); EG(ret, err);
170*f0865ec9SKyle Evans 
171*f0865ec9SKyle Evans 	(*on_curve) = (!cmp);
172*f0865ec9SKyle Evans 
173*f0865ec9SKyle Evans err:
174*f0865ec9SKyle Evans 	fp_uninit(&tmp1);
175*f0865ec9SKyle Evans         fp_uninit(&tmp2);
176*f0865ec9SKyle Evans 
177*f0865ec9SKyle Evans         return ret;
178*f0865ec9SKyle Evans }
179*f0865ec9SKyle Evans 
180*f0865ec9SKyle Evans /*
181*f0865ec9SKyle Evans  * Same as previous but using an affine point instead of pair of coordinates
182*f0865ec9SKyle Evans  * and a curve
183*f0865ec9SKyle Evans  */
aff_pt_is_on_curve(aff_pt_src_t pt,int * on_curve)184*f0865ec9SKyle Evans int aff_pt_is_on_curve(aff_pt_src_t pt, int *on_curve)
185*f0865ec9SKyle Evans {
186*f0865ec9SKyle Evans 	int ret;
187*f0865ec9SKyle Evans 
188*f0865ec9SKyle Evans 	MUST_HAVE((on_curve != NULL), ret, err);
189*f0865ec9SKyle Evans 	ret = aff_pt_check_initialized(pt); EG(ret, err);
190*f0865ec9SKyle Evans 	ret = is_on_shortw_curve(&(pt->x), &(pt->y), pt->crv, on_curve);
191*f0865ec9SKyle Evans 
192*f0865ec9SKyle Evans err:
193*f0865ec9SKyle Evans 	return ret;
194*f0865ec9SKyle Evans }
195*f0865ec9SKyle Evans 
196*f0865ec9SKyle Evans /*
197*f0865ec9SKyle Evans  * Copy 'in' affine point into 'out'. 'out' is initialized by the function.
198*f0865ec9SKyle Evans  * 0 is returned on success, -1 on error.
199*f0865ec9SKyle Evans  */
ec_shortw_aff_copy(aff_pt_t out,aff_pt_src_t in)200*f0865ec9SKyle Evans int ec_shortw_aff_copy(aff_pt_t out, aff_pt_src_t in)
201*f0865ec9SKyle Evans {
202*f0865ec9SKyle Evans 	int ret;
203*f0865ec9SKyle Evans 
204*f0865ec9SKyle Evans 	ret = aff_pt_check_initialized(in); EG(ret, err);
205*f0865ec9SKyle Evans 	ret = aff_pt_init(out, in->crv); EG(ret, err);
206*f0865ec9SKyle Evans 	ret = fp_copy(&(out->x), &(in->x)); EG(ret, err);
207*f0865ec9SKyle Evans 	ret = fp_copy(&(out->y), &(in->y));
208*f0865ec9SKyle Evans 
209*f0865ec9SKyle Evans err:
210*f0865ec9SKyle Evans 	return ret;
211*f0865ec9SKyle Evans }
212*f0865ec9SKyle Evans 
213*f0865ec9SKyle Evans /*
214*f0865ec9SKyle Evans  * Compare affine points 'in1' and 'in2'. On success, 0 is returned and
215*f0865ec9SKyle Evans  * comparison value is given using 'cmp' (0 if equal, a non-zero value
216*f0865ec9SKyle Evans  * if they are different). -1 is returned on error.
217*f0865ec9SKyle Evans  */
ec_shortw_aff_cmp(aff_pt_src_t in1,aff_pt_src_t in2,int * cmp)218*f0865ec9SKyle Evans int ec_shortw_aff_cmp(aff_pt_src_t in1, aff_pt_src_t in2, int *cmp)
219*f0865ec9SKyle Evans {
220*f0865ec9SKyle Evans 	int ret, cmp_x, cmp_y;
221*f0865ec9SKyle Evans 
222*f0865ec9SKyle Evans 	MUST_HAVE((cmp != NULL), ret, err);
223*f0865ec9SKyle Evans 
224*f0865ec9SKyle Evans 	ret = aff_pt_check_initialized(in1); EG(ret, err);
225*f0865ec9SKyle Evans 	ret = aff_pt_check_initialized(in2); EG(ret, err);
226*f0865ec9SKyle Evans 
227*f0865ec9SKyle Evans 	MUST_HAVE((in1->crv == in2->crv), ret, err);
228*f0865ec9SKyle Evans 
229*f0865ec9SKyle Evans 	ret = fp_cmp(&(in1->x), &(in2->x), &cmp_x); EG(ret, err);
230*f0865ec9SKyle Evans 	ret = fp_cmp(&(in1->y), &(in2->y), &cmp_y); EG(ret, err);
231*f0865ec9SKyle Evans 
232*f0865ec9SKyle Evans 	(*cmp) = (cmp_x | cmp_y);
233*f0865ec9SKyle Evans 
234*f0865ec9SKyle Evans err:
235*f0865ec9SKyle Evans 	return ret;
236*f0865ec9SKyle Evans }
237*f0865ec9SKyle Evans 
238*f0865ec9SKyle Evans /*
239*f0865ec9SKyle Evans  * Check if given affine points 'in1' and 'in2' on the same curve are equal
240*f0865ec9SKyle Evans  * or opposite. On success, 0 is returned and 'aff_is_eq_or_opp' contains:
241*f0865ec9SKyle Evans  *  - 1 if points are equal or opposite
242*f0865ec9SKyle Evans  *  - 0 if not
243*f0865ec9SKyle Evans  * The function returns -1 on error, in which case 'aff_is_eq_or_opp'
244*f0865ec9SKyle Evans  * is left untouched.
245*f0865ec9SKyle Evans  */
ec_shortw_aff_eq_or_opp(aff_pt_src_t in1,aff_pt_src_t in2,int * aff_is_eq_or_opp)246*f0865ec9SKyle Evans int ec_shortw_aff_eq_or_opp(aff_pt_src_t in1, aff_pt_src_t in2,
247*f0865ec9SKyle Evans 			    int *aff_is_eq_or_opp)
248*f0865ec9SKyle Evans {
249*f0865ec9SKyle Evans 	int ret, cmp, eq_or_opp;
250*f0865ec9SKyle Evans 
251*f0865ec9SKyle Evans 	ret = aff_pt_check_initialized(in1); EG(ret, err);
252*f0865ec9SKyle Evans 	ret = aff_pt_check_initialized(in2); EG(ret, err);
253*f0865ec9SKyle Evans 	MUST_HAVE((in1->crv == in2->crv), ret, err);
254*f0865ec9SKyle Evans 	MUST_HAVE((aff_is_eq_or_opp != NULL), ret, err);
255*f0865ec9SKyle Evans 
256*f0865ec9SKyle Evans 	ret = fp_cmp(&(in1->x), &(in2->x), &cmp); EG(ret, err);
257*f0865ec9SKyle Evans 	ret = fp_eq_or_opp(&(in1->y), &(in2->y), &eq_or_opp); EG(ret, err);
258*f0865ec9SKyle Evans 
259*f0865ec9SKyle Evans 	(*aff_is_eq_or_opp) = ((cmp == 0) & eq_or_opp);
260*f0865ec9SKyle Evans 
261*f0865ec9SKyle Evans err:
262*f0865ec9SKyle Evans 	return ret;
263*f0865ec9SKyle Evans }
264*f0865ec9SKyle Evans 
265*f0865ec9SKyle Evans /*
266*f0865ec9SKyle Evans  * Import an affine point from a buffer with the following layout; the 2
267*f0865ec9SKyle Evans  * coordinates (elements of Fp) are each encoded on p_len bytes, where p_len
268*f0865ec9SKyle Evans  * is the size of p in bytes (e.g. 66 for a prime p of 521 bits). Each
269*f0865ec9SKyle Evans  * coordinate is encoded in big endian. Size of buffer must exactly match
270*f0865ec9SKyle Evans  * 2 * p_len. The function returns 0 on success, -1 on error.
271*f0865ec9SKyle Evans  */
aff_pt_import_from_buf(aff_pt_t pt,const u8 * pt_buf,u16 pt_buf_len,ec_shortw_crv_src_t crv)272*f0865ec9SKyle Evans int aff_pt_import_from_buf(aff_pt_t pt,
273*f0865ec9SKyle Evans 			   const u8 *pt_buf,
274*f0865ec9SKyle Evans 			   u16 pt_buf_len, ec_shortw_crv_src_t crv)
275*f0865ec9SKyle Evans {
276*f0865ec9SKyle Evans 	fp_ctx_src_t ctx;
277*f0865ec9SKyle Evans 	u16 coord_len;
278*f0865ec9SKyle Evans 	int ret, on_curve;
279*f0865ec9SKyle Evans 
280*f0865ec9SKyle Evans 	MUST_HAVE((pt_buf != NULL), ret, err);
281*f0865ec9SKyle Evans 	MUST_HAVE((pt != NULL), ret, err);
282*f0865ec9SKyle Evans 	ret = ec_shortw_crv_check_initialized(crv); EG(ret, err);
283*f0865ec9SKyle Evans 
284*f0865ec9SKyle Evans 	ctx = crv->a.ctx;
285*f0865ec9SKyle Evans 	coord_len = (u16)BYTECEIL(ctx->p_bitlen);
286*f0865ec9SKyle Evans 
287*f0865ec9SKyle Evans 	MUST_HAVE((pt_buf_len == (2 * coord_len)), ret, err);
288*f0865ec9SKyle Evans 
289*f0865ec9SKyle Evans 	ret = fp_init_from_buf(&(pt->x), ctx, pt_buf, coord_len); EG(ret, err);
290*f0865ec9SKyle Evans 	ret = fp_init_from_buf(&(pt->y), ctx, pt_buf + coord_len, coord_len); EG(ret, err);
291*f0865ec9SKyle Evans 
292*f0865ec9SKyle Evans 	/* Set the curve */
293*f0865ec9SKyle Evans 	pt->crv = crv;
294*f0865ec9SKyle Evans 
295*f0865ec9SKyle Evans 	/* Mark the point as initialized */
296*f0865ec9SKyle Evans 	pt->magic = AFF_PT_MAGIC;
297*f0865ec9SKyle Evans 
298*f0865ec9SKyle Evans 	/*
299*f0865ec9SKyle Evans 	 * Check that the point is indeed on provided curve, uninitialize it
300*f0865ec9SKyle Evans 	 * if this is not the case.
301*f0865ec9SKyle Evans 	 */
302*f0865ec9SKyle Evans 	ret = aff_pt_is_on_curve(pt, &on_curve); EG(ret, err);
303*f0865ec9SKyle Evans 
304*f0865ec9SKyle Evans 	if (!on_curve) {
305*f0865ec9SKyle Evans 		aff_pt_uninit(pt);
306*f0865ec9SKyle Evans 		ret = -1;
307*f0865ec9SKyle Evans 	} else {
308*f0865ec9SKyle Evans 		ret = 0;
309*f0865ec9SKyle Evans 	}
310*f0865ec9SKyle Evans 
311*f0865ec9SKyle Evans err:
312*f0865ec9SKyle Evans 	PTR_NULLIFY(ctx);
313*f0865ec9SKyle Evans 
314*f0865ec9SKyle Evans 	return ret;
315*f0865ec9SKyle Evans }
316*f0865ec9SKyle Evans 
317*f0865ec9SKyle Evans 
318*f0865ec9SKyle Evans /*
319*f0865ec9SKyle Evans  * Export an affine point 'pt' to a buffer with the following layout; the 2
320*f0865ec9SKyle Evans  * coordinates (elements of Fp) are each encoded on p_len bytes, where p_len
321*f0865ec9SKyle Evans  * is the size of p in bytes (e.g. 66 for a prime p of 521 bits). Each
322*f0865ec9SKyle Evans  * coordinate is encoded in big endian. Size of buffer must exactly match
323*f0865ec9SKyle Evans  * 2 * p_len.
324*f0865ec9SKyle Evans  */
aff_pt_export_to_buf(aff_pt_src_t pt,u8 * pt_buf,u32 pt_buf_len)325*f0865ec9SKyle Evans int aff_pt_export_to_buf(aff_pt_src_t pt, u8 *pt_buf, u32 pt_buf_len)
326*f0865ec9SKyle Evans {
327*f0865ec9SKyle Evans 	u16 coord_len;
328*f0865ec9SKyle Evans 	int ret, on_curve;
329*f0865ec9SKyle Evans 
330*f0865ec9SKyle Evans 	MUST_HAVE((pt_buf != NULL), ret, err);
331*f0865ec9SKyle Evans 
332*f0865ec9SKyle Evans 	/* The point to be exported must be on the curve */
333*f0865ec9SKyle Evans 	ret = aff_pt_is_on_curve(pt, &on_curve); EG(ret, err);
334*f0865ec9SKyle Evans 	MUST_HAVE((on_curve), ret, err);
335*f0865ec9SKyle Evans 
336*f0865ec9SKyle Evans 	/* buffer size must match 2 * p_len */
337*f0865ec9SKyle Evans 	coord_len = (u16)BYTECEIL(pt->crv->a.ctx->p_bitlen);
338*f0865ec9SKyle Evans 	MUST_HAVE((pt_buf_len == (2 * coord_len)), ret, err);
339*f0865ec9SKyle Evans 
340*f0865ec9SKyle Evans 	/* Export the two coordinates */
341*f0865ec9SKyle Evans 	ret = fp_export_to_buf(pt_buf, coord_len, &(pt->x)); EG(ret, err);
342*f0865ec9SKyle Evans 	ret = fp_export_to_buf(pt_buf + coord_len, coord_len, &(pt->y));
343*f0865ec9SKyle Evans 
344*f0865ec9SKyle Evans err:
345*f0865ec9SKyle Evans 	return ret;
346*f0865ec9SKyle Evans }
347