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