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