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