Home | History | Annotate | Download | only in ec
      1 /* Originally written by Bodo Moeller and Nils Larsch 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 (at) 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 (at) cryptsoft.com).  This product includes software written by Tim
     52  * Hudson (tjh (at) 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 <openssl/bn.h>
     71 #include <openssl/err.h>
     72 #include <openssl/mem.h>
     73 
     74 #include "internal.h"
     75 
     76 
     77 const EC_METHOD *EC_GFp_mont_method(void) {
     78   static const EC_METHOD ret = {EC_FLAGS_DEFAULT_OCT,
     79                                 ec_GFp_mont_group_init,
     80                                 ec_GFp_mont_group_finish,
     81                                 ec_GFp_mont_group_clear_finish,
     82                                 ec_GFp_mont_group_copy,
     83                                 ec_GFp_mont_group_set_curve,
     84                                 ec_GFp_simple_group_get_curve,
     85                                 ec_GFp_simple_group_get_degree,
     86                                 ec_GFp_simple_group_check_discriminant,
     87                                 ec_GFp_simple_point_init,
     88                                 ec_GFp_simple_point_finish,
     89                                 ec_GFp_simple_point_clear_finish,
     90                                 ec_GFp_simple_point_copy,
     91                                 ec_GFp_simple_point_set_to_infinity,
     92                                 ec_GFp_simple_set_Jprojective_coordinates_GFp,
     93                                 ec_GFp_simple_get_Jprojective_coordinates_GFp,
     94                                 ec_GFp_simple_point_set_affine_coordinates,
     95                                 ec_GFp_simple_point_get_affine_coordinates,
     96                                 0,
     97                                 0,
     98                                 0,
     99                                 ec_GFp_simple_add,
    100                                 ec_GFp_simple_dbl,
    101                                 ec_GFp_simple_invert,
    102                                 ec_GFp_simple_is_at_infinity,
    103                                 ec_GFp_simple_is_on_curve,
    104                                 ec_GFp_simple_cmp,
    105                                 ec_GFp_simple_make_affine,
    106                                 ec_GFp_simple_points_make_affine,
    107                                 0 /* mul */,
    108                                 0 /* precompute_mult */,
    109                                 0 /* have_precompute_mult */,
    110                                 ec_GFp_mont_field_mul,
    111                                 ec_GFp_mont_field_sqr,
    112                                 0 /* field_div */,
    113                                 ec_GFp_mont_field_encode,
    114                                 ec_GFp_mont_field_decode,
    115                                 ec_GFp_mont_field_set_to_one};
    116 
    117   return &ret;
    118 }
    119 
    120 int ec_GFp_mont_group_init(EC_GROUP *group) {
    121   int ok;
    122 
    123   ok = ec_GFp_simple_group_init(group);
    124   group->mont = NULL;
    125   group->one = NULL;
    126   return ok;
    127 }
    128 
    129 void ec_GFp_mont_group_finish(EC_GROUP *group) {
    130   BN_MONT_CTX_free(group->mont);
    131   group->mont = NULL;
    132   BN_free(group->one);
    133   group->one = NULL;
    134   ec_GFp_simple_group_finish(group);
    135 }
    136 
    137 void ec_GFp_mont_group_clear_finish(EC_GROUP *group) {
    138   BN_MONT_CTX_free(group->mont);
    139   group->mont = NULL;
    140   BN_clear_free(group->one);
    141   group->one = NULL;
    142   ec_GFp_simple_group_clear_finish(group);
    143 }
    144 
    145 int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
    146   BN_MONT_CTX_free(dest->mont);
    147   dest->mont = NULL;
    148   BN_clear_free(dest->one);
    149   dest->one = NULL;
    150 
    151   if (!ec_GFp_simple_group_copy(dest, src)) {
    152     return 0;
    153   }
    154 
    155   if (src->mont != NULL) {
    156     dest->mont = BN_MONT_CTX_new();
    157     if (dest->mont == NULL) {
    158       return 0;
    159     }
    160     if (!BN_MONT_CTX_copy(dest->mont, src->mont)) {
    161       goto err;
    162     }
    163   }
    164   if (src->one != NULL) {
    165     dest->one = BN_dup(src->one);
    166     if (dest->one == NULL) {
    167       goto err;
    168     }
    169   }
    170 
    171   return 1;
    172 
    173 err:
    174   BN_MONT_CTX_free(dest->mont);
    175   dest->mont = NULL;
    176   return 0;
    177 }
    178 
    179 int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
    180                                 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
    181   BN_CTX *new_ctx = NULL;
    182   BN_MONT_CTX *mont = NULL;
    183   BIGNUM *one = NULL;
    184   int ret = 0;
    185 
    186   BN_MONT_CTX_free(group->mont);
    187   group->mont = NULL;
    188   BN_free(group->one);
    189   group->one = NULL;
    190 
    191   if (ctx == NULL) {
    192     ctx = new_ctx = BN_CTX_new();
    193     if (ctx == NULL) {
    194       return 0;
    195     }
    196   }
    197 
    198   mont = BN_MONT_CTX_new();
    199   if (mont == NULL) {
    200     goto err;
    201   }
    202   if (!BN_MONT_CTX_set(mont, p, ctx)) {
    203     OPENSSL_PUT_ERROR(EC, ec_GFp_mont_group_set_curve, ERR_R_BN_LIB);
    204     goto err;
    205   }
    206   one = BN_new();
    207   if (one == NULL || !BN_to_montgomery(one, BN_value_one(), mont, ctx)) {
    208     goto err;
    209   }
    210 
    211   group->mont = mont;
    212   mont = NULL;
    213   group->one = one;
    214   one = NULL;
    215 
    216   ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
    217 
    218   if (!ret) {
    219     BN_MONT_CTX_free(group->mont);
    220     group->mont = NULL;
    221     BN_free(group->one);
    222     group->one = NULL;
    223   }
    224 
    225 err:
    226   BN_CTX_free(new_ctx);
    227   BN_MONT_CTX_free(mont);
    228   BN_free(one);
    229   return ret;
    230 }
    231 
    232 int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
    233                           const BIGNUM *b, BN_CTX *ctx) {
    234   if (group->mont == NULL) {
    235     OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_mul, EC_R_NOT_INITIALIZED);
    236     return 0;
    237   }
    238 
    239   return BN_mod_mul_montgomery(r, a, b, group->mont, ctx);
    240 }
    241 
    242 int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
    243                           BN_CTX *ctx) {
    244   if (group->mont == NULL) {
    245     OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_sqr, EC_R_NOT_INITIALIZED);
    246     return 0;
    247   }
    248 
    249   return BN_mod_mul_montgomery(r, a, a, group->mont, ctx);
    250 }
    251 
    252 int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
    253                              BN_CTX *ctx) {
    254   if (group->mont == NULL) {
    255     OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_encode, EC_R_NOT_INITIALIZED);
    256     return 0;
    257   }
    258 
    259   return BN_to_montgomery(r, a, group->mont, ctx);
    260 }
    261 
    262 int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
    263                              BN_CTX *ctx) {
    264   if (group->mont == NULL) {
    265     OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_decode, EC_R_NOT_INITIALIZED);
    266     return 0;
    267   }
    268 
    269   return BN_from_montgomery(r, a, group->mont, ctx);
    270 }
    271 
    272 int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r,
    273                                  BN_CTX *ctx) {
    274   if (group->one == NULL) {
    275     OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_set_to_one, EC_R_NOT_INITIALIZED);
    276     return 0;
    277   }
    278 
    279   if (!BN_copy(r, group->one)) {
    280     return 0;
    281   }
    282   return 1;
    283 }
    284