OLD | NEW |
| (Empty) |
1 /* crypto/ec/ec2_smpl.c */ | |
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/err.h> | |
71 | |
72 #include "ec_lcl.h" | |
73 | |
74 #ifndef OPENSSL_NO_EC2M | |
75 | |
76 #ifdef OPENSSL_FIPS | |
77 #include <openssl/fips.h> | |
78 #endif | |
79 | |
80 | |
81 const EC_METHOD *EC_GF2m_simple_method(void) | |
82 { | |
83 #ifdef OPENSSL_FIPS | |
84 return fips_ec_gf2m_simple_method(); | |
85 #else | |
86 static const EC_METHOD ret = { | |
87 EC_FLAGS_DEFAULT_OCT, | |
88 NID_X9_62_characteristic_two_field, | |
89 ec_GF2m_simple_group_init, | |
90 ec_GF2m_simple_group_finish, | |
91 ec_GF2m_simple_group_clear_finish, | |
92 ec_GF2m_simple_group_copy, | |
93 ec_GF2m_simple_group_set_curve, | |
94 ec_GF2m_simple_group_get_curve, | |
95 ec_GF2m_simple_group_get_degree, | |
96 ec_GF2m_simple_group_check_discriminant, | |
97 ec_GF2m_simple_point_init, | |
98 ec_GF2m_simple_point_finish, | |
99 ec_GF2m_simple_point_clear_finish, | |
100 ec_GF2m_simple_point_copy, | |
101 ec_GF2m_simple_point_set_to_infinity, | |
102 0 /* set_Jprojective_coordinates_GFp */, | |
103 0 /* get_Jprojective_coordinates_GFp */, | |
104 ec_GF2m_simple_point_set_affine_coordinates, | |
105 ec_GF2m_simple_point_get_affine_coordinates, | |
106 0,0,0, | |
107 ec_GF2m_simple_add, | |
108 ec_GF2m_simple_dbl, | |
109 ec_GF2m_simple_invert, | |
110 ec_GF2m_simple_is_at_infinity, | |
111 ec_GF2m_simple_is_on_curve, | |
112 ec_GF2m_simple_cmp, | |
113 ec_GF2m_simple_make_affine, | |
114 ec_GF2m_simple_points_make_affine, | |
115 | |
116 /* the following three method functions are defined in ec2_mult.
c */ | |
117 ec_GF2m_simple_mul, | |
118 ec_GF2m_precompute_mult, | |
119 ec_GF2m_have_precompute_mult, | |
120 | |
121 ec_GF2m_simple_field_mul, | |
122 ec_GF2m_simple_field_sqr, | |
123 ec_GF2m_simple_field_div, | |
124 0 /* field_encode */, | |
125 0 /* field_decode */, | |
126 0 /* field_set_to_one */ }; | |
127 | |
128 return &ret; | |
129 #endif | |
130 } | |
131 | |
132 | |
133 /* Initialize a GF(2^m)-based EC_GROUP structure. | |
134 * Note that all other members are handled by EC_GROUP_new. | |
135 */ | |
136 int ec_GF2m_simple_group_init(EC_GROUP *group) | |
137 { | |
138 BN_init(&group->field); | |
139 BN_init(&group->a); | |
140 BN_init(&group->b); | |
141 return 1; | |
142 } | |
143 | |
144 | |
145 /* Free a GF(2^m)-based EC_GROUP structure. | |
146 * Note that all other members are handled by EC_GROUP_free. | |
147 */ | |
148 void ec_GF2m_simple_group_finish(EC_GROUP *group) | |
149 { | |
150 BN_free(&group->field); | |
151 BN_free(&group->a); | |
152 BN_free(&group->b); | |
153 } | |
154 | |
155 | |
156 /* Clear and free a GF(2^m)-based EC_GROUP structure. | |
157 * Note that all other members are handled by EC_GROUP_clear_free. | |
158 */ | |
159 void ec_GF2m_simple_group_clear_finish(EC_GROUP *group) | |
160 { | |
161 BN_clear_free(&group->field); | |
162 BN_clear_free(&group->a); | |
163 BN_clear_free(&group->b); | |
164 group->poly[0] = 0; | |
165 group->poly[1] = 0; | |
166 group->poly[2] = 0; | |
167 group->poly[3] = 0; | |
168 group->poly[4] = 0; | |
169 group->poly[5] = -1; | |
170 } | |
171 | |
172 | |
173 /* Copy a GF(2^m)-based EC_GROUP structure. | |
174 * Note that all other members are handled by EC_GROUP_copy. | |
175 */ | |
176 int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) | |
177 { | |
178 int i; | |
179 if (!BN_copy(&dest->field, &src->field)) return 0; | |
180 if (!BN_copy(&dest->a, &src->a)) return 0; | |
181 if (!BN_copy(&dest->b, &src->b)) return 0; | |
182 dest->poly[0] = src->poly[0]; | |
183 dest->poly[1] = src->poly[1]; | |
184 dest->poly[2] = src->poly[2]; | |
185 dest->poly[3] = src->poly[3]; | |
186 dest->poly[4] = src->poly[4]; | |
187 dest->poly[5] = src->poly[5]; | |
188 if (bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2)
== NULL) return 0; | |
189 if (bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2)
== NULL) return 0; | |
190 for (i = dest->a.top; i < dest->a.dmax; i++) dest->a.d[i] = 0; | |
191 for (i = dest->b.top; i < dest->b.dmax; i++) dest->b.d[i] = 0; | |
192 return 1; | |
193 } | |
194 | |
195 | |
196 /* Set the curve parameters of an EC_GROUP structure. */ | |
197 int ec_GF2m_simple_group_set_curve(EC_GROUP *group, | |
198 const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) | |
199 { | |
200 int ret = 0, i; | |
201 | |
202 /* group->field */ | |
203 if (!BN_copy(&group->field, p)) goto err; | |
204 i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1; | |
205 if ((i != 5) && (i != 3)) | |
206 { | |
207 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIEL
D); | |
208 goto err; | |
209 } | |
210 | |
211 /* group->a */ | |
212 if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) goto err; | |
213 if(bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2
) == NULL) goto err; | |
214 for (i = group->a.top; i < group->a.dmax; i++) group->a.d[i] = 0; | |
215 | |
216 /* group->b */ | |
217 if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) goto err; | |
218 if(bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2
) == NULL) goto err; | |
219 for (i = group->b.top; i < group->b.dmax; i++) group->b.d[i] = 0; | |
220 | |
221 ret = 1; | |
222 err: | |
223 return ret; | |
224 } | |
225 | |
226 | |
227 /* Get the curve parameters of an EC_GROUP structure. | |
228 * If p, a, or b are NULL then there values will not be set but the method will
return with success. | |
229 */ | |
230 int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
BIGNUM *b, BN_CTX *ctx) | |
231 { | |
232 int ret = 0; | |
233 | |
234 if (p != NULL) | |
235 { | |
236 if (!BN_copy(p, &group->field)) return 0; | |
237 } | |
238 | |
239 if (a != NULL) | |
240 { | |
241 if (!BN_copy(a, &group->a)) goto err; | |
242 } | |
243 | |
244 if (b != NULL) | |
245 { | |
246 if (!BN_copy(b, &group->b)) goto err; | |
247 } | |
248 | |
249 ret = 1; | |
250 | |
251 err: | |
252 return ret; | |
253 } | |
254 | |
255 | |
256 /* Gets the degree of the field. For a curve over GF(2^m) this is the value m.
*/ | |
257 int ec_GF2m_simple_group_get_degree(const EC_GROUP *group) | |
258 { | |
259 return BN_num_bits(&group->field)-1; | |
260 } | |
261 | |
262 | |
263 /* Checks the discriminant of the curve. | |
264 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) | |
265 */ | |
266 int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) | |
267 { | |
268 int ret = 0; | |
269 BIGNUM *b; | |
270 BN_CTX *new_ctx = NULL; | |
271 | |
272 if (ctx == NULL) | |
273 { | |
274 ctx = new_ctx = BN_CTX_new(); | |
275 if (ctx == NULL) | |
276 { | |
277 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_
R_MALLOC_FAILURE); | |
278 goto err; | |
279 } | |
280 } | |
281 BN_CTX_start(ctx); | |
282 b = BN_CTX_get(ctx); | |
283 if (b == NULL) goto err; | |
284 | |
285 if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) goto err; | |
286 | |
287 /* check the discriminant: | |
288 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) | |
289 */ | |
290 if (BN_is_zero(b)) goto err; | |
291 | |
292 ret = 1; | |
293 | |
294 err: | |
295 if (ctx != NULL) | |
296 BN_CTX_end(ctx); | |
297 if (new_ctx != NULL) | |
298 BN_CTX_free(new_ctx); | |
299 return ret; | |
300 } | |
301 | |
302 | |
303 /* Initializes an EC_POINT. */ | |
304 int ec_GF2m_simple_point_init(EC_POINT *point) | |
305 { | |
306 BN_init(&point->X); | |
307 BN_init(&point->Y); | |
308 BN_init(&point->Z); | |
309 return 1; | |
310 } | |
311 | |
312 | |
313 /* Frees an EC_POINT. */ | |
314 void ec_GF2m_simple_point_finish(EC_POINT *point) | |
315 { | |
316 BN_free(&point->X); | |
317 BN_free(&point->Y); | |
318 BN_free(&point->Z); | |
319 } | |
320 | |
321 | |
322 /* Clears and frees an EC_POINT. */ | |
323 void ec_GF2m_simple_point_clear_finish(EC_POINT *point) | |
324 { | |
325 BN_clear_free(&point->X); | |
326 BN_clear_free(&point->Y); | |
327 BN_clear_free(&point->Z); | |
328 point->Z_is_one = 0; | |
329 } | |
330 | |
331 | |
332 /* Copy the contents of one EC_POINT into another. Assumes dest is initialized.
*/ | |
333 int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src) | |
334 { | |
335 if (!BN_copy(&dest->X, &src->X)) return 0; | |
336 if (!BN_copy(&dest->Y, &src->Y)) return 0; | |
337 if (!BN_copy(&dest->Z, &src->Z)) return 0; | |
338 dest->Z_is_one = src->Z_is_one; | |
339 | |
340 return 1; | |
341 } | |
342 | |
343 | |
344 /* Set an EC_POINT to the point at infinity. | |
345 * A point at infinity is represented by having Z=0. | |
346 */ | |
347 int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) | |
348 { | |
349 point->Z_is_one = 0; | |
350 BN_zero(&point->Z); | |
351 return 1; | |
352 } | |
353 | |
354 | |
355 /* Set the coordinates of an EC_POINT using affine coordinates. | |
356 * Note that the simple implementation only uses affine coordinates. | |
357 */ | |
358 int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT
*point, | |
359 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) | |
360 { | |
361 int ret = 0; | |
362 if (x == NULL || y == NULL) | |
363 { | |
364 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PA
SSED_NULL_PARAMETER); | |
365 return 0; | |
366 } | |
367 | |
368 if (!BN_copy(&point->X, x)) goto err; | |
369 BN_set_negative(&point->X, 0); | |
370 if (!BN_copy(&point->Y, y)) goto err; | |
371 BN_set_negative(&point->Y, 0); | |
372 if (!BN_copy(&point->Z, BN_value_one())) goto err; | |
373 BN_set_negative(&point->Z, 0); | |
374 point->Z_is_one = 1; | |
375 ret = 1; | |
376 | |
377 err: | |
378 return ret; | |
379 } | |
380 | |
381 | |
382 /* Gets the affine coordinates of an EC_POINT. | |
383 * Note that the simple implementation only uses affine coordinates. | |
384 */ | |
385 int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_
POINT *point, | |
386 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) | |
387 { | |
388 int ret = 0; | |
389 | |
390 if (EC_POINT_is_at_infinity(group, point)) | |
391 { | |
392 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POI
NT_AT_INFINITY); | |
393 return 0; | |
394 } | |
395 | |
396 if (BN_cmp(&point->Z, BN_value_one())) | |
397 { | |
398 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SH
OULD_NOT_HAVE_BEEN_CALLED); | |
399 return 0; | |
400 } | |
401 if (x != NULL) | |
402 { | |
403 if (!BN_copy(x, &point->X)) goto err; | |
404 BN_set_negative(x, 0); | |
405 } | |
406 if (y != NULL) | |
407 { | |
408 if (!BN_copy(y, &point->Y)) goto err; | |
409 BN_set_negative(y, 0); | |
410 } | |
411 ret = 1; | |
412 | |
413 err: | |
414 return ret; | |
415 } | |
416 | |
417 /* Computes a + b and stores the result in r. r could be a or b, a could be b. | |
418 * Uses algorithm A.10.2 of IEEE P1363. | |
419 */ | |
420 int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, co
nst EC_POINT *b, BN_CTX *ctx) | |
421 { | |
422 BN_CTX *new_ctx = NULL; | |
423 BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t; | |
424 int ret = 0; | |
425 | |
426 if (EC_POINT_is_at_infinity(group, a)) | |
427 { | |
428 if (!EC_POINT_copy(r, b)) return 0; | |
429 return 1; | |
430 } | |
431 | |
432 if (EC_POINT_is_at_infinity(group, b)) | |
433 { | |
434 if (!EC_POINT_copy(r, a)) return 0; | |
435 return 1; | |
436 } | |
437 | |
438 if (ctx == NULL) | |
439 { | |
440 ctx = new_ctx = BN_CTX_new(); | |
441 if (ctx == NULL) | |
442 return 0; | |
443 } | |
444 | |
445 BN_CTX_start(ctx); | |
446 x0 = BN_CTX_get(ctx); | |
447 y0 = BN_CTX_get(ctx); | |
448 x1 = BN_CTX_get(ctx); | |
449 y1 = BN_CTX_get(ctx); | |
450 x2 = BN_CTX_get(ctx); | |
451 y2 = BN_CTX_get(ctx); | |
452 s = BN_CTX_get(ctx); | |
453 t = BN_CTX_get(ctx); | |
454 if (t == NULL) goto err; | |
455 | |
456 if (a->Z_is_one) | |
457 { | |
458 if (!BN_copy(x0, &a->X)) goto err; | |
459 if (!BN_copy(y0, &a->Y)) goto err; | |
460 } | |
461 else | |
462 { | |
463 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)
) goto err; | |
464 } | |
465 if (b->Z_is_one) | |
466 { | |
467 if (!BN_copy(x1, &b->X)) goto err; | |
468 if (!BN_copy(y1, &b->Y)) goto err; | |
469 } | |
470 else | |
471 { | |
472 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)
) goto err; | |
473 } | |
474 | |
475 | |
476 if (BN_GF2m_cmp(x0, x1)) | |
477 { | |
478 if (!BN_GF2m_add(t, x0, x1)) goto err; | |
479 if (!BN_GF2m_add(s, y0, y1)) goto err; | |
480 if (!group->meth->field_div(group, s, s, t, ctx)) goto err; | |
481 if (!group->meth->field_sqr(group, x2, s, ctx)) goto err; | |
482 if (!BN_GF2m_add(x2, x2, &group->a)) goto err; | |
483 if (!BN_GF2m_add(x2, x2, s)) goto err; | |
484 if (!BN_GF2m_add(x2, x2, t)) goto err; | |
485 } | |
486 else | |
487 { | |
488 if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) | |
489 { | |
490 if (!EC_POINT_set_to_infinity(group, r)) goto err; | |
491 ret = 1; | |
492 goto err; | |
493 } | |
494 if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err; | |
495 if (!BN_GF2m_add(s, s, x1)) goto err; | |
496 | |
497 if (!group->meth->field_sqr(group, x2, s, ctx)) goto err; | |
498 if (!BN_GF2m_add(x2, x2, s)) goto err; | |
499 if (!BN_GF2m_add(x2, x2, &group->a)) goto err; | |
500 } | |
501 | |
502 if (!BN_GF2m_add(y2, x1, x2)) goto err; | |
503 if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err; | |
504 if (!BN_GF2m_add(y2, y2, x2)) goto err; | |
505 if (!BN_GF2m_add(y2, y2, y1)) goto err; | |
506 | |
507 if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto e
rr; | |
508 | |
509 ret = 1; | |
510 | |
511 err: | |
512 BN_CTX_end(ctx); | |
513 if (new_ctx != NULL) | |
514 BN_CTX_free(new_ctx); | |
515 return ret; | |
516 } | |
517 | |
518 | |
519 /* Computes 2 * a and stores the result in r. r could be a. | |
520 * Uses algorithm A.10.2 of IEEE P1363. | |
521 */ | |
522 int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN
_CTX *ctx) | |
523 { | |
524 return ec_GF2m_simple_add(group, r, a, a, ctx); | |
525 } | |
526 | |
527 | |
528 int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) | |
529 { | |
530 if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) | |
531 /* point is its own inverse */ | |
532 return 1; | |
533 | |
534 if (!EC_POINT_make_affine(group, point, ctx)) return 0; | |
535 return BN_GF2m_add(&point->Y, &point->X, &point->Y); | |
536 } | |
537 | |
538 | |
539 /* Indicates whether the given point is the point at infinity. */ | |
540 int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) | |
541 { | |
542 return BN_is_zero(&point->Z); | |
543 } | |
544 | |
545 | |
546 /* Determines whether the given EC_POINT is an actual point on the curve defined | |
547 * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation: | |
548 * y^2 + x*y = x^3 + a*x^2 + b. | |
549 */ | |
550 int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_
CTX *ctx) | |
551 { | |
552 int ret = -1; | |
553 BN_CTX *new_ctx = NULL; | |
554 BIGNUM *lh, *y2; | |
555 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNU
M *, BN_CTX *); | |
556 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); | |
557 | |
558 if (EC_POINT_is_at_infinity(group, point)) | |
559 return 1; | |
560 | |
561 field_mul = group->meth->field_mul; | |
562 field_sqr = group->meth->field_sqr; | |
563 | |
564 /* only support affine coordinates */ | |
565 if (!point->Z_is_one) return -1; | |
566 | |
567 if (ctx == NULL) | |
568 { | |
569 ctx = new_ctx = BN_CTX_new(); | |
570 if (ctx == NULL) | |
571 return -1; | |
572 } | |
573 | |
574 BN_CTX_start(ctx); | |
575 y2 = BN_CTX_get(ctx); | |
576 lh = BN_CTX_get(ctx); | |
577 if (lh == NULL) goto err; | |
578 | |
579 /* We have a curve defined by a Weierstrass equation | |
580 * y^2 + x*y = x^3 + a*x^2 + b. | |
581 * <=> x^3 + a*x^2 + x*y + b + y^2 = 0 | |
582 * <=> ((x + a) * x + y ) * x + b + y^2 = 0 | |
583 */ | |
584 if (!BN_GF2m_add(lh, &point->X, &group->a)) goto err; | |
585 if (!field_mul(group, lh, lh, &point->X, ctx)) goto err; | |
586 if (!BN_GF2m_add(lh, lh, &point->Y)) goto err; | |
587 if (!field_mul(group, lh, lh, &point->X, ctx)) goto err; | |
588 if (!BN_GF2m_add(lh, lh, &group->b)) goto err; | |
589 if (!field_sqr(group, y2, &point->Y, ctx)) goto err; | |
590 if (!BN_GF2m_add(lh, lh, y2)) goto err; | |
591 ret = BN_is_zero(lh); | |
592 err: | |
593 if (ctx) BN_CTX_end(ctx); | |
594 if (new_ctx) BN_CTX_free(new_ctx); | |
595 return ret; | |
596 } | |
597 | |
598 | |
599 /* Indicates whether two points are equal. | |
600 * Return values: | |
601 * -1 error | |
602 * 0 equal (in affine coordinates) | |
603 * 1 not equal | |
604 */ | |
605 int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT
*b, BN_CTX *ctx) | |
606 { | |
607 BIGNUM *aX, *aY, *bX, *bY; | |
608 BN_CTX *new_ctx = NULL; | |
609 int ret = -1; | |
610 | |
611 if (EC_POINT_is_at_infinity(group, a)) | |
612 { | |
613 return EC_POINT_is_at_infinity(group, b) ? 0 : 1; | |
614 } | |
615 | |
616 if (EC_POINT_is_at_infinity(group, b)) | |
617 return 1; | |
618 | |
619 if (a->Z_is_one && b->Z_is_one) | |
620 { | |
621 return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0
) ? 0 : 1; | |
622 } | |
623 | |
624 if (ctx == NULL) | |
625 { | |
626 ctx = new_ctx = BN_CTX_new(); | |
627 if (ctx == NULL) | |
628 return -1; | |
629 } | |
630 | |
631 BN_CTX_start(ctx); | |
632 aX = BN_CTX_get(ctx); | |
633 aY = BN_CTX_get(ctx); | |
634 bX = BN_CTX_get(ctx); | |
635 bY = BN_CTX_get(ctx); | |
636 if (bY == NULL) goto err; | |
637 | |
638 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) goto e
rr; | |
639 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) goto e
rr; | |
640 ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1; | |
641 | |
642 err: | |
643 if (ctx) BN_CTX_end(ctx); | |
644 if (new_ctx) BN_CTX_free(new_ctx); | |
645 return ret; | |
646 } | |
647 | |
648 | |
649 /* Forces the given EC_POINT to internally use affine coordinates. */ | |
650 int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *c
tx) | |
651 { | |
652 BN_CTX *new_ctx = NULL; | |
653 BIGNUM *x, *y; | |
654 int ret = 0; | |
655 | |
656 if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) | |
657 return 1; | |
658 | |
659 if (ctx == NULL) | |
660 { | |
661 ctx = new_ctx = BN_CTX_new(); | |
662 if (ctx == NULL) | |
663 return 0; | |
664 } | |
665 | |
666 BN_CTX_start(ctx); | |
667 x = BN_CTX_get(ctx); | |
668 y = BN_CTX_get(ctx); | |
669 if (y == NULL) goto err; | |
670 | |
671 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto
err; | |
672 if (!BN_copy(&point->X, x)) goto err; | |
673 if (!BN_copy(&point->Y, y)) goto err; | |
674 if (!BN_one(&point->Z)) goto err; | |
675 | |
676 ret = 1; | |
677 | |
678 err: | |
679 if (ctx) BN_CTX_end(ctx); | |
680 if (new_ctx) BN_CTX_free(new_ctx); | |
681 return ret; | |
682 } | |
683 | |
684 | |
685 /* Forces each of the EC_POINTs in the given array to use affine coordinates. */ | |
686 int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POIN
T *points[], BN_CTX *ctx) | |
687 { | |
688 size_t i; | |
689 | |
690 for (i = 0; i < num; i++) | |
691 { | |
692 if (!group->meth->make_affine(group, points[i], ctx)) return 0; | |
693 } | |
694 | |
695 return 1; | |
696 } | |
697 | |
698 | |
699 /* Wrapper to simple binary polynomial field multiplication implementation. */ | |
700 int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx) | |
701 { | |
702 return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx); | |
703 } | |
704 | |
705 | |
706 /* Wrapper to simple binary polynomial field squaring implementation. */ | |
707 int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
BN_CTX *ctx) | |
708 { | |
709 return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx); | |
710 } | |
711 | |
712 | |
713 /* Wrapper to simple binary polynomial field division implementation. */ | |
714 int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx) | |
715 { | |
716 return BN_GF2m_mod_div(r, a, b, &group->field, ctx); | |
717 } | |
718 | |
719 #endif | |
OLD | NEW |