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