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