fix memory leaks
[openssl.git] / crypto / ec / ecp_smpl.c
1 /*
2  * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 /* ====================================================================
11  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
12  * Portions of this software developed by SUN MICROSYSTEMS, INC.,
13  * and contributed to the OpenSSL project.
14  */
15
16 #include <openssl/err.h>
17 #include <openssl/symhacks.h>
18
19 #include "ec_lcl.h"
20
21 const EC_METHOD *EC_GFp_simple_method(void)
22 {
23     static const EC_METHOD ret = {
24         EC_FLAGS_DEFAULT_OCT,
25         NID_X9_62_prime_field,
26         ec_GFp_simple_group_init,
27         ec_GFp_simple_group_finish,
28         ec_GFp_simple_group_clear_finish,
29         ec_GFp_simple_group_copy,
30         ec_GFp_simple_group_set_curve,
31         ec_GFp_simple_group_get_curve,
32         ec_GFp_simple_group_get_degree,
33         ec_group_simple_order_bits,
34         ec_GFp_simple_group_check_discriminant,
35         ec_GFp_simple_point_init,
36         ec_GFp_simple_point_finish,
37         ec_GFp_simple_point_clear_finish,
38         ec_GFp_simple_point_copy,
39         ec_GFp_simple_point_set_to_infinity,
40         ec_GFp_simple_set_Jprojective_coordinates_GFp,
41         ec_GFp_simple_get_Jprojective_coordinates_GFp,
42         ec_GFp_simple_point_set_affine_coordinates,
43         ec_GFp_simple_point_get_affine_coordinates,
44         0, 0, 0,
45         ec_GFp_simple_add,
46         ec_GFp_simple_dbl,
47         ec_GFp_simple_invert,
48         ec_GFp_simple_is_at_infinity,
49         ec_GFp_simple_is_on_curve,
50         ec_GFp_simple_cmp,
51         ec_GFp_simple_make_affine,
52         ec_GFp_simple_points_make_affine,
53         0 /* mul */ ,
54         0 /* precompute_mult */ ,
55         0 /* have_precompute_mult */ ,
56         ec_GFp_simple_field_mul,
57         ec_GFp_simple_field_sqr,
58         0 /* field_div */ ,
59         0 /* field_encode */ ,
60         0 /* field_decode */ ,
61         0,                      /* field_set_to_one */
62         ec_key_simple_priv2oct,
63         ec_key_simple_oct2priv,
64         0, /* set private */
65         ec_key_simple_generate_key,
66         ec_key_simple_check_key,
67         ec_key_simple_generate_public_key,
68         0, /* keycopy */
69         0, /* keyfinish */
70         ecdh_simple_compute_key
71     };
72
73     return &ret;
74 }
75
76 /*
77  * Most method functions in this file are designed to work with
78  * non-trivial representations of field elements if necessary
79  * (see ecp_mont.c): while standard modular addition and subtraction
80  * are used, the field_mul and field_sqr methods will be used for
81  * multiplication, and field_encode and field_decode (if defined)
82  * will be used for converting between representations.
83  *
84  * Functions ec_GFp_simple_points_make_affine() and
85  * ec_GFp_simple_point_get_affine_coordinates() specifically assume
86  * that if a non-trivial representation is used, it is a Montgomery
87  * representation (i.e. 'encoding' means multiplying by some factor R).
88  */
89
90 int ec_GFp_simple_group_init(EC_GROUP *group)
91 {
92     group->field = BN_new();
93     group->a = BN_new();
94     group->b = BN_new();
95     if (group->field == NULL || group->a == NULL || group->b == NULL) {
96         BN_free(group->field);
97         BN_free(group->a);
98         BN_free(group->b);
99         return 0;
100     }
101     group->a_is_minus3 = 0;
102     return 1;
103 }
104
105 void ec_GFp_simple_group_finish(EC_GROUP *group)
106 {
107     BN_free(group->field);
108     BN_free(group->a);
109     BN_free(group->b);
110 }
111
112 void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
113 {
114     BN_clear_free(group->field);
115     BN_clear_free(group->a);
116     BN_clear_free(group->b);
117 }
118
119 int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
120 {
121     if (!BN_copy(dest->field, src->field))
122         return 0;
123     if (!BN_copy(dest->a, src->a))
124         return 0;
125     if (!BN_copy(dest->b, src->b))
126         return 0;
127
128     dest->a_is_minus3 = src->a_is_minus3;
129
130     return 1;
131 }
132
133 int ec_GFp_simple_group_set_curve(EC_GROUP *group,
134                                   const BIGNUM *p, const BIGNUM *a,
135                                   const BIGNUM *b, BN_CTX *ctx)
136 {
137     int ret = 0;
138     BN_CTX *new_ctx = NULL;
139     BIGNUM *tmp_a;
140
141     /* p must be a prime > 3 */
142     if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) {
143         ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
144         return 0;
145     }
146
147     if (ctx == NULL) {
148         ctx = new_ctx = BN_CTX_new();
149         if (ctx == NULL)
150             return 0;
151     }
152
153     BN_CTX_start(ctx);
154     tmp_a = BN_CTX_get(ctx);
155     if (tmp_a == NULL)
156         goto err;
157
158     /* group->field */
159     if (!BN_copy(group->field, p))
160         goto err;
161     BN_set_negative(group->field, 0);
162
163     /* group->a */
164     if (!BN_nnmod(tmp_a, a, p, ctx))
165         goto err;
166     if (group->meth->field_encode) {
167         if (!group->meth->field_encode(group, group->a, tmp_a, ctx))
168             goto err;
169     } else if (!BN_copy(group->a, tmp_a))
170         goto err;
171
172     /* group->b */
173     if (!BN_nnmod(group->b, b, p, ctx))
174         goto err;
175     if (group->meth->field_encode)
176         if (!group->meth->field_encode(group, group->b, group->b, ctx))
177             goto err;
178
179     /* group->a_is_minus3 */
180     if (!BN_add_word(tmp_a, 3))
181         goto err;
182     group->a_is_minus3 = (0 == BN_cmp(tmp_a, group->field));
183
184     ret = 1;
185
186  err:
187     BN_CTX_end(ctx);
188     BN_CTX_free(new_ctx);
189     return ret;
190 }
191
192 int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
193                                   BIGNUM *b, BN_CTX *ctx)
194 {
195     int ret = 0;
196     BN_CTX *new_ctx = NULL;
197
198     if (p != NULL) {
199         if (!BN_copy(p, group->field))
200             return 0;
201     }
202
203     if (a != NULL || b != NULL) {
204         if (group->meth->field_decode) {
205             if (ctx == NULL) {
206                 ctx = new_ctx = BN_CTX_new();
207                 if (ctx == NULL)
208                     return 0;
209             }
210             if (a != NULL) {
211                 if (!group->meth->field_decode(group, a, group->a, ctx))
212                     goto err;
213             }
214             if (b != NULL) {
215                 if (!group->meth->field_decode(group, b, group->b, ctx))
216                     goto err;
217             }
218         } else {
219             if (a != NULL) {
220                 if (!BN_copy(a, group->a))
221                     goto err;
222             }
223             if (b != NULL) {
224                 if (!BN_copy(b, group->b))
225                     goto err;
226             }
227         }
228     }
229
230     ret = 1;
231
232  err:
233     BN_CTX_free(new_ctx);
234     return ret;
235 }
236
237 int ec_GFp_simple_group_get_degree(const EC_GROUP *group)
238 {
239     return BN_num_bits(group->field);
240 }
241
242 int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
243 {
244     int ret = 0;
245     BIGNUM *a, *b, *order, *tmp_1, *tmp_2;
246     const BIGNUM *p = group->field;
247     BN_CTX *new_ctx = NULL;
248
249     if (ctx == NULL) {
250         ctx = new_ctx = BN_CTX_new();
251         if (ctx == NULL) {
252             ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT,
253                   ERR_R_MALLOC_FAILURE);
254             goto err;
255         }
256     }
257     BN_CTX_start(ctx);
258     a = BN_CTX_get(ctx);
259     b = BN_CTX_get(ctx);
260     tmp_1 = BN_CTX_get(ctx);
261     tmp_2 = BN_CTX_get(ctx);
262     order = BN_CTX_get(ctx);
263     if (order == NULL)
264         goto err;
265
266     if (group->meth->field_decode) {
267         if (!group->meth->field_decode(group, a, group->a, ctx))
268             goto err;
269         if (!group->meth->field_decode(group, b, group->b, ctx))
270             goto err;
271     } else {
272         if (!BN_copy(a, group->a))
273             goto err;
274         if (!BN_copy(b, group->b))
275             goto err;
276     }
277
278     /*-
279      * check the discriminant:
280      * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
281      * 0 =< a, b < p
282      */
283     if (BN_is_zero(a)) {
284         if (BN_is_zero(b))
285             goto err;
286     } else if (!BN_is_zero(b)) {
287         if (!BN_mod_sqr(tmp_1, a, p, ctx))
288             goto err;
289         if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx))
290             goto err;
291         if (!BN_lshift(tmp_1, tmp_2, 2))
292             goto err;
293         /* tmp_1 = 4*a^3 */
294
295         if (!BN_mod_sqr(tmp_2, b, p, ctx))
296             goto err;
297         if (!BN_mul_word(tmp_2, 27))
298             goto err;
299         /* tmp_2 = 27*b^2 */
300
301         if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx))
302             goto err;
303         if (BN_is_zero(a))
304             goto err;
305     }
306     ret = 1;
307
308  err:
309     if (ctx != NULL)
310         BN_CTX_end(ctx);
311     BN_CTX_free(new_ctx);
312     return ret;
313 }
314
315 int ec_GFp_simple_point_init(EC_POINT *point)
316 {
317     point->X = BN_new();
318     point->Y = BN_new();
319     point->Z = BN_new();
320     point->Z_is_one = 0;
321
322     if (point->X == NULL || point->Y == NULL || point->Z == NULL) {
323         BN_free(point->X);
324         BN_free(point->Y);
325         BN_free(point->Z);
326         return 0;
327     }
328     return 1;
329 }
330
331 void ec_GFp_simple_point_finish(EC_POINT *point)
332 {
333     BN_free(point->X);
334     BN_free(point->Y);
335     BN_free(point->Z);
336 }
337
338 void ec_GFp_simple_point_clear_finish(EC_POINT *point)
339 {
340     BN_clear_free(point->X);
341     BN_clear_free(point->Y);
342     BN_clear_free(point->Z);
343     point->Z_is_one = 0;
344 }
345
346 int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
347 {
348     if (!BN_copy(dest->X, src->X))
349         return 0;
350     if (!BN_copy(dest->Y, src->Y))
351         return 0;
352     if (!BN_copy(dest->Z, src->Z))
353         return 0;
354     dest->Z_is_one = src->Z_is_one;
355
356     return 1;
357 }
358
359 int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group,
360                                         EC_POINT *point)
361 {
362     point->Z_is_one = 0;
363     BN_zero(point->Z);
364     return 1;
365 }
366
367 int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
368                                                   EC_POINT *point,
369                                                   const BIGNUM *x,
370                                                   const BIGNUM *y,
371                                                   const BIGNUM *z,
372                                                   BN_CTX *ctx)
373 {
374     BN_CTX *new_ctx = NULL;
375     int ret = 0;
376
377     if (ctx == NULL) {
378         ctx = new_ctx = BN_CTX_new();
379         if (ctx == NULL)
380             return 0;
381     }
382
383     if (x != NULL) {
384         if (!BN_nnmod(point->X, x, group->field, ctx))
385             goto err;
386         if (group->meth->field_encode) {
387             if (!group->meth->field_encode(group, point->X, point->X, ctx))
388                 goto err;
389         }
390     }
391
392     if (y != NULL) {
393         if (!BN_nnmod(point->Y, y, group->field, ctx))
394             goto err;
395         if (group->meth->field_encode) {
396             if (!group->meth->field_encode(group, point->Y, point->Y, ctx))
397                 goto err;
398         }
399     }
400
401     if (z != NULL) {
402         int Z_is_one;
403
404         if (!BN_nnmod(point->Z, z, group->field, ctx))
405             goto err;
406         Z_is_one = BN_is_one(point->Z);
407         if (group->meth->field_encode) {
408             if (Z_is_one && (group->meth->field_set_to_one != 0)) {
409                 if (!group->meth->field_set_to_one(group, point->Z, ctx))
410                     goto err;
411             } else {
412                 if (!group->
413                     meth->field_encode(group, point->Z, point->Z, ctx))
414                     goto err;
415             }
416         }
417         point->Z_is_one = Z_is_one;
418     }
419
420     ret = 1;
421
422  err:
423     BN_CTX_free(new_ctx);
424     return ret;
425 }
426
427 int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
428                                                   const EC_POINT *point,
429                                                   BIGNUM *x, BIGNUM *y,
430                                                   BIGNUM *z, BN_CTX *ctx)
431 {
432     BN_CTX *new_ctx = NULL;
433     int ret = 0;
434
435     if (group->meth->field_decode != 0) {
436         if (ctx == NULL) {
437             ctx = new_ctx = BN_CTX_new();
438             if (ctx == NULL)
439                 return 0;
440         }
441
442         if (x != NULL) {
443             if (!group->meth->field_decode(group, x, point->X, ctx))
444                 goto err;
445         }
446         if (y != NULL) {
447             if (!group->meth->field_decode(group, y, point->Y, ctx))
448                 goto err;
449         }
450         if (z != NULL) {
451             if (!group->meth->field_decode(group, z, point->Z, ctx))
452                 goto err;
453         }
454     } else {
455         if (x != NULL) {
456             if (!BN_copy(x, point->X))
457                 goto err;
458         }
459         if (y != NULL) {
460             if (!BN_copy(y, point->Y))
461                 goto err;
462         }
463         if (z != NULL) {
464             if (!BN_copy(z, point->Z))
465                 goto err;
466         }
467     }
468
469     ret = 1;
470
471  err:
472     BN_CTX_free(new_ctx);
473     return ret;
474 }
475
476 int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group,
477                                                EC_POINT *point,
478                                                const BIGNUM *x,
479                                                const BIGNUM *y, BN_CTX *ctx)
480 {
481     if (x == NULL || y == NULL) {
482         /*
483          * unlike for projective coordinates, we do not tolerate this
484          */
485         ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES,
486               ERR_R_PASSED_NULL_PARAMETER);
487         return 0;
488     }
489
490     return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y,
491                                                     BN_value_one(), ctx);
492 }
493
494 int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
495                                                const EC_POINT *point,
496                                                BIGNUM *x, BIGNUM *y,
497                                                BN_CTX *ctx)
498 {
499     BN_CTX *new_ctx = NULL;
500     BIGNUM *Z, *Z_1, *Z_2, *Z_3;
501     const BIGNUM *Z_;
502     int ret = 0;
503
504     if (EC_POINT_is_at_infinity(group, point)) {
505         ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,
506               EC_R_POINT_AT_INFINITY);
507         return 0;
508     }
509
510     if (ctx == NULL) {
511         ctx = new_ctx = BN_CTX_new();
512         if (ctx == NULL)
513             return 0;
514     }
515
516     BN_CTX_start(ctx);
517     Z = BN_CTX_get(ctx);
518     Z_1 = BN_CTX_get(ctx);
519     Z_2 = BN_CTX_get(ctx);
520     Z_3 = BN_CTX_get(ctx);
521     if (Z_3 == NULL)
522         goto err;
523
524     /* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */
525
526     if (group->meth->field_decode) {
527         if (!group->meth->field_decode(group, Z, point->Z, ctx))
528             goto err;
529         Z_ = Z;
530     } else {
531         Z_ = point->Z;
532     }
533
534     if (BN_is_one(Z_)) {
535         if (group->meth->field_decode) {
536             if (x != NULL) {
537                 if (!group->meth->field_decode(group, x, point->X, ctx))
538                     goto err;
539             }
540             if (y != NULL) {
541                 if (!group->meth->field_decode(group, y, point->Y, ctx))
542                     goto err;
543             }
544         } else {
545             if (x != NULL) {
546                 if (!BN_copy(x, point->X))
547                     goto err;
548             }
549             if (y != NULL) {
550                 if (!BN_copy(y, point->Y))
551                     goto err;
552             }
553         }
554     } else {
555         if (!BN_mod_inverse(Z_1, Z_, group->field, ctx)) {
556             ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,
557                   ERR_R_BN_LIB);
558             goto err;
559         }
560
561         if (group->meth->field_encode == 0) {
562             /* field_sqr works on standard representation */
563             if (!group->meth->field_sqr(group, Z_2, Z_1, ctx))
564                 goto err;
565         } else {
566             if (!BN_mod_sqr(Z_2, Z_1, group->field, ctx))
567                 goto err;
568         }
569
570         if (x != NULL) {
571             /*
572              * in the Montgomery case, field_mul will cancel out Montgomery
573              * factor in X:
574              */
575             if (!group->meth->field_mul(group, x, point->X, Z_2, ctx))
576                 goto err;
577         }
578
579         if (y != NULL) {
580             if (group->meth->field_encode == 0) {
581                 /*
582                  * field_mul works on standard representation
583                  */
584                 if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx))
585                     goto err;
586             } else {
587                 if (!BN_mod_mul(Z_3, Z_2, Z_1, group->field, ctx))
588                     goto err;
589             }
590
591             /*
592              * in the Montgomery case, field_mul will cancel out Montgomery
593              * factor in Y:
594              */
595             if (!group->meth->field_mul(group, y, point->Y, Z_3, ctx))
596                 goto err;
597         }
598     }
599
600     ret = 1;
601
602  err:
603     BN_CTX_end(ctx);
604     BN_CTX_free(new_ctx);
605     return ret;
606 }
607
608 int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
609                       const EC_POINT *b, BN_CTX *ctx)
610 {
611     int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
612                       const BIGNUM *, BN_CTX *);
613     int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
614     const BIGNUM *p;
615     BN_CTX *new_ctx = NULL;
616     BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
617     int ret = 0;
618
619     if (a == b)
620         return EC_POINT_dbl(group, r, a, ctx);
621     if (EC_POINT_is_at_infinity(group, a))
622         return EC_POINT_copy(r, b);
623     if (EC_POINT_is_at_infinity(group, b))
624         return EC_POINT_copy(r, a);
625
626     field_mul = group->meth->field_mul;
627     field_sqr = group->meth->field_sqr;
628     p = group->field;
629
630     if (ctx == NULL) {
631         ctx = new_ctx = BN_CTX_new();
632         if (ctx == NULL)
633             return 0;
634     }
635
636     BN_CTX_start(ctx);
637     n0 = BN_CTX_get(ctx);
638     n1 = BN_CTX_get(ctx);
639     n2 = BN_CTX_get(ctx);
640     n3 = BN_CTX_get(ctx);
641     n4 = BN_CTX_get(ctx);
642     n5 = BN_CTX_get(ctx);
643     n6 = BN_CTX_get(ctx);
644     if (n6 == NULL)
645         goto end;
646
647     /*
648      * Note that in this function we must not read components of 'a' or 'b'
649      * once we have written the corresponding components of 'r'. ('r' might
650      * be one of 'a' or 'b'.)
651      */
652
653     /* n1, n2 */
654     if (b->Z_is_one) {
655         if (!BN_copy(n1, a->X))
656             goto end;
657         if (!BN_copy(n2, a->Y))
658             goto end;
659         /* n1 = X_a */
660         /* n2 = Y_a */
661     } else {
662         if (!field_sqr(group, n0, b->Z, ctx))
663             goto end;
664         if (!field_mul(group, n1, a->X, n0, ctx))
665             goto end;
666         /* n1 = X_a * Z_b^2 */
667
668         if (!field_mul(group, n0, n0, b->Z, ctx))
669             goto end;
670         if (!field_mul(group, n2, a->Y, n0, ctx))
671             goto end;
672         /* n2 = Y_a * Z_b^3 */
673     }
674
675     /* n3, n4 */
676     if (a->Z_is_one) {
677         if (!BN_copy(n3, b->X))
678             goto end;
679         if (!BN_copy(n4, b->Y))
680             goto end;
681         /* n3 = X_b */
682         /* n4 = Y_b */
683     } else {
684         if (!field_sqr(group, n0, a->Z, ctx))
685             goto end;
686         if (!field_mul(group, n3, b->X, n0, ctx))
687             goto end;
688         /* n3 = X_b * Z_a^2 */
689
690         if (!field_mul(group, n0, n0, a->Z, ctx))
691             goto end;
692         if (!field_mul(group, n4, b->Y, n0, ctx))
693             goto end;
694         /* n4 = Y_b * Z_a^3 */
695     }
696
697     /* n5, n6 */
698     if (!BN_mod_sub_quick(n5, n1, n3, p))
699         goto end;
700     if (!BN_mod_sub_quick(n6, n2, n4, p))
701         goto end;
702     /* n5 = n1 - n3 */
703     /* n6 = n2 - n4 */
704
705     if (BN_is_zero(n5)) {
706         if (BN_is_zero(n6)) {
707             /* a is the same point as b */
708             BN_CTX_end(ctx);
709             ret = EC_POINT_dbl(group, r, a, ctx);
710             ctx = NULL;
711             goto end;
712         } else {
713             /* a is the inverse of b */
714             BN_zero(r->Z);
715             r->Z_is_one = 0;
716             ret = 1;
717             goto end;
718         }
719     }
720
721     /* 'n7', 'n8' */
722     if (!BN_mod_add_quick(n1, n1, n3, p))
723         goto end;
724     if (!BN_mod_add_quick(n2, n2, n4, p))
725         goto end;
726     /* 'n7' = n1 + n3 */
727     /* 'n8' = n2 + n4 */
728
729     /* Z_r */
730     if (a->Z_is_one && b->Z_is_one) {
731         if (!BN_copy(r->Z, n5))
732             goto end;
733     } else {
734         if (a->Z_is_one) {
735             if (!BN_copy(n0, b->Z))
736                 goto end;
737         } else if (b->Z_is_one) {
738             if (!BN_copy(n0, a->Z))
739                 goto end;
740         } else {
741             if (!field_mul(group, n0, a->Z, b->Z, ctx))
742                 goto end;
743         }
744         if (!field_mul(group, r->Z, n0, n5, ctx))
745             goto end;
746     }
747     r->Z_is_one = 0;
748     /* Z_r = Z_a * Z_b * n5 */
749
750     /* X_r */
751     if (!field_sqr(group, n0, n6, ctx))
752         goto end;
753     if (!field_sqr(group, n4, n5, ctx))
754         goto end;
755     if (!field_mul(group, n3, n1, n4, ctx))
756         goto end;
757     if (!BN_mod_sub_quick(r->X, n0, n3, p))
758         goto end;
759     /* X_r = n6^2 - n5^2 * 'n7' */
760
761     /* 'n9' */
762     if (!BN_mod_lshift1_quick(n0, r->X, p))
763         goto end;
764     if (!BN_mod_sub_quick(n0, n3, n0, p))
765         goto end;
766     /* n9 = n5^2 * 'n7' - 2 * X_r */
767
768     /* Y_r */
769     if (!field_mul(group, n0, n0, n6, ctx))
770         goto end;
771     if (!field_mul(group, n5, n4, n5, ctx))
772         goto end;               /* now n5 is n5^3 */
773     if (!field_mul(group, n1, n2, n5, ctx))
774         goto end;
775     if (!BN_mod_sub_quick(n0, n0, n1, p))
776         goto end;
777     if (BN_is_odd(n0))
778         if (!BN_add(n0, n0, p))
779             goto end;
780     /* now  0 <= n0 < 2*p,  and n0 is even */
781     if (!BN_rshift1(r->Y, n0))
782         goto end;
783     /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
784
785     ret = 1;
786
787  end:
788     if (ctx)                    /* otherwise we already called BN_CTX_end */
789         BN_CTX_end(ctx);
790     BN_CTX_free(new_ctx);
791     return ret;
792 }
793
794 int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
795                       BN_CTX *ctx)
796 {
797     int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
798                       const BIGNUM *, BN_CTX *);
799     int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
800     const BIGNUM *p;
801     BN_CTX *new_ctx = NULL;
802     BIGNUM *n0, *n1, *n2, *n3;
803     int ret = 0;
804
805     if (EC_POINT_is_at_infinity(group, a)) {
806         BN_zero(r->Z);
807         r->Z_is_one = 0;
808         return 1;
809     }
810
811     field_mul = group->meth->field_mul;
812     field_sqr = group->meth->field_sqr;
813     p = group->field;
814
815     if (ctx == NULL) {
816         ctx = new_ctx = BN_CTX_new();
817         if (ctx == NULL)
818             return 0;
819     }
820
821     BN_CTX_start(ctx);
822     n0 = BN_CTX_get(ctx);
823     n1 = BN_CTX_get(ctx);
824     n2 = BN_CTX_get(ctx);
825     n3 = BN_CTX_get(ctx);
826     if (n3 == NULL)
827         goto err;
828
829     /*
830      * Note that in this function we must not read components of 'a' once we
831      * have written the corresponding components of 'r'. ('r' might the same
832      * as 'a'.)
833      */
834
835     /* n1 */
836     if (a->Z_is_one) {
837         if (!field_sqr(group, n0, a->X, ctx))
838             goto err;
839         if (!BN_mod_lshift1_quick(n1, n0, p))
840             goto err;
841         if (!BN_mod_add_quick(n0, n0, n1, p))
842             goto err;
843         if (!BN_mod_add_quick(n1, n0, group->a, p))
844             goto err;
845         /* n1 = 3 * X_a^2 + a_curve */
846     } else if (group->a_is_minus3) {
847         if (!field_sqr(group, n1, a->Z, ctx))
848             goto err;
849         if (!BN_mod_add_quick(n0, a->X, n1, p))
850             goto err;
851         if (!BN_mod_sub_quick(n2, a->X, n1, p))
852             goto err;
853         if (!field_mul(group, n1, n0, n2, ctx))
854             goto err;
855         if (!BN_mod_lshift1_quick(n0, n1, p))
856             goto err;
857         if (!BN_mod_add_quick(n1, n0, n1, p))
858             goto err;
859         /*-
860          * n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
861          *    = 3 * X_a^2 - 3 * Z_a^4
862          */
863     } else {
864         if (!field_sqr(group, n0, a->X, ctx))
865             goto err;
866         if (!BN_mod_lshift1_quick(n1, n0, p))
867             goto err;
868         if (!BN_mod_add_quick(n0, n0, n1, p))
869             goto err;
870         if (!field_sqr(group, n1, a->Z, ctx))
871             goto err;
872         if (!field_sqr(group, n1, n1, ctx))
873             goto err;
874         if (!field_mul(group, n1, n1, group->a, ctx))
875             goto err;
876         if (!BN_mod_add_quick(n1, n1, n0, p))
877             goto err;
878         /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
879     }
880
881     /* Z_r */
882     if (a->Z_is_one) {
883         if (!BN_copy(n0, a->Y))
884             goto err;
885     } else {
886         if (!field_mul(group, n0, a->Y, a->Z, ctx))
887             goto err;
888     }
889     if (!BN_mod_lshift1_quick(r->Z, n0, p))
890         goto err;
891     r->Z_is_one = 0;
892     /* Z_r = 2 * Y_a * Z_a */
893
894     /* n2 */
895     if (!field_sqr(group, n3, a->Y, ctx))
896         goto err;
897     if (!field_mul(group, n2, a->X, n3, ctx))
898         goto err;
899     if (!BN_mod_lshift_quick(n2, n2, 2, p))
900         goto err;
901     /* n2 = 4 * X_a * Y_a^2 */
902
903     /* X_r */
904     if (!BN_mod_lshift1_quick(n0, n2, p))
905         goto err;
906     if (!field_sqr(group, r->X, n1, ctx))
907         goto err;
908     if (!BN_mod_sub_quick(r->X, r->X, n0, p))
909         goto err;
910     /* X_r = n1^2 - 2 * n2 */
911
912     /* n3 */
913     if (!field_sqr(group, n0, n3, ctx))
914         goto err;
915     if (!BN_mod_lshift_quick(n3, n0, 3, p))
916         goto err;
917     /* n3 = 8 * Y_a^4 */
918
919     /* Y_r */
920     if (!BN_mod_sub_quick(n0, n2, r->X, p))
921         goto err;
922     if (!field_mul(group, n0, n1, n0, ctx))
923         goto err;
924     if (!BN_mod_sub_quick(r->Y, n0, n3, p))
925         goto err;
926     /* Y_r = n1 * (n2 - X_r) - n3 */
927
928     ret = 1;
929
930  err:
931     BN_CTX_end(ctx);
932     BN_CTX_free(new_ctx);
933     return ret;
934 }
935
936 int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
937 {
938     if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y))
939         /* point is its own inverse */
940         return 1;
941
942     return BN_usub(point->Y, group->field, point->Y);
943 }
944
945 int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
946 {
947     return BN_is_zero(point->Z);
948 }
949
950 int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
951                               BN_CTX *ctx)
952 {
953     int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
954                       const BIGNUM *, BN_CTX *);
955     int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
956     const BIGNUM *p;
957     BN_CTX *new_ctx = NULL;
958     BIGNUM *rh, *tmp, *Z4, *Z6;
959     int ret = -1;
960
961     if (EC_POINT_is_at_infinity(group, point))
962         return 1;
963
964     field_mul = group->meth->field_mul;
965     field_sqr = group->meth->field_sqr;
966     p = group->field;
967
968     if (ctx == NULL) {
969         ctx = new_ctx = BN_CTX_new();
970         if (ctx == NULL)
971             return -1;
972     }
973
974     BN_CTX_start(ctx);
975     rh = BN_CTX_get(ctx);
976     tmp = BN_CTX_get(ctx);
977     Z4 = BN_CTX_get(ctx);
978     Z6 = BN_CTX_get(ctx);
979     if (Z6 == NULL)
980         goto err;
981
982     /*-
983      * We have a curve defined by a Weierstrass equation
984      *      y^2 = x^3 + a*x + b.
985      * The point to consider is given in Jacobian projective coordinates
986      * where  (X, Y, Z)  represents  (x, y) = (X/Z^2, Y/Z^3).
987      * Substituting this and multiplying by  Z^6  transforms the above equation into
988      *      Y^2 = X^3 + a*X*Z^4 + b*Z^6.
989      * To test this, we add up the right-hand side in 'rh'.
990      */
991
992     /* rh := X^2 */
993     if (!field_sqr(group, rh, point->X, ctx))
994         goto err;
995
996     if (!point->Z_is_one) {
997         if (!field_sqr(group, tmp, point->Z, ctx))
998             goto err;
999         if (!field_sqr(group, Z4, tmp, ctx))
1000             goto err;
1001         if (!field_mul(group, Z6, Z4, tmp, ctx))
1002             goto err;
1003
1004         /* rh := (rh + a*Z^4)*X */
1005         if (group->a_is_minus3) {
1006             if (!BN_mod_lshift1_quick(tmp, Z4, p))
1007                 goto err;
1008             if (!BN_mod_add_quick(tmp, tmp, Z4, p))
1009                 goto err;
1010             if (!BN_mod_sub_quick(rh, rh, tmp, p))
1011                 goto err;
1012             if (!field_mul(group, rh, rh, point->X, ctx))
1013                 goto err;
1014         } else {
1015             if (!field_mul(group, tmp, Z4, group->a, ctx))
1016                 goto err;
1017             if (!BN_mod_add_quick(rh, rh, tmp, p))
1018                 goto err;
1019             if (!field_mul(group, rh, rh, point->X, ctx))
1020                 goto err;
1021         }
1022
1023         /* rh := rh + b*Z^6 */
1024         if (!field_mul(group, tmp, group->b, Z6, ctx))
1025             goto err;
1026         if (!BN_mod_add_quick(rh, rh, tmp, p))
1027             goto err;
1028     } else {
1029         /* point->Z_is_one */
1030
1031         /* rh := (rh + a)*X */
1032         if (!BN_mod_add_quick(rh, rh, group->a, p))
1033             goto err;
1034         if (!field_mul(group, rh, rh, point->X, ctx))
1035             goto err;
1036         /* rh := rh + b */
1037         if (!BN_mod_add_quick(rh, rh, group->b, p))
1038             goto err;
1039     }
1040
1041     /* 'lh' := Y^2 */
1042     if (!field_sqr(group, tmp, point->Y, ctx))
1043         goto err;
1044
1045     ret = (0 == BN_ucmp(tmp, rh));
1046
1047  err:
1048     BN_CTX_end(ctx);
1049     BN_CTX_free(new_ctx);
1050     return ret;
1051 }
1052
1053 int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
1054                       const EC_POINT *b, BN_CTX *ctx)
1055 {
1056     /*-
1057      * return values:
1058      *  -1   error
1059      *   0   equal (in affine coordinates)
1060      *   1   not equal
1061      */
1062
1063     int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
1064                       const BIGNUM *, BN_CTX *);
1065     int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1066     BN_CTX *new_ctx = NULL;
1067     BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
1068     const BIGNUM *tmp1_, *tmp2_;
1069     int ret = -1;
1070
1071     if (EC_POINT_is_at_infinity(group, a)) {
1072         return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
1073     }
1074
1075     if (EC_POINT_is_at_infinity(group, b))
1076         return 1;
1077
1078     if (a->Z_is_one && b->Z_is_one) {
1079         return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1;
1080     }
1081
1082     field_mul = group->meth->field_mul;
1083     field_sqr = group->meth->field_sqr;
1084
1085     if (ctx == NULL) {
1086         ctx = new_ctx = BN_CTX_new();
1087         if (ctx == NULL)
1088             return -1;
1089     }
1090
1091     BN_CTX_start(ctx);
1092     tmp1 = BN_CTX_get(ctx);
1093     tmp2 = BN_CTX_get(ctx);
1094     Za23 = BN_CTX_get(ctx);
1095     Zb23 = BN_CTX_get(ctx);
1096     if (Zb23 == NULL)
1097         goto end;
1098
1099     /*-
1100      * We have to decide whether
1101      *     (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
1102      * or equivalently, whether
1103      *     (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
1104      */
1105
1106     if (!b->Z_is_one) {
1107         if (!field_sqr(group, Zb23, b->Z, ctx))
1108             goto end;
1109         if (!field_mul(group, tmp1, a->X, Zb23, ctx))
1110             goto end;
1111         tmp1_ = tmp1;
1112     } else
1113         tmp1_ = a->X;
1114     if (!a->Z_is_one) {
1115         if (!field_sqr(group, Za23, a->Z, ctx))
1116             goto end;
1117         if (!field_mul(group, tmp2, b->X, Za23, ctx))
1118             goto end;
1119         tmp2_ = tmp2;
1120     } else
1121         tmp2_ = b->X;
1122
1123     /* compare  X_a*Z_b^2  with  X_b*Z_a^2 */
1124     if (BN_cmp(tmp1_, tmp2_) != 0) {
1125         ret = 1;                /* points differ */
1126         goto end;
1127     }
1128
1129     if (!b->Z_is_one) {
1130         if (!field_mul(group, Zb23, Zb23, b->Z, ctx))
1131             goto end;
1132         if (!field_mul(group, tmp1, a->Y, Zb23, ctx))
1133             goto end;
1134         /* tmp1_ = tmp1 */
1135     } else
1136         tmp1_ = a->Y;
1137     if (!a->Z_is_one) {
1138         if (!field_mul(group, Za23, Za23, a->Z, ctx))
1139             goto end;
1140         if (!field_mul(group, tmp2, b->Y, Za23, ctx))
1141             goto end;
1142         /* tmp2_ = tmp2 */
1143     } else
1144         tmp2_ = b->Y;
1145
1146     /* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */
1147     if (BN_cmp(tmp1_, tmp2_) != 0) {
1148         ret = 1;                /* points differ */
1149         goto end;
1150     }
1151
1152     /* points are equal */
1153     ret = 0;
1154
1155  end:
1156     BN_CTX_end(ctx);
1157     BN_CTX_free(new_ctx);
1158     return ret;
1159 }
1160
1161 int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
1162                               BN_CTX *ctx)
1163 {
1164     BN_CTX *new_ctx = NULL;
1165     BIGNUM *x, *y;
1166     int ret = 0;
1167
1168     if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
1169         return 1;
1170
1171     if (ctx == NULL) {
1172         ctx = new_ctx = BN_CTX_new();
1173         if (ctx == NULL)
1174             return 0;
1175     }
1176
1177     BN_CTX_start(ctx);
1178     x = BN_CTX_get(ctx);
1179     y = BN_CTX_get(ctx);
1180     if (y == NULL)
1181         goto err;
1182
1183     if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx))
1184         goto err;
1185     if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
1186         goto err;
1187     if (!point->Z_is_one) {
1188         ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
1189         goto err;
1190     }
1191
1192     ret = 1;
1193
1194  err:
1195     BN_CTX_end(ctx);
1196     BN_CTX_free(new_ctx);
1197     return ret;
1198 }
1199
1200 int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
1201                                      EC_POINT *points[], BN_CTX *ctx)
1202 {
1203     BN_CTX *new_ctx = NULL;
1204     BIGNUM *tmp, *tmp_Z;
1205     BIGNUM **prod_Z = NULL;
1206     size_t i;
1207     int ret = 0;
1208
1209     if (num == 0)
1210         return 1;
1211
1212     if (ctx == NULL) {
1213         ctx = new_ctx = BN_CTX_new();
1214         if (ctx == NULL)
1215             return 0;
1216     }
1217
1218     BN_CTX_start(ctx);
1219     tmp = BN_CTX_get(ctx);
1220     tmp_Z = BN_CTX_get(ctx);
1221     if (tmp == NULL || tmp_Z == NULL)
1222         goto err;
1223
1224     prod_Z = OPENSSL_malloc(num * sizeof prod_Z[0]);
1225     if (prod_Z == NULL)
1226         goto err;
1227     for (i = 0; i < num; i++) {
1228         prod_Z[i] = BN_new();
1229         if (prod_Z[i] == NULL)
1230             goto err;
1231     }
1232
1233     /*
1234      * Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z,
1235      * skipping any zero-valued inputs (pretend that they're 1).
1236      */
1237
1238     if (!BN_is_zero(points[0]->Z)) {
1239         if (!BN_copy(prod_Z[0], points[0]->Z))
1240             goto err;
1241     } else {
1242         if (group->meth->field_set_to_one != 0) {
1243             if (!group->meth->field_set_to_one(group, prod_Z[0], ctx))
1244                 goto err;
1245         } else {
1246             if (!BN_one(prod_Z[0]))
1247                 goto err;
1248         }
1249     }
1250
1251     for (i = 1; i < num; i++) {
1252         if (!BN_is_zero(points[i]->Z)) {
1253             if (!group->
1254                 meth->field_mul(group, prod_Z[i], prod_Z[i - 1], points[i]->Z,
1255                                 ctx))
1256                 goto err;
1257         } else {
1258             if (!BN_copy(prod_Z[i], prod_Z[i - 1]))
1259                 goto err;
1260         }
1261     }
1262
1263     /*
1264      * Now use a single explicit inversion to replace every non-zero
1265      * points[i]->Z by its inverse.
1266      */
1267
1268     if (!BN_mod_inverse(tmp, prod_Z[num - 1], group->field, ctx)) {
1269         ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
1270         goto err;
1271     }
1272     if (group->meth->field_encode != 0) {
1273         /*
1274          * In the Montgomery case, we just turned R*H (representing H) into
1275          * 1/(R*H), but we need R*(1/H) (representing 1/H); i.e. we need to
1276          * multiply by the Montgomery factor twice.
1277          */
1278         if (!group->meth->field_encode(group, tmp, tmp, ctx))
1279             goto err;
1280         if (!group->meth->field_encode(group, tmp, tmp, ctx))
1281             goto err;
1282     }
1283
1284     for (i = num - 1; i > 0; --i) {
1285         /*
1286          * Loop invariant: tmp is the product of the inverses of points[0]->Z
1287          * .. points[i]->Z (zero-valued inputs skipped).
1288          */
1289         if (!BN_is_zero(points[i]->Z)) {
1290             /*
1291              * Set tmp_Z to the inverse of points[i]->Z (as product of Z
1292              * inverses 0 .. i, Z values 0 .. i - 1).
1293              */
1294             if (!group->
1295                 meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx))
1296                 goto err;
1297             /*
1298              * Update tmp to satisfy the loop invariant for i - 1.
1299              */
1300             if (!group->meth->field_mul(group, tmp, tmp, points[i]->Z, ctx))
1301                 goto err;
1302             /* Replace points[i]->Z by its inverse. */
1303             if (!BN_copy(points[i]->Z, tmp_Z))
1304                 goto err;
1305         }
1306     }
1307
1308     if (!BN_is_zero(points[0]->Z)) {
1309         /* Replace points[0]->Z by its inverse. */
1310         if (!BN_copy(points[0]->Z, tmp))
1311             goto err;
1312     }
1313
1314     /* Finally, fix up the X and Y coordinates for all points. */
1315
1316     for (i = 0; i < num; i++) {
1317         EC_POINT *p = points[i];
1318
1319         if (!BN_is_zero(p->Z)) {
1320             /* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */
1321
1322             if (!group->meth->field_sqr(group, tmp, p->Z, ctx))
1323                 goto err;
1324             if (!group->meth->field_mul(group, p->X, p->X, tmp, ctx))
1325                 goto err;
1326
1327             if (!group->meth->field_mul(group, tmp, tmp, p->Z, ctx))
1328                 goto err;
1329             if (!group->meth->field_mul(group, p->Y, p->Y, tmp, ctx))
1330                 goto err;
1331
1332             if (group->meth->field_set_to_one != 0) {
1333                 if (!group->meth->field_set_to_one(group, p->Z, ctx))
1334                     goto err;
1335             } else {
1336                 if (!BN_one(p->Z))
1337                     goto err;
1338             }
1339             p->Z_is_one = 1;
1340         }
1341     }
1342
1343     ret = 1;
1344
1345  err:
1346     BN_CTX_end(ctx);
1347     BN_CTX_free(new_ctx);
1348     if (prod_Z != NULL) {
1349         for (i = 0; i < num; i++) {
1350             if (prod_Z[i] == NULL)
1351                 break;
1352             BN_clear_free(prod_Z[i]);
1353         }
1354         OPENSSL_free(prod_Z);
1355     }
1356     return ret;
1357 }
1358
1359 int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
1360                             const BIGNUM *b, BN_CTX *ctx)
1361 {
1362     return BN_mod_mul(r, a, b, group->field, ctx);
1363 }
1364
1365 int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
1366                             BN_CTX *ctx)
1367 {
1368     return BN_mod_sqr(r, a, group->field, ctx);
1369 }