add a comment
[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 #include <openssl/err.h>
66 #include <openssl/symhacks.h>
67
68 #include "ec_lcl.h"
69
70 const EC_METHOD *EC_GFp_simple_method(void)
71         {
72         static const EC_METHOD ret = {
73                 NID_X9_62_prime_field,
74                 ec_GFp_simple_group_init,
75                 ec_GFp_simple_group_finish,
76                 ec_GFp_simple_group_clear_finish,
77                 ec_GFp_simple_group_copy,
78                 ec_GFp_simple_group_set_curve,
79                 ec_GFp_simple_group_get_curve,
80                 ec_GFp_simple_group_get_degree,
81                 ec_GFp_simple_group_check_discriminant,
82                 ec_GFp_simple_point_init,
83                 ec_GFp_simple_point_finish,
84                 ec_GFp_simple_point_clear_finish,
85                 ec_GFp_simple_point_copy,
86                 ec_GFp_simple_point_set_to_infinity,
87                 ec_GFp_simple_set_Jprojective_coordinates_GFp,
88                 ec_GFp_simple_get_Jprojective_coordinates_GFp,
89                 ec_GFp_simple_point_set_affine_coordinates,
90                 ec_GFp_simple_point_get_affine_coordinates,
91                 ec_GFp_simple_set_compressed_coordinates,
92                 ec_GFp_simple_point2oct,
93                 ec_GFp_simple_oct2point,
94                 ec_GFp_simple_add,
95                 ec_GFp_simple_dbl,
96                 ec_GFp_simple_invert,
97                 0 /* mul */,
98                 0 /* precompute_mult */,
99                 ec_GFp_simple_is_at_infinity,
100                 ec_GFp_simple_is_on_curve,
101                 ec_GFp_simple_cmp,
102                 ec_GFp_simple_make_affine,
103                 ec_GFp_simple_points_make_affine,
104                 ec_GFp_simple_field_mul,
105                 ec_GFp_simple_field_sqr,
106                 0 /* field_div */,
107                 0 /* field_encode */,
108                 0 /* field_decode */,
109                 0 /* field_set_to_one */ };
110
111         return &ret;
112         }
113
114
115 /* Most method functions in this file are designed to work with
116  * non-trivial representations of field elements if necessary
117  * (see ecp_mont.c): while standard modular addition and subtraction
118  * are used, the field_mul and field_sqr methods will be used for
119  * multiplication, and field_encode and field_decode (if defined)
120  * will be used for converting between representations.
121
122  * Functions ec_GFp_simple_points_make_affine() and
123  * ec_GFp_simple_point_get_affine_coordinates() specifically assume
124  * that if a non-trivial representation is used, it is a Montgomery
125  * representation (i.e. 'encoding' means multiplying by some factor R).
126  */
127
128
129 int ec_GFp_simple_group_init(EC_GROUP *group)
130         {
131         BN_init(&group->field);
132         BN_init(&group->a);
133         BN_init(&group->b);
134         group->a_is_minus3 = 0;
135         return 1;
136         }
137
138
139 void ec_GFp_simple_group_finish(EC_GROUP *group)
140         {
141         BN_free(&group->field);
142         BN_free(&group->a);
143         BN_free(&group->b);
144         }
145
146
147 void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
148         {
149         BN_clear_free(&group->field);
150         BN_clear_free(&group->a);
151         BN_clear_free(&group->b);
152         }
153
154
155 int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
156         {
157         if (!BN_copy(&dest->field, &src->field)) return 0;
158         if (!BN_copy(&dest->a, &src->a)) return 0;
159         if (!BN_copy(&dest->b, &src->b)) return 0;
160
161         dest->a_is_minus3 = src->a_is_minus3;
162
163         return 1;
164         }
165
166
167 int ec_GFp_simple_group_set_curve(EC_GROUP *group,
168         const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
169         {
170         int ret = 0;
171         BN_CTX *new_ctx = NULL;
172         BIGNUM *tmp_a;
173         
174         /* p must be a prime > 3 */
175         if (BN_num_bits(p) <= 2 || !BN_is_odd(p))
176                 {
177                 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
178                 return 0;
179                 }
180
181         if (ctx == NULL)
182                 {
183                 ctx = new_ctx = BN_CTX_new();
184                 if (ctx == NULL)
185                         return 0;
186                 }
187
188         BN_CTX_start(ctx);
189         tmp_a = BN_CTX_get(ctx);
190         if (tmp_a == NULL) goto err;
191
192         /* group->field */
193         if (!BN_copy(&group->field, p)) goto err;
194         BN_set_sign(&group->field, 0);
195
196         /* group->a */
197         if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
198         if (group->meth->field_encode)
199                 { if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) goto err; }     
200         else
201                 if (!BN_copy(&group->a, tmp_a)) goto err;
202         
203         /* group->b */
204         if (!BN_nnmod(&group->b, b, p, ctx)) goto err;
205         if (group->meth->field_encode)
206                 if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) goto err;
207         
208         /* group->a_is_minus3 */
209         if (!BN_add_word(tmp_a, 3)) goto err;
210         group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
211
212         ret = 1;
213
214  err:
215         BN_CTX_end(ctx);
216         if (new_ctx != NULL)
217                 BN_CTX_free(new_ctx);
218         return ret;
219         }
220
221
222 int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
223         {
224         int ret = 0;
225         BN_CTX *new_ctx = NULL;
226         
227         if (p != NULL)
228                 {
229                 if (!BN_copy(p, &group->field)) return 0;
230                 }
231
232         if (a != NULL || b != NULL)
233                 {
234                 if (group->meth->field_decode)
235                         {
236                         if (ctx == NULL)
237                                 {
238                                 ctx = new_ctx = BN_CTX_new();
239                                 if (ctx == NULL)
240                                         return 0;
241                                 }
242                         if (a != NULL)
243                                 {
244                                 if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
245                                 }
246                         if (b != NULL)
247                                 {
248                                 if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
249                                 }
250                         }
251                 else
252                         {
253                         if (a != NULL)
254                                 {
255                                 if (!BN_copy(a, &group->a)) goto err;
256                                 }
257                         if (b != NULL)
258                                 {
259                                 if (!BN_copy(b, &group->b)) goto err;
260                                 }
261                         }
262                 }
263         
264         ret = 1;
265         
266  err:
267         if (new_ctx)
268                 BN_CTX_free(new_ctx);
269         return ret;
270         }
271
272
273 int ec_GFp_simple_group_get_degree(const EC_GROUP *group)
274         {
275         return BN_num_bits(&group->field);
276         }
277
278
279 int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
280         {
281         int ret = 0;
282         BIGNUM *a,*b,*order,*tmp_1,*tmp_2;
283         const BIGNUM *p = &group->field;
284         BN_CTX *new_ctx = NULL;
285
286         if (ctx == NULL)
287                 {
288                 ctx = new_ctx = BN_CTX_new();
289                 if (ctx == NULL)
290                         {
291                         ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
292                         goto err;
293                         }
294                 }
295         BN_CTX_start(ctx);
296         a = BN_CTX_get(ctx);
297         b = BN_CTX_get(ctx);
298         tmp_1 = BN_CTX_get(ctx);
299         tmp_2 = BN_CTX_get(ctx);
300         order = BN_CTX_get(ctx);
301         if (order == NULL) goto err;
302
303         if (group->meth->field_decode)
304                 {
305                 if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
306                 if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
307                 }
308         else
309                 {
310                 if (!BN_copy(a, &group->a)) goto err;
311                 if (!BN_copy(b, &group->b)) goto err;
312                 }
313         
314         /* check the discriminant:
315          * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p) 
316          * 0 =< a, b < p */
317         if (BN_is_zero(a))
318                 {
319                 if (BN_is_zero(b)) goto err;
320                 }
321         else if (!BN_is_zero(b))
322                 {
323                 if (!BN_mod_sqr(tmp_1, a, p, ctx)) goto err;
324                 if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) goto err;
325                 if (!BN_lshift(tmp_1, tmp_2, 2)) goto err;
326                 /* tmp_1 = 4*a^3 */
327
328                 if (!BN_mod_sqr(tmp_2, b, p, ctx)) goto err;
329                 if (!BN_mul_word(tmp_2, 27)) goto err;
330                 /* tmp_2 = 27*b^2 */
331
332                 if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) goto err;
333                 if (BN_is_zero(a)) goto err;
334                 }
335         ret = 1;
336
337 err:
338         BN_CTX_end(ctx);
339         if (new_ctx != NULL)
340                 BN_CTX_free(new_ctx);
341         return ret;
342         }
343
344
345 int ec_GFp_simple_point_init(EC_POINT *point)
346         {
347         BN_init(&point->X);
348         BN_init(&point->Y);
349         BN_init(&point->Z);
350         point->Z_is_one = 0;
351
352         return 1;
353         }
354
355
356 void ec_GFp_simple_point_finish(EC_POINT *point)
357         {
358         BN_free(&point->X);
359         BN_free(&point->Y);
360         BN_free(&point->Z);
361         }
362
363
364 void ec_GFp_simple_point_clear_finish(EC_POINT *point)
365         {
366         BN_clear_free(&point->X);
367         BN_clear_free(&point->Y);
368         BN_clear_free(&point->Z);
369         point->Z_is_one = 0;
370         }
371
372
373 int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
374         {
375         if (!BN_copy(&dest->X, &src->X)) return 0;
376         if (!BN_copy(&dest->Y, &src->Y)) return 0;
377         if (!BN_copy(&dest->Z, &src->Z)) return 0;
378         dest->Z_is_one = src->Z_is_one;
379
380         return 1;
381         }
382
383
384 int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
385         {
386         point->Z_is_one = 0;
387         return (BN_zero(&point->Z));
388         }
389
390
391 int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
392         const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
393         {
394         BN_CTX *new_ctx = NULL;
395         int ret = 0;
396         
397         if (ctx == NULL)
398                 {
399                 ctx = new_ctx = BN_CTX_new();
400                 if (ctx == NULL)
401                         return 0;
402                 }
403
404         if (x != NULL)
405                 {
406                 if (!BN_nnmod(&point->X, x, &group->field, ctx)) goto err;
407                 if (group->meth->field_encode)
408                         {
409                         if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) goto err;
410                         }
411                 }
412         
413         if (y != NULL)
414                 {
415                 if (!BN_nnmod(&point->Y, y, &group->field, ctx)) goto err;
416                 if (group->meth->field_encode)
417                         {
418                         if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) goto err;
419                         }
420                 }
421         
422         if (z != NULL)
423                 {
424                 int Z_is_one;
425
426                 if (!BN_nnmod(&point->Z, z, &group->field, ctx)) goto err;
427                 Z_is_one = BN_is_one(&point->Z);
428                 if (group->meth->field_encode)
429                         {
430                         if (Z_is_one && (group->meth->field_set_to_one != 0))
431                                 {
432                                 if (!group->meth->field_set_to_one(group, &point->Z, ctx)) goto err;
433                                 }
434                         else
435                                 {
436                                 if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) goto err;
437                                 }
438                         }
439                 point->Z_is_one = Z_is_one;
440                 }
441         
442         ret = 1;
443         
444  err:
445         if (new_ctx != NULL)
446                 BN_CTX_free(new_ctx);
447         return ret;
448         }
449
450
451 int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
452         BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
453         {
454         BN_CTX *new_ctx = NULL;
455         int ret = 0;
456         
457         if (group->meth->field_decode != 0)
458                 {
459                 if (ctx == NULL)
460                         {
461                         ctx = new_ctx = BN_CTX_new();
462                         if (ctx == NULL)
463                                 return 0;
464                         }
465
466                 if (x != NULL)
467                         {
468                         if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
469                         }
470                 if (y != NULL)
471                         {
472                         if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
473                         }
474                 if (z != NULL)
475                         {
476                         if (!group->meth->field_decode(group, z, &point->Z, ctx)) goto err;
477                         }
478                 }
479         else    
480                 {
481                 if (x != NULL)
482                         {
483                         if (!BN_copy(x, &point->X)) goto err;
484                         }
485                 if (y != NULL)
486                         {
487                         if (!BN_copy(y, &point->Y)) goto err;
488                         }
489                 if (z != NULL)
490                         {
491                         if (!BN_copy(z, &point->Z)) goto err;
492                         }
493                 }
494         
495         ret = 1;
496
497  err:
498         if (new_ctx != NULL)
499                 BN_CTX_free(new_ctx);
500         return ret;
501         }
502
503
504 int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
505         const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
506         {
507         if (x == NULL || y == NULL)
508                 {
509                 /* unlike for projective coordinates, we do not tolerate this */
510                 ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
511                 return 0;
512                 }
513
514         return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx);
515         }
516
517
518 int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
519         BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
520         {
521         BN_CTX *new_ctx = NULL;
522         BIGNUM *Z, *Z_1, *Z_2, *Z_3;
523         const BIGNUM *Z_;
524         int ret = 0;
525
526         if (EC_POINT_is_at_infinity(group, point))
527                 {
528                 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
529                 return 0;
530                 }
531
532         if (ctx == NULL)
533                 {
534                 ctx = new_ctx = BN_CTX_new();
535                 if (ctx == NULL)
536                         return 0;
537                 }
538
539         BN_CTX_start(ctx);
540         Z = BN_CTX_get(ctx);
541         Z_1 = BN_CTX_get(ctx);
542         Z_2 = BN_CTX_get(ctx);
543         Z_3 = BN_CTX_get(ctx);
544         if (Z_3 == NULL) goto err;
545
546         /* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */
547         
548         if (group->meth->field_decode)
549                 {
550                 if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err;
551                 Z_ = Z;
552                 }
553         else
554                 {
555                 Z_ = &point->Z;
556                 }
557         
558         if (BN_is_one(Z_))
559                 {
560                 if (group->meth->field_decode)
561                         {
562                         if (x != NULL)
563                                 {
564                                 if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
565                                 }
566                         if (y != NULL)
567                                 {
568                                 if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
569                                 }
570                         }
571                 else
572                         {
573                         if (x != NULL)
574                                 {
575                                 if (!BN_copy(x, &point->X)) goto err;
576                                 }
577                         if (y != NULL)
578                                 {
579                                 if (!BN_copy(y, &point->Y)) goto err;
580                                 }
581                         }
582                 }
583         else
584                 {
585                 if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx))
586                         {
587                         ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
588                         goto err;
589                         }
590                 
591                 if (group->meth->field_encode == 0)
592                         {
593                         /* field_sqr works on standard representation */
594                         if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) goto err;
595                         }
596                 else
597                         {
598                         if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err;
599                         }
600         
601                 if (x != NULL)
602                         {
603                         /* in the Montgomery case, field_mul will cancel out Montgomery factor in X: */
604                         if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) goto err;
605                         }
606
607                 if (y != NULL)
608                         {
609                         if (group->meth->field_encode == 0)
610                                 {
611                                 /* field_mul works on standard representation */
612                                 if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err;
613                                 }
614                         else
615                                 {
616                                 if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
617                                 }
618
619                         /* in the Montgomery case, field_mul will cancel out Montgomery factor in Y: */
620                         if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) goto err;
621                         }
622                 }
623
624         ret = 1;
625
626  err:
627         BN_CTX_end(ctx);
628         if (new_ctx != NULL)
629                 BN_CTX_free(new_ctx);
630         return ret;
631         }
632
633
634 int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
635         const BIGNUM *x_, int y_bit, BN_CTX *ctx)
636         {
637         BN_CTX *new_ctx = NULL;
638         BIGNUM *tmp1, *tmp2, *x, *y;
639         int ret = 0;
640
641         if (ctx == NULL)
642                 {
643                 ctx = new_ctx = BN_CTX_new();
644                 if (ctx == NULL)
645                         return 0;
646                 }
647
648         y_bit = (y_bit != 0);
649
650         BN_CTX_start(ctx);
651         tmp1 = BN_CTX_get(ctx);
652         tmp2 = BN_CTX_get(ctx);
653         x = BN_CTX_get(ctx);
654         y = BN_CTX_get(ctx);
655         if (y == NULL) goto err;
656
657         /* Recover y.  We have a Weierstrass equation
658          *     y^2 = x^3 + a*x + b,
659          * so  y  is one of the square roots of  x^3 + a*x + b.
660          */
661
662         /* tmp1 := x^3 */
663         if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
664         if (group->meth->field_decode == 0)
665                 {
666                 /* field_{sqr,mul} work on standard representation */
667                 if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
668                 if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
669                 }
670         else
671                 {
672                 if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
673                 if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
674                 }
675         
676         /* tmp1 := tmp1 + a*x */
677         if (group->a_is_minus3)
678                 {
679                 if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
680                 if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
681                 if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
682                 }
683         else
684                 {
685                 if (group->meth->field_decode)
686                         {
687                         if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
688                         if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
689                         }
690                 else
691                         {
692                         /* field_mul works on standard representation */
693                         if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
694                         }
695                 
696                 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
697                 }
698         
699         /* tmp1 := tmp1 + b */
700         if (group->meth->field_decode)
701                 {
702                 if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
703                 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
704                 }
705         else
706                 {
707                 if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
708                 }
709         
710         if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
711                 {
712                 unsigned long err = ERR_peek_error();
713                 
714                 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
715                         {
716                         (void)ERR_get_error();
717                         ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
718                         }
719                 else
720                         ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
721                 goto err;
722                 }
723
724         if (y_bit != BN_is_odd(y))
725                 {
726                 if (BN_is_zero(y))
727                         {
728                         int kron;
729
730                         kron = BN_kronecker(x, &group->field, ctx);
731                         if (kron == -2) goto err;
732
733                         if (kron == 1)
734                                 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
735                         else
736                                 /* BN_mod_sqrt() should have cought this error (not a square) */
737                                 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
738                         goto err;
739                         }
740                 if (!BN_usub(y, &group->field, y)) goto err;
741                 }
742         if (y_bit != BN_is_odd(y))
743                 {
744                 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
745                 goto err;
746                 }
747
748         if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
749
750         ret = 1;
751
752  err:
753         BN_CTX_end(ctx);
754         if (new_ctx != NULL)
755                 BN_CTX_free(new_ctx);
756         return ret;
757         }
758
759
760 size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
761         unsigned char *buf, size_t len, BN_CTX *ctx)
762         {
763         size_t ret;
764         BN_CTX *new_ctx = NULL;
765         int used_ctx = 0;
766         BIGNUM *x, *y;
767         size_t field_len, i, skip;
768
769         if ((form != POINT_CONVERSION_COMPRESSED)
770                 && (form != POINT_CONVERSION_UNCOMPRESSED)
771                 && (form != POINT_CONVERSION_HYBRID))
772                 {
773                 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
774                 goto err;
775                 }
776
777         if (EC_POINT_is_at_infinity(group, point))
778                 {
779                 /* encodes to a single 0 octet */
780                 if (buf != NULL)
781                         {
782                         if (len < 1)
783                                 {
784                                 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
785                                 return 0;
786                                 }
787                         buf[0] = 0;
788                         }
789                 return 1;
790                 }
791
792
793         /* ret := required output buffer length */
794         field_len = BN_num_bytes(&group->field);
795         ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
796
797         /* if 'buf' is NULL, just return required length */
798         if (buf != NULL)
799                 {
800                 if (len < ret)
801                         {
802                         ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
803                         goto err;
804                         }
805
806                 if (ctx == NULL)
807                         {
808                         ctx = new_ctx = BN_CTX_new();
809                         if (ctx == NULL)
810                                 return 0;
811                         }
812
813                 BN_CTX_start(ctx);
814                 used_ctx = 1;
815                 x = BN_CTX_get(ctx);
816                 y = BN_CTX_get(ctx);
817                 if (y == NULL) goto err;
818
819                 if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
820
821                 if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
822                         buf[0] = form + 1;
823                 else
824                         buf[0] = form;
825         
826                 i = 1;
827                 
828                 skip = field_len - BN_num_bytes(x);
829                 if (skip > field_len)
830                         {
831                         ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
832                         goto err;
833                         }
834                 while (skip > 0)
835                         {
836                         buf[i++] = 0;
837                         skip--;
838                         }
839                 skip = BN_bn2bin(x, buf + i);
840                 i += skip;
841                 if (i != 1 + field_len)
842                         {
843                         ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
844                         goto err;
845                         }
846
847                 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
848                         {
849                         skip = field_len - BN_num_bytes(y);
850                         if (skip > field_len)
851                                 {
852                                 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
853                                 goto err;
854                                 }
855                         while (skip > 0)
856                                 {
857                                 buf[i++] = 0;
858                                 skip--;
859                                 }
860                         skip = BN_bn2bin(y, buf + i);
861                         i += skip;
862                         }
863
864                 if (i != ret)
865                         {
866                         ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
867                         goto err;
868                         }
869                 }
870         
871         if (used_ctx)
872                 BN_CTX_end(ctx);
873         if (new_ctx != NULL)
874                 BN_CTX_free(new_ctx);
875         return ret;
876
877  err:
878         if (used_ctx)
879                 BN_CTX_end(ctx);
880         if (new_ctx != NULL)
881                 BN_CTX_free(new_ctx);
882         return 0;
883         }
884
885
886 int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
887         const unsigned char *buf, size_t len, BN_CTX *ctx)
888         {
889         point_conversion_form_t form;
890         int y_bit;
891         BN_CTX *new_ctx = NULL;
892         BIGNUM *x, *y;
893         size_t field_len, enc_len;
894         int ret = 0;
895
896         if (len == 0)
897                 {
898                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
899                 return 0;
900                 }
901         form = buf[0];
902         y_bit = form & 1;
903         form = form & ~1;
904         if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
905                 && (form != POINT_CONVERSION_UNCOMPRESSED)
906                 && (form != POINT_CONVERSION_HYBRID))
907                 {
908                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
909                 return 0;
910                 }
911         if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
912                 {
913                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
914                 return 0;
915                 }
916
917         if (form == 0)
918                 {
919                 if (len != 1)
920                         {
921                         ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
922                         return 0;
923                         }
924
925                 return EC_POINT_set_to_infinity(group, point);
926                 }
927         
928         field_len = BN_num_bytes(&group->field);
929         enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
930
931         if (len != enc_len)
932                 {
933                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
934                 return 0;
935                 }
936
937         if (ctx == NULL)
938                 {
939                 ctx = new_ctx = BN_CTX_new();
940                 if (ctx == NULL)
941                         return 0;
942                 }
943
944         BN_CTX_start(ctx);
945         x = BN_CTX_get(ctx);
946         y = BN_CTX_get(ctx);
947         if (y == NULL) goto err;
948
949         if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
950         if (BN_ucmp(x, &group->field) >= 0)
951                 {
952                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
953                 goto err;
954                 }
955
956         if (form == POINT_CONVERSION_COMPRESSED)
957                 {
958                 if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
959                 }
960         else
961                 {
962                 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
963                 if (BN_ucmp(y, &group->field) >= 0)
964                         {
965                         ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
966                         goto err;
967                         }
968                 if (form == POINT_CONVERSION_HYBRID)
969                         {
970                         if (y_bit != BN_is_odd(y))
971                                 {
972                                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
973                                 goto err;
974                                 }
975                         }
976
977                 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
978                 }
979         
980         if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
981                 {
982                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
983                 goto err;
984                 }
985
986         ret = 1;
987         
988  err:
989         BN_CTX_end(ctx);
990         if (new_ctx != NULL)
991                 BN_CTX_free(new_ctx);
992         return ret;
993         }
994
995
996 int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
997         {
998         int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
999         int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1000         const BIGNUM *p;
1001         BN_CTX *new_ctx = NULL;
1002         BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
1003         int ret = 0;
1004         
1005         if (a == b)
1006                 return EC_POINT_dbl(group, r, a, ctx);
1007         if (EC_POINT_is_at_infinity(group, a))
1008                 return EC_POINT_copy(r, b);
1009         if (EC_POINT_is_at_infinity(group, b))
1010                 return EC_POINT_copy(r, a);
1011         
1012         field_mul = group->meth->field_mul;
1013         field_sqr = group->meth->field_sqr;
1014         p = &group->field;
1015
1016         if (ctx == NULL)
1017                 {
1018                 ctx = new_ctx = BN_CTX_new();
1019                 if (ctx == NULL)
1020                         return 0;
1021                 }
1022
1023         BN_CTX_start(ctx);
1024         n0 = BN_CTX_get(ctx);
1025         n1 = BN_CTX_get(ctx);
1026         n2 = BN_CTX_get(ctx);
1027         n3 = BN_CTX_get(ctx);
1028         n4 = BN_CTX_get(ctx);
1029         n5 = BN_CTX_get(ctx);
1030         n6 = BN_CTX_get(ctx);
1031         if (n6 == NULL) goto end;
1032
1033         /* Note that in this function we must not read components of 'a' or 'b'
1034          * once we have written the corresponding components of 'r'.
1035          * ('r' might be one of 'a' or 'b'.)
1036          */
1037
1038         /* n1, n2 */
1039         if (b->Z_is_one)
1040                 {
1041                 if (!BN_copy(n1, &a->X)) goto end;
1042                 if (!BN_copy(n2, &a->Y)) goto end;
1043                 /* n1 = X_a */
1044                 /* n2 = Y_a */
1045                 }
1046         else
1047                 {
1048                 if (!field_sqr(group, n0, &b->Z, ctx)) goto end;
1049                 if (!field_mul(group, n1, &a->X, n0, ctx)) goto end;
1050                 /* n1 = X_a * Z_b^2 */
1051
1052                 if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end;
1053                 if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end;
1054                 /* n2 = Y_a * Z_b^3 */
1055                 }
1056
1057         /* n3, n4 */
1058         if (a->Z_is_one)
1059                 {
1060                 if (!BN_copy(n3, &b->X)) goto end;
1061                 if (!BN_copy(n4, &b->Y)) goto end;
1062                 /* n3 = X_b */
1063                 /* n4 = Y_b */
1064                 }
1065         else
1066                 {
1067                 if (!field_sqr(group, n0, &a->Z, ctx)) goto end;
1068                 if (!field_mul(group, n3, &b->X, n0, ctx)) goto end;
1069                 /* n3 = X_b * Z_a^2 */
1070
1071                 if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end;
1072                 if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end;
1073                 /* n4 = Y_b * Z_a^3 */
1074                 }
1075
1076         /* n5, n6 */
1077         if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end;
1078         if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end;
1079         /* n5 = n1 - n3 */
1080         /* n6 = n2 - n4 */
1081
1082         if (BN_is_zero(n5))
1083                 {
1084                 if (BN_is_zero(n6))
1085                         {
1086                         /* a is the same point as b */
1087                         BN_CTX_end(ctx);
1088                         ret = EC_POINT_dbl(group, r, a, ctx);
1089                         ctx = NULL;
1090                         goto end;
1091                         }
1092                 else
1093                         {
1094                         /* a is the inverse of b */
1095                         if (!BN_zero(&r->Z)) goto end;
1096                         r->Z_is_one = 0;
1097                         ret = 1;
1098                         goto end;
1099                         }
1100                 }
1101
1102         /* 'n7', 'n8' */
1103         if (!BN_mod_add_quick(n1, n1, n3, p)) goto end;
1104         if (!BN_mod_add_quick(n2, n2, n4, p)) goto end;
1105         /* 'n7' = n1 + n3 */
1106         /* 'n8' = n2 + n4 */
1107
1108         /* Z_r */
1109         if (a->Z_is_one && b->Z_is_one)
1110                 {
1111                 if (!BN_copy(&r->Z, n5)) goto end;
1112                 }
1113         else
1114                 {
1115                 if (a->Z_is_one)
1116                         { if (!BN_copy(n0, &b->Z)) goto end; }
1117                 else if (b->Z_is_one)
1118                         { if (!BN_copy(n0, &a->Z)) goto end; }
1119                 else
1120                         { if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; }
1121                 if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end;
1122                 }
1123         r->Z_is_one = 0;
1124         /* Z_r = Z_a * Z_b * n5 */
1125
1126         /* X_r */
1127         if (!field_sqr(group, n0, n6, ctx)) goto end;
1128         if (!field_sqr(group, n4, n5, ctx)) goto end;
1129         if (!field_mul(group, n3, n1, n4, ctx)) goto end;
1130         if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end;
1131         /* X_r = n6^2 - n5^2 * 'n7' */
1132         
1133         /* 'n9' */
1134         if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end;
1135         if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end;
1136         /* n9 = n5^2 * 'n7' - 2 * X_r */
1137
1138         /* Y_r */
1139         if (!field_mul(group, n0, n0, n6, ctx)) goto end;
1140         if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */
1141         if (!field_mul(group, n1, n2, n5, ctx)) goto end;
1142         if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end;
1143         if (BN_is_odd(n0))
1144                 if (!BN_add(n0, n0, p)) goto end;
1145         /* now  0 <= n0 < 2*p,  and n0 is even */
1146         if (!BN_rshift1(&r->Y, n0)) goto end;
1147         /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
1148
1149         ret = 1;
1150
1151  end:
1152         if (ctx) /* otherwise we already called BN_CTX_end */
1153                 BN_CTX_end(ctx);
1154         if (new_ctx != NULL)
1155                 BN_CTX_free(new_ctx);
1156         return ret;
1157         }
1158
1159
1160 int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
1161         {
1162         int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1163         int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1164         const BIGNUM *p;
1165         BN_CTX *new_ctx = NULL;
1166         BIGNUM *n0, *n1, *n2, *n3;
1167         int ret = 0;
1168         
1169         if (EC_POINT_is_at_infinity(group, a))
1170                 {
1171                 if (!BN_zero(&r->Z)) return 0;
1172                 r->Z_is_one = 0;
1173                 return 1;
1174                 }
1175
1176         field_mul = group->meth->field_mul;
1177         field_sqr = group->meth->field_sqr;
1178         p = &group->field;
1179
1180         if (ctx == NULL)
1181                 {
1182                 ctx = new_ctx = BN_CTX_new();
1183                 if (ctx == NULL)
1184                         return 0;
1185                 }
1186
1187         BN_CTX_start(ctx);
1188         n0 = BN_CTX_get(ctx);
1189         n1 = BN_CTX_get(ctx);
1190         n2 = BN_CTX_get(ctx);
1191         n3 = BN_CTX_get(ctx);
1192         if (n3 == NULL) goto err;
1193
1194         /* Note that in this function we must not read components of 'a'
1195          * once we have written the corresponding components of 'r'.
1196          * ('r' might the same as 'a'.)
1197          */
1198
1199         /* n1 */
1200         if (a->Z_is_one)
1201                 {
1202                 if (!field_sqr(group, n0, &a->X, ctx)) goto err;
1203                 if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
1204                 if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
1205                 if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err;
1206                 /* n1 = 3 * X_a^2 + a_curve */
1207                 }
1208         else if (group->a_is_minus3)
1209                 {
1210                 if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
1211                 if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err;
1212                 if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err;
1213                 if (!field_mul(group, n1, n0, n2, ctx)) goto err;
1214                 if (!BN_mod_lshift1_quick(n0, n1, p)) goto err;
1215                 if (!BN_mod_add_quick(n1, n0, n1, p)) goto err;
1216                 /* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
1217                  *    = 3 * X_a^2 - 3 * Z_a^4 */
1218                 }
1219         else
1220                 {
1221                 if (!field_sqr(group, n0, &a->X, ctx)) goto err;
1222                 if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
1223                 if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
1224                 if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
1225                 if (!field_sqr(group, n1, n1, ctx)) goto err;
1226                 if (!field_mul(group, n1, n1, &group->a, ctx)) goto err;
1227                 if (!BN_mod_add_quick(n1, n1, n0, p)) goto err;
1228                 /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
1229                 }
1230
1231         /* Z_r */
1232         if (a->Z_is_one)
1233                 {
1234                 if (!BN_copy(n0, &a->Y)) goto err;
1235                 }
1236         else
1237                 {
1238                 if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err;
1239                 }
1240         if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err;
1241         r->Z_is_one = 0;
1242         /* Z_r = 2 * Y_a * Z_a */
1243
1244         /* n2 */
1245         if (!field_sqr(group, n3, &a->Y, ctx)) goto err;
1246         if (!field_mul(group, n2, &a->X, n3, ctx)) goto err;
1247         if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err;
1248         /* n2 = 4 * X_a * Y_a^2 */
1249
1250         /* X_r */
1251         if (!BN_mod_lshift1_quick(n0, n2, p)) goto err;
1252         if (!field_sqr(group, &r->X, n1, ctx)) goto err;
1253         if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err;
1254         /* X_r = n1^2 - 2 * n2 */
1255         
1256         /* n3 */
1257         if (!field_sqr(group, n0, n3, ctx)) goto err;
1258         if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err;
1259         /* n3 = 8 * Y_a^4 */
1260         
1261         /* Y_r */
1262         if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err;
1263         if (!field_mul(group, n0, n1, n0, ctx)) goto err;
1264         if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err;
1265         /* Y_r = n1 * (n2 - X_r) - n3 */
1266
1267         ret = 1;
1268
1269  err:
1270         BN_CTX_end(ctx);
1271         if (new_ctx != NULL)
1272                 BN_CTX_free(new_ctx);
1273         return ret;
1274         }
1275
1276
1277 int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1278         {
1279         if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
1280                 /* point is its own inverse */
1281                 return 1;
1282         
1283         return BN_usub(&point->Y, &group->field, &point->Y);
1284         }
1285
1286
1287 int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
1288         {
1289         return BN_is_zero(&point->Z);
1290         }
1291
1292
1293 int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
1294         {
1295         int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1296         int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1297         const BIGNUM *p;
1298         BN_CTX *new_ctx = NULL;
1299         BIGNUM *rh, *tmp1, *tmp2, *Z4, *Z6;
1300         int ret = -1;
1301
1302         if (EC_POINT_is_at_infinity(group, point))
1303                 return 1;
1304         
1305         field_mul = group->meth->field_mul;
1306         field_sqr = group->meth->field_sqr;
1307         p = &group->field;
1308
1309         if (ctx == NULL)
1310                 {
1311                 ctx = new_ctx = BN_CTX_new();
1312                 if (ctx == NULL)
1313                         return -1;
1314                 }
1315
1316         BN_CTX_start(ctx);
1317         rh = BN_CTX_get(ctx);
1318         tmp1 = BN_CTX_get(ctx);
1319         tmp2 = BN_CTX_get(ctx);
1320         Z4 = BN_CTX_get(ctx);
1321         Z6 = BN_CTX_get(ctx);
1322         if (Z6 == NULL) goto err;
1323
1324         /* We have a curve defined by a Weierstrass equation
1325          *      y^2 = x^3 + a*x + b.
1326          * The point to consider is given in Jacobian projective coordinates
1327          * where  (X, Y, Z)  represents  (x, y) = (X/Z^2, Y/Z^3).
1328          * Substituting this and multiplying by  Z^6  transforms the above equation into
1329          *      Y^2 = X^3 + a*X*Z^4 + b*Z^6.
1330          * To test this, we add up the right-hand side in 'rh'.
1331          */
1332
1333         /* rh := X^3 */
1334         if (!field_sqr(group, rh, &point->X, ctx)) goto err;
1335         if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1336
1337         if (!point->Z_is_one)
1338                 {
1339                 if (!field_sqr(group, tmp1, &point->Z, ctx)) goto err;
1340                 if (!field_sqr(group, Z4, tmp1, ctx)) goto err;
1341                 if (!field_mul(group, Z6, Z4, tmp1, ctx)) goto err;
1342
1343                 /* rh := rh + a*X*Z^4 */
1344                 if (!field_mul(group, tmp1, &point->X, Z4, ctx)) goto err;
1345                 if (group->a_is_minus3)
1346                         {
1347                         if (!BN_mod_lshift1_quick(tmp2, tmp1, p)) goto err;
1348                         if (!BN_mod_add_quick(tmp2, tmp2, tmp1, p)) goto err;
1349                         if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err;
1350                         }
1351                 else
1352                         {
1353                         if (!field_mul(group, tmp2, tmp1, &group->a, ctx)) goto err;
1354                         if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err;
1355                         }
1356
1357                 /* rh := rh + b*Z^6 */
1358                 if (!field_mul(group, tmp1, &group->b, Z6, ctx)) goto err;
1359                 if (!BN_mod_add_quick(rh, rh, tmp1, p)) goto err;
1360                 }
1361         else
1362                 {
1363                 /* point->Z_is_one */
1364
1365                 /* rh := rh + a*X */
1366                 if (group->a_is_minus3)
1367                         {
1368                         if (!BN_mod_lshift1_quick(tmp2, &point->X, p)) goto err;
1369                         if (!BN_mod_add_quick(tmp2, tmp2, &point->X, p)) goto err;
1370                         if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err;
1371                         }
1372                 else
1373                         {
1374                         if (!field_mul(group, tmp2, &point->X, &group->a, ctx)) goto err;
1375                         if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err;
1376                         }
1377
1378                 /* rh := rh + b */
1379                 if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err;
1380                 }
1381
1382         /* 'lh' := Y^2 */
1383         if (!field_sqr(group, tmp1, &point->Y, ctx)) goto err;
1384
1385         ret = (0 == BN_cmp(tmp1, rh));
1386
1387  err:
1388         BN_CTX_end(ctx);
1389         if (new_ctx != NULL)
1390                 BN_CTX_free(new_ctx);
1391         return ret;
1392         }
1393
1394
1395 int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
1396         {
1397         /* return values:
1398          *  -1   error
1399          *   0   equal (in affine coordinates)
1400          *   1   not equal
1401          */
1402
1403         int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1404         int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1405         BN_CTX *new_ctx = NULL;
1406         BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
1407         const BIGNUM *tmp1_, *tmp2_;
1408         int ret = -1;
1409         
1410         if (EC_POINT_is_at_infinity(group, a))
1411                 {
1412                 return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
1413                 }
1414         
1415         if (a->Z_is_one && b->Z_is_one)
1416                 {
1417                 return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
1418                 }
1419
1420         field_mul = group->meth->field_mul;
1421         field_sqr = group->meth->field_sqr;
1422
1423         if (ctx == NULL)
1424                 {
1425                 ctx = new_ctx = BN_CTX_new();
1426                 if (ctx == NULL)
1427                         return -1;
1428                 }
1429
1430         BN_CTX_start(ctx);
1431         tmp1 = BN_CTX_get(ctx);
1432         tmp2 = BN_CTX_get(ctx);
1433         Za23 = BN_CTX_get(ctx);
1434         Zb23 = BN_CTX_get(ctx);
1435         if (Zb23 == NULL) goto end;
1436
1437         /* We have to decide whether
1438          *     (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
1439          * or equivalently, whether
1440          *     (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
1441          */
1442
1443         if (!b->Z_is_one)
1444                 {
1445                 if (!field_sqr(group, Zb23, &b->Z, ctx)) goto end;
1446                 if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) goto end;
1447                 tmp1_ = tmp1;
1448                 }
1449         else
1450                 tmp1_ = &a->X;
1451         if (!a->Z_is_one)
1452                 {
1453                 if (!field_sqr(group, Za23, &a->Z, ctx)) goto end;
1454                 if (!field_mul(group, tmp2, &b->X, Za23, ctx)) goto end;
1455                 tmp2_ = tmp2;
1456                 }
1457         else
1458                 tmp2_ = &b->X;
1459         
1460         /* compare  X_a*Z_b^2  with  X_b*Z_a^2 */
1461         if (BN_cmp(tmp1_, tmp2_) != 0)
1462                 {
1463                 ret = 1; /* points differ */
1464                 goto end;
1465                 }
1466
1467
1468         if (!b->Z_is_one)
1469                 {
1470                 if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) goto end;
1471                 if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) goto end;
1472                 /* tmp1_ = tmp1 */
1473                 }
1474         else
1475                 tmp1_ = &a->Y;
1476         if (!a->Z_is_one)
1477                 {
1478                 if (!field_mul(group, Za23, Za23, &a->Z, ctx)) goto end;
1479                 if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) goto end;
1480                 /* tmp2_ = tmp2 */
1481                 }
1482         else
1483                 tmp2_ = &b->Y;
1484
1485         /* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */
1486         if (BN_cmp(tmp1_, tmp2_) != 0)
1487                 {
1488                 ret = 1; /* points differ */
1489                 goto end;
1490                 }
1491
1492         /* points are equal */
1493         ret = 0;
1494
1495  end:
1496         BN_CTX_end(ctx);
1497         if (new_ctx != NULL)
1498                 BN_CTX_free(new_ctx);
1499         return ret;
1500         }
1501
1502
1503 int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1504         {
1505         BN_CTX *new_ctx = NULL;
1506         BIGNUM *x, *y;
1507         int ret = 0;
1508
1509         if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
1510                 return 1;
1511
1512         if (ctx == NULL)
1513                 {
1514                 ctx = new_ctx = BN_CTX_new();
1515                 if (ctx == NULL)
1516                         return 0;
1517                 }
1518
1519         BN_CTX_start(ctx);
1520         x = BN_CTX_get(ctx);
1521         y = BN_CTX_get(ctx);
1522         if (y == NULL) goto err;
1523
1524         if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
1525         if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
1526         if (!point->Z_is_one)
1527                 {
1528                 ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
1529                 goto err;
1530                 }
1531         
1532         ret = 1;
1533
1534  err:
1535         BN_CTX_end(ctx);
1536         if (new_ctx != NULL)
1537                 BN_CTX_free(new_ctx);
1538         return ret;
1539         }
1540
1541
1542 int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
1543         {
1544         BN_CTX *new_ctx = NULL;
1545         BIGNUM *tmp0, *tmp1;
1546         size_t pow2 = 0;
1547         BIGNUM **heap = NULL;
1548         size_t i;
1549         int ret = 0;
1550
1551         if (num == 0)
1552                 return 1;
1553
1554         if (ctx == NULL)
1555                 {
1556                 ctx = new_ctx = BN_CTX_new();
1557                 if (ctx == NULL)
1558                         return 0;
1559                 }
1560
1561         BN_CTX_start(ctx);
1562         tmp0 = BN_CTX_get(ctx);
1563         tmp1 = BN_CTX_get(ctx);
1564         if (tmp0  == NULL || tmp1 == NULL) goto err;
1565
1566         /* Before converting the individual points, compute inverses of all Z values.
1567          * Modular inversion is rather slow, but luckily we can do with a single
1568          * explicit inversion, plus about 3 multiplications per input value.
1569          */
1570
1571         pow2 = 1;
1572         while (num > pow2)
1573                 pow2 <<= 1;
1574         /* Now pow2 is the smallest power of 2 satifsying pow2 >= num.
1575          * We need twice that. */
1576         pow2 <<= 1;
1577
1578         heap = OPENSSL_malloc(pow2 * sizeof heap[0]);
1579         if (heap == NULL) goto err;
1580         
1581         /* The array is used as a binary tree, exactly as in heapsort:
1582          *
1583          *                               heap[1]
1584          *                 heap[2]                     heap[3]
1585          *          heap[4]       heap[5]       heap[6]       heap[7]
1586          *   heap[8]heap[9] heap[10]heap[11] heap[12]heap[13] heap[14] heap[15]
1587          *
1588          * We put the Z's in the last line;
1589          * then we set each other node to the product of its two child-nodes (where
1590          * empty or 0 entries are treated as ones);
1591          * then we invert heap[1];
1592          * then we invert each other node by replacing it by the product of its
1593          * parent (after inversion) and its sibling (before inversion).
1594          */
1595         heap[0] = NULL;
1596         for (i = pow2/2 - 1; i > 0; i--)
1597                 heap[i] = NULL;
1598         for (i = 0; i < num; i++)
1599                 heap[pow2/2 + i] = &points[i]->Z;
1600         for (i = pow2/2 + num; i < pow2; i++)
1601                 heap[i] = NULL;
1602         
1603         /* set each node to the product of its children */
1604         for (i = pow2/2 - 1; i > 0; i--)
1605                 {
1606                 heap[i] = BN_new();
1607                 if (heap[i] == NULL) goto err;
1608                 
1609                 if (heap[2*i] != NULL)
1610                         {
1611                         if ((heap[2*i + 1] == NULL) || BN_is_zero(heap[2*i + 1]))
1612                                 {
1613                                 if (!BN_copy(heap[i], heap[2*i])) goto err;
1614                                 }
1615                         else
1616                                 {
1617                                 if (BN_is_zero(heap[2*i]))
1618                                         {
1619                                         if (!BN_copy(heap[i], heap[2*i + 1])) goto err;
1620                                         }
1621                                 else
1622                                         {
1623                                         if (!group->meth->field_mul(group, heap[i],
1624                                                 heap[2*i], heap[2*i + 1], ctx)) goto err;
1625                                         }
1626                                 }
1627                         }
1628                 }
1629
1630         /* invert heap[1] */
1631         if (!BN_is_zero(heap[1]))
1632                 {
1633                 if (!BN_mod_inverse(heap[1], heap[1], &group->field, ctx))
1634                         {
1635                         ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
1636                         goto err;
1637                         }
1638                 }
1639         if (group->meth->field_encode != 0)
1640                 {
1641                 /* in the Montgomery case, we just turned  R*H  (representing H)
1642                  * into  1/(R*H),  but we need  R*(1/H)  (representing 1/H);
1643                  * i.e. we have need to multiply by the Montgomery factor twice */
1644                 if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
1645                 if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
1646                 }
1647
1648         /* set other heap[i]'s to their inverses */
1649         for (i = 2; i < pow2/2 + num; i += 2)
1650                 {
1651                 /* i is even */
1652                 if ((heap[i + 1] != NULL) && !BN_is_zero(heap[i + 1]))
1653                         {
1654                         if (!group->meth->field_mul(group, tmp0, heap[i/2], heap[i + 1], ctx)) goto err;
1655                         if (!group->meth->field_mul(group, tmp1, heap[i/2], heap[i], ctx)) goto err;
1656                         if (!BN_copy(heap[i], tmp0)) goto err;
1657                         if (!BN_copy(heap[i + 1], tmp1)) goto err;
1658                         }
1659                 else
1660                         {
1661                         if (!BN_copy(heap[i], heap[i/2])) goto err;
1662                         }
1663                 }
1664
1665         /* we have replaced all non-zero Z's by their inverses, now fix up all the points */
1666         for (i = 0; i < num; i++)
1667                 {
1668                 EC_POINT *p = points[i];
1669                 
1670                 if (!BN_is_zero(&p->Z))
1671                         {
1672                         /* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */
1673
1674                         if (!group->meth->field_sqr(group, tmp1, &p->Z, ctx)) goto err;
1675                         if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx)) goto err;
1676
1677                         if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx)) goto err;
1678                         if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx)) goto err;
1679                 
1680                         if (group->meth->field_set_to_one != 0)
1681                                 {
1682                                 if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err;
1683                                 }
1684                         else
1685                                 {
1686                                 if (!BN_one(&p->Z)) goto err;
1687                                 }
1688                         p->Z_is_one = 1;
1689                         }
1690                 }
1691
1692         ret = 1;
1693                 
1694  err:
1695         BN_CTX_end(ctx);
1696         if (new_ctx != NULL)
1697                 BN_CTX_free(new_ctx);
1698         if (heap != NULL)
1699                 {
1700                 /* heap[pow2/2] .. heap[pow2-1] have not been allocated locally! */
1701                 for (i = pow2/2 - 1; i > 0; i--)
1702                         {
1703                         if (heap[i] != NULL)
1704                                 BN_clear_free(heap[i]);
1705                         }
1706                 OPENSSL_free(heap);
1707                 }
1708         return ret;
1709         }
1710
1711
1712 int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1713         {
1714         return BN_mod_mul(r, a, b, &group->field, ctx);
1715         }
1716
1717
1718 int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
1719         {
1720         return BN_mod_sqr(r, a, &group->field, ctx);
1721         }