]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/ec/ecp_smpl.c
Reorganise ECC code for inclusion in FIPS module.
[thirdparty/openssl.git] / crypto / ec / ecp_smpl.c
1 /* crypto/ec/ecp_smpl.c */
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 #define OPENSSL_FIPSAPI
66
67 #include <openssl/err.h>
68 #include <openssl/symhacks.h>
69
70 #include "ec_lcl.h"
71
72 const EC_METHOD *EC_GFp_simple_method(void)
73 {
74 static const EC_METHOD ret = {
75 EC_FLAGS_DEFAULT_OCT,
76 NID_X9_62_prime_field,
77 ec_GFp_simple_group_init,
78 ec_GFp_simple_group_finish,
79 ec_GFp_simple_group_clear_finish,
80 ec_GFp_simple_group_copy,
81 ec_GFp_simple_group_set_curve,
82 ec_GFp_simple_group_get_curve,
83 ec_GFp_simple_group_get_degree,
84 ec_GFp_simple_group_check_discriminant,
85 ec_GFp_simple_point_init,
86 ec_GFp_simple_point_finish,
87 ec_GFp_simple_point_clear_finish,
88 ec_GFp_simple_point_copy,
89 ec_GFp_simple_point_set_to_infinity,
90 ec_GFp_simple_set_Jprojective_coordinates_GFp,
91 ec_GFp_simple_get_Jprojective_coordinates_GFp,
92 ec_GFp_simple_point_set_affine_coordinates,
93 ec_GFp_simple_point_get_affine_coordinates,
94 0,0,0,
95 ec_GFp_simple_add,
96 ec_GFp_simple_dbl,
97 ec_GFp_simple_invert,
98 ec_GFp_simple_is_at_infinity,
99 ec_GFp_simple_is_on_curve,
100 ec_GFp_simple_cmp,
101 ec_GFp_simple_make_affine,
102 ec_GFp_simple_points_make_affine,
103 0 /* mul */,
104 0 /* precompute_mult */,
105 0 /* have_precompute_mult */,
106 ec_GFp_simple_field_mul,
107 ec_GFp_simple_field_sqr,
108 0 /* field_div */,
109 0 /* field_encode */,
110 0 /* field_decode */,
111 0 /* field_set_to_one */ };
112
113 return &ret;
114 }
115
116
117 /* Most method functions in this file are designed to work with
118 * non-trivial representations of field elements if necessary
119 * (see ecp_mont.c): while standard modular addition and subtraction
120 * are used, the field_mul and field_sqr methods will be used for
121 * multiplication, and field_encode and field_decode (if defined)
122 * will be used for converting between representations.
123
124 * Functions ec_GFp_simple_points_make_affine() and
125 * ec_GFp_simple_point_get_affine_coordinates() specifically assume
126 * that if a non-trivial representation is used, it is a Montgomery
127 * representation (i.e. 'encoding' means multiplying by some factor R).
128 */
129
130
131 int ec_GFp_simple_group_init(EC_GROUP *group)
132 {
133 BN_init(&group->field);
134 BN_init(&group->a);
135 BN_init(&group->b);
136 group->a_is_minus3 = 0;
137 return 1;
138 }
139
140
141 void ec_GFp_simple_group_finish(EC_GROUP *group)
142 {
143 BN_free(&group->field);
144 BN_free(&group->a);
145 BN_free(&group->b);
146 }
147
148
149 void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
150 {
151 BN_clear_free(&group->field);
152 BN_clear_free(&group->a);
153 BN_clear_free(&group->b);
154 }
155
156
157 int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
158 {
159 if (!BN_copy(&dest->field, &src->field)) return 0;
160 if (!BN_copy(&dest->a, &src->a)) return 0;
161 if (!BN_copy(&dest->b, &src->b)) return 0;
162
163 dest->a_is_minus3 = src->a_is_minus3;
164
165 return 1;
166 }
167
168
169 int ec_GFp_simple_group_set_curve(EC_GROUP *group,
170 const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
171 {
172 int ret = 0;
173 BN_CTX *new_ctx = NULL;
174 BIGNUM *tmp_a;
175
176 /* p must be a prime > 3 */
177 if (BN_num_bits(p) <= 2 || !BN_is_odd(p))
178 {
179 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
180 return 0;
181 }
182
183 if (ctx == NULL)
184 {
185 ctx = new_ctx = BN_CTX_new();
186 if (ctx == NULL)
187 return 0;
188 }
189
190 BN_CTX_start(ctx);
191 tmp_a = BN_CTX_get(ctx);
192 if (tmp_a == NULL) goto err;
193
194 /* group->field */
195 if (!BN_copy(&group->field, p)) goto err;
196 BN_set_negative(&group->field, 0);
197
198 /* group->a */
199 if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
200 if (group->meth->field_encode)
201 { if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) goto err; }
202 else
203 if (!BN_copy(&group->a, tmp_a)) goto err;
204
205 /* group->b */
206 if (!BN_nnmod(&group->b, b, p, ctx)) goto err;
207 if (group->meth->field_encode)
208 if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) goto err;
209
210 /* group->a_is_minus3 */
211 if (!BN_add_word(tmp_a, 3)) goto err;
212 group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
213
214 ret = 1;
215
216 err:
217 BN_CTX_end(ctx);
218 if (new_ctx != NULL)
219 BN_CTX_free(new_ctx);
220 return ret;
221 }
222
223
224 int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
225 {
226 int ret = 0;
227 BN_CTX *new_ctx = NULL;
228
229 if (p != NULL)
230 {
231 if (!BN_copy(p, &group->field)) return 0;
232 }
233
234 if (a != NULL || b != NULL)
235 {
236 if (group->meth->field_decode)
237 {
238 if (ctx == NULL)
239 {
240 ctx = new_ctx = BN_CTX_new();
241 if (ctx == NULL)
242 return 0;
243 }
244 if (a != NULL)
245 {
246 if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
247 }
248 if (b != NULL)
249 {
250 if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
251 }
252 }
253 else
254 {
255 if (a != NULL)
256 {
257 if (!BN_copy(a, &group->a)) goto err;
258 }
259 if (b != NULL)
260 {
261 if (!BN_copy(b, &group->b)) goto err;
262 }
263 }
264 }
265
266 ret = 1;
267
268 err:
269 if (new_ctx)
270 BN_CTX_free(new_ctx);
271 return ret;
272 }
273
274
275 int ec_GFp_simple_group_get_degree(const EC_GROUP *group)
276 {
277 return BN_num_bits(&group->field);
278 }
279
280
281 int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
282 {
283 int ret = 0;
284 BIGNUM *a,*b,*order,*tmp_1,*tmp_2;
285 const BIGNUM *p = &group->field;
286 BN_CTX *new_ctx = NULL;
287
288 if (ctx == NULL)
289 {
290 ctx = new_ctx = BN_CTX_new();
291 if (ctx == NULL)
292 {
293 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
294 goto err;
295 }
296 }
297 BN_CTX_start(ctx);
298 a = BN_CTX_get(ctx);
299 b = BN_CTX_get(ctx);
300 tmp_1 = BN_CTX_get(ctx);
301 tmp_2 = BN_CTX_get(ctx);
302 order = BN_CTX_get(ctx);
303 if (order == NULL) goto err;
304
305 if (group->meth->field_decode)
306 {
307 if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
308 if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
309 }
310 else
311 {
312 if (!BN_copy(a, &group->a)) goto err;
313 if (!BN_copy(b, &group->b)) goto err;
314 }
315
316 /* check the discriminant:
317 * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
318 * 0 =< a, b < p */
319 if (BN_is_zero(a))
320 {
321 if (BN_is_zero(b)) goto err;
322 }
323 else if (!BN_is_zero(b))
324 {
325 if (!BN_mod_sqr(tmp_1, a, p, ctx)) goto err;
326 if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) goto err;
327 if (!BN_lshift(tmp_1, tmp_2, 2)) goto err;
328 /* tmp_1 = 4*a^3 */
329
330 if (!BN_mod_sqr(tmp_2, b, p, ctx)) goto err;
331 if (!BN_mul_word(tmp_2, 27)) goto err;
332 /* tmp_2 = 27*b^2 */
333
334 if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) goto err;
335 if (BN_is_zero(a)) goto err;
336 }
337 ret = 1;
338
339 err:
340 if (ctx != NULL)
341 BN_CTX_end(ctx);
342 if (new_ctx != NULL)
343 BN_CTX_free(new_ctx);
344 return ret;
345 }
346
347
348 int ec_GFp_simple_point_init(EC_POINT *point)
349 {
350 BN_init(&point->X);
351 BN_init(&point->Y);
352 BN_init(&point->Z);
353 point->Z_is_one = 0;
354
355 return 1;
356 }
357
358
359 void ec_GFp_simple_point_finish(EC_POINT *point)
360 {
361 BN_free(&point->X);
362 BN_free(&point->Y);
363 BN_free(&point->Z);
364 }
365
366
367 void ec_GFp_simple_point_clear_finish(EC_POINT *point)
368 {
369 BN_clear_free(&point->X);
370 BN_clear_free(&point->Y);
371 BN_clear_free(&point->Z);
372 point->Z_is_one = 0;
373 }
374
375
376 int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
377 {
378 if (!BN_copy(&dest->X, &src->X)) return 0;
379 if (!BN_copy(&dest->Y, &src->Y)) return 0;
380 if (!BN_copy(&dest->Z, &src->Z)) return 0;
381 dest->Z_is_one = src->Z_is_one;
382
383 return 1;
384 }
385
386
387 int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
388 {
389 point->Z_is_one = 0;
390 BN_zero(&point->Z);
391 return 1;
392 }
393
394
395 int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
396 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
397 {
398 BN_CTX *new_ctx = NULL;
399 int ret = 0;
400
401 if (ctx == NULL)
402 {
403 ctx = new_ctx = BN_CTX_new();
404 if (ctx == NULL)
405 return 0;
406 }
407
408 if (x != NULL)
409 {
410 if (!BN_nnmod(&point->X, x, &group->field, ctx)) goto err;
411 if (group->meth->field_encode)
412 {
413 if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) goto err;
414 }
415 }
416
417 if (y != NULL)
418 {
419 if (!BN_nnmod(&point->Y, y, &group->field, ctx)) goto err;
420 if (group->meth->field_encode)
421 {
422 if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) goto err;
423 }
424 }
425
426 if (z != NULL)
427 {
428 int Z_is_one;
429
430 if (!BN_nnmod(&point->Z, z, &group->field, ctx)) goto err;
431 Z_is_one = BN_is_one(&point->Z);
432 if (group->meth->field_encode)
433 {
434 if (Z_is_one && (group->meth->field_set_to_one != 0))
435 {
436 if (!group->meth->field_set_to_one(group, &point->Z, ctx)) goto err;
437 }
438 else
439 {
440 if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) goto err;
441 }
442 }
443 point->Z_is_one = Z_is_one;
444 }
445
446 ret = 1;
447
448 err:
449 if (new_ctx != NULL)
450 BN_CTX_free(new_ctx);
451 return ret;
452 }
453
454
455 int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
456 BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
457 {
458 BN_CTX *new_ctx = NULL;
459 int ret = 0;
460
461 if (group->meth->field_decode != 0)
462 {
463 if (ctx == NULL)
464 {
465 ctx = new_ctx = BN_CTX_new();
466 if (ctx == NULL)
467 return 0;
468 }
469
470 if (x != NULL)
471 {
472 if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
473 }
474 if (y != NULL)
475 {
476 if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
477 }
478 if (z != NULL)
479 {
480 if (!group->meth->field_decode(group, z, &point->Z, ctx)) goto err;
481 }
482 }
483 else
484 {
485 if (x != NULL)
486 {
487 if (!BN_copy(x, &point->X)) goto err;
488 }
489 if (y != NULL)
490 {
491 if (!BN_copy(y, &point->Y)) goto err;
492 }
493 if (z != NULL)
494 {
495 if (!BN_copy(z, &point->Z)) goto err;
496 }
497 }
498
499 ret = 1;
500
501 err:
502 if (new_ctx != NULL)
503 BN_CTX_free(new_ctx);
504 return ret;
505 }
506
507
508 int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
509 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
510 {
511 if (x == NULL || y == NULL)
512 {
513 /* unlike for projective coordinates, we do not tolerate this */
514 ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
515 return 0;
516 }
517
518 return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx);
519 }
520
521
522 int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
523 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
524 {
525 BN_CTX *new_ctx = NULL;
526 BIGNUM *Z, *Z_1, *Z_2, *Z_3;
527 const BIGNUM *Z_;
528 int ret = 0;
529
530 if (EC_POINT_is_at_infinity(group, point))
531 {
532 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
533 return 0;
534 }
535
536 if (ctx == NULL)
537 {
538 ctx = new_ctx = BN_CTX_new();
539 if (ctx == NULL)
540 return 0;
541 }
542
543 BN_CTX_start(ctx);
544 Z = BN_CTX_get(ctx);
545 Z_1 = BN_CTX_get(ctx);
546 Z_2 = BN_CTX_get(ctx);
547 Z_3 = BN_CTX_get(ctx);
548 if (Z_3 == NULL) goto err;
549
550 /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */
551
552 if (group->meth->field_decode)
553 {
554 if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err;
555 Z_ = Z;
556 }
557 else
558 {
559 Z_ = &point->Z;
560 }
561
562 if (BN_is_one(Z_))
563 {
564 if (group->meth->field_decode)
565 {
566 if (x != NULL)
567 {
568 if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
569 }
570 if (y != NULL)
571 {
572 if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
573 }
574 }
575 else
576 {
577 if (x != NULL)
578 {
579 if (!BN_copy(x, &point->X)) goto err;
580 }
581 if (y != NULL)
582 {
583 if (!BN_copy(y, &point->Y)) goto err;
584 }
585 }
586 }
587 else
588 {
589 if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx))
590 {
591 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
592 goto err;
593 }
594
595 if (group->meth->field_encode == 0)
596 {
597 /* field_sqr works on standard representation */
598 if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) goto err;
599 }
600 else
601 {
602 if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err;
603 }
604
605 if (x != NULL)
606 {
607 /* in the Montgomery case, field_mul will cancel out Montgomery factor in X: */
608 if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) goto err;
609 }
610
611 if (y != NULL)
612 {
613 if (group->meth->field_encode == 0)
614 {
615 /* field_mul works on standard representation */
616 if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err;
617 }
618 else
619 {
620 if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
621 }
622
623 /* in the Montgomery case, field_mul will cancel out Montgomery factor in Y: */
624 if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) goto err;
625 }
626 }
627
628 ret = 1;
629
630 err:
631 BN_CTX_end(ctx);
632 if (new_ctx != NULL)
633 BN_CTX_free(new_ctx);
634 return ret;
635 }
636
637 int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
638 {
639 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
640 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
641 const BIGNUM *p;
642 BN_CTX *new_ctx = NULL;
643 BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
644 int ret = 0;
645
646 if (a == b)
647 return EC_POINT_dbl(group, r, a, ctx);
648 if (EC_POINT_is_at_infinity(group, a))
649 return EC_POINT_copy(r, b);
650 if (EC_POINT_is_at_infinity(group, b))
651 return EC_POINT_copy(r, a);
652
653 field_mul = group->meth->field_mul;
654 field_sqr = group->meth->field_sqr;
655 p = &group->field;
656
657 if (ctx == NULL)
658 {
659 ctx = new_ctx = BN_CTX_new();
660 if (ctx == NULL)
661 return 0;
662 }
663
664 BN_CTX_start(ctx);
665 n0 = BN_CTX_get(ctx);
666 n1 = BN_CTX_get(ctx);
667 n2 = BN_CTX_get(ctx);
668 n3 = BN_CTX_get(ctx);
669 n4 = BN_CTX_get(ctx);
670 n5 = BN_CTX_get(ctx);
671 n6 = BN_CTX_get(ctx);
672 if (n6 == NULL) goto end;
673
674 /* Note that in this function we must not read components of 'a' or 'b'
675 * once we have written the corresponding components of 'r'.
676 * ('r' might be one of 'a' or 'b'.)
677 */
678
679 /* n1, n2 */
680 if (b->Z_is_one)
681 {
682 if (!BN_copy(n1, &a->X)) goto end;
683 if (!BN_copy(n2, &a->Y)) goto end;
684 /* n1 = X_a */
685 /* n2 = Y_a */
686 }
687 else
688 {
689 if (!field_sqr(group, n0, &b->Z, ctx)) goto end;
690 if (!field_mul(group, n1, &a->X, n0, ctx)) goto end;
691 /* n1 = X_a * Z_b^2 */
692
693 if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end;
694 if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end;
695 /* n2 = Y_a * Z_b^3 */
696 }
697
698 /* n3, n4 */
699 if (a->Z_is_one)
700 {
701 if (!BN_copy(n3, &b->X)) goto end;
702 if (!BN_copy(n4, &b->Y)) goto end;
703 /* n3 = X_b */
704 /* n4 = Y_b */
705 }
706 else
707 {
708 if (!field_sqr(group, n0, &a->Z, ctx)) goto end;
709 if (!field_mul(group, n3, &b->X, n0, ctx)) goto end;
710 /* n3 = X_b * Z_a^2 */
711
712 if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end;
713 if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end;
714 /* n4 = Y_b * Z_a^3 */
715 }
716
717 /* n5, n6 */
718 if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end;
719 if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end;
720 /* n5 = n1 - n3 */
721 /* n6 = n2 - n4 */
722
723 if (BN_is_zero(n5))
724 {
725 if (BN_is_zero(n6))
726 {
727 /* a is the same point as b */
728 BN_CTX_end(ctx);
729 ret = EC_POINT_dbl(group, r, a, ctx);
730 ctx = NULL;
731 goto end;
732 }
733 else
734 {
735 /* a is the inverse of b */
736 BN_zero(&r->Z);
737 r->Z_is_one = 0;
738 ret = 1;
739 goto end;
740 }
741 }
742
743 /* 'n7', 'n8' */
744 if (!BN_mod_add_quick(n1, n1, n3, p)) goto end;
745 if (!BN_mod_add_quick(n2, n2, n4, p)) goto end;
746 /* 'n7' = n1 + n3 */
747 /* 'n8' = n2 + n4 */
748
749 /* Z_r */
750 if (a->Z_is_one && b->Z_is_one)
751 {
752 if (!BN_copy(&r->Z, n5)) goto end;
753 }
754 else
755 {
756 if (a->Z_is_one)
757 { if (!BN_copy(n0, &b->Z)) goto end; }
758 else if (b->Z_is_one)
759 { if (!BN_copy(n0, &a->Z)) goto end; }
760 else
761 { if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; }
762 if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end;
763 }
764 r->Z_is_one = 0;
765 /* Z_r = Z_a * Z_b * n5 */
766
767 /* X_r */
768 if (!field_sqr(group, n0, n6, ctx)) goto end;
769 if (!field_sqr(group, n4, n5, ctx)) goto end;
770 if (!field_mul(group, n3, n1, n4, ctx)) goto end;
771 if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end;
772 /* X_r = n6^2 - n5^2 * 'n7' */
773
774 /* 'n9' */
775 if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end;
776 if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end;
777 /* n9 = n5^2 * 'n7' - 2 * X_r */
778
779 /* Y_r */
780 if (!field_mul(group, n0, n0, n6, ctx)) goto end;
781 if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */
782 if (!field_mul(group, n1, n2, n5, ctx)) goto end;
783 if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end;
784 if (BN_is_odd(n0))
785 if (!BN_add(n0, n0, p)) goto end;
786 /* now 0 <= n0 < 2*p, and n0 is even */
787 if (!BN_rshift1(&r->Y, n0)) goto end;
788 /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
789
790 ret = 1;
791
792 end:
793 if (ctx) /* otherwise we already called BN_CTX_end */
794 BN_CTX_end(ctx);
795 if (new_ctx != NULL)
796 BN_CTX_free(new_ctx);
797 return ret;
798 }
799
800
801 int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
802 {
803 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
804 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
805 const BIGNUM *p;
806 BN_CTX *new_ctx = NULL;
807 BIGNUM *n0, *n1, *n2, *n3;
808 int ret = 0;
809
810 if (EC_POINT_is_at_infinity(group, a))
811 {
812 BN_zero(&r->Z);
813 r->Z_is_one = 0;
814 return 1;
815 }
816
817 field_mul = group->meth->field_mul;
818 field_sqr = group->meth->field_sqr;
819 p = &group->field;
820
821 if (ctx == NULL)
822 {
823 ctx = new_ctx = BN_CTX_new();
824 if (ctx == NULL)
825 return 0;
826 }
827
828 BN_CTX_start(ctx);
829 n0 = BN_CTX_get(ctx);
830 n1 = BN_CTX_get(ctx);
831 n2 = BN_CTX_get(ctx);
832 n3 = BN_CTX_get(ctx);
833 if (n3 == NULL) goto err;
834
835 /* Note that in this function we must not read components of 'a'
836 * once we have written the corresponding components of 'r'.
837 * ('r' might the same as 'a'.)
838 */
839
840 /* n1 */
841 if (a->Z_is_one)
842 {
843 if (!field_sqr(group, n0, &a->X, ctx)) goto err;
844 if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
845 if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
846 if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err;
847 /* n1 = 3 * X_a^2 + a_curve */
848 }
849 else if (group->a_is_minus3)
850 {
851 if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
852 if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err;
853 if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err;
854 if (!field_mul(group, n1, n0, n2, ctx)) goto err;
855 if (!BN_mod_lshift1_quick(n0, n1, p)) goto err;
856 if (!BN_mod_add_quick(n1, n0, n1, p)) goto err;
857 /* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
858 * = 3 * X_a^2 - 3 * Z_a^4 */
859 }
860 else
861 {
862 if (!field_sqr(group, n0, &a->X, ctx)) goto err;
863 if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
864 if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
865 if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
866 if (!field_sqr(group, n1, n1, ctx)) goto err;
867 if (!field_mul(group, n1, n1, &group->a, ctx)) goto err;
868 if (!BN_mod_add_quick(n1, n1, n0, p)) goto err;
869 /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
870 }
871
872 /* Z_r */
873 if (a->Z_is_one)
874 {
875 if (!BN_copy(n0, &a->Y)) goto err;
876 }
877 else
878 {
879 if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err;
880 }
881 if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err;
882 r->Z_is_one = 0;
883 /* Z_r = 2 * Y_a * Z_a */
884
885 /* n2 */
886 if (!field_sqr(group, n3, &a->Y, ctx)) goto err;
887 if (!field_mul(group, n2, &a->X, n3, ctx)) goto err;
888 if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err;
889 /* n2 = 4 * X_a * Y_a^2 */
890
891 /* X_r */
892 if (!BN_mod_lshift1_quick(n0, n2, p)) goto err;
893 if (!field_sqr(group, &r->X, n1, ctx)) goto err;
894 if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err;
895 /* X_r = n1^2 - 2 * n2 */
896
897 /* n3 */
898 if (!field_sqr(group, n0, n3, ctx)) goto err;
899 if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err;
900 /* n3 = 8 * Y_a^4 */
901
902 /* Y_r */
903 if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err;
904 if (!field_mul(group, n0, n1, n0, ctx)) goto err;
905 if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err;
906 /* Y_r = n1 * (n2 - X_r) - n3 */
907
908 ret = 1;
909
910 err:
911 BN_CTX_end(ctx);
912 if (new_ctx != NULL)
913 BN_CTX_free(new_ctx);
914 return ret;
915 }
916
917
918 int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
919 {
920 if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
921 /* point is its own inverse */
922 return 1;
923
924 return BN_usub(&point->Y, &group->field, &point->Y);
925 }
926
927
928 int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
929 {
930 return BN_is_zero(&point->Z);
931 }
932
933
934 int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
935 {
936 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
937 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
938 const BIGNUM *p;
939 BN_CTX *new_ctx = NULL;
940 BIGNUM *rh, *tmp, *Z4, *Z6;
941 int ret = -1;
942
943 if (EC_POINT_is_at_infinity(group, point))
944 return 1;
945
946 field_mul = group->meth->field_mul;
947 field_sqr = group->meth->field_sqr;
948 p = &group->field;
949
950 if (ctx == NULL)
951 {
952 ctx = new_ctx = BN_CTX_new();
953 if (ctx == NULL)
954 return -1;
955 }
956
957 BN_CTX_start(ctx);
958 rh = BN_CTX_get(ctx);
959 tmp = BN_CTX_get(ctx);
960 Z4 = BN_CTX_get(ctx);
961 Z6 = BN_CTX_get(ctx);
962 if (Z6 == NULL) goto err;
963
964 /* We have a curve defined by a Weierstrass equation
965 * y^2 = x^3 + a*x + b.
966 * The point to consider is given in Jacobian projective coordinates
967 * where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3).
968 * Substituting this and multiplying by Z^6 transforms the above equation into
969 * Y^2 = X^3 + a*X*Z^4 + b*Z^6.
970 * To test this, we add up the right-hand side in 'rh'.
971 */
972
973 /* rh := X^2 */
974 if (!field_sqr(group, rh, &point->X, ctx)) goto err;
975
976 if (!point->Z_is_one)
977 {
978 if (!field_sqr(group, tmp, &point->Z, ctx)) goto err;
979 if (!field_sqr(group, Z4, tmp, ctx)) goto err;
980 if (!field_mul(group, Z6, Z4, tmp, ctx)) goto err;
981
982 /* rh := (rh + a*Z^4)*X */
983 if (group->a_is_minus3)
984 {
985 if (!BN_mod_lshift1_quick(tmp, Z4, p)) goto err;
986 if (!BN_mod_add_quick(tmp, tmp, Z4, p)) goto err;
987 if (!BN_mod_sub_quick(rh, rh, tmp, p)) goto err;
988 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
989 }
990 else
991 {
992 if (!field_mul(group, tmp, Z4, &group->a, ctx)) goto err;
993 if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
994 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
995 }
996
997 /* rh := rh + b*Z^6 */
998 if (!field_mul(group, tmp, &group->b, Z6, ctx)) goto err;
999 if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
1000 }
1001 else
1002 {
1003 /* point->Z_is_one */
1004
1005 /* rh := (rh + a)*X */
1006 if (!BN_mod_add_quick(rh, rh, &group->a, p)) goto err;
1007 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1008 /* rh := rh + b */
1009 if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err;
1010 }
1011
1012 /* 'lh' := Y^2 */
1013 if (!field_sqr(group, tmp, &point->Y, ctx)) goto err;
1014
1015 ret = (0 == BN_ucmp(tmp, rh));
1016
1017 err:
1018 BN_CTX_end(ctx);
1019 if (new_ctx != NULL)
1020 BN_CTX_free(new_ctx);
1021 return ret;
1022 }
1023
1024
1025 int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
1026 {
1027 /* return values:
1028 * -1 error
1029 * 0 equal (in affine coordinates)
1030 * 1 not equal
1031 */
1032
1033 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1034 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1035 BN_CTX *new_ctx = NULL;
1036 BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
1037 const BIGNUM *tmp1_, *tmp2_;
1038 int ret = -1;
1039
1040 if (EC_POINT_is_at_infinity(group, a))
1041 {
1042 return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
1043 }
1044
1045 if (EC_POINT_is_at_infinity(group, b))
1046 return 1;
1047
1048 if (a->Z_is_one && b->Z_is_one)
1049 {
1050 return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
1051 }
1052
1053 field_mul = group->meth->field_mul;
1054 field_sqr = group->meth->field_sqr;
1055
1056 if (ctx == NULL)
1057 {
1058 ctx = new_ctx = BN_CTX_new();
1059 if (ctx == NULL)
1060 return -1;
1061 }
1062
1063 BN_CTX_start(ctx);
1064 tmp1 = BN_CTX_get(ctx);
1065 tmp2 = BN_CTX_get(ctx);
1066 Za23 = BN_CTX_get(ctx);
1067 Zb23 = BN_CTX_get(ctx);
1068 if (Zb23 == NULL) goto end;
1069
1070 /* We have to decide whether
1071 * (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
1072 * or equivalently, whether
1073 * (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
1074 */
1075
1076 if (!b->Z_is_one)
1077 {
1078 if (!field_sqr(group, Zb23, &b->Z, ctx)) goto end;
1079 if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) goto end;
1080 tmp1_ = tmp1;
1081 }
1082 else
1083 tmp1_ = &a->X;
1084 if (!a->Z_is_one)
1085 {
1086 if (!field_sqr(group, Za23, &a->Z, ctx)) goto end;
1087 if (!field_mul(group, tmp2, &b->X, Za23, ctx)) goto end;
1088 tmp2_ = tmp2;
1089 }
1090 else
1091 tmp2_ = &b->X;
1092
1093 /* compare X_a*Z_b^2 with X_b*Z_a^2 */
1094 if (BN_cmp(tmp1_, tmp2_) != 0)
1095 {
1096 ret = 1; /* points differ */
1097 goto end;
1098 }
1099
1100
1101 if (!b->Z_is_one)
1102 {
1103 if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) goto end;
1104 if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) goto end;
1105 /* tmp1_ = tmp1 */
1106 }
1107 else
1108 tmp1_ = &a->Y;
1109 if (!a->Z_is_one)
1110 {
1111 if (!field_mul(group, Za23, Za23, &a->Z, ctx)) goto end;
1112 if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) goto end;
1113 /* tmp2_ = tmp2 */
1114 }
1115 else
1116 tmp2_ = &b->Y;
1117
1118 /* compare Y_a*Z_b^3 with Y_b*Z_a^3 */
1119 if (BN_cmp(tmp1_, tmp2_) != 0)
1120 {
1121 ret = 1; /* points differ */
1122 goto end;
1123 }
1124
1125 /* points are equal */
1126 ret = 0;
1127
1128 end:
1129 BN_CTX_end(ctx);
1130 if (new_ctx != NULL)
1131 BN_CTX_free(new_ctx);
1132 return ret;
1133 }
1134
1135
1136 int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1137 {
1138 BN_CTX *new_ctx = NULL;
1139 BIGNUM *x, *y;
1140 int ret = 0;
1141
1142 if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
1143 return 1;
1144
1145 if (ctx == NULL)
1146 {
1147 ctx = new_ctx = BN_CTX_new();
1148 if (ctx == NULL)
1149 return 0;
1150 }
1151
1152 BN_CTX_start(ctx);
1153 x = BN_CTX_get(ctx);
1154 y = BN_CTX_get(ctx);
1155 if (y == NULL) goto err;
1156
1157 if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
1158 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
1159 if (!point->Z_is_one)
1160 {
1161 ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
1162 goto err;
1163 }
1164
1165 ret = 1;
1166
1167 err:
1168 BN_CTX_end(ctx);
1169 if (new_ctx != NULL)
1170 BN_CTX_free(new_ctx);
1171 return ret;
1172 }
1173
1174
1175 int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
1176 {
1177 BN_CTX *new_ctx = NULL;
1178 BIGNUM *tmp0, *tmp1;
1179 size_t pow2 = 0;
1180 BIGNUM **heap = NULL;
1181 size_t i;
1182 int ret = 0;
1183
1184 if (num == 0)
1185 return 1;
1186
1187 if (ctx == NULL)
1188 {
1189 ctx = new_ctx = BN_CTX_new();
1190 if (ctx == NULL)
1191 return 0;
1192 }
1193
1194 BN_CTX_start(ctx);
1195 tmp0 = BN_CTX_get(ctx);
1196 tmp1 = BN_CTX_get(ctx);
1197 if (tmp0 == NULL || tmp1 == NULL) goto err;
1198
1199 /* Before converting the individual points, compute inverses of all Z values.
1200 * Modular inversion is rather slow, but luckily we can do with a single
1201 * explicit inversion, plus about 3 multiplications per input value.
1202 */
1203
1204 pow2 = 1;
1205 while (num > pow2)
1206 pow2 <<= 1;
1207 /* Now pow2 is the smallest power of 2 satifsying pow2 >= num.
1208 * We need twice that. */
1209 pow2 <<= 1;
1210
1211 heap = OPENSSL_malloc(pow2 * sizeof heap[0]);
1212 if (heap == NULL) goto err;
1213
1214 /* The array is used as a binary tree, exactly as in heapsort:
1215 *
1216 * heap[1]
1217 * heap[2] heap[3]
1218 * heap[4] heap[5] heap[6] heap[7]
1219 * heap[8]heap[9] heap[10]heap[11] heap[12]heap[13] heap[14] heap[15]
1220 *
1221 * We put the Z's in the last line;
1222 * then we set each other node to the product of its two child-nodes (where
1223 * empty or 0 entries are treated as ones);
1224 * then we invert heap[1];
1225 * then we invert each other node by replacing it by the product of its
1226 * parent (after inversion) and its sibling (before inversion).
1227 */
1228 heap[0] = NULL;
1229 for (i = pow2/2 - 1; i > 0; i--)
1230 heap[i] = NULL;
1231 for (i = 0; i < num; i++)
1232 heap[pow2/2 + i] = &points[i]->Z;
1233 for (i = pow2/2 + num; i < pow2; i++)
1234 heap[i] = NULL;
1235
1236 /* set each node to the product of its children */
1237 for (i = pow2/2 - 1; i > 0; i--)
1238 {
1239 heap[i] = BN_new();
1240 if (heap[i] == NULL) goto err;
1241
1242 if (heap[2*i] != NULL)
1243 {
1244 if ((heap[2*i + 1] == NULL) || BN_is_zero(heap[2*i + 1]))
1245 {
1246 if (!BN_copy(heap[i], heap[2*i])) goto err;
1247 }
1248 else
1249 {
1250 if (BN_is_zero(heap[2*i]))
1251 {
1252 if (!BN_copy(heap[i], heap[2*i + 1])) goto err;
1253 }
1254 else
1255 {
1256 if (!group->meth->field_mul(group, heap[i],
1257 heap[2*i], heap[2*i + 1], ctx)) goto err;
1258 }
1259 }
1260 }
1261 }
1262
1263 /* invert heap[1] */
1264 if (!BN_is_zero(heap[1]))
1265 {
1266 if (!BN_mod_inverse(heap[1], heap[1], &group->field, ctx))
1267 {
1268 ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
1269 goto err;
1270 }
1271 }
1272 if (group->meth->field_encode != 0)
1273 {
1274 /* in the Montgomery case, we just turned R*H (representing H)
1275 * into 1/(R*H), but we need R*(1/H) (representing 1/H);
1276 * i.e. we have need to multiply by the Montgomery factor twice */
1277 if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
1278 if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
1279 }
1280
1281 /* set other heap[i]'s to their inverses */
1282 for (i = 2; i < pow2/2 + num; i += 2)
1283 {
1284 /* i is even */
1285 if ((heap[i + 1] != NULL) && !BN_is_zero(heap[i + 1]))
1286 {
1287 if (!group->meth->field_mul(group, tmp0, heap[i/2], heap[i + 1], ctx)) goto err;
1288 if (!group->meth->field_mul(group, tmp1, heap[i/2], heap[i], ctx)) goto err;
1289 if (!BN_copy(heap[i], tmp0)) goto err;
1290 if (!BN_copy(heap[i + 1], tmp1)) goto err;
1291 }
1292 else
1293 {
1294 if (!BN_copy(heap[i], heap[i/2])) goto err;
1295 }
1296 }
1297
1298 /* we have replaced all non-zero Z's by their inverses, now fix up all the points */
1299 for (i = 0; i < num; i++)
1300 {
1301 EC_POINT *p = points[i];
1302
1303 if (!BN_is_zero(&p->Z))
1304 {
1305 /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1) */
1306
1307 if (!group->meth->field_sqr(group, tmp1, &p->Z, ctx)) goto err;
1308 if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx)) goto err;
1309
1310 if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx)) goto err;
1311 if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx)) goto err;
1312
1313 if (group->meth->field_set_to_one != 0)
1314 {
1315 if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err;
1316 }
1317 else
1318 {
1319 if (!BN_one(&p->Z)) goto err;
1320 }
1321 p->Z_is_one = 1;
1322 }
1323 }
1324
1325 ret = 1;
1326
1327 err:
1328 BN_CTX_end(ctx);
1329 if (new_ctx != NULL)
1330 BN_CTX_free(new_ctx);
1331 if (heap != NULL)
1332 {
1333 /* heap[pow2/2] .. heap[pow2-1] have not been allocated locally! */
1334 for (i = pow2/2 - 1; i > 0; i--)
1335 {
1336 if (heap[i] != NULL)
1337 BN_clear_free(heap[i]);
1338 }
1339 OPENSSL_free(heap);
1340 }
1341 return ret;
1342 }
1343
1344
1345 int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1346 {
1347 return BN_mod_mul(r, a, b, &group->field, ctx);
1348 }
1349
1350
1351 int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
1352 {
1353 return BN_mod_sqr(r, a, &group->field, ctx);
1354 }