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