implement and use new macros BN_get_sign(), BN_set_sign()
[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 *X, *Y, *Z, *Z_1, *Z_2, *Z_3;
509         const BIGNUM *X_, *Y_, *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         X = BN_CTX_get(ctx);
527         Y = BN_CTX_get(ctx);
528         Z = BN_CTX_get(ctx);
529         Z_1 = BN_CTX_get(ctx);
530         Z_2 = BN_CTX_get(ctx);
531         Z_3 = BN_CTX_get(ctx);
532         if (Z_3 == NULL) goto err;
533
534         /* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */
535         
536         if (group->meth->field_decode)
537                 {
538                 if (!group->meth->field_decode(group, X, &point->X, ctx)) goto err;
539                 if (!group->meth->field_decode(group, Y, &point->Y, ctx)) goto err;
540                 if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err;
541                 X_ = X; Y_ = Y; Z_ = Z;
542                 }
543         else
544                 {
545                 X_ = &point->X;
546                 Y_ = &point->Y;
547                 Z_ = &point->Z;
548                 }
549         
550         if (BN_is_one(Z_))
551                 {
552                 if (x != NULL)
553                         {
554                         if (!BN_copy(x, X_)) goto err;
555                         }
556                 if (y != NULL)
557                         {
558                         if (!BN_copy(y, Y_)) goto err;
559                         }
560                 }
561         else
562                 {
563                 if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx))
564                         {
565                         ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
566                         goto err;
567                         }
568                 
569                 if (group->meth->field_encode == 0)
570                         {
571                         /* field_sqr works on standard representation */
572                         if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) goto err;
573                         }
574                 else
575                         {
576                         if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err;
577                         }
578         
579                 if (x != NULL)
580                         {
581                         if (group->meth->field_encode == 0)
582                                 {
583                                 /* field_mul works on standard representation */
584                                 if (!group->meth->field_mul(group, x, X_, Z_2, ctx)) goto err;
585                                 }
586                         else
587                                 {
588                                 if (!BN_mod_mul(x, X_, Z_2, &group->field, ctx)) goto err;
589                                 }
590                         }
591
592                 if (y != NULL)
593                         {
594                         if (group->meth->field_encode == 0)
595                                 {
596                                 /* field_mul works on standard representation */
597                                 if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err;
598                                 if (!group->meth->field_mul(group, y, Y_, Z_3, ctx)) goto err;
599                                 
600                                 }
601                         else
602                                 {
603                                 if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
604                                 if (!BN_mod_mul(y, Y_, Z_3, &group->field, ctx)) goto err;
605                                 }
606                         }
607                 }
608
609         ret = 1;
610
611  err:
612         BN_CTX_end(ctx);
613         if (new_ctx != NULL)
614                 BN_CTX_free(new_ctx);
615         return ret;
616         }
617
618
619 int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
620         const BIGNUM *x_, int y_bit, BN_CTX *ctx)
621         {
622         BN_CTX *new_ctx = NULL;
623         BIGNUM *tmp1, *tmp2, *x, *y;
624         int ret = 0;
625
626         if (ctx == NULL)
627                 {
628                 ctx = new_ctx = BN_CTX_new();
629                 if (ctx == NULL)
630                         return 0;
631                 }
632
633         y_bit = (y_bit != 0);
634
635         BN_CTX_start(ctx);
636         tmp1 = BN_CTX_get(ctx);
637         tmp2 = BN_CTX_get(ctx);
638         x = BN_CTX_get(ctx);
639         y = BN_CTX_get(ctx);
640         if (y == NULL) goto err;
641
642         /* Recover y.  We have a Weierstrass equation
643          *     y^2 = x^3 + a*x + b,
644          * so  y  is one of the square roots of  x^3 + a*x + b.
645          */
646
647         /* tmp1 := x^3 */
648         if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
649         if (group->meth->field_decode == 0)
650                 {
651                 /* field_{sqr,mul} work on standard representation */
652                 if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
653                 if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
654                 }
655         else
656                 {
657                 if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
658                 if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
659                 }
660         
661         /* tmp1 := tmp1 + a*x */
662         if (group->a_is_minus3)
663                 {
664                 if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
665                 if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
666                 if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
667                 }
668         else
669                 {
670                 if (group->meth->field_decode)
671                         {
672                         if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
673                         if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
674                         }
675                 else
676                         {
677                         /* field_mul works on standard representation */
678                         if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
679                         }
680                 
681                 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
682                 }
683         
684         /* tmp1 := tmp1 + b */
685         if (group->meth->field_decode)
686                 {
687                 if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
688                 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
689                 }
690         else
691                 {
692                 if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
693                 }
694         
695         if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
696                 {
697                 unsigned long err = ERR_peek_error();
698                 
699                 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
700                         {
701                         (void)ERR_get_error();
702                         ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
703                         }
704                 else
705                         ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
706                 goto err;
707                 }
708
709         if (y_bit != BN_is_odd(y))
710                 {
711                 if (BN_is_zero(y))
712                         {
713                         int kron;
714
715                         kron = BN_kronecker(x, &group->field, ctx);
716                         if (kron == -2) goto err;
717
718                         if (kron == 1)
719                                 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
720                         else
721                                 /* BN_mod_sqrt() should have cought this error (not a square) */
722                                 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
723                         goto err;
724                         }
725                 if (!BN_usub(y, &group->field, y)) goto err;
726                 }
727         if (y_bit != BN_is_odd(y))
728                 {
729                 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
730                 goto err;
731                 }
732
733         if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
734
735         ret = 1;
736
737  err:
738         BN_CTX_end(ctx);
739         if (new_ctx != NULL)
740                 BN_CTX_free(new_ctx);
741         return ret;
742         }
743
744
745 size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
746         unsigned char *buf, size_t len, BN_CTX *ctx)
747         {
748         size_t ret;
749         BN_CTX *new_ctx = NULL;
750         int used_ctx = 0;
751         BIGNUM *x, *y;
752         size_t field_len, i, skip;
753
754         if ((form != POINT_CONVERSION_COMPRESSED)
755                 && (form != POINT_CONVERSION_UNCOMPRESSED)
756                 && (form != POINT_CONVERSION_HYBRID))
757                 {
758                 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
759                 goto err;
760                 }
761
762         if (EC_POINT_is_at_infinity(group, point))
763                 {
764                 /* encodes to a single 0 octet */
765                 if (buf != NULL)
766                         {
767                         if (len < 1)
768                                 {
769                                 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
770                                 return 0;
771                                 }
772                         buf[0] = 0;
773                         }
774                 return 1;
775                 }
776
777
778         /* ret := required output buffer length */
779         field_len = BN_num_bytes(&group->field);
780         ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
781
782         /* if 'buf' is NULL, just return required length */
783         if (buf != NULL)
784                 {
785                 if (len < ret)
786                         {
787                         ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
788                         goto err;
789                         }
790
791                 if (ctx == NULL)
792                         {
793                         ctx = new_ctx = BN_CTX_new();
794                         if (ctx == NULL)
795                                 return 0;
796                         }
797
798                 BN_CTX_start(ctx);
799                 used_ctx = 1;
800                 x = BN_CTX_get(ctx);
801                 y = BN_CTX_get(ctx);
802                 if (y == NULL) goto err;
803
804                 if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
805
806                 if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
807                         buf[0] = form + 1;
808                 else
809                         buf[0] = form;
810         
811                 i = 1;
812                 
813                 skip = field_len - BN_num_bytes(x);
814                 if (skip > field_len)
815                         {
816                         ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
817                         goto err;
818                         }
819                 while (skip > 0)
820                         {
821                         buf[i++] = 0;
822                         skip--;
823                         }
824                 skip = BN_bn2bin(x, buf + i);
825                 i += skip;
826                 if (i != 1 + field_len)
827                         {
828                         ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
829                         goto err;
830                         }
831
832                 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
833                         {
834                         skip = field_len - BN_num_bytes(y);
835                         if (skip > field_len)
836                                 {
837                                 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
838                                 goto err;
839                                 }
840                         while (skip > 0)
841                                 {
842                                 buf[i++] = 0;
843                                 skip--;
844                                 }
845                         skip = BN_bn2bin(y, buf + i);
846                         i += skip;
847                         }
848
849                 if (i != ret)
850                         {
851                         ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
852                         goto err;
853                         }
854                 }
855         
856         if (used_ctx)
857                 BN_CTX_end(ctx);
858         if (new_ctx != NULL)
859                 BN_CTX_free(new_ctx);
860         return ret;
861
862  err:
863         if (used_ctx)
864                 BN_CTX_end(ctx);
865         if (new_ctx != NULL)
866                 BN_CTX_free(new_ctx);
867         return 0;
868         }
869
870
871 int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
872         const unsigned char *buf, size_t len, BN_CTX *ctx)
873         {
874         point_conversion_form_t form;
875         int y_bit;
876         BN_CTX *new_ctx = NULL;
877         BIGNUM *x, *y;
878         size_t field_len, enc_len;
879         int ret = 0;
880
881         if (len == 0)
882                 {
883                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
884                 return 0;
885                 }
886         form = buf[0];
887         y_bit = form & 1;
888         form = form & ~1;
889         if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
890                 && (form != POINT_CONVERSION_UNCOMPRESSED)
891                 && (form != POINT_CONVERSION_HYBRID))
892                 {
893                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
894                 return 0;
895                 }
896         if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
897                 {
898                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
899                 return 0;
900                 }
901
902         if (form == 0)
903                 {
904                 if (len != 1)
905                         {
906                         ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
907                         return 0;
908                         }
909
910                 return EC_POINT_set_to_infinity(group, point);
911                 }
912         
913         field_len = BN_num_bytes(&group->field);
914         enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
915
916         if (len != enc_len)
917                 {
918                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
919                 return 0;
920                 }
921
922         if (ctx == NULL)
923                 {
924                 ctx = new_ctx = BN_CTX_new();
925                 if (ctx == NULL)
926                         return 0;
927                 }
928
929         BN_CTX_start(ctx);
930         x = BN_CTX_get(ctx);
931         y = BN_CTX_get(ctx);
932         if (y == NULL) goto err;
933
934         if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
935         if (BN_ucmp(x, &group->field) >= 0)
936                 {
937                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
938                 goto err;
939                 }
940
941         if (form == POINT_CONVERSION_COMPRESSED)
942                 {
943                 if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
944                 }
945         else
946                 {
947                 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
948                 if (BN_ucmp(y, &group->field) >= 0)
949                         {
950                         ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
951                         goto err;
952                         }
953                 if (form == POINT_CONVERSION_HYBRID)
954                         {
955                         if (y_bit != BN_is_odd(y))
956                                 {
957                                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
958                                 goto err;
959                                 }
960                         }
961
962                 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
963                 }
964         
965         if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
966                 {
967                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
968                 goto err;
969                 }
970
971         ret = 1;
972         
973  err:
974         BN_CTX_end(ctx);
975         if (new_ctx != NULL)
976                 BN_CTX_free(new_ctx);
977         return ret;
978         }
979
980
981 int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
982         {
983         int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
984         int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
985         const BIGNUM *p;
986         BN_CTX *new_ctx = NULL;
987         BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
988         int ret = 0;
989         
990         if (a == b)
991                 return EC_POINT_dbl(group, r, a, ctx);
992         if (EC_POINT_is_at_infinity(group, a))
993                 return EC_POINT_copy(r, b);
994         if (EC_POINT_is_at_infinity(group, b))
995                 return EC_POINT_copy(r, a);
996         
997         field_mul = group->meth->field_mul;
998         field_sqr = group->meth->field_sqr;
999         p = &group->field;
1000
1001         if (ctx == NULL)
1002                 {
1003                 ctx = new_ctx = BN_CTX_new();
1004                 if (ctx == NULL)
1005                         return 0;
1006                 }
1007
1008         BN_CTX_start(ctx);
1009         n0 = BN_CTX_get(ctx);
1010         n1 = BN_CTX_get(ctx);
1011         n2 = BN_CTX_get(ctx);
1012         n3 = BN_CTX_get(ctx);
1013         n4 = BN_CTX_get(ctx);
1014         n5 = BN_CTX_get(ctx);
1015         n6 = BN_CTX_get(ctx);
1016         if (n6 == NULL) goto end;
1017
1018         /* Note that in this function we must not read components of 'a' or 'b'
1019          * once we have written the corresponding components of 'r'.
1020          * ('r' might be one of 'a' or 'b'.)
1021          */
1022
1023         /* n1, n2 */
1024         if (b->Z_is_one)
1025                 {
1026                 if (!BN_copy(n1, &a->X)) goto end;
1027                 if (!BN_copy(n2, &a->Y)) goto end;
1028                 /* n1 = X_a */
1029                 /* n2 = Y_a */
1030                 }
1031         else
1032                 {
1033                 if (!field_sqr(group, n0, &b->Z, ctx)) goto end;
1034                 if (!field_mul(group, n1, &a->X, n0, ctx)) goto end;
1035                 /* n1 = X_a * Z_b^2 */
1036
1037                 if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end;
1038                 if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end;
1039                 /* n2 = Y_a * Z_b^3 */
1040                 }
1041
1042         /* n3, n4 */
1043         if (a->Z_is_one)
1044                 {
1045                 if (!BN_copy(n3, &b->X)) goto end;
1046                 if (!BN_copy(n4, &b->Y)) goto end;
1047                 /* n3 = X_b */
1048                 /* n4 = Y_b */
1049                 }
1050         else
1051                 {
1052                 if (!field_sqr(group, n0, &a->Z, ctx)) goto end;
1053                 if (!field_mul(group, n3, &b->X, n0, ctx)) goto end;
1054                 /* n3 = X_b * Z_a^2 */
1055
1056                 if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end;
1057                 if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end;
1058                 /* n4 = Y_b * Z_a^3 */
1059                 }
1060
1061         /* n5, n6 */
1062         if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end;
1063         if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end;
1064         /* n5 = n1 - n3 */
1065         /* n6 = n2 - n4 */
1066
1067         if (BN_is_zero(n5))
1068                 {
1069                 if (BN_is_zero(n6))
1070                         {
1071                         /* a is the same point as b */
1072                         BN_CTX_end(ctx);
1073                         ret = EC_POINT_dbl(group, r, a, ctx);
1074                         ctx = NULL;
1075                         goto end;
1076                         }
1077                 else
1078                         {
1079                         /* a is the inverse of b */
1080                         if (!BN_zero(&r->Z)) goto end;
1081                         r->Z_is_one = 0;
1082                         ret = 1;
1083                         goto end;
1084                         }
1085                 }
1086
1087         /* 'n7', 'n8' */
1088         if (!BN_mod_add_quick(n1, n1, n3, p)) goto end;
1089         if (!BN_mod_add_quick(n2, n2, n4, p)) goto end;
1090         /* 'n7' = n1 + n3 */
1091         /* 'n8' = n2 + n4 */
1092
1093         /* Z_r */
1094         if (a->Z_is_one && b->Z_is_one)
1095                 {
1096                 if (!BN_copy(&r->Z, n5)) goto end;
1097                 }
1098         else
1099                 {
1100                 if (a->Z_is_one)
1101                         { if (!BN_copy(n0, &b->Z)) goto end; }
1102                 else if (b->Z_is_one)
1103                         { if (!BN_copy(n0, &a->Z)) goto end; }
1104                 else
1105                         { if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; }
1106                 if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end;
1107                 }
1108         r->Z_is_one = 0;
1109         /* Z_r = Z_a * Z_b * n5 */
1110
1111         /* X_r */
1112         if (!field_sqr(group, n0, n6, ctx)) goto end;
1113         if (!field_sqr(group, n4, n5, ctx)) goto end;
1114         if (!field_mul(group, n3, n1, n4, ctx)) goto end;
1115         if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end;
1116         /* X_r = n6^2 - n5^2 * 'n7' */
1117         
1118         /* 'n9' */
1119         if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end;
1120         if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end;
1121         /* n9 = n5^2 * 'n7' - 2 * X_r */
1122
1123         /* Y_r */
1124         if (!field_mul(group, n0, n0, n6, ctx)) goto end;
1125         if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */
1126         if (!field_mul(group, n1, n2, n5, ctx)) goto end;
1127         if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end;
1128         if (BN_is_odd(n0))
1129                 if (!BN_add(n0, n0, p)) goto end;
1130         /* now  0 <= n0 < 2*p,  and n0 is even */
1131         if (!BN_rshift1(&r->Y, n0)) goto end;
1132         /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
1133
1134         ret = 1;
1135
1136  end:
1137         if (ctx) /* otherwise we already called BN_CTX_end */
1138                 BN_CTX_end(ctx);
1139         if (new_ctx != NULL)
1140                 BN_CTX_free(new_ctx);
1141         return ret;
1142         }
1143
1144
1145 int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
1146         {
1147         int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1148         int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1149         const BIGNUM *p;
1150         BN_CTX *new_ctx = NULL;
1151         BIGNUM *n0, *n1, *n2, *n3;
1152         int ret = 0;
1153         
1154         if (EC_POINT_is_at_infinity(group, a))
1155                 {
1156                 if (!BN_zero(&r->Z)) return 0;
1157                 r->Z_is_one = 0;
1158                 return 1;
1159                 }
1160
1161         field_mul = group->meth->field_mul;
1162         field_sqr = group->meth->field_sqr;
1163         p = &group->field;
1164
1165         if (ctx == NULL)
1166                 {
1167                 ctx = new_ctx = BN_CTX_new();
1168                 if (ctx == NULL)
1169                         return 0;
1170                 }
1171
1172         BN_CTX_start(ctx);
1173         n0 = BN_CTX_get(ctx);
1174         n1 = BN_CTX_get(ctx);
1175         n2 = BN_CTX_get(ctx);
1176         n3 = BN_CTX_get(ctx);
1177         if (n3 == NULL) goto err;
1178
1179         /* Note that in this function we must not read components of 'a'
1180          * once we have written the corresponding components of 'r'.
1181          * ('r' might the same as 'a'.)
1182          */
1183
1184         /* n1 */
1185         if (a->Z_is_one)
1186                 {
1187                 if (!field_sqr(group, n0, &a->X, ctx)) goto err;
1188                 if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
1189                 if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
1190                 if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err;
1191                 /* n1 = 3 * X_a^2 + a_curve */
1192                 }
1193         else if (group->a_is_minus3)
1194                 {
1195                 if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
1196                 if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err;
1197                 if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err;
1198                 if (!field_mul(group, n1, n0, n2, ctx)) goto err;
1199                 if (!BN_mod_lshift1_quick(n0, n1, p)) goto err;
1200                 if (!BN_mod_add_quick(n1, n0, n1, p)) goto err;
1201                 /* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
1202                  *    = 3 * X_a^2 - 3 * Z_a^4 */
1203                 }
1204         else
1205                 {
1206                 if (!field_sqr(group, n0, &a->X, ctx)) goto err;
1207                 if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
1208                 if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
1209                 if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
1210                 if (!field_sqr(group, n1, n1, ctx)) goto err;
1211                 if (!field_mul(group, n1, n1, &group->a, ctx)) goto err;
1212                 if (!BN_mod_add_quick(n1, n1, n0, p)) goto err;
1213                 /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
1214                 }
1215
1216         /* Z_r */
1217         if (a->Z_is_one)
1218                 {
1219                 if (!BN_copy(n0, &a->Y)) goto err;
1220                 }
1221         else
1222                 {
1223                 if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err;
1224                 }
1225         if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err;
1226         r->Z_is_one = 0;
1227         /* Z_r = 2 * Y_a * Z_a */
1228
1229         /* n2 */
1230         if (!field_sqr(group, n3, &a->Y, ctx)) goto err;
1231         if (!field_mul(group, n2, &a->X, n3, ctx)) goto err;
1232         if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err;
1233         /* n2 = 4 * X_a * Y_a^2 */
1234
1235         /* X_r */
1236         if (!BN_mod_lshift1_quick(n0, n2, p)) goto err;
1237         if (!field_sqr(group, &r->X, n1, ctx)) goto err;
1238         if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err;
1239         /* X_r = n1^2 - 2 * n2 */
1240         
1241         /* n3 */
1242         if (!field_sqr(group, n0, n3, ctx)) goto err;
1243         if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err;
1244         /* n3 = 8 * Y_a^4 */
1245         
1246         /* Y_r */
1247         if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err;
1248         if (!field_mul(group, n0, n1, n0, ctx)) goto err;
1249         if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err;
1250         /* Y_r = n1 * (n2 - X_r) - n3 */
1251
1252         ret = 1;
1253
1254  err:
1255         BN_CTX_end(ctx);
1256         if (new_ctx != NULL)
1257                 BN_CTX_free(new_ctx);
1258         return ret;
1259         }
1260
1261
1262 int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1263         {
1264         if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
1265                 /* point is its own inverse */
1266                 return 1;
1267         
1268         return BN_usub(&point->Y, &group->field, &point->Y);
1269         }
1270
1271
1272 int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
1273         {
1274         return BN_is_zero(&point->Z);
1275         }
1276
1277
1278 int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
1279         {
1280         int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1281         int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1282         const BIGNUM *p;
1283         BN_CTX *new_ctx = NULL;
1284         BIGNUM *rh, *tmp1, *tmp2, *Z4, *Z6;
1285         int ret = -1;
1286
1287         if (EC_POINT_is_at_infinity(group, point))
1288                 return 1;
1289         
1290         field_mul = group->meth->field_mul;
1291         field_sqr = group->meth->field_sqr;
1292         p = &group->field;
1293
1294         if (ctx == NULL)
1295                 {
1296                 ctx = new_ctx = BN_CTX_new();
1297                 if (ctx == NULL)
1298                         return -1;
1299                 }
1300
1301         BN_CTX_start(ctx);
1302         rh = BN_CTX_get(ctx);
1303         tmp1 = BN_CTX_get(ctx);
1304         tmp2 = BN_CTX_get(ctx);
1305         Z4 = BN_CTX_get(ctx);
1306         Z6 = BN_CTX_get(ctx);
1307         if (Z6 == NULL) goto err;
1308
1309         /* We have a curve defined by a Weierstrass equation
1310          *      y^2 = x^3 + a*x + b.
1311          * The point to consider is given in Jacobian projective coordinates
1312          * where  (X, Y, Z)  represents  (x, y) = (X/Z^2, Y/Z^3).
1313          * Substituting this and multiplying by  Z^6  transforms the above equation into
1314          *      Y^2 = X^3 + a*X*Z^4 + b*Z^6.
1315          * To test this, we add up the right-hand side in 'rh'.
1316          */
1317
1318         /* rh := X^3 */
1319         if (!field_sqr(group, rh, &point->X, ctx)) goto err;
1320         if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1321
1322         if (!point->Z_is_one)
1323                 {
1324                 if (!field_sqr(group, tmp1, &point->Z, ctx)) goto err;
1325                 if (!field_sqr(group, Z4, tmp1, ctx)) goto err;
1326                 if (!field_mul(group, Z6, Z4, tmp1, ctx)) goto err;
1327
1328                 /* rh := rh + a*X*Z^4 */
1329                 if (!field_mul(group, tmp1, &point->X, Z4, ctx)) goto err;
1330                 if (group->a_is_minus3)
1331                         {
1332                         if (!BN_mod_lshift1_quick(tmp2, tmp1, p)) goto err;
1333                         if (!BN_mod_add_quick(tmp2, tmp2, tmp1, p)) goto err;
1334                         if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err;
1335                         }
1336                 else
1337                         {
1338                         if (!field_mul(group, tmp2, tmp1, &group->a, ctx)) goto err;
1339                         if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err;
1340                         }
1341
1342                 /* rh := rh + b*Z^6 */
1343                 if (!field_mul(group, tmp1, &group->b, Z6, ctx)) goto err;
1344                 if (!BN_mod_add_quick(rh, rh, tmp1, p)) goto err;
1345                 }
1346         else
1347                 {
1348                 /* point->Z_is_one */
1349
1350                 /* rh := rh + a*X */
1351                 if (group->a_is_minus3)
1352                         {
1353                         if (!BN_mod_lshift1_quick(tmp2, &point->X, p)) goto err;
1354                         if (!BN_mod_add_quick(tmp2, tmp2, &point->X, p)) goto err;
1355                         if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err;
1356                         }
1357                 else
1358                         {
1359                         if (!field_mul(group, tmp2, &point->X, &group->a, ctx)) goto err;
1360                         if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err;
1361                         }
1362
1363                 /* rh := rh + b */
1364                 if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err;
1365                 }
1366
1367         /* 'lh' := Y^2 */
1368         if (!field_sqr(group, tmp1, &point->Y, ctx)) goto err;
1369
1370         ret = (0 == BN_cmp(tmp1, rh));
1371
1372  err:
1373         BN_CTX_end(ctx);
1374         if (new_ctx != NULL)
1375                 BN_CTX_free(new_ctx);
1376         return ret;
1377         }
1378
1379
1380 int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
1381         {
1382         /* return values:
1383          *  -1   error
1384          *   0   equal (in affine coordinates)
1385          *   1   not equal
1386          */
1387
1388         int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1389         int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1390         BN_CTX *new_ctx = NULL;
1391         BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
1392         const BIGNUM *tmp1_, *tmp2_;
1393         int ret = -1;
1394         
1395         if (EC_POINT_is_at_infinity(group, a))
1396                 {
1397                 return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
1398                 }
1399         
1400         if (a->Z_is_one && b->Z_is_one)
1401                 {
1402                 return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
1403                 }
1404
1405         field_mul = group->meth->field_mul;
1406         field_sqr = group->meth->field_sqr;
1407
1408         if (ctx == NULL)
1409                 {
1410                 ctx = new_ctx = BN_CTX_new();
1411                 if (ctx == NULL)
1412                         return -1;
1413                 }
1414
1415         BN_CTX_start(ctx);
1416         tmp1 = BN_CTX_get(ctx);
1417         tmp2 = BN_CTX_get(ctx);
1418         Za23 = BN_CTX_get(ctx);
1419         Zb23 = BN_CTX_get(ctx);
1420         if (Zb23 == NULL) goto end;
1421
1422         /* We have to decide whether
1423          *     (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
1424          * or equivalently, whether
1425          *     (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
1426          */
1427
1428         if (!b->Z_is_one)
1429                 {
1430                 if (!field_sqr(group, Zb23, &b->Z, ctx)) goto end;
1431                 if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) goto end;
1432                 tmp1_ = tmp1;
1433                 }
1434         else
1435                 tmp1_ = &a->X;
1436         if (!a->Z_is_one)
1437                 {
1438                 if (!field_sqr(group, Za23, &a->Z, ctx)) goto end;
1439                 if (!field_mul(group, tmp2, &b->X, Za23, ctx)) goto end;
1440                 tmp2_ = tmp2;
1441                 }
1442         else
1443                 tmp2_ = &b->X;
1444         
1445         /* compare  X_a*Z_b^2  with  X_b*Z_a^2 */
1446         if (BN_cmp(tmp1_, tmp2_) != 0)
1447                 {
1448                 ret = 1; /* points differ */
1449                 goto end;
1450                 }
1451
1452
1453         if (!b->Z_is_one)
1454                 {
1455                 if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) goto end;
1456                 if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) goto end;
1457                 /* tmp1_ = tmp1 */
1458                 }
1459         else
1460                 tmp1_ = &a->Y;
1461         if (!a->Z_is_one)
1462                 {
1463                 if (!field_mul(group, Za23, Za23, &a->Z, ctx)) goto end;
1464                 if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) goto end;
1465                 /* tmp2_ = tmp2 */
1466                 }
1467         else
1468                 tmp2_ = &b->Y;
1469
1470         /* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */
1471         if (BN_cmp(tmp1_, tmp2_) != 0)
1472                 {
1473                 ret = 1; /* points differ */
1474                 goto end;
1475                 }
1476
1477         /* points are equal */
1478         ret = 0;
1479
1480  end:
1481         BN_CTX_end(ctx);
1482         if (new_ctx != NULL)
1483                 BN_CTX_free(new_ctx);
1484         return ret;
1485         }
1486
1487
1488 int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1489         {
1490         BN_CTX *new_ctx = NULL;
1491         BIGNUM *x, *y;
1492         int ret = 0;
1493
1494         if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
1495                 return 1;
1496
1497         if (ctx == NULL)
1498                 {
1499                 ctx = new_ctx = BN_CTX_new();
1500                 if (ctx == NULL)
1501                         return 0;
1502                 }
1503
1504         BN_CTX_start(ctx);
1505         x = BN_CTX_get(ctx);
1506         y = BN_CTX_get(ctx);
1507         if (y == NULL) goto err;
1508
1509         if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
1510         if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
1511         if (!point->Z_is_one)
1512                 {
1513                 ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
1514                 goto err;
1515                 }
1516         
1517         ret = 1;
1518
1519  err:
1520         BN_CTX_end(ctx);
1521         if (new_ctx != NULL)
1522                 BN_CTX_free(new_ctx);
1523         return ret;
1524         }
1525
1526
1527 int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
1528         {
1529         BN_CTX *new_ctx = NULL;
1530         BIGNUM *tmp0, *tmp1;
1531         size_t pow2 = 0;
1532         BIGNUM **heap = NULL;
1533         size_t i;
1534         int ret = 0;
1535
1536         if (num == 0)
1537                 return 1;
1538
1539         if (ctx == NULL)
1540                 {
1541                 ctx = new_ctx = BN_CTX_new();
1542                 if (ctx == NULL)
1543                         return 0;
1544                 }
1545
1546         BN_CTX_start(ctx);
1547         tmp0 = BN_CTX_get(ctx);
1548         tmp1 = BN_CTX_get(ctx);
1549         if (tmp0  == NULL || tmp1 == NULL) goto err;
1550
1551         /* Before converting the individual points, compute inverses of all Z values.
1552          * Modular inversion is rather slow, but luckily we can do with a single
1553          * explicit inversion, plus about 3 multiplications per input value.
1554          */
1555
1556         pow2 = 1;
1557         while (num > pow2)
1558                 pow2 <<= 1;
1559         /* Now pow2 is the smallest power of 2 satifsying pow2 >= num.
1560          * We need twice that. */
1561         pow2 <<= 1;
1562
1563         heap = OPENSSL_malloc(pow2 * sizeof heap[0]);
1564         if (heap == NULL) goto err;
1565         
1566         /* The array is used as a binary tree, exactly as in heapsort:
1567          *
1568          *                               heap[1]
1569          *                 heap[2]                     heap[3]
1570          *          heap[4]       heap[5]       heap[6]       heap[7]
1571          *   heap[8]heap[9] heap[10]heap[11] heap[12]heap[13] heap[14] heap[15]
1572          *
1573          * We put the Z's in the last line;
1574          * then we set each other node to the product of its two child-nodes (where
1575          * empty or 0 entries are treated as ones);
1576          * then we invert heap[1];
1577          * then we invert each other node by replacing it by the product of its
1578          * parent (after inversion) and its sibling (before inversion).
1579          */
1580         heap[0] = NULL;
1581         for (i = pow2/2 - 1; i > 0; i--)
1582                 heap[i] = NULL;
1583         for (i = 0; i < num; i++)
1584                 heap[pow2/2 + i] = &points[i]->Z;
1585         for (i = pow2/2 + num; i < pow2; i++)
1586                 heap[i] = NULL;
1587         
1588         /* set each node to the product of its children */
1589         for (i = pow2/2 - 1; i > 0; i--)
1590                 {
1591                 heap[i] = BN_new();
1592                 if (heap[i] == NULL) goto err;
1593                 
1594                 if (heap[2*i] != NULL)
1595                         {
1596                         if ((heap[2*i + 1] == NULL) || BN_is_zero(heap[2*i + 1]))
1597                                 {
1598                                 if (!BN_copy(heap[i], heap[2*i])) goto err;
1599                                 }
1600                         else
1601                                 {
1602                                 if (BN_is_zero(heap[2*i]))
1603                                         {
1604                                         if (!BN_copy(heap[i], heap[2*i + 1])) goto err;
1605                                         }
1606                                 else
1607                                         {
1608                                         if (!group->meth->field_mul(group, heap[i],
1609                                                 heap[2*i], heap[2*i + 1], ctx)) goto err;
1610                                         }
1611                                 }
1612                         }
1613                 }
1614
1615         /* invert heap[1] */
1616         if (!BN_is_zero(heap[1]))
1617                 {
1618                 if (!BN_mod_inverse(heap[1], heap[1], &group->field, ctx))
1619                         {
1620                         ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
1621                         goto err;
1622                         }
1623                 }
1624         if (group->meth->field_encode != 0)
1625                 {
1626                 /* in the Montgomery case, we just turned  R*H  (representing H)
1627                  * into  1/(R*H),  but we need  R*(1/H)  (representing 1/H);
1628                  * i.e. we have need to multiply by the Montgomery factor twice */
1629                 if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
1630                 if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
1631                 }
1632
1633         /* set other heap[i]'s to their inverses */
1634         for (i = 2; i < pow2/2 + num; i += 2)
1635                 {
1636                 /* i is even */
1637                 if ((heap[i + 1] != NULL) && !BN_is_zero(heap[i + 1]))
1638                         {
1639                         if (!group->meth->field_mul(group, tmp0, heap[i/2], heap[i + 1], ctx)) goto err;
1640                         if (!group->meth->field_mul(group, tmp1, heap[i/2], heap[i], ctx)) goto err;
1641                         if (!BN_copy(heap[i], tmp0)) goto err;
1642                         if (!BN_copy(heap[i + 1], tmp1)) goto err;
1643                         }
1644                 else
1645                         {
1646                         if (!BN_copy(heap[i], heap[i/2])) goto err;
1647                         }
1648                 }
1649
1650         /* we have replaced all non-zero Z's by their inverses, now fix up all the points */
1651         for (i = 0; i < num; i++)
1652                 {
1653                 EC_POINT *p = points[i];
1654                 
1655                 if (!BN_is_zero(&p->Z))
1656                         {
1657                         /* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */
1658
1659                         if (!group->meth->field_sqr(group, tmp1, &p->Z, ctx)) goto err;
1660                         if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx)) goto err;
1661
1662                         if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx)) goto err;
1663                         if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx)) goto err;
1664                 
1665                         if (group->meth->field_set_to_one != 0)
1666                                 {
1667                                 if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err;
1668                                 }
1669                         else
1670                                 {
1671                                 if (!BN_one(&p->Z)) goto err;
1672                                 }
1673                         p->Z_is_one = 1;
1674                         }
1675                 }
1676
1677         ret = 1;
1678                 
1679  err:
1680         BN_CTX_end(ctx);
1681         if (new_ctx != NULL)
1682                 BN_CTX_free(new_ctx);
1683         if (heap != NULL)
1684                 {
1685                 /* heap[pow2/2] .. heap[pow2-1] have not been allocated locally! */
1686                 for (i = pow2/2 - 1; i > 0; i--)
1687                         {
1688                         if (heap[i] != NULL)
1689                                 BN_clear_free(heap[i]);
1690                         }
1691                 OPENSSL_free(heap);
1692                 }
1693         return ret;
1694         }
1695
1696
1697 int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1698         {
1699         return BN_mod_mul(r, a, b, &group->field, ctx);
1700         }
1701
1702
1703 int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
1704         {
1705         return BN_mod_sqr(r, a, &group->field, ctx);
1706         }