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