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