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