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