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