LCOV - code coverage report
Current view: top level - third_party/openssl/crypto/ec - ecp_smpl.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 279 517 54.0 %
Date: 2015-10-10 Functions: 18 28 64.3 %

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

Generated by: LCOV version 1.10