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