File: | src/lib/libcrypto/ec/ecp_smpl.c |
Warning: | line 1175, column 16 Access to field 'Z_is_one' results in a dereference of a null pointer (loaded from variable 'p') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ecp_smpl.c,v 1.56 2023/08/03 18:53:56 tb Exp $ */ | |||
2 | /* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> | |||
3 | * for the OpenSSL project. | |||
4 | * Includes code written by Bodo Moeller for the OpenSSL project. | |||
5 | */ | |||
6 | /* ==================================================================== | |||
7 | * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. | |||
8 | * | |||
9 | * Redistribution and use in source and binary forms, with or without | |||
10 | * modification, are permitted provided that the following conditions | |||
11 | * are met: | |||
12 | * | |||
13 | * 1. Redistributions of source code must retain the above copyright | |||
14 | * notice, this list of conditions and the following disclaimer. | |||
15 | * | |||
16 | * 2. Redistributions in binary form must reproduce the above copyright | |||
17 | * notice, this list of conditions and the following disclaimer in | |||
18 | * the documentation and/or other materials provided with the | |||
19 | * distribution. | |||
20 | * | |||
21 | * 3. All advertising materials mentioning features or use of this | |||
22 | * software must display the following acknowledgment: | |||
23 | * "This product includes software developed by the OpenSSL Project | |||
24 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |||
25 | * | |||
26 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |||
27 | * endorse or promote products derived from this software without | |||
28 | * prior written permission. For written permission, please contact | |||
29 | * openssl-core@openssl.org. | |||
30 | * | |||
31 | * 5. Products derived from this software may not be called "OpenSSL" | |||
32 | * nor may "OpenSSL" appear in their names without prior written | |||
33 | * permission of the OpenSSL Project. | |||
34 | * | |||
35 | * 6. Redistributions of any form whatsoever must retain the following | |||
36 | * acknowledgment: | |||
37 | * "This product includes software developed by the OpenSSL Project | |||
38 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |||
39 | * | |||
40 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |||
41 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
43 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |||
44 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
45 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
47 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
49 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
50 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |||
51 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |||
52 | * ==================================================================== | |||
53 | * | |||
54 | * This product includes cryptographic software written by Eric Young | |||
55 | * (eay@cryptsoft.com). This product includes software written by Tim | |||
56 | * Hudson (tjh@cryptsoft.com). | |||
57 | * | |||
58 | */ | |||
59 | /* ==================================================================== | |||
60 | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. | |||
61 | * Portions of this software developed by SUN MICROSYSTEMS, INC., | |||
62 | * and contributed to the OpenSSL project. | |||
63 | */ | |||
64 | ||||
65 | #include <openssl/err.h> | |||
66 | ||||
67 | #include "bn_local.h" | |||
68 | #include "ec_local.h" | |||
69 | ||||
70 | /* | |||
71 | * Most method functions in this file are designed to work with | |||
72 | * non-trivial representations of field elements if necessary | |||
73 | * (see ecp_mont.c): while standard modular addition and subtraction | |||
74 | * are used, the field_mul and field_sqr methods will be used for | |||
75 | * multiplication, and field_encode and field_decode (if defined) | |||
76 | * will be used for converting between representations. | |||
77 | * | |||
78 | * Functions ec_GFp_simple_points_make_affine() and | |||
79 | * ec_GFp_simple_point_get_affine_coordinates() specifically assume | |||
80 | * that if a non-trivial representation is used, it is a Montgomery | |||
81 | * representation (i.e. 'encoding' means multiplying by some factor R). | |||
82 | */ | |||
83 | ||||
84 | int | |||
85 | ec_GFp_simple_group_init(EC_GROUP *group) | |||
86 | { | |||
87 | BN_init(&group->field); | |||
88 | BN_init(&group->a); | |||
89 | BN_init(&group->b); | |||
90 | group->a_is_minus3 = 0; | |||
91 | return 1; | |||
92 | } | |||
93 | ||||
94 | void | |||
95 | ec_GFp_simple_group_finish(EC_GROUP *group) | |||
96 | { | |||
97 | BN_free(&group->field); | |||
98 | BN_free(&group->a); | |||
99 | BN_free(&group->b); | |||
100 | } | |||
101 | ||||
102 | int | |||
103 | ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) | |||
104 | { | |||
105 | if (!bn_copy(&dest->field, &src->field)) | |||
106 | return 0; | |||
107 | if (!bn_copy(&dest->a, &src->a)) | |||
108 | return 0; | |||
109 | if (!bn_copy(&dest->b, &src->b)) | |||
110 | return 0; | |||
111 | ||||
112 | dest->a_is_minus3 = src->a_is_minus3; | |||
113 | ||||
114 | return 1; | |||
115 | } | |||
116 | ||||
117 | static int | |||
118 | ec_decode_scalar(const EC_GROUP *group, BIGNUM *bn, const BIGNUM *x, BN_CTX *ctx) | |||
119 | { | |||
120 | if (bn == NULL((void *)0)) | |||
121 | return 1; | |||
122 | ||||
123 | if (group->meth->field_decode != NULL((void *)0)) | |||
124 | return group->meth->field_decode(group, bn, x, ctx); | |||
125 | ||||
126 | return bn_copy(bn, x); | |||
127 | } | |||
128 | ||||
129 | static int | |||
130 | ec_encode_scalar(const EC_GROUP *group, BIGNUM *bn, const BIGNUM *x, BN_CTX *ctx) | |||
131 | { | |||
132 | if (!BN_nnmod(bn, x, &group->field, ctx)) | |||
133 | return 0; | |||
134 | ||||
135 | if (group->meth->field_encode != NULL((void *)0)) | |||
136 | return group->meth->field_encode(group, bn, bn, ctx); | |||
137 | ||||
138 | return 1; | |||
139 | } | |||
140 | ||||
141 | static int | |||
142 | ec_encode_z_coordinate(const EC_GROUP *group, BIGNUM *bn, int *is_one, | |||
143 | const BIGNUM *z, BN_CTX *ctx) | |||
144 | { | |||
145 | if (!BN_nnmod(bn, z, &group->field, ctx)) | |||
146 | return 0; | |||
147 | ||||
148 | *is_one = BN_is_one(bn); | |||
149 | if (*is_one && group->meth->field_set_to_one != NULL((void *)0)) | |||
150 | return group->meth->field_set_to_one(group, bn, ctx); | |||
151 | ||||
152 | if (group->meth->field_encode != NULL((void *)0)) | |||
153 | return group->meth->field_encode(group, bn, bn, ctx); | |||
154 | ||||
155 | return 1; | |||
156 | } | |||
157 | ||||
158 | int | |||
159 | ec_GFp_simple_group_set_curve(EC_GROUP *group, | |||
160 | const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) | |||
161 | { | |||
162 | BIGNUM *a_plus_3; | |||
163 | int ret = 0; | |||
164 | ||||
165 | /* p must be a prime > 3 */ | |||
166 | if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) { | |||
167 | ECerror(EC_R_INVALID_FIELD)ERR_put_error(16,(0xfff),(103),"/usr/src/lib/libcrypto/ec/ecp_smpl.c" ,167); | |||
168 | return 0; | |||
169 | } | |||
170 | ||||
171 | BN_CTX_start(ctx); | |||
172 | ||||
173 | if ((a_plus_3 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
174 | goto err; | |||
175 | ||||
176 | if (!bn_copy(&group->field, p)) | |||
177 | goto err; | |||
178 | BN_set_negative(&group->field, 0); | |||
179 | ||||
180 | if (!ec_encode_scalar(group, &group->a, a, ctx)) | |||
181 | goto err; | |||
182 | if (!ec_encode_scalar(group, &group->b, b, ctx)) | |||
183 | goto err; | |||
184 | ||||
185 | if (!BN_set_word(a_plus_3, 3)) | |||
186 | goto err; | |||
187 | if (!BN_mod_add(a_plus_3, a_plus_3, a, &group->field, ctx)) | |||
188 | goto err; | |||
189 | ||||
190 | group->a_is_minus3 = BN_is_zero(a_plus_3); | |||
191 | ||||
192 | ret = 1; | |||
193 | ||||
194 | err: | |||
195 | BN_CTX_end(ctx); | |||
196 | ||||
197 | return ret; | |||
198 | } | |||
199 | ||||
200 | int | |||
201 | ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, | |||
202 | BIGNUM *b, BN_CTX *ctx) | |||
203 | { | |||
204 | if (p != NULL((void *)0)) { | |||
205 | if (!bn_copy(p, &group->field)) | |||
206 | return 0; | |||
207 | } | |||
208 | if (!ec_decode_scalar(group, a, &group->a, ctx)) | |||
209 | return 0; | |||
210 | if (!ec_decode_scalar(group, b, &group->b, ctx)) | |||
211 | return 0; | |||
212 | ||||
213 | return 1; | |||
214 | } | |||
215 | ||||
216 | int | |||
217 | ec_GFp_simple_group_get_degree(const EC_GROUP *group) | |||
218 | { | |||
219 | return BN_num_bits(&group->field); | |||
220 | } | |||
221 | ||||
222 | int | |||
223 | ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) | |||
224 | { | |||
225 | BIGNUM *p, *a, *b, *discriminant; | |||
226 | int ret = 0; | |||
227 | ||||
228 | BN_CTX_start(ctx); | |||
229 | ||||
230 | if ((p = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
231 | goto err; | |||
232 | if ((a = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
233 | goto err; | |||
234 | if ((b = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
235 | goto err; | |||
236 | if ((discriminant = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
237 | goto err; | |||
238 | ||||
239 | if (!EC_GROUP_get_curve(group, p, a, b, ctx)) | |||
240 | goto err; | |||
241 | ||||
242 | /* | |||
243 | * Check that the discriminant 4a^3 + 27b^2 is non-zero modulo p. | |||
244 | */ | |||
245 | ||||
246 | if (BN_is_zero(a) && BN_is_zero(b)) | |||
247 | goto err; | |||
248 | if (BN_is_zero(a) || BN_is_zero(b)) | |||
249 | goto done; | |||
250 | ||||
251 | /* Compute the discriminant: first 4a^3, then 27b^2, then their sum. */ | |||
252 | if (!BN_mod_sqr(discriminant, a, p, ctx)) | |||
253 | goto err; | |||
254 | if (!BN_mod_mul(discriminant, discriminant, a, p, ctx)) | |||
255 | goto err; | |||
256 | if (!BN_lshift(discriminant, discriminant, 2)) | |||
257 | goto err; | |||
258 | ||||
259 | if (!BN_mod_sqr(b, b, p, ctx)) | |||
260 | goto err; | |||
261 | if (!BN_mul_word(b, 27)) | |||
262 | goto err; | |||
263 | ||||
264 | if (!BN_mod_add(discriminant, discriminant, b, p, ctx)) | |||
265 | goto err; | |||
266 | ||||
267 | if (BN_is_zero(discriminant)) | |||
268 | goto err; | |||
269 | ||||
270 | done: | |||
271 | ret = 1; | |||
272 | ||||
273 | err: | |||
274 | BN_CTX_end(ctx); | |||
275 | ||||
276 | return ret; | |||
277 | } | |||
278 | ||||
279 | int | |||
280 | ec_GFp_simple_point_init(EC_POINT * point) | |||
281 | { | |||
282 | BN_init(&point->X); | |||
283 | BN_init(&point->Y); | |||
284 | BN_init(&point->Z); | |||
285 | point->Z_is_one = 0; | |||
286 | ||||
287 | return 1; | |||
288 | } | |||
289 | ||||
290 | void | |||
291 | ec_GFp_simple_point_finish(EC_POINT *point) | |||
292 | { | |||
293 | BN_free(&point->X); | |||
294 | BN_free(&point->Y); | |||
295 | BN_free(&point->Z); | |||
296 | point->Z_is_one = 0; | |||
297 | } | |||
298 | ||||
299 | int | |||
300 | ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) | |||
301 | { | |||
302 | if (!bn_copy(&dest->X, &src->X)) | |||
303 | return 0; | |||
304 | if (!bn_copy(&dest->Y, &src->Y)) | |||
305 | return 0; | |||
306 | if (!bn_copy(&dest->Z, &src->Z)) | |||
307 | return 0; | |||
308 | dest->Z_is_one = src->Z_is_one; | |||
309 | ||||
310 | return 1; | |||
311 | } | |||
312 | ||||
313 | int | |||
314 | ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) | |||
315 | { | |||
316 | point->Z_is_one = 0; | |||
317 | BN_zero(&point->Z); | |||
318 | return 1; | |||
319 | } | |||
320 | ||||
321 | int | |||
322 | ec_GFp_simple_set_Jprojective_coordinates(const EC_GROUP *group, | |||
323 | EC_POINT *point, const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, | |||
324 | BN_CTX *ctx) | |||
325 | { | |||
326 | int ret = 0; | |||
327 | ||||
328 | /* | |||
329 | * Setting individual coordinates allows the creation of bad points. | |||
330 | * EC_POINT_set_Jprojective_coordinates() checks at the API boundary. | |||
331 | */ | |||
332 | ||||
333 | if (x != NULL((void *)0)) { | |||
334 | if (!ec_encode_scalar(group, &point->X, x, ctx)) | |||
335 | goto err; | |||
336 | } | |||
337 | if (y != NULL((void *)0)) { | |||
338 | if (!ec_encode_scalar(group, &point->Y, y, ctx)) | |||
339 | goto err; | |||
340 | } | |||
341 | if (z != NULL((void *)0)) { | |||
342 | if (!ec_encode_z_coordinate(group, &point->Z, &point->Z_is_one, | |||
343 | z, ctx)) | |||
344 | goto err; | |||
345 | } | |||
346 | ||||
347 | ret = 1; | |||
348 | ||||
349 | err: | |||
350 | return ret; | |||
351 | } | |||
352 | ||||
353 | int | |||
354 | ec_GFp_simple_get_Jprojective_coordinates(const EC_GROUP *group, | |||
355 | const EC_POINT *point, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx) | |||
356 | { | |||
357 | int ret = 0; | |||
358 | ||||
359 | if (!ec_decode_scalar(group, x, &point->X, ctx)) | |||
360 | goto err; | |||
361 | if (!ec_decode_scalar(group, y, &point->Y, ctx)) | |||
362 | goto err; | |||
363 | if (!ec_decode_scalar(group, z, &point->Z, ctx)) | |||
364 | goto err; | |||
365 | ||||
366 | ret = 1; | |||
367 | ||||
368 | err: | |||
369 | return ret; | |||
370 | } | |||
371 | ||||
372 | int | |||
373 | ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, | |||
374 | const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) | |||
375 | { | |||
376 | if (x == NULL((void *)0) || y == NULL((void *)0)) { | |||
377 | /* unlike for projective coordinates, we do not tolerate this */ | |||
378 | ECerror(ERR_R_PASSED_NULL_PARAMETER)ERR_put_error(16,(0xfff),((3|64)),"/usr/src/lib/libcrypto/ec/ecp_smpl.c" ,378); | |||
379 | return 0; | |||
380 | } | |||
381 | return EC_POINT_set_Jprojective_coordinates(group, point, x, y, | |||
382 | BN_value_one(), ctx); | |||
383 | } | |||
384 | ||||
385 | int | |||
386 | ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, | |||
387 | const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) | |||
388 | { | |||
389 | BIGNUM *z, *Z, *Z_1, *Z_2, *Z_3; | |||
390 | int ret = 0; | |||
391 | ||||
392 | if (EC_POINT_is_at_infinity(group, point) > 0) { | |||
393 | ECerror(EC_R_POINT_AT_INFINITY)ERR_put_error(16,(0xfff),(106),"/usr/src/lib/libcrypto/ec/ecp_smpl.c" ,393); | |||
394 | return 0; | |||
395 | } | |||
396 | ||||
397 | BN_CTX_start(ctx); | |||
398 | ||||
399 | if ((z = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
400 | goto err; | |||
401 | if ((Z = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
402 | goto err; | |||
403 | if ((Z_1 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
404 | goto err; | |||
405 | if ((Z_2 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
406 | goto err; | |||
407 | if ((Z_3 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
408 | goto err; | |||
409 | ||||
410 | /* Convert from projective coordinates (X, Y, Z) into (X/Z^2, Y/Z^3). */ | |||
411 | ||||
412 | if (!ec_decode_scalar(group, z, &point->Z, ctx)) | |||
413 | goto err; | |||
414 | ||||
415 | if (BN_is_one(z)) { | |||
416 | if (!ec_decode_scalar(group, x, &point->X, ctx)) | |||
417 | goto err; | |||
418 | if (!ec_decode_scalar(group, y, &point->Y, ctx)) | |||
419 | goto err; | |||
420 | goto done; | |||
421 | } | |||
422 | ||||
423 | if (BN_mod_inverse_ct(Z_1, z, &group->field, ctx) == NULL((void *)0)) { | |||
424 | ECerror(ERR_R_BN_LIB)ERR_put_error(16,(0xfff),(3),"/usr/src/lib/libcrypto/ec/ecp_smpl.c" ,424); | |||
425 | goto err; | |||
426 | } | |||
427 | if (group->meth->field_encode == NULL((void *)0)) { | |||
428 | /* field_sqr works on standard representation */ | |||
429 | if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) | |||
430 | goto err; | |||
431 | } else { | |||
432 | if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) | |||
433 | goto err; | |||
434 | } | |||
435 | ||||
436 | if (x != NULL((void *)0)) { | |||
437 | /* | |||
438 | * in the Montgomery case, field_mul will cancel out | |||
439 | * Montgomery factor in X: | |||
440 | */ | |||
441 | if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) | |||
442 | goto err; | |||
443 | } | |||
444 | if (y != NULL((void *)0)) { | |||
445 | if (group->meth->field_encode == NULL((void *)0)) { | |||
446 | /* field_mul works on standard representation */ | |||
447 | if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) | |||
448 | goto err; | |||
449 | } else { | |||
450 | if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) | |||
451 | goto err; | |||
452 | } | |||
453 | ||||
454 | /* | |||
455 | * in the Montgomery case, field_mul will cancel out | |||
456 | * Montgomery factor in Y: | |||
457 | */ | |||
458 | if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) | |||
459 | goto err; | |||
460 | } | |||
461 | ||||
462 | done: | |||
463 | ret = 1; | |||
464 | ||||
465 | err: | |||
466 | BN_CTX_end(ctx); | |||
467 | ||||
468 | return ret; | |||
469 | } | |||
470 | ||||
471 | int | |||
472 | ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) | |||
473 | { | |||
474 | int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); | |||
475 | int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); | |||
476 | BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6; | |||
477 | const BIGNUM *p; | |||
478 | int ret = 0; | |||
479 | ||||
480 | if (a == b) | |||
481 | return EC_POINT_dbl(group, r, a, ctx); | |||
482 | if (EC_POINT_is_at_infinity(group, a) > 0) | |||
483 | return EC_POINT_copy(r, b); | |||
484 | if (EC_POINT_is_at_infinity(group, b) > 0) | |||
485 | return EC_POINT_copy(r, a); | |||
486 | ||||
487 | field_mul = group->meth->field_mul; | |||
488 | field_sqr = group->meth->field_sqr; | |||
489 | p = &group->field; | |||
490 | ||||
491 | BN_CTX_start(ctx); | |||
492 | ||||
493 | if ((n0 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
494 | goto end; | |||
495 | if ((n1 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
496 | goto end; | |||
497 | if ((n2 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
498 | goto end; | |||
499 | if ((n3 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
500 | goto end; | |||
501 | if ((n4 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
502 | goto end; | |||
503 | if ((n5 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
504 | goto end; | |||
505 | if ((n6 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
506 | goto end; | |||
507 | ||||
508 | /* | |||
509 | * Note that in this function we must not read components of 'a' or | |||
510 | * 'b' once we have written the corresponding components of 'r'. ('r' | |||
511 | * might be one of 'a' or 'b'.) | |||
512 | */ | |||
513 | ||||
514 | /* n1, n2 */ | |||
515 | if (b->Z_is_one) { | |||
516 | if (!bn_copy(n1, &a->X)) | |||
517 | goto end; | |||
518 | if (!bn_copy(n2, &a->Y)) | |||
519 | goto end; | |||
520 | /* n1 = X_a */ | |||
521 | /* n2 = Y_a */ | |||
522 | } else { | |||
523 | if (!field_sqr(group, n0, &b->Z, ctx)) | |||
524 | goto end; | |||
525 | if (!field_mul(group, n1, &a->X, n0, ctx)) | |||
526 | goto end; | |||
527 | /* n1 = X_a * Z_b^2 */ | |||
528 | ||||
529 | if (!field_mul(group, n0, n0, &b->Z, ctx)) | |||
530 | goto end; | |||
531 | if (!field_mul(group, n2, &a->Y, n0, ctx)) | |||
532 | goto end; | |||
533 | /* n2 = Y_a * Z_b^3 */ | |||
534 | } | |||
535 | ||||
536 | /* n3, n4 */ | |||
537 | if (a->Z_is_one) { | |||
538 | if (!bn_copy(n3, &b->X)) | |||
539 | goto end; | |||
540 | if (!bn_copy(n4, &b->Y)) | |||
541 | goto end; | |||
542 | /* n3 = X_b */ | |||
543 | /* n4 = Y_b */ | |||
544 | } else { | |||
545 | if (!field_sqr(group, n0, &a->Z, ctx)) | |||
546 | goto end; | |||
547 | if (!field_mul(group, n3, &b->X, n0, ctx)) | |||
548 | goto end; | |||
549 | /* n3 = X_b * Z_a^2 */ | |||
550 | ||||
551 | if (!field_mul(group, n0, n0, &a->Z, ctx)) | |||
552 | goto end; | |||
553 | if (!field_mul(group, n4, &b->Y, n0, ctx)) | |||
554 | goto end; | |||
555 | /* n4 = Y_b * Z_a^3 */ | |||
556 | } | |||
557 | ||||
558 | /* n5, n6 */ | |||
559 | if (!BN_mod_sub_quick(n5, n1, n3, p)) | |||
560 | goto end; | |||
561 | if (!BN_mod_sub_quick(n6, n2, n4, p)) | |||
562 | goto end; | |||
563 | /* n5 = n1 - n3 */ | |||
564 | /* n6 = n2 - n4 */ | |||
565 | ||||
566 | if (BN_is_zero(n5)) { | |||
567 | if (BN_is_zero(n6)) { | |||
568 | /* a is the same point as b */ | |||
569 | BN_CTX_end(ctx); | |||
570 | ret = EC_POINT_dbl(group, r, a, ctx); | |||
571 | ctx = NULL((void *)0); | |||
572 | goto end; | |||
573 | } else { | |||
574 | /* a is the inverse of b */ | |||
575 | BN_zero(&r->Z); | |||
576 | r->Z_is_one = 0; | |||
577 | ret = 1; | |||
578 | goto end; | |||
579 | } | |||
580 | } | |||
581 | /* 'n7', 'n8' */ | |||
582 | if (!BN_mod_add_quick(n1, n1, n3, p)) | |||
583 | goto end; | |||
584 | if (!BN_mod_add_quick(n2, n2, n4, p)) | |||
585 | goto end; | |||
586 | /* 'n7' = n1 + n3 */ | |||
587 | /* 'n8' = n2 + n4 */ | |||
588 | ||||
589 | /* Z_r */ | |||
590 | if (a->Z_is_one && b->Z_is_one) { | |||
591 | if (!bn_copy(&r->Z, n5)) | |||
592 | goto end; | |||
593 | } else { | |||
594 | if (a->Z_is_one) { | |||
595 | if (!bn_copy(n0, &b->Z)) | |||
596 | goto end; | |||
597 | } else if (b->Z_is_one) { | |||
598 | if (!bn_copy(n0, &a->Z)) | |||
599 | goto end; | |||
600 | } else { | |||
601 | if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) | |||
602 | goto end; | |||
603 | } | |||
604 | if (!field_mul(group, &r->Z, n0, n5, ctx)) | |||
605 | goto end; | |||
606 | } | |||
607 | r->Z_is_one = 0; | |||
608 | /* Z_r = Z_a * Z_b * n5 */ | |||
609 | ||||
610 | /* X_r */ | |||
611 | if (!field_sqr(group, n0, n6, ctx)) | |||
612 | goto end; | |||
613 | if (!field_sqr(group, n4, n5, ctx)) | |||
614 | goto end; | |||
615 | if (!field_mul(group, n3, n1, n4, ctx)) | |||
616 | goto end; | |||
617 | if (!BN_mod_sub_quick(&r->X, n0, n3, p)) | |||
618 | goto end; | |||
619 | /* X_r = n6^2 - n5^2 * 'n7' */ | |||
620 | ||||
621 | /* 'n9' */ | |||
622 | if (!BN_mod_lshift1_quick(n0, &r->X, p)) | |||
623 | goto end; | |||
624 | if (!BN_mod_sub_quick(n0, n3, n0, p)) | |||
625 | goto end; | |||
626 | /* n9 = n5^2 * 'n7' - 2 * X_r */ | |||
627 | ||||
628 | /* Y_r */ | |||
629 | if (!field_mul(group, n0, n0, n6, ctx)) | |||
630 | goto end; | |||
631 | if (!field_mul(group, n5, n4, n5, ctx)) | |||
632 | goto end; /* now n5 is n5^3 */ | |||
633 | if (!field_mul(group, n1, n2, n5, ctx)) | |||
634 | goto end; | |||
635 | if (!BN_mod_sub_quick(n0, n0, n1, p)) | |||
636 | goto end; | |||
637 | if (BN_is_odd(n0)) | |||
638 | if (!BN_add(n0, n0, p)) | |||
639 | goto end; | |||
640 | /* now 0 <= n0 < 2*p, and n0 is even */ | |||
641 | if (!BN_rshift1(&r->Y, n0)) | |||
642 | goto end; | |||
643 | /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */ | |||
644 | ||||
645 | ret = 1; | |||
646 | ||||
647 | end: | |||
648 | BN_CTX_end(ctx); | |||
649 | ||||
650 | return ret; | |||
651 | } | |||
652 | ||||
653 | int | |||
654 | ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx) | |||
655 | { | |||
656 | int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); | |||
657 | int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); | |||
658 | const BIGNUM *p; | |||
659 | BIGNUM *n0, *n1, *n2, *n3; | |||
660 | int ret = 0; | |||
661 | ||||
662 | if (EC_POINT_is_at_infinity(group, a) > 0) | |||
663 | return EC_POINT_set_to_infinity(group, r); | |||
664 | ||||
665 | field_mul = group->meth->field_mul; | |||
666 | field_sqr = group->meth->field_sqr; | |||
667 | p = &group->field; | |||
668 | ||||
669 | BN_CTX_start(ctx); | |||
670 | ||||
671 | if ((n0 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
672 | goto err; | |||
673 | if ((n1 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
674 | goto err; | |||
675 | if ((n2 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
676 | goto err; | |||
677 | if ((n3 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
678 | goto err; | |||
679 | ||||
680 | /* | |||
681 | * Note that in this function we must not read components of 'a' once | |||
682 | * we have written the corresponding components of 'r'. ('r' might | |||
683 | * the same as 'a'.) | |||
684 | */ | |||
685 | ||||
686 | /* n1 */ | |||
687 | if (a->Z_is_one) { | |||
688 | if (!field_sqr(group, n0, &a->X, ctx)) | |||
689 | goto err; | |||
690 | if (!BN_mod_lshift1_quick(n1, n0, p)) | |||
691 | goto err; | |||
692 | if (!BN_mod_add_quick(n0, n0, n1, p)) | |||
693 | goto err; | |||
694 | if (!BN_mod_add_quick(n1, n0, &group->a, p)) | |||
695 | goto err; | |||
696 | /* n1 = 3 * X_a^2 + a_curve */ | |||
697 | } else if (group->a_is_minus3) { | |||
698 | if (!field_sqr(group, n1, &a->Z, ctx)) | |||
699 | goto err; | |||
700 | if (!BN_mod_add_quick(n0, &a->X, n1, p)) | |||
701 | goto err; | |||
702 | if (!BN_mod_sub_quick(n2, &a->X, n1, p)) | |||
703 | goto err; | |||
704 | if (!field_mul(group, n1, n0, n2, ctx)) | |||
705 | goto err; | |||
706 | if (!BN_mod_lshift1_quick(n0, n1, p)) | |||
707 | goto err; | |||
708 | if (!BN_mod_add_quick(n1, n0, n1, p)) | |||
709 | goto err; | |||
710 | /* | |||
711 | * n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) = 3 * X_a^2 - 3 * | |||
712 | * Z_a^4 | |||
713 | */ | |||
714 | } else { | |||
715 | if (!field_sqr(group, n0, &a->X, ctx)) | |||
716 | goto err; | |||
717 | if (!BN_mod_lshift1_quick(n1, n0, p)) | |||
718 | goto err; | |||
719 | if (!BN_mod_add_quick(n0, n0, n1, p)) | |||
720 | goto err; | |||
721 | if (!field_sqr(group, n1, &a->Z, ctx)) | |||
722 | goto err; | |||
723 | if (!field_sqr(group, n1, n1, ctx)) | |||
724 | goto err; | |||
725 | if (!field_mul(group, n1, n1, &group->a, ctx)) | |||
726 | goto err; | |||
727 | if (!BN_mod_add_quick(n1, n1, n0, p)) | |||
728 | goto err; | |||
729 | /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */ | |||
730 | } | |||
731 | ||||
732 | /* Z_r */ | |||
733 | if (a->Z_is_one) { | |||
734 | if (!bn_copy(n0, &a->Y)) | |||
735 | goto err; | |||
736 | } else { | |||
737 | if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) | |||
738 | goto err; | |||
739 | } | |||
740 | if (!BN_mod_lshift1_quick(&r->Z, n0, p)) | |||
741 | goto err; | |||
742 | r->Z_is_one = 0; | |||
743 | /* Z_r = 2 * Y_a * Z_a */ | |||
744 | ||||
745 | /* n2 */ | |||
746 | if (!field_sqr(group, n3, &a->Y, ctx)) | |||
747 | goto err; | |||
748 | if (!field_mul(group, n2, &a->X, n3, ctx)) | |||
749 | goto err; | |||
750 | if (!BN_mod_lshift_quick(n2, n2, 2, p)) | |||
751 | goto err; | |||
752 | /* n2 = 4 * X_a * Y_a^2 */ | |||
753 | ||||
754 | /* X_r */ | |||
755 | if (!BN_mod_lshift1_quick(n0, n2, p)) | |||
756 | goto err; | |||
757 | if (!field_sqr(group, &r->X, n1, ctx)) | |||
758 | goto err; | |||
759 | if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) | |||
760 | goto err; | |||
761 | /* X_r = n1^2 - 2 * n2 */ | |||
762 | ||||
763 | /* n3 */ | |||
764 | if (!field_sqr(group, n0, n3, ctx)) | |||
765 | goto err; | |||
766 | if (!BN_mod_lshift_quick(n3, n0, 3, p)) | |||
767 | goto err; | |||
768 | /* n3 = 8 * Y_a^4 */ | |||
769 | ||||
770 | /* Y_r */ | |||
771 | if (!BN_mod_sub_quick(n0, n2, &r->X, p)) | |||
772 | goto err; | |||
773 | if (!field_mul(group, n0, n1, n0, ctx)) | |||
774 | goto err; | |||
775 | if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) | |||
776 | goto err; | |||
777 | /* Y_r = n1 * (n2 - X_r) - n3 */ | |||
778 | ||||
779 | ret = 1; | |||
780 | ||||
781 | err: | |||
782 | BN_CTX_end(ctx); | |||
783 | ||||
784 | return ret; | |||
785 | } | |||
786 | ||||
787 | int | |||
788 | ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) | |||
789 | { | |||
790 | if (EC_POINT_is_at_infinity(group, point) > 0 || BN_is_zero(&point->Y)) | |||
791 | /* point is its own inverse */ | |||
792 | return 1; | |||
793 | ||||
794 | return BN_usub(&point->Y, &group->field, &point->Y); | |||
795 | } | |||
796 | ||||
797 | int | |||
798 | ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) | |||
799 | { | |||
800 | return BN_is_zero(&point->Z); | |||
801 | } | |||
802 | ||||
803 | int | |||
804 | ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) | |||
805 | { | |||
806 | int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); | |||
807 | int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); | |||
808 | const BIGNUM *p; | |||
809 | BIGNUM *rh, *tmp, *Z4, *Z6; | |||
810 | int ret = -1; | |||
811 | ||||
812 | if (EC_POINT_is_at_infinity(group, point) > 0) | |||
813 | return 1; | |||
814 | ||||
815 | field_mul = group->meth->field_mul; | |||
816 | field_sqr = group->meth->field_sqr; | |||
817 | p = &group->field; | |||
818 | ||||
819 | BN_CTX_start(ctx); | |||
820 | ||||
821 | if ((rh = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
822 | goto err; | |||
823 | if ((tmp = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
824 | goto err; | |||
825 | if ((Z4 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
826 | goto err; | |||
827 | if ((Z6 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
828 | goto err; | |||
829 | ||||
830 | /* | |||
831 | * We have a curve defined by a Weierstrass equation y^2 = x^3 + a*x | |||
832 | * + b. The point to consider is given in Jacobian projective | |||
833 | * coordinates where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). | |||
834 | * Substituting this and multiplying by Z^6 transforms the above | |||
835 | * equation into Y^2 = X^3 + a*X*Z^4 + b*Z^6. To test this, we add up | |||
836 | * the right-hand side in 'rh'. | |||
837 | */ | |||
838 | ||||
839 | /* rh := X^2 */ | |||
840 | if (!field_sqr(group, rh, &point->X, ctx)) | |||
841 | goto err; | |||
842 | ||||
843 | if (!point->Z_is_one) { | |||
844 | if (!field_sqr(group, tmp, &point->Z, ctx)) | |||
845 | goto err; | |||
846 | if (!field_sqr(group, Z4, tmp, ctx)) | |||
847 | goto err; | |||
848 | if (!field_mul(group, Z6, Z4, tmp, ctx)) | |||
849 | goto err; | |||
850 | ||||
851 | /* rh := (rh + a*Z^4)*X */ | |||
852 | if (group->a_is_minus3) { | |||
853 | if (!BN_mod_lshift1_quick(tmp, Z4, p)) | |||
854 | goto err; | |||
855 | if (!BN_mod_add_quick(tmp, tmp, Z4, p)) | |||
856 | goto err; | |||
857 | if (!BN_mod_sub_quick(rh, rh, tmp, p)) | |||
858 | goto err; | |||
859 | if (!field_mul(group, rh, rh, &point->X, ctx)) | |||
860 | goto err; | |||
861 | } else { | |||
862 | if (!field_mul(group, tmp, Z4, &group->a, ctx)) | |||
863 | goto err; | |||
864 | if (!BN_mod_add_quick(rh, rh, tmp, p)) | |||
865 | goto err; | |||
866 | if (!field_mul(group, rh, rh, &point->X, ctx)) | |||
867 | goto err; | |||
868 | } | |||
869 | ||||
870 | /* rh := rh + b*Z^6 */ | |||
871 | if (!field_mul(group, tmp, &group->b, Z6, ctx)) | |||
872 | goto err; | |||
873 | if (!BN_mod_add_quick(rh, rh, tmp, p)) | |||
874 | goto err; | |||
875 | } else { | |||
876 | /* point->Z_is_one */ | |||
877 | ||||
878 | /* rh := (rh + a)*X */ | |||
879 | if (!BN_mod_add_quick(rh, rh, &group->a, p)) | |||
880 | goto err; | |||
881 | if (!field_mul(group, rh, rh, &point->X, ctx)) | |||
882 | goto err; | |||
883 | /* rh := rh + b */ | |||
884 | if (!BN_mod_add_quick(rh, rh, &group->b, p)) | |||
885 | goto err; | |||
886 | } | |||
887 | ||||
888 | /* 'lh' := Y^2 */ | |||
889 | if (!field_sqr(group, tmp, &point->Y, ctx)) | |||
890 | goto err; | |||
891 | ||||
892 | ret = (0 == BN_ucmp(tmp, rh)); | |||
893 | ||||
894 | err: | |||
895 | BN_CTX_end(ctx); | |||
896 | ||||
897 | return ret; | |||
898 | } | |||
899 | ||||
900 | int | |||
901 | ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) | |||
902 | { | |||
903 | /* | |||
904 | * return values: -1 error 0 equal (in affine coordinates) 1 | |||
905 | * not equal | |||
906 | */ | |||
907 | ||||
908 | int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); | |||
909 | int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); | |||
910 | BIGNUM *tmp1, *tmp2, *Za23, *Zb23; | |||
911 | const BIGNUM *tmp1_, *tmp2_; | |||
912 | int ret = -1; | |||
913 | ||||
914 | if (EC_POINT_is_at_infinity(group, a) > 0) | |||
915 | return EC_POINT_is_at_infinity(group, b) > 0 ? 0 : 1; | |||
916 | ||||
917 | if (EC_POINT_is_at_infinity(group, b) > 0) | |||
918 | return 1; | |||
919 | ||||
920 | if (a->Z_is_one && b->Z_is_one) | |||
921 | return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; | |||
922 | ||||
923 | field_mul = group->meth->field_mul; | |||
924 | field_sqr = group->meth->field_sqr; | |||
925 | ||||
926 | BN_CTX_start(ctx); | |||
927 | ||||
928 | if ((tmp1 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
929 | goto end; | |||
930 | if ((tmp2 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
931 | goto end; | |||
932 | if ((Za23 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
933 | goto end; | |||
934 | if ((Zb23 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
935 | goto end; | |||
936 | ||||
937 | /* | |||
938 | * We have to decide whether (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, | |||
939 | * Y_b/Z_b^3), or equivalently, whether (X_a*Z_b^2, Y_a*Z_b^3) = | |||
940 | * (X_b*Z_a^2, Y_b*Z_a^3). | |||
941 | */ | |||
942 | ||||
943 | if (!b->Z_is_one) { | |||
944 | if (!field_sqr(group, Zb23, &b->Z, ctx)) | |||
945 | goto end; | |||
946 | if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) | |||
947 | goto end; | |||
948 | tmp1_ = tmp1; | |||
949 | } else | |||
950 | tmp1_ = &a->X; | |||
951 | if (!a->Z_is_one) { | |||
952 | if (!field_sqr(group, Za23, &a->Z, ctx)) | |||
953 | goto end; | |||
954 | if (!field_mul(group, tmp2, &b->X, Za23, ctx)) | |||
955 | goto end; | |||
956 | tmp2_ = tmp2; | |||
957 | } else | |||
958 | tmp2_ = &b->X; | |||
959 | ||||
960 | /* compare X_a*Z_b^2 with X_b*Z_a^2 */ | |||
961 | if (BN_cmp(tmp1_, tmp2_) != 0) { | |||
962 | ret = 1; /* points differ */ | |||
963 | goto end; | |||
964 | } | |||
965 | if (!b->Z_is_one) { | |||
966 | if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) | |||
967 | goto end; | |||
968 | if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) | |||
969 | goto end; | |||
970 | /* tmp1_ = tmp1 */ | |||
971 | } else | |||
972 | tmp1_ = &a->Y; | |||
973 | if (!a->Z_is_one) { | |||
974 | if (!field_mul(group, Za23, Za23, &a->Z, ctx)) | |||
975 | goto end; | |||
976 | if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) | |||
977 | goto end; | |||
978 | /* tmp2_ = tmp2 */ | |||
979 | } else | |||
980 | tmp2_ = &b->Y; | |||
981 | ||||
982 | /* compare Y_a*Z_b^3 with Y_b*Z_a^3 */ | |||
983 | if (BN_cmp(tmp1_, tmp2_) != 0) { | |||
984 | ret = 1; /* points differ */ | |||
985 | goto end; | |||
986 | } | |||
987 | /* points are equal */ | |||
988 | ret = 0; | |||
989 | ||||
990 | end: | |||
991 | BN_CTX_end(ctx); | |||
992 | ||||
993 | return ret; | |||
994 | } | |||
995 | ||||
996 | int | |||
997 | ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) | |||
998 | { | |||
999 | BIGNUM *x, *y; | |||
1000 | int ret = 0; | |||
1001 | ||||
1002 | if (point->Z_is_one || EC_POINT_is_at_infinity(group, point) > 0) | |||
1003 | return 1; | |||
1004 | ||||
1005 | BN_CTX_start(ctx); | |||
1006 | ||||
1007 | if ((x = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
1008 | goto err; | |||
1009 | if ((y = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
1010 | goto err; | |||
1011 | ||||
1012 | if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx)) | |||
1013 | goto err; | |||
1014 | if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) | |||
1015 | goto err; | |||
1016 | if (!point->Z_is_one) { | |||
1017 | ECerror(ERR_R_INTERNAL_ERROR)ERR_put_error(16,(0xfff),((4|64)),"/usr/src/lib/libcrypto/ec/ecp_smpl.c" ,1017); | |||
1018 | goto err; | |||
1019 | } | |||
1020 | ret = 1; | |||
1021 | ||||
1022 | err: | |||
1023 | BN_CTX_end(ctx); | |||
1024 | ||||
1025 | return ret; | |||
1026 | } | |||
1027 | ||||
1028 | int | |||
1029 | ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) | |||
1030 | { | |||
1031 | BIGNUM *tmp0, *tmp1; | |||
1032 | size_t pow2 = 0; | |||
1033 | BIGNUM **heap = NULL((void *)0); | |||
1034 | size_t i; | |||
1035 | int ret = 0; | |||
1036 | ||||
1037 | if (num == 0) | |||
| ||||
1038 | return 1; | |||
1039 | ||||
1040 | BN_CTX_start(ctx); | |||
1041 | ||||
1042 | if ((tmp0 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
1043 | goto err; | |||
1044 | if ((tmp1 = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
1045 | goto err; | |||
1046 | ||||
1047 | /* | |||
1048 | * Before converting the individual points, compute inverses of all Z | |||
1049 | * values. Modular inversion is rather slow, but luckily we can do | |||
1050 | * with a single explicit inversion, plus about 3 multiplications per | |||
1051 | * input value. | |||
1052 | */ | |||
1053 | ||||
1054 | pow2 = 1; | |||
1055 | while (num > pow2) | |||
1056 | pow2 <<= 1; | |||
1057 | /* | |||
1058 | * Now pow2 is the smallest power of 2 satifsying pow2 >= num. We | |||
1059 | * need twice that. | |||
1060 | */ | |||
1061 | pow2 <<= 1; | |||
1062 | ||||
1063 | heap = reallocarray(NULL((void *)0), pow2, sizeof heap[0]); | |||
1064 | if (heap == NULL((void *)0)) | |||
1065 | goto err; | |||
1066 | ||||
1067 | /* | |||
1068 | * The array is used as a binary tree, exactly as in heapsort: | |||
1069 | * | |||
1070 | * heap[1] heap[2] heap[3] heap[4] heap[5] | |||
1071 | * heap[6] heap[7] heap[8]heap[9] heap[10]heap[11] | |||
1072 | * heap[12]heap[13] heap[14] heap[15] | |||
1073 | * | |||
1074 | * We put the Z's in the last line; then we set each other node to the | |||
1075 | * product of its two child-nodes (where empty or 0 entries are | |||
1076 | * treated as ones); then we invert heap[1]; then we invert each | |||
1077 | * other node by replacing it by the product of its parent (after | |||
1078 | * inversion) and its sibling (before inversion). | |||
1079 | */ | |||
1080 | heap[0] = NULL((void *)0); | |||
1081 | for (i = pow2 / 2 - 1; i > 0; i--) | |||
1082 | heap[i] = NULL((void *)0); | |||
1083 | for (i = 0; i < num; i++) | |||
1084 | heap[pow2 / 2 + i] = &points[i]->Z; | |||
1085 | for (i = pow2 / 2 + num; i < pow2; i++) | |||
1086 | heap[i] = NULL((void *)0); | |||
1087 | ||||
1088 | /* set each node to the product of its children */ | |||
1089 | for (i = pow2 / 2 - 1; i > 0; i--) { | |||
1090 | heap[i] = BN_new(); | |||
1091 | if (heap[i] == NULL((void *)0)) | |||
1092 | goto err; | |||
1093 | ||||
1094 | if (heap[2 * i] != NULL((void *)0)) { | |||
1095 | if ((heap[2 * i + 1] == NULL((void *)0)) || BN_is_zero(heap[2 * i + 1])) { | |||
1096 | if (!bn_copy(heap[i], heap[2 * i])) | |||
1097 | goto err; | |||
1098 | } else { | |||
1099 | if (BN_is_zero(heap[2 * i])) { | |||
1100 | if (!bn_copy(heap[i], heap[2 * i + 1])) | |||
1101 | goto err; | |||
1102 | } else { | |||
1103 | if (!group->meth->field_mul(group, heap[i], | |||
1104 | heap[2 * i], heap[2 * i + 1], ctx)) | |||
1105 | goto err; | |||
1106 | } | |||
1107 | } | |||
1108 | } | |||
1109 | } | |||
1110 | ||||
1111 | /* invert heap[1] */ | |||
1112 | if (!BN_is_zero(heap[1])) { | |||
1113 | if (BN_mod_inverse_ct(heap[1], heap[1], &group->field, ctx) == NULL((void *)0)) { | |||
1114 | ECerror(ERR_R_BN_LIB)ERR_put_error(16,(0xfff),(3),"/usr/src/lib/libcrypto/ec/ecp_smpl.c" ,1114); | |||
1115 | goto err; | |||
1116 | } | |||
1117 | } | |||
1118 | if (group->meth->field_encode != NULL((void *)0)) { | |||
1119 | /* | |||
1120 | * in the Montgomery case, we just turned R*H (representing | |||
1121 | * H) into 1/(R*H), but we need R*(1/H) (representing | |||
1122 | * 1/H); i.e. we have need to multiply by the Montgomery | |||
1123 | * factor twice | |||
1124 | */ | |||
1125 | if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) | |||
1126 | goto err; | |||
1127 | if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) | |||
1128 | goto err; | |||
1129 | } | |||
1130 | /* set other heap[i]'s to their inverses */ | |||
1131 | for (i = 2; i < pow2 / 2 + num; i += 2) { | |||
1132 | /* i is even */ | |||
1133 | if ((heap[i + 1] != NULL((void *)0)) && !BN_is_zero(heap[i + 1])) { | |||
1134 | if (!group->meth->field_mul(group, tmp0, heap[i / 2], heap[i + 1], ctx)) | |||
1135 | goto err; | |||
1136 | if (!group->meth->field_mul(group, tmp1, heap[i / 2], heap[i], ctx)) | |||
1137 | goto err; | |||
1138 | if (!bn_copy(heap[i], tmp0)) | |||
1139 | goto err; | |||
1140 | if (!bn_copy(heap[i + 1], tmp1)) | |||
1141 | goto err; | |||
1142 | } else { | |||
1143 | if (!bn_copy(heap[i], heap[i / 2])) | |||
1144 | goto err; | |||
1145 | } | |||
1146 | } | |||
1147 | ||||
1148 | /* | |||
1149 | * we have replaced all non-zero Z's by their inverses, now fix up | |||
1150 | * all the points | |||
1151 | */ | |||
1152 | for (i = 0; i < num; i++) { | |||
1153 | EC_POINT *p = points[i]; | |||
1154 | ||||
1155 | if (!BN_is_zero(&p->Z)) { | |||
1156 | /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1) */ | |||
1157 | ||||
1158 | if (!group->meth->field_sqr(group, tmp1, &p->Z, ctx)) | |||
1159 | goto err; | |||
1160 | if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx)) | |||
1161 | goto err; | |||
1162 | ||||
1163 | if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx)) | |||
1164 | goto err; | |||
1165 | if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx)) | |||
1166 | goto err; | |||
1167 | ||||
1168 | if (group->meth->field_set_to_one != NULL((void *)0)) { | |||
1169 | if (!group->meth->field_set_to_one(group, &p->Z, ctx)) | |||
1170 | goto err; | |||
1171 | } else { | |||
1172 | if (!BN_one(&p->Z)) | |||
1173 | goto err; | |||
1174 | } | |||
1175 | p->Z_is_one = 1; | |||
| ||||
1176 | } | |||
1177 | } | |||
1178 | ||||
1179 | ret = 1; | |||
1180 | ||||
1181 | err: | |||
1182 | BN_CTX_end(ctx); | |||
1183 | ||||
1184 | if (heap != NULL((void *)0)) { | |||
1185 | /* | |||
1186 | * heap[pow2/2] .. heap[pow2-1] have not been allocated | |||
1187 | * locally! | |||
1188 | */ | |||
1189 | for (i = pow2 / 2 - 1; i > 0; i--) { | |||
1190 | BN_free(heap[i]); | |||
1191 | } | |||
1192 | free(heap); | |||
1193 | } | |||
1194 | return ret; | |||
1195 | } | |||
1196 | ||||
1197 | int | |||
1198 | ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) | |||
1199 | { | |||
1200 | return BN_mod_mul(r, a, b, &group->field, ctx); | |||
1201 | } | |||
1202 | ||||
1203 | int | |||
1204 | ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) | |||
1205 | { | |||
1206 | return BN_mod_sqr(r, a, &group->field, ctx); | |||
1207 | } | |||
1208 | ||||
1209 | /* | |||
1210 | * Apply randomization of EC point projective coordinates: | |||
1211 | * | |||
1212 | * (X, Y, Z) = (lambda^2 * X, lambda^3 * Y, lambda * Z) | |||
1213 | * | |||
1214 | * where lambda is in the interval [1, group->field). | |||
1215 | */ | |||
1216 | int | |||
1217 | ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx) | |||
1218 | { | |||
1219 | BIGNUM *lambda = NULL((void *)0); | |||
1220 | BIGNUM *tmp = NULL((void *)0); | |||
1221 | int ret = 0; | |||
1222 | ||||
1223 | BN_CTX_start(ctx); | |||
1224 | if ((lambda = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
1225 | goto err; | |||
1226 | if ((tmp = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
1227 | goto err; | |||
1228 | ||||
1229 | /* Generate lambda in [1, group->field). */ | |||
1230 | if (!bn_rand_interval(lambda, 1, &group->field)) | |||
1231 | goto err; | |||
1232 | ||||
1233 | if (group->meth->field_encode != NULL((void *)0) && | |||
1234 | !group->meth->field_encode(group, lambda, lambda, ctx)) | |||
1235 | goto err; | |||
1236 | ||||
1237 | /* Z = lambda * Z */ | |||
1238 | if (!group->meth->field_mul(group, &p->Z, lambda, &p->Z, ctx)) | |||
1239 | goto err; | |||
1240 | ||||
1241 | /* tmp = lambda^2 */ | |||
1242 | if (!group->meth->field_sqr(group, tmp, lambda, ctx)) | |||
1243 | goto err; | |||
1244 | ||||
1245 | /* X = lambda^2 * X */ | |||
1246 | if (!group->meth->field_mul(group, &p->X, tmp, &p->X, ctx)) | |||
1247 | goto err; | |||
1248 | ||||
1249 | /* tmp = lambda^3 */ | |||
1250 | if (!group->meth->field_mul(group, tmp, tmp, lambda, ctx)) | |||
1251 | goto err; | |||
1252 | ||||
1253 | /* Y = lambda^3 * Y */ | |||
1254 | if (!group->meth->field_mul(group, &p->Y, tmp, &p->Y, ctx)) | |||
1255 | goto err; | |||
1256 | ||||
1257 | /* Disable optimized arithmetics after replacing Z by lambda * Z. */ | |||
1258 | p->Z_is_one = 0; | |||
1259 | ||||
1260 | ret = 1; | |||
1261 | ||||
1262 | err: | |||
1263 | BN_CTX_end(ctx); | |||
1264 | return ret; | |||
1265 | } | |||
1266 | ||||
1267 | #define EC_POINT_BN_set_flags(P, flags) do { \ | |||
1268 | BN_set_flags(&(P)->X, (flags)); \ | |||
1269 | BN_set_flags(&(P)->Y, (flags)); \ | |||
1270 | BN_set_flags(&(P)->Z, (flags)); \ | |||
1271 | } while(0) | |||
1272 | ||||
1273 | #define EC_POINT_CSWAP(c, a, b, w, t) do { \ | |||
1274 | if (!BN_swap_ct(c, &(a)->X, &(b)->X, w) || \ | |||
1275 | !BN_swap_ct(c, &(a)->Y, &(b)->Y, w) || \ | |||
1276 | !BN_swap_ct(c, &(a)->Z, &(b)->Z, w)) \ | |||
1277 | goto err; \ | |||
1278 | t = ((a)->Z_is_one ^ (b)->Z_is_one) & (c); \ | |||
1279 | (a)->Z_is_one ^= (t); \ | |||
1280 | (b)->Z_is_one ^= (t); \ | |||
1281 | } while(0) | |||
1282 | ||||
1283 | /* | |||
1284 | * This function computes (in constant time) a point multiplication over the | |||
1285 | * EC group. | |||
1286 | * | |||
1287 | * At a high level, it is Montgomery ladder with conditional swaps. | |||
1288 | * | |||
1289 | * It performs either a fixed point multiplication | |||
1290 | * (scalar * generator) | |||
1291 | * when point is NULL, or a variable point multiplication | |||
1292 | * (scalar * point) | |||
1293 | * when point is not NULL. | |||
1294 | * | |||
1295 | * scalar should be in the range [0,n) otherwise all constant time bets are off. | |||
1296 | * | |||
1297 | * NB: This says nothing about EC_POINT_add and EC_POINT_dbl, | |||
1298 | * which of course are not constant time themselves. | |||
1299 | * | |||
1300 | * The product is stored in r. | |||
1301 | * | |||
1302 | * Returns 1 on success, 0 otherwise. | |||
1303 | */ | |||
1304 | static int | |||
1305 | ec_GFp_simple_mul_ct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, | |||
1306 | const EC_POINT *point, BN_CTX *ctx) | |||
1307 | { | |||
1308 | int i, cardinality_bits, group_top, kbit, pbit, Z_is_one; | |||
1309 | EC_POINT *s = NULL((void *)0); | |||
1310 | BIGNUM *k = NULL((void *)0); | |||
1311 | BIGNUM *lambda = NULL((void *)0); | |||
1312 | BIGNUM *cardinality = NULL((void *)0); | |||
1313 | int ret = 0; | |||
1314 | ||||
1315 | BN_CTX_start(ctx); | |||
1316 | ||||
1317 | if ((s = EC_POINT_new(group)) == NULL((void *)0)) | |||
1318 | goto err; | |||
1319 | ||||
1320 | if (point == NULL((void *)0)) { | |||
1321 | if (!EC_POINT_copy(s, group->generator)) | |||
1322 | goto err; | |||
1323 | } else { | |||
1324 | if (!EC_POINT_copy(s, point)) | |||
1325 | goto err; | |||
1326 | } | |||
1327 | ||||
1328 | EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME0x04); | |||
1329 | ||||
1330 | if ((cardinality = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
1331 | goto err; | |||
1332 | if ((lambda = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
1333 | goto err; | |||
1334 | if ((k = BN_CTX_get(ctx)) == NULL((void *)0)) | |||
1335 | goto err; | |||
1336 | if (!BN_mul(cardinality, &group->order, &group->cofactor, ctx)) | |||
1337 | goto err; | |||
1338 | ||||
1339 | /* | |||
1340 | * Group cardinalities are often on a word boundary. | |||
1341 | * So when we pad the scalar, some timing diff might | |||
1342 | * pop if it needs to be expanded due to carries. | |||
1343 | * So expand ahead of time. | |||
1344 | */ | |||
1345 | cardinality_bits = BN_num_bits(cardinality); | |||
1346 | group_top = cardinality->top; | |||
1347 | if (!bn_wexpand(k, group_top + 2) || | |||
1348 | !bn_wexpand(lambda, group_top + 2)) | |||
1349 | goto err; | |||
1350 | ||||
1351 | if (!bn_copy(k, scalar)) | |||
1352 | goto err; | |||
1353 | ||||
1354 | BN_set_flags(k, BN_FLG_CONSTTIME0x04); | |||
1355 | ||||
1356 | if (BN_num_bits(k) > cardinality_bits || BN_is_negative(k)) { | |||
1357 | /* | |||
1358 | * This is an unusual input, and we don't guarantee | |||
1359 | * constant-timeness | |||
1360 | */ | |||
1361 | if (!BN_nnmod(k, k, cardinality, ctx)) | |||
1362 | goto err; | |||
1363 | } | |||
1364 | ||||
1365 | if (!BN_add(lambda, k, cardinality)) | |||
1366 | goto err; | |||
1367 | BN_set_flags(lambda, BN_FLG_CONSTTIME0x04); | |||
1368 | if (!BN_add(k, lambda, cardinality)) | |||
1369 | goto err; | |||
1370 | /* | |||
1371 | * lambda := scalar + cardinality | |||
1372 | * k := scalar + 2*cardinality | |||
1373 | */ | |||
1374 | kbit = BN_is_bit_set(lambda, cardinality_bits); | |||
1375 | if (!BN_swap_ct(kbit, k, lambda, group_top + 2)) | |||
1376 | goto err; | |||
1377 | ||||
1378 | group_top = group->field.top; | |||
1379 | if (!bn_wexpand(&s->X, group_top) || | |||
1380 | !bn_wexpand(&s->Y, group_top) || | |||
1381 | !bn_wexpand(&s->Z, group_top) || | |||
1382 | !bn_wexpand(&r->X, group_top) || | |||
1383 | !bn_wexpand(&r->Y, group_top) || | |||
1384 | !bn_wexpand(&r->Z, group_top)) | |||
1385 | goto err; | |||
1386 | ||||
1387 | /* | |||
1388 | * Apply coordinate blinding for EC_POINT if the underlying EC_METHOD | |||
1389 | * implements it. | |||
1390 | */ | |||
1391 | if (!ec_point_blind_coordinates(group, s, ctx)) | |||
1392 | goto err; | |||
1393 | ||||
1394 | /* top bit is a 1, in a fixed pos */ | |||
1395 | if (!EC_POINT_copy(r, s)) | |||
1396 | goto err; | |||
1397 | ||||
1398 | EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME0x04); | |||
1399 | ||||
1400 | if (!EC_POINT_dbl(group, s, s, ctx)) | |||
1401 | goto err; | |||
1402 | ||||
1403 | pbit = 0; | |||
1404 | ||||
1405 | /* | |||
1406 | * The ladder step, with branches, is | |||
1407 | * | |||
1408 | * k[i] == 0: S = add(R, S), R = dbl(R) | |||
1409 | * k[i] == 1: R = add(S, R), S = dbl(S) | |||
1410 | * | |||
1411 | * Swapping R, S conditionally on k[i] leaves you with state | |||
1412 | * | |||
1413 | * k[i] == 0: T, U = R, S | |||
1414 | * k[i] == 1: T, U = S, R | |||
1415 | * | |||
1416 | * Then perform the ECC ops. | |||
1417 | * | |||
1418 | * U = add(T, U) | |||
1419 | * T = dbl(T) | |||
1420 | * | |||
1421 | * Which leaves you with state | |||
1422 | * | |||
1423 | * k[i] == 0: U = add(R, S), T = dbl(R) | |||
1424 | * k[i] == 1: U = add(S, R), T = dbl(S) | |||
1425 | * | |||
1426 | * Swapping T, U conditionally on k[i] leaves you with state | |||
1427 | * | |||
1428 | * k[i] == 0: R, S = T, U | |||
1429 | * k[i] == 1: R, S = U, T | |||
1430 | * | |||
1431 | * Which leaves you with state | |||
1432 | * | |||
1433 | * k[i] == 0: S = add(R, S), R = dbl(R) | |||
1434 | * k[i] == 1: R = add(S, R), S = dbl(S) | |||
1435 | * | |||
1436 | * So we get the same logic, but instead of a branch it's a | |||
1437 | * conditional swap, followed by ECC ops, then another conditional swap. | |||
1438 | * | |||
1439 | * Optimization: The end of iteration i and start of i-1 looks like | |||
1440 | * | |||
1441 | * ... | |||
1442 | * CSWAP(k[i], R, S) | |||
1443 | * ECC | |||
1444 | * CSWAP(k[i], R, S) | |||
1445 | * (next iteration) | |||
1446 | * CSWAP(k[i-1], R, S) | |||
1447 | * ECC | |||
1448 | * CSWAP(k[i-1], R, S) | |||
1449 | * ... | |||
1450 | * | |||
1451 | * So instead of two contiguous swaps, you can merge the condition | |||
1452 | * bits and do a single swap. | |||
1453 | * | |||
1454 | * k[i] k[i-1] Outcome | |||
1455 | * 0 0 No Swap | |||
1456 | * 0 1 Swap | |||
1457 | * 1 0 Swap | |||
1458 | * 1 1 No Swap | |||
1459 | * | |||
1460 | * This is XOR. pbit tracks the previous bit of k. | |||
1461 | */ | |||
1462 | ||||
1463 | for (i = cardinality_bits - 1; i >= 0; i--) { | |||
1464 | kbit = BN_is_bit_set(k, i) ^ pbit; | |||
1465 | EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one); | |||
1466 | if (!EC_POINT_add(group, s, r, s, ctx)) | |||
1467 | goto err; | |||
1468 | if (!EC_POINT_dbl(group, r, r, ctx)) | |||
1469 | goto err; | |||
1470 | /* | |||
1471 | * pbit logic merges this cswap with that of the | |||
1472 | * next iteration | |||
1473 | */ | |||
1474 | pbit ^= kbit; | |||
1475 | } | |||
1476 | /* one final cswap to move the right value into r */ | |||
1477 | EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one); | |||
1478 | ||||
1479 | ret = 1; | |||
1480 | ||||
1481 | err: | |||
1482 | EC_POINT_free(s); | |||
1483 | BN_CTX_end(ctx); | |||
1484 | ||||
1485 | return ret; | |||
1486 | } | |||
1487 | ||||
1488 | #undef EC_POINT_BN_set_flags | |||
1489 | #undef EC_POINT_CSWAP | |||
1490 | ||||
1491 | int | |||
1492 | ec_GFp_simple_mul_generator_ct(const EC_GROUP *group, EC_POINT *r, | |||
1493 | const BIGNUM *scalar, BN_CTX *ctx) | |||
1494 | { | |||
1495 | return ec_GFp_simple_mul_ct(group, r, scalar, NULL((void *)0), ctx); | |||
1496 | } | |||
1497 | ||||
1498 | int | |||
1499 | ec_GFp_simple_mul_single_ct(const EC_GROUP *group, EC_POINT *r, | |||
1500 | const BIGNUM *scalar, const EC_POINT *point, BN_CTX *ctx) | |||
1501 | { | |||
1502 | return ec_GFp_simple_mul_ct(group, r, scalar, point, ctx); | |||
1503 | } | |||
1504 | ||||
1505 | int | |||
1506 | ec_GFp_simple_mul_double_nonct(const EC_GROUP *group, EC_POINT *r, | |||
1507 | const BIGNUM *g_scalar, const BIGNUM *p_scalar, const EC_POINT *point, | |||
1508 | BN_CTX *ctx) | |||
1509 | { | |||
1510 | return ec_wNAF_mul(group, r, g_scalar, 1, &point, &p_scalar, ctx); | |||
1511 | } | |||
1512 | ||||
1513 | static const EC_METHOD ec_GFp_simple_method = { | |||
1514 | .field_type = NID_X9_62_prime_field406, | |||
1515 | .group_init = ec_GFp_simple_group_init, | |||
1516 | .group_finish = ec_GFp_simple_group_finish, | |||
1517 | .group_copy = ec_GFp_simple_group_copy, | |||
1518 | .group_set_curve = ec_GFp_simple_group_set_curve, | |||
1519 | .group_get_curve = ec_GFp_simple_group_get_curve, | |||
1520 | .group_get_degree = ec_GFp_simple_group_get_degree, | |||
1521 | .group_order_bits = ec_group_simple_order_bits, | |||
1522 | .group_check_discriminant = ec_GFp_simple_group_check_discriminant, | |||
1523 | .point_init = ec_GFp_simple_point_init, | |||
1524 | .point_finish = ec_GFp_simple_point_finish, | |||
1525 | .point_copy = ec_GFp_simple_point_copy, | |||
1526 | .point_set_to_infinity = ec_GFp_simple_point_set_to_infinity, | |||
1527 | .point_set_Jprojective_coordinates = | |||
1528 | ec_GFp_simple_set_Jprojective_coordinates, | |||
1529 | .point_get_Jprojective_coordinates = | |||
1530 | ec_GFp_simple_get_Jprojective_coordinates, | |||
1531 | .point_set_affine_coordinates = | |||
1532 | ec_GFp_simple_point_set_affine_coordinates, | |||
1533 | .point_get_affine_coordinates = | |||
1534 | ec_GFp_simple_point_get_affine_coordinates, | |||
1535 | .point_set_compressed_coordinates = | |||
1536 | ec_GFp_simple_set_compressed_coordinates, | |||
1537 | .point2oct = ec_GFp_simple_point2oct, | |||
1538 | .oct2point = ec_GFp_simple_oct2point, | |||
1539 | .add = ec_GFp_simple_add, | |||
1540 | .dbl = ec_GFp_simple_dbl, | |||
1541 | .invert = ec_GFp_simple_invert, | |||
1542 | .is_at_infinity = ec_GFp_simple_is_at_infinity, | |||
1543 | .is_on_curve = ec_GFp_simple_is_on_curve, | |||
1544 | .point_cmp = ec_GFp_simple_cmp, | |||
1545 | .make_affine = ec_GFp_simple_make_affine, | |||
1546 | .points_make_affine = ec_GFp_simple_points_make_affine, | |||
1547 | .mul_generator_ct = ec_GFp_simple_mul_generator_ct, | |||
1548 | .mul_single_ct = ec_GFp_simple_mul_single_ct, | |||
1549 | .mul_double_nonct = ec_GFp_simple_mul_double_nonct, | |||
1550 | .field_mul = ec_GFp_simple_field_mul, | |||
1551 | .field_sqr = ec_GFp_simple_field_sqr, | |||
1552 | .blind_coordinates = ec_GFp_simple_blind_coordinates, | |||
1553 | }; | |||
1554 | ||||
1555 | const EC_METHOD * | |||
1556 | EC_GFp_simple_method(void) | |||
1557 | { | |||
1558 | return &ec_GFp_simple_method; | |||
1559 | } | |||
1560 | LCRYPTO_ALIAS(EC_GFp_simple_method)asm(""); |