/src/libressl/crypto/ec/ec2_smpl.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* $OpenBSD: ec2_smpl.c,v 1.23 2021/09/08 17:29:21 tb Exp $ */ |
2 | | /* ==================================================================== |
3 | | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. |
4 | | * |
5 | | * The Elliptic Curve Public-Key Crypto Library (ECC Code) included |
6 | | * herein is developed by SUN MICROSYSTEMS, INC., and is contributed |
7 | | * to the OpenSSL project. |
8 | | * |
9 | | * The ECC Code is licensed pursuant to the OpenSSL open source |
10 | | * license provided below. |
11 | | * |
12 | | * The software is originally written by Sheueling Chang Shantz and |
13 | | * Douglas Stebila of Sun Microsystems Laboratories. |
14 | | * |
15 | | */ |
16 | | /* ==================================================================== |
17 | | * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. |
18 | | * |
19 | | * Redistribution and use in source and binary forms, with or without |
20 | | * modification, are permitted provided that the following conditions |
21 | | * are met: |
22 | | * |
23 | | * 1. Redistributions of source code must retain the above copyright |
24 | | * notice, this list of conditions and the following disclaimer. |
25 | | * |
26 | | * 2. Redistributions in binary form must reproduce the above copyright |
27 | | * notice, this list of conditions and the following disclaimer in |
28 | | * the documentation and/or other materials provided with the |
29 | | * distribution. |
30 | | * |
31 | | * 3. All advertising materials mentioning features or use of this |
32 | | * software must display the following acknowledgment: |
33 | | * "This product includes software developed by the OpenSSL Project |
34 | | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" |
35 | | * |
36 | | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
37 | | * endorse or promote products derived from this software without |
38 | | * prior written permission. For written permission, please contact |
39 | | * openssl-core@openssl.org. |
40 | | * |
41 | | * 5. Products derived from this software may not be called "OpenSSL" |
42 | | * nor may "OpenSSL" appear in their names without prior written |
43 | | * permission of the OpenSSL Project. |
44 | | * |
45 | | * 6. Redistributions of any form whatsoever must retain the following |
46 | | * acknowledgment: |
47 | | * "This product includes software developed by the OpenSSL Project |
48 | | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" |
49 | | * |
50 | | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
51 | | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
52 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
53 | | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
54 | | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
55 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
56 | | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
57 | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
58 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
59 | | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
60 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
61 | | * OF THE POSSIBILITY OF SUCH DAMAGE. |
62 | | * ==================================================================== |
63 | | * |
64 | | * This product includes cryptographic software written by Eric Young |
65 | | * (eay@cryptsoft.com). This product includes software written by Tim |
66 | | * Hudson (tjh@cryptsoft.com). |
67 | | * |
68 | | */ |
69 | | |
70 | | #include <openssl/opensslconf.h> |
71 | | |
72 | | #include <openssl/err.h> |
73 | | |
74 | | #include "ec_lcl.h" |
75 | | |
76 | | #ifndef OPENSSL_NO_EC2M |
77 | | |
78 | | const EC_METHOD * |
79 | | EC_GF2m_simple_method(void) |
80 | 583 | { |
81 | 583 | static const EC_METHOD ret = { |
82 | 583 | .flags = EC_FLAGS_DEFAULT_OCT, |
83 | 583 | .field_type = NID_X9_62_characteristic_two_field, |
84 | 583 | .group_init = ec_GF2m_simple_group_init, |
85 | 583 | .group_finish = ec_GF2m_simple_group_finish, |
86 | 583 | .group_clear_finish = ec_GF2m_simple_group_clear_finish, |
87 | 583 | .group_copy = ec_GF2m_simple_group_copy, |
88 | 583 | .group_set_curve = ec_GF2m_simple_group_set_curve, |
89 | 583 | .group_get_curve = ec_GF2m_simple_group_get_curve, |
90 | 583 | .group_get_degree = ec_GF2m_simple_group_get_degree, |
91 | 583 | .group_order_bits = ec_group_simple_order_bits, |
92 | 583 | .group_check_discriminant = |
93 | 583 | ec_GF2m_simple_group_check_discriminant, |
94 | 583 | .point_init = ec_GF2m_simple_point_init, |
95 | 583 | .point_finish = ec_GF2m_simple_point_finish, |
96 | 583 | .point_clear_finish = ec_GF2m_simple_point_clear_finish, |
97 | 583 | .point_copy = ec_GF2m_simple_point_copy, |
98 | 583 | .point_set_to_infinity = ec_GF2m_simple_point_set_to_infinity, |
99 | 583 | .point_set_affine_coordinates = |
100 | 583 | ec_GF2m_simple_point_set_affine_coordinates, |
101 | 583 | .point_get_affine_coordinates = |
102 | 583 | ec_GF2m_simple_point_get_affine_coordinates, |
103 | 583 | .add = ec_GF2m_simple_add, |
104 | 583 | .dbl = ec_GF2m_simple_dbl, |
105 | 583 | .invert = ec_GF2m_simple_invert, |
106 | 583 | .is_at_infinity = ec_GF2m_simple_is_at_infinity, |
107 | 583 | .is_on_curve = ec_GF2m_simple_is_on_curve, |
108 | 583 | .point_cmp = ec_GF2m_simple_cmp, |
109 | 583 | .make_affine = ec_GF2m_simple_make_affine, |
110 | 583 | .points_make_affine = ec_GF2m_simple_points_make_affine, |
111 | 583 | .mul_generator_ct = ec_GFp_simple_mul_generator_ct, |
112 | 583 | .mul_single_ct = ec_GFp_simple_mul_single_ct, |
113 | 583 | .mul_double_nonct = ec_GFp_simple_mul_double_nonct, |
114 | 583 | .precompute_mult = ec_GF2m_precompute_mult, |
115 | 583 | .have_precompute_mult = ec_GF2m_have_precompute_mult, |
116 | 583 | .field_mul = ec_GF2m_simple_field_mul, |
117 | 583 | .field_sqr = ec_GF2m_simple_field_sqr, |
118 | 583 | .field_div = ec_GF2m_simple_field_div, |
119 | 583 | .blind_coordinates = NULL, |
120 | 583 | }; |
121 | | |
122 | 583 | return &ret; |
123 | 583 | } |
124 | | |
125 | | |
126 | | /* Initialize a GF(2^m)-based EC_GROUP structure. |
127 | | * Note that all other members are handled by EC_GROUP_new. |
128 | | */ |
129 | | int |
130 | | ec_GF2m_simple_group_init(EC_GROUP * group) |
131 | 1.22k | { |
132 | 1.22k | BN_init(&group->field); |
133 | 1.22k | BN_init(&group->a); |
134 | 1.22k | BN_init(&group->b); |
135 | 1.22k | return 1; |
136 | 1.22k | } |
137 | | |
138 | | |
139 | | /* Free a GF(2^m)-based EC_GROUP structure. |
140 | | * Note that all other members are handled by EC_GROUP_free. |
141 | | */ |
142 | | void |
143 | | ec_GF2m_simple_group_finish(EC_GROUP * group) |
144 | 1.22k | { |
145 | 1.22k | BN_free(&group->field); |
146 | 1.22k | BN_free(&group->a); |
147 | 1.22k | BN_free(&group->b); |
148 | 1.22k | } |
149 | | |
150 | | |
151 | | /* Clear and free a GF(2^m)-based EC_GROUP structure. |
152 | | * Note that all other members are handled by EC_GROUP_clear_free. |
153 | | */ |
154 | | void |
155 | | ec_GF2m_simple_group_clear_finish(EC_GROUP * group) |
156 | 0 | { |
157 | 0 | BN_clear_free(&group->field); |
158 | 0 | BN_clear_free(&group->a); |
159 | 0 | BN_clear_free(&group->b); |
160 | 0 | group->poly[0] = 0; |
161 | 0 | group->poly[1] = 0; |
162 | 0 | group->poly[2] = 0; |
163 | 0 | group->poly[3] = 0; |
164 | 0 | group->poly[4] = 0; |
165 | 0 | group->poly[5] = -1; |
166 | 0 | } |
167 | | |
168 | | |
169 | | /* Copy a GF(2^m)-based EC_GROUP structure. |
170 | | * Note that all other members are handled by EC_GROUP_copy. |
171 | | */ |
172 | | int |
173 | | ec_GF2m_simple_group_copy(EC_GROUP * dest, const EC_GROUP * src) |
174 | 645 | { |
175 | 645 | int i; |
176 | | |
177 | 645 | if (!BN_copy(&dest->field, &src->field)) |
178 | 0 | return 0; |
179 | 645 | if (!BN_copy(&dest->a, &src->a)) |
180 | 0 | return 0; |
181 | 645 | if (!BN_copy(&dest->b, &src->b)) |
182 | 0 | return 0; |
183 | 645 | dest->poly[0] = src->poly[0]; |
184 | 645 | dest->poly[1] = src->poly[1]; |
185 | 645 | dest->poly[2] = src->poly[2]; |
186 | 645 | dest->poly[3] = src->poly[3]; |
187 | 645 | dest->poly[4] = src->poly[4]; |
188 | 645 | dest->poly[5] = src->poly[5]; |
189 | 645 | if (bn_wexpand(&dest->a, (int) (dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) |
190 | 0 | return 0; |
191 | 645 | if (bn_wexpand(&dest->b, (int) (dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) |
192 | 0 | return 0; |
193 | 3.32k | for (i = dest->a.top; i < dest->a.dmax; i++) |
194 | 2.67k | dest->a.d[i] = 0; |
195 | 2.08k | for (i = dest->b.top; i < dest->b.dmax; i++) |
196 | 1.44k | dest->b.d[i] = 0; |
197 | 645 | return 1; |
198 | 645 | } |
199 | | |
200 | | |
201 | | /* Set the curve parameters of an EC_GROUP structure. */ |
202 | | int |
203 | | ec_GF2m_simple_group_set_curve(EC_GROUP * group, |
204 | | const BIGNUM * p, const BIGNUM * a, const BIGNUM * b, BN_CTX * ctx) |
205 | 583 | { |
206 | 583 | int ret = 0, i; |
207 | | |
208 | | /* group->field */ |
209 | 583 | if (!BN_copy(&group->field, p)) |
210 | 0 | goto err; |
211 | 583 | i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1; |
212 | 583 | if ((i != 5) && (i != 3)) { |
213 | 0 | ECerror(EC_R_UNSUPPORTED_FIELD); |
214 | 0 | goto err; |
215 | 0 | } |
216 | | /* group->a */ |
217 | 583 | if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) |
218 | 0 | goto err; |
219 | 583 | if (bn_wexpand(&group->a, (int) (group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) |
220 | 0 | goto err; |
221 | 2.50k | for (i = group->a.top; i < group->a.dmax; i++) |
222 | 1.92k | group->a.d[i] = 0; |
223 | | |
224 | | /* group->b */ |
225 | 583 | if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) |
226 | 0 | goto err; |
227 | 583 | if (bn_wexpand(&group->b, (int) (group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) |
228 | 0 | goto err; |
229 | 1.75k | for (i = group->b.top; i < group->b.dmax; i++) |
230 | 1.17k | group->b.d[i] = 0; |
231 | | |
232 | 583 | ret = 1; |
233 | 583 | err: |
234 | 583 | return ret; |
235 | 583 | } |
236 | | |
237 | | |
238 | | /* Get the curve parameters of an EC_GROUP structure. |
239 | | * If p, a, or b are NULL then there values will not be set but the method will return with success. |
240 | | */ |
241 | | int |
242 | | ec_GF2m_simple_group_get_curve(const EC_GROUP *group, |
243 | | BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) |
244 | 0 | { |
245 | 0 | int ret = 0; |
246 | |
|
247 | 0 | if (p != NULL) { |
248 | 0 | if (!BN_copy(p, &group->field)) |
249 | 0 | return 0; |
250 | 0 | } |
251 | 0 | if (a != NULL) { |
252 | 0 | if (!BN_copy(a, &group->a)) |
253 | 0 | goto err; |
254 | 0 | } |
255 | 0 | if (b != NULL) { |
256 | 0 | if (!BN_copy(b, &group->b)) |
257 | 0 | goto err; |
258 | 0 | } |
259 | 0 | ret = 1; |
260 | |
|
261 | 0 | err: |
262 | 0 | return ret; |
263 | 0 | } |
264 | | |
265 | | |
266 | | /* Gets the degree of the field. For a curve over GF(2^m) this is the value m. */ |
267 | | int |
268 | | ec_GF2m_simple_group_get_degree(const EC_GROUP * group) |
269 | 0 | { |
270 | 0 | return BN_num_bits(&group->field) - 1; |
271 | 0 | } |
272 | | |
273 | | |
274 | | /* Checks the discriminant of the curve. |
275 | | * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) |
276 | | */ |
277 | | int |
278 | | ec_GF2m_simple_group_check_discriminant(const EC_GROUP * group, BN_CTX * ctx) |
279 | 0 | { |
280 | 0 | int ret = 0; |
281 | 0 | BIGNUM *b; |
282 | 0 | BN_CTX *new_ctx = NULL; |
283 | |
|
284 | 0 | if (ctx == NULL) { |
285 | 0 | ctx = new_ctx = BN_CTX_new(); |
286 | 0 | if (ctx == NULL) { |
287 | 0 | ECerror(ERR_R_MALLOC_FAILURE); |
288 | 0 | goto err; |
289 | 0 | } |
290 | 0 | } |
291 | 0 | BN_CTX_start(ctx); |
292 | 0 | if ((b = BN_CTX_get(ctx)) == NULL) |
293 | 0 | goto err; |
294 | | |
295 | 0 | if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) |
296 | 0 | goto err; |
297 | | |
298 | | /* |
299 | | * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic |
300 | | * curve <=> b != 0 (mod p) |
301 | | */ |
302 | 0 | if (BN_is_zero(b)) |
303 | 0 | goto err; |
304 | | |
305 | 0 | ret = 1; |
306 | |
|
307 | 0 | err: |
308 | 0 | if (ctx != NULL) |
309 | 0 | BN_CTX_end(ctx); |
310 | 0 | BN_CTX_free(new_ctx); |
311 | 0 | return ret; |
312 | 0 | } |
313 | | |
314 | | |
315 | | /* Initializes an EC_POINT. */ |
316 | | int |
317 | | ec_GF2m_simple_point_init(EC_POINT * point) |
318 | 4.72k | { |
319 | 4.72k | BN_init(&point->X); |
320 | 4.72k | BN_init(&point->Y); |
321 | 4.72k | BN_init(&point->Z); |
322 | 4.72k | return 1; |
323 | 4.72k | } |
324 | | |
325 | | |
326 | | /* Frees an EC_POINT. */ |
327 | | void |
328 | | ec_GF2m_simple_point_finish(EC_POINT * point) |
329 | 4.18k | { |
330 | 4.18k | BN_free(&point->X); |
331 | 4.18k | BN_free(&point->Y); |
332 | 4.18k | BN_free(&point->Z); |
333 | 4.18k | } |
334 | | |
335 | | |
336 | | /* Clears and frees an EC_POINT. */ |
337 | | void |
338 | | ec_GF2m_simple_point_clear_finish(EC_POINT * point) |
339 | 545 | { |
340 | 545 | BN_clear_free(&point->X); |
341 | 545 | BN_clear_free(&point->Y); |
342 | 545 | BN_clear_free(&point->Z); |
343 | 545 | point->Z_is_one = 0; |
344 | 545 | } |
345 | | |
346 | | |
347 | | /* Copy the contents of one EC_POINT into another. Assumes dest is initialized. */ |
348 | | int |
349 | | ec_GF2m_simple_point_copy(EC_POINT * dest, const EC_POINT * src) |
350 | 5.66k | { |
351 | 5.66k | if (!BN_copy(&dest->X, &src->X)) |
352 | 0 | return 0; |
353 | 5.66k | if (!BN_copy(&dest->Y, &src->Y)) |
354 | 0 | return 0; |
355 | 5.66k | if (!BN_copy(&dest->Z, &src->Z)) |
356 | 0 | return 0; |
357 | 5.66k | dest->Z_is_one = src->Z_is_one; |
358 | | |
359 | 5.66k | return 1; |
360 | 5.66k | } |
361 | | |
362 | | |
363 | | /* Set an EC_POINT to the point at infinity. |
364 | | * A point at infinity is represented by having Z=0. |
365 | | */ |
366 | | int |
367 | | ec_GF2m_simple_point_set_to_infinity(const EC_GROUP * group, EC_POINT * point) |
368 | 2.32k | { |
369 | 2.32k | point->Z_is_one = 0; |
370 | 2.32k | BN_zero(&point->Z); |
371 | 2.32k | return 1; |
372 | 2.32k | } |
373 | | |
374 | | |
375 | | /* Set the coordinates of an EC_POINT using affine coordinates. |
376 | | * Note that the simple implementation only uses affine coordinates. |
377 | | */ |
378 | | int |
379 | | ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP * group, EC_POINT * point, |
380 | | const BIGNUM * x, const BIGNUM * y, BN_CTX * ctx) |
381 | 202k | { |
382 | 202k | int ret = 0; |
383 | 202k | if (x == NULL || y == NULL) { |
384 | 0 | ECerror(ERR_R_PASSED_NULL_PARAMETER); |
385 | 0 | return 0; |
386 | 0 | } |
387 | 202k | if (!BN_copy(&point->X, x)) |
388 | 0 | goto err; |
389 | 202k | BN_set_negative(&point->X, 0); |
390 | 202k | if (!BN_copy(&point->Y, y)) |
391 | 0 | goto err; |
392 | 202k | BN_set_negative(&point->Y, 0); |
393 | 202k | if (!BN_copy(&point->Z, BN_value_one())) |
394 | 0 | goto err; |
395 | 202k | BN_set_negative(&point->Z, 0); |
396 | 202k | point->Z_is_one = 1; |
397 | 202k | ret = 1; |
398 | | |
399 | 202k | err: |
400 | 202k | return ret; |
401 | 202k | } |
402 | | |
403 | | |
404 | | /* Gets the affine coordinates of an EC_POINT. |
405 | | * Note that the simple implementation only uses affine coordinates. |
406 | | */ |
407 | | int |
408 | | ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, |
409 | | const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) |
410 | 412 | { |
411 | 412 | int ret = 0; |
412 | | |
413 | 412 | if (EC_POINT_is_at_infinity(group, point) > 0) { |
414 | 36 | ECerror(EC_R_POINT_AT_INFINITY); |
415 | 36 | return 0; |
416 | 36 | } |
417 | 376 | if (BN_cmp(&point->Z, BN_value_one())) { |
418 | 0 | ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
419 | 0 | return 0; |
420 | 0 | } |
421 | 376 | if (x != NULL) { |
422 | 376 | if (!BN_copy(x, &point->X)) |
423 | 0 | goto err; |
424 | 376 | BN_set_negative(x, 0); |
425 | 376 | } |
426 | 376 | if (y != NULL) { |
427 | 270 | if (!BN_copy(y, &point->Y)) |
428 | 0 | goto err; |
429 | 270 | BN_set_negative(y, 0); |
430 | 270 | } |
431 | 376 | ret = 1; |
432 | | |
433 | 376 | err: |
434 | 376 | return ret; |
435 | 376 | } |
436 | | |
437 | | /* Computes a + b and stores the result in r. r could be a or b, a could be b. |
438 | | * Uses algorithm A.10.2 of IEEE P1363. |
439 | | */ |
440 | | int |
441 | | ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, |
442 | | const EC_POINT *b, BN_CTX *ctx) |
443 | 214k | { |
444 | 214k | BN_CTX *new_ctx = NULL; |
445 | 214k | BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t; |
446 | 214k | int ret = 0; |
447 | | |
448 | 214k | if (EC_POINT_is_at_infinity(group, a) > 0) { |
449 | 9.04k | if (!EC_POINT_copy(r, b)) |
450 | 0 | return 0; |
451 | 9.04k | return 1; |
452 | 9.04k | } |
453 | 205k | if (EC_POINT_is_at_infinity(group, b) > 0) { |
454 | 1.36k | if (!EC_POINT_copy(r, a)) |
455 | 0 | return 0; |
456 | 1.36k | return 1; |
457 | 1.36k | } |
458 | 204k | if (ctx == NULL) { |
459 | 23 | ctx = new_ctx = BN_CTX_new(); |
460 | 23 | if (ctx == NULL) |
461 | 0 | return 0; |
462 | 23 | } |
463 | 204k | BN_CTX_start(ctx); |
464 | 204k | if ((x0 = BN_CTX_get(ctx)) == NULL) |
465 | 0 | goto err; |
466 | 204k | if ((y0 = BN_CTX_get(ctx)) == NULL) |
467 | 0 | goto err; |
468 | 204k | if ((x1 = BN_CTX_get(ctx)) == NULL) |
469 | 0 | goto err; |
470 | 204k | if ((y1 = BN_CTX_get(ctx)) == NULL) |
471 | 0 | goto err; |
472 | 204k | if ((x2 = BN_CTX_get(ctx)) == NULL) |
473 | 0 | goto err; |
474 | 204k | if ((y2 = BN_CTX_get(ctx)) == NULL) |
475 | 0 | goto err; |
476 | 204k | if ((s = BN_CTX_get(ctx)) == NULL) |
477 | 0 | goto err; |
478 | 204k | if ((t = BN_CTX_get(ctx)) == NULL) |
479 | 0 | goto err; |
480 | | |
481 | 204k | if (a->Z_is_one) { |
482 | 204k | if (!BN_copy(x0, &a->X)) |
483 | 0 | goto err; |
484 | 204k | if (!BN_copy(y0, &a->Y)) |
485 | 0 | goto err; |
486 | 204k | } else { |
487 | 0 | if (!EC_POINT_get_affine_coordinates(group, a, x0, y0, ctx)) |
488 | 0 | goto err; |
489 | 0 | } |
490 | 204k | if (b->Z_is_one) { |
491 | 204k | if (!BN_copy(x1, &b->X)) |
492 | 0 | goto err; |
493 | 204k | if (!BN_copy(y1, &b->Y)) |
494 | 0 | goto err; |
495 | 204k | } else { |
496 | 0 | if (!EC_POINT_get_affine_coordinates(group, b, x1, y1, ctx)) |
497 | 0 | goto err; |
498 | 0 | } |
499 | | |
500 | | |
501 | 204k | if (BN_GF2m_cmp(x0, x1)) { |
502 | 96.1k | if (!BN_GF2m_add(t, x0, x1)) |
503 | 0 | goto err; |
504 | 96.1k | if (!BN_GF2m_add(s, y0, y1)) |
505 | 0 | goto err; |
506 | 96.1k | if (!group->meth->field_div(group, s, s, t, ctx)) |
507 | 0 | goto err; |
508 | 96.1k | if (!group->meth->field_sqr(group, x2, s, ctx)) |
509 | 0 | goto err; |
510 | 96.1k | if (!BN_GF2m_add(x2, x2, &group->a)) |
511 | 0 | goto err; |
512 | 96.1k | if (!BN_GF2m_add(x2, x2, s)) |
513 | 0 | goto err; |
514 | 96.1k | if (!BN_GF2m_add(x2, x2, t)) |
515 | 0 | goto err; |
516 | 107k | } else { |
517 | 107k | if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) { |
518 | 2.32k | if (!EC_POINT_set_to_infinity(group, r)) |
519 | 0 | goto err; |
520 | 2.32k | ret = 1; |
521 | 2.32k | goto err; |
522 | 2.32k | } |
523 | 105k | if (!group->meth->field_div(group, s, y1, x1, ctx)) |
524 | 0 | goto err; |
525 | 105k | if (!BN_GF2m_add(s, s, x1)) |
526 | 0 | goto err; |
527 | | |
528 | 105k | if (!group->meth->field_sqr(group, x2, s, ctx)) |
529 | 0 | goto err; |
530 | 105k | if (!BN_GF2m_add(x2, x2, s)) |
531 | 0 | goto err; |
532 | 105k | if (!BN_GF2m_add(x2, x2, &group->a)) |
533 | 0 | goto err; |
534 | 105k | } |
535 | | |
536 | 201k | if (!BN_GF2m_add(y2, x1, x2)) |
537 | 0 | goto err; |
538 | 201k | if (!group->meth->field_mul(group, y2, y2, s, ctx)) |
539 | 0 | goto err; |
540 | 201k | if (!BN_GF2m_add(y2, y2, x2)) |
541 | 0 | goto err; |
542 | 201k | if (!BN_GF2m_add(y2, y2, y1)) |
543 | 0 | goto err; |
544 | | |
545 | 201k | if (!EC_POINT_set_affine_coordinates(group, r, x2, y2, ctx)) |
546 | 0 | goto err; |
547 | | |
548 | 201k | ret = 1; |
549 | | |
550 | 204k | err: |
551 | 204k | BN_CTX_end(ctx); |
552 | 204k | BN_CTX_free(new_ctx); |
553 | 204k | return ret; |
554 | 201k | } |
555 | | |
556 | | |
557 | | /* Computes 2 * a and stores the result in r. r could be a. |
558 | | * Uses algorithm A.10.2 of IEEE P1363. |
559 | | */ |
560 | | int |
561 | | ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, |
562 | | BN_CTX *ctx) |
563 | 113k | { |
564 | 113k | return ec_GF2m_simple_add(group, r, a, a, ctx); |
565 | 113k | } |
566 | | |
567 | | int |
568 | | ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) |
569 | 2.76k | { |
570 | 2.76k | if (EC_POINT_is_at_infinity(group, point) > 0 || BN_is_zero(&point->Y)) |
571 | | /* point is its own inverse */ |
572 | 632 | return 1; |
573 | | |
574 | 2.13k | if (!EC_POINT_make_affine(group, point, ctx)) |
575 | 0 | return 0; |
576 | 2.13k | return BN_GF2m_add(&point->Y, &point->X, &point->Y); |
577 | 2.13k | } |
578 | | |
579 | | |
580 | | /* Indicates whether the given point is the point at infinity. */ |
581 | | int |
582 | | ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) |
583 | 625k | { |
584 | 625k | return BN_is_zero(&point->Z); |
585 | 625k | } |
586 | | |
587 | | |
588 | | /* Determines whether the given EC_POINT is an actual point on the curve defined |
589 | | * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation: |
590 | | * y^2 + x*y = x^3 + a*x^2 + b. |
591 | | */ |
592 | | int |
593 | | ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) |
594 | 202k | { |
595 | 202k | int ret = -1; |
596 | 202k | BN_CTX *new_ctx = NULL; |
597 | 202k | BIGNUM *lh, *y2; |
598 | 202k | int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); |
599 | 202k | int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); |
600 | | |
601 | 202k | if (EC_POINT_is_at_infinity(group, point) > 0) |
602 | 0 | return 1; |
603 | | |
604 | 202k | field_mul = group->meth->field_mul; |
605 | 202k | field_sqr = group->meth->field_sqr; |
606 | | |
607 | | /* only support affine coordinates */ |
608 | 202k | if (!point->Z_is_one) |
609 | 0 | return -1; |
610 | | |
611 | 202k | if (ctx == NULL) { |
612 | 266 | ctx = new_ctx = BN_CTX_new(); |
613 | 266 | if (ctx == NULL) |
614 | 0 | return -1; |
615 | 266 | } |
616 | 202k | BN_CTX_start(ctx); |
617 | 202k | if ((y2 = BN_CTX_get(ctx)) == NULL) |
618 | 0 | goto err; |
619 | 202k | if ((lh = BN_CTX_get(ctx)) == NULL) |
620 | 0 | goto err; |
621 | | |
622 | | /* |
623 | | * We have a curve defined by a Weierstrass equation y^2 + x*y = x^3 |
624 | | * + a*x^2 + b. <=> x^3 + a*x^2 + x*y + b + y^2 = 0 <=> ((x + a) * x |
625 | | * + y ) * x + b + y^2 = 0 |
626 | | */ |
627 | 202k | if (!BN_GF2m_add(lh, &point->X, &group->a)) |
628 | 0 | goto err; |
629 | 202k | if (!field_mul(group, lh, lh, &point->X, ctx)) |
630 | 0 | goto err; |
631 | 202k | if (!BN_GF2m_add(lh, lh, &point->Y)) |
632 | 0 | goto err; |
633 | 202k | if (!field_mul(group, lh, lh, &point->X, ctx)) |
634 | 0 | goto err; |
635 | 202k | if (!BN_GF2m_add(lh, lh, &group->b)) |
636 | 0 | goto err; |
637 | 202k | if (!field_sqr(group, y2, &point->Y, ctx)) |
638 | 0 | goto err; |
639 | 202k | if (!BN_GF2m_add(lh, lh, y2)) |
640 | 0 | goto err; |
641 | 202k | ret = BN_is_zero(lh); |
642 | 202k | err: |
643 | 202k | if (ctx) |
644 | 202k | BN_CTX_end(ctx); |
645 | 202k | BN_CTX_free(new_ctx); |
646 | 202k | return ret; |
647 | 202k | } |
648 | | |
649 | | |
650 | | /* Indicates whether two points are equal. |
651 | | * Return values: |
652 | | * -1 error |
653 | | * 0 equal (in affine coordinates) |
654 | | * 1 not equal |
655 | | */ |
656 | | int |
657 | | ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, |
658 | | const EC_POINT *b, BN_CTX *ctx) |
659 | 0 | { |
660 | 0 | BIGNUM *aX, *aY, *bX, *bY; |
661 | 0 | BN_CTX *new_ctx = NULL; |
662 | 0 | int ret = -1; |
663 | |
|
664 | 0 | if (EC_POINT_is_at_infinity(group, a) > 0) { |
665 | 0 | return EC_POINT_is_at_infinity(group, b) > 0 ? 0 : 1; |
666 | 0 | } |
667 | 0 | if (EC_POINT_is_at_infinity(group, b) > 0) |
668 | 0 | return 1; |
669 | | |
670 | 0 | if (a->Z_is_one && b->Z_is_one) { |
671 | 0 | return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; |
672 | 0 | } |
673 | 0 | if (ctx == NULL) { |
674 | 0 | ctx = new_ctx = BN_CTX_new(); |
675 | 0 | if (ctx == NULL) |
676 | 0 | return -1; |
677 | 0 | } |
678 | 0 | BN_CTX_start(ctx); |
679 | 0 | if ((aX = BN_CTX_get(ctx)) == NULL) |
680 | 0 | goto err; |
681 | 0 | if ((aY = BN_CTX_get(ctx)) == NULL) |
682 | 0 | goto err; |
683 | 0 | if ((bX = BN_CTX_get(ctx)) == NULL) |
684 | 0 | goto err; |
685 | 0 | if ((bY = BN_CTX_get(ctx)) == NULL) |
686 | 0 | goto err; |
687 | | |
688 | 0 | if (!EC_POINT_get_affine_coordinates(group, a, aX, aY, ctx)) |
689 | 0 | goto err; |
690 | 0 | if (!EC_POINT_get_affine_coordinates(group, b, bX, bY, ctx)) |
691 | 0 | goto err; |
692 | 0 | ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1; |
693 | |
|
694 | 0 | err: |
695 | 0 | if (ctx) |
696 | 0 | BN_CTX_end(ctx); |
697 | 0 | BN_CTX_free(new_ctx); |
698 | 0 | return ret; |
699 | 0 | } |
700 | | |
701 | | |
702 | | /* Forces the given EC_POINT to internally use affine coordinates. */ |
703 | | int |
704 | | ec_GF2m_simple_make_affine(const EC_GROUP * group, EC_POINT * point, BN_CTX * ctx) |
705 | 2.67k | { |
706 | 2.67k | BN_CTX *new_ctx = NULL; |
707 | 2.67k | BIGNUM *x, *y; |
708 | 2.67k | int ret = 0; |
709 | | |
710 | 2.67k | if (point->Z_is_one || EC_POINT_is_at_infinity(group, point) > 0) |
711 | 2.67k | return 1; |
712 | | |
713 | 0 | if (ctx == NULL) { |
714 | 0 | ctx = new_ctx = BN_CTX_new(); |
715 | 0 | if (ctx == NULL) |
716 | 0 | return 0; |
717 | 0 | } |
718 | 0 | BN_CTX_start(ctx); |
719 | 0 | if ((x = BN_CTX_get(ctx)) == NULL) |
720 | 0 | goto err; |
721 | 0 | if ((y = BN_CTX_get(ctx)) == NULL) |
722 | 0 | goto err; |
723 | | |
724 | 0 | if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx)) |
725 | 0 | goto err; |
726 | 0 | if (!BN_copy(&point->X, x)) |
727 | 0 | goto err; |
728 | 0 | if (!BN_copy(&point->Y, y)) |
729 | 0 | goto err; |
730 | 0 | if (!BN_one(&point->Z)) |
731 | 0 | goto err; |
732 | | |
733 | 0 | ret = 1; |
734 | |
|
735 | 0 | err: |
736 | 0 | if (ctx) |
737 | 0 | BN_CTX_end(ctx); |
738 | 0 | BN_CTX_free(new_ctx); |
739 | 0 | return ret; |
740 | 0 | } |
741 | | |
742 | | |
743 | | /* Forces each of the EC_POINTs in the given array to use affine coordinates. */ |
744 | | int |
745 | | ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, |
746 | | EC_POINT *points[], BN_CTX *ctx) |
747 | 62 | { |
748 | 62 | size_t i; |
749 | | |
750 | 607 | for (i = 0; i < num; i++) { |
751 | 545 | if (!group->meth->make_affine(group, points[i], ctx)) |
752 | 0 | return 0; |
753 | 545 | } |
754 | | |
755 | 62 | return 1; |
756 | 62 | } |
757 | | |
758 | | |
759 | | /* Wrapper to simple binary polynomial field multiplication implementation. */ |
760 | | int |
761 | | ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, |
762 | | const BIGNUM *b, BN_CTX *ctx) |
763 | 607k | { |
764 | 607k | return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx); |
765 | 607k | } |
766 | | |
767 | | |
768 | | /* Wrapper to simple binary polynomial field squaring implementation. */ |
769 | | int |
770 | | ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, |
771 | | BN_CTX *ctx) |
772 | 404k | { |
773 | 404k | return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx); |
774 | 404k | } |
775 | | |
776 | | |
777 | | /* Wrapper to simple binary polynomial field division implementation. */ |
778 | | int |
779 | | ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, |
780 | | const BIGNUM *b, BN_CTX *ctx) |
781 | 201k | { |
782 | 201k | return BN_GF2m_mod_div(r, a, b, &group->field, ctx); |
783 | 201k | } |
784 | | |
785 | | #endif |