LCOV - code coverage report
Current view: top level - third_party/openssl/crypto/ec - ecp_oct.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 68 174 39.1 %
Date: 2015-10-10 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /* crypto/ec/ecp_oct.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             : #include "ec_lcl.h"
      70             : 
      71           0 : int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
      72             :                                              EC_POINT *point,
      73             :                                              const BIGNUM *x_, int y_bit,
      74             :                                              BN_CTX *ctx)
      75             : {
      76             :     BN_CTX *new_ctx = NULL;
      77             :     BIGNUM *tmp1, *tmp2, *x, *y;
      78             :     int ret = 0;
      79             : 
      80             :     /* clear error queue */
      81           0 :     ERR_clear_error();
      82             : 
      83           0 :     if (ctx == NULL) {
      84           0 :         ctx = new_ctx = BN_CTX_new();
      85           0 :         if (ctx == NULL)
      86             :             return 0;
      87             :     }
      88             : 
      89           0 :     y_bit = (y_bit != 0);
      90             : 
      91           0 :     BN_CTX_start(ctx);
      92           0 :     tmp1 = BN_CTX_get(ctx);
      93           0 :     tmp2 = BN_CTX_get(ctx);
      94           0 :     x = BN_CTX_get(ctx);
      95           0 :     y = BN_CTX_get(ctx);
      96           0 :     if (y == NULL)
      97             :         goto err;
      98             : 
      99             :     /*-
     100             :      * Recover y.  We have a Weierstrass equation
     101             :      *     y^2 = x^3 + a*x + b,
     102             :      * so  y  is one of the square roots of  x^3 + a*x + b.
     103             :      */
     104             : 
     105             :     /* tmp1 := x^3 */
     106           0 :     if (!BN_nnmod(x, x_, &group->field, ctx))
     107             :         goto err;
     108           0 :     if (group->meth->field_decode == 0) {
     109             :         /* field_{sqr,mul} work on standard representation */
     110           0 :         if (!group->meth->field_sqr(group, tmp2, x_, ctx))
     111             :             goto err;
     112           0 :         if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx))
     113             :             goto err;
     114             :     } else {
     115           0 :         if (!BN_mod_sqr(tmp2, x_, &group->field, ctx))
     116             :             goto err;
     117           0 :         if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx))
     118             :             goto err;
     119             :     }
     120             : 
     121             :     /* tmp1 := tmp1 + a*x */
     122           0 :     if (group->a_is_minus3) {
     123           0 :         if (!BN_mod_lshift1_quick(tmp2, x, &group->field))
     124             :             goto err;
     125           0 :         if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field))
     126             :             goto err;
     127           0 :         if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field))
     128             :             goto err;
     129             :     } else {
     130           0 :         if (group->meth->field_decode) {
     131           0 :             if (!group->meth->field_decode(group, tmp2, &group->a, ctx))
     132             :                 goto err;
     133           0 :             if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx))
     134             :                 goto err;
     135             :         } else {
     136             :             /* field_mul works on standard representation */
     137           0 :             if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx))
     138             :                 goto err;
     139             :         }
     140             : 
     141           0 :         if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field))
     142             :             goto err;
     143             :     }
     144             : 
     145             :     /* tmp1 := tmp1 + b */
     146           0 :     if (group->meth->field_decode) {
     147           0 :         if (!group->meth->field_decode(group, tmp2, &group->b, ctx))
     148             :             goto err;
     149           0 :         if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field))
     150             :             goto err;
     151             :     } else {
     152           0 :         if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field))
     153             :             goto err;
     154             :     }
     155             : 
     156           0 :     if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) {
     157           0 :         unsigned long err = ERR_peek_last_error();
     158             : 
     159           0 :         if (ERR_GET_LIB(err) == ERR_LIB_BN
     160           0 :             && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) {
     161           0 :             ERR_clear_error();
     162           0 :             ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
     163             :                   EC_R_INVALID_COMPRESSED_POINT);
     164             :         } else
     165           0 :             ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
     166             :                   ERR_R_BN_LIB);
     167             :         goto err;
     168             :     }
     169             : 
     170           0 :     if (y_bit != BN_is_odd(y)) {
     171           0 :         if (BN_is_zero(y)) {
     172             :             int kron;
     173             : 
     174           0 :             kron = BN_kronecker(x, &group->field, ctx);
     175           0 :             if (kron == -2)
     176             :                 goto err;
     177             : 
     178           0 :             if (kron == 1)
     179           0 :                 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
     180             :                       EC_R_INVALID_COMPRESSION_BIT);
     181             :             else
     182             :                 /*
     183             :                  * BN_mod_sqrt() should have cought this error (not a square)
     184             :                  */
     185           0 :                 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
     186             :                       EC_R_INVALID_COMPRESSED_POINT);
     187             :             goto err;
     188             :         }
     189           0 :         if (!BN_usub(y, &group->field, y))
     190             :             goto err;
     191             :     }
     192           0 :     if (y_bit != BN_is_odd(y)) {
     193           0 :         ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
     194             :               ERR_R_INTERNAL_ERROR);
     195           0 :         goto err;
     196             :     }
     197             : 
     198           0 :     if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
     199             :         goto err;
     200             : 
     201             :     ret = 1;
     202             : 
     203             :  err:
     204           0 :     BN_CTX_end(ctx);
     205           0 :     if (new_ctx != NULL)
     206           0 :         BN_CTX_free(new_ctx);
     207           0 :     return ret;
     208             : }
     209             : 
     210        1486 : size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
     211             :                                point_conversion_form_t form,
     212             :                                unsigned char *buf, size_t len, BN_CTX *ctx)
     213             : {
     214             :     size_t ret;
     215             :     BN_CTX *new_ctx = NULL;
     216             :     int used_ctx = 0;
     217             :     BIGNUM *x, *y;
     218             :     size_t field_len, i, skip;
     219             : 
     220        2972 :     if ((form != POINT_CONVERSION_COMPRESSED)
     221        1486 :         && (form != POINT_CONVERSION_UNCOMPRESSED)
     222           0 :         && (form != POINT_CONVERSION_HYBRID)) {
     223           0 :         ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
     224           0 :         goto err;
     225             :     }
     226             : 
     227        1486 :     if (EC_POINT_is_at_infinity(group, point)) {
     228             :         /* encodes to a single 0 octet */
     229           0 :         if (buf != NULL) {
     230           0 :             if (len < 1) {
     231           0 :                 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
     232           0 :                 return 0;
     233             :             }
     234           0 :             buf[0] = 0;
     235             :         }
     236             :         return 1;
     237             :     }
     238             : 
     239             :     /* ret := required output buffer length */
     240        1486 :     field_len = BN_num_bytes(&group->field);
     241             :     ret =
     242             :         (form ==
     243        1486 :          POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
     244             : 
     245             :     /* if 'buf' is NULL, just return required length */
     246        1486 :     if (buf != NULL) {
     247         743 :         if (len < ret) {
     248           0 :             ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
     249           0 :             goto err;
     250             :         }
     251             : 
     252         743 :         if (ctx == NULL) {
     253           0 :             ctx = new_ctx = BN_CTX_new();
     254           0 :             if (ctx == NULL)
     255             :                 return 0;
     256             :         }
     257             : 
     258         743 :         BN_CTX_start(ctx);
     259             :         used_ctx = 1;
     260         743 :         x = BN_CTX_get(ctx);
     261         743 :         y = BN_CTX_get(ctx);
     262         743 :         if (y == NULL)
     263             :             goto err;
     264             : 
     265         743 :         if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx))
     266             :             goto err;
     267             : 
     268        1486 :         if ((form == POINT_CONVERSION_COMPRESSED
     269         743 :              || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
     270           0 :             buf[0] = form + 1;
     271             :         else
     272         743 :             buf[0] = form;
     273             : 
     274             :         i = 1;
     275             : 
     276         743 :         skip = field_len - BN_num_bytes(x);
     277         743 :         if (skip > field_len) {
     278           0 :             ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
     279           0 :             goto err;
     280             :         }
     281         744 :         while (skip > 0) {
     282           1 :             buf[i++] = 0;
     283           1 :             skip--;
     284             :         }
     285         743 :         skip = BN_bn2bin(x, buf + i);
     286         743 :         i += skip;
     287         743 :         if (i != 1 + field_len) {
     288           0 :             ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
     289           0 :             goto err;
     290             :         }
     291             : 
     292        1486 :         if (form == POINT_CONVERSION_UNCOMPRESSED
     293         743 :             || form == POINT_CONVERSION_HYBRID) {
     294         743 :             skip = field_len - BN_num_bytes(y);
     295         743 :             if (skip > field_len) {
     296           0 :                 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
     297           0 :                 goto err;
     298             :             }
     299         747 :             while (skip > 0) {
     300           4 :                 buf[i++] = 0;
     301           4 :                 skip--;
     302             :             }
     303         743 :             skip = BN_bn2bin(y, buf + i);
     304         743 :             i += skip;
     305             :         }
     306             : 
     307         743 :         if (i != ret) {
     308           0 :             ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
     309           0 :             goto err;
     310             :         }
     311             :     }
     312             : 
     313        1486 :     if (used_ctx)
     314         743 :         BN_CTX_end(ctx);
     315        1486 :     if (new_ctx != NULL)
     316           0 :         BN_CTX_free(new_ctx);
     317        1486 :     return ret;
     318             : 
     319             :  err:
     320           0 :     if (used_ctx)
     321           0 :         BN_CTX_end(ctx);
     322           0 :     if (new_ctx != NULL)
     323           0 :         BN_CTX_free(new_ctx);
     324             :     return 0;
     325             : }
     326             : 
     327         737 : int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
     328             :                             const unsigned char *buf, size_t len, BN_CTX *ctx)
     329             : {
     330             :     point_conversion_form_t form;
     331             :     int y_bit;
     332             :     BN_CTX *new_ctx = NULL;
     333             :     BIGNUM *x, *y;
     334             :     size_t field_len, enc_len;
     335             :     int ret = 0;
     336             : 
     337         737 :     if (len == 0) {
     338           0 :         ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
     339           0 :         return 0;
     340             :     }
     341         737 :     form = buf[0];
     342         737 :     y_bit = form & 1;
     343         737 :     form = form & ~1U;
     344         737 :     if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
     345         737 :         && (form != POINT_CONVERSION_UNCOMPRESSED)
     346         737 :         && (form != POINT_CONVERSION_HYBRID)) {
     347           0 :         ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
     348           0 :         return 0;
     349             :     }
     350         737 :     if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) {
     351           0 :         ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
     352           0 :         return 0;
     353             :     }
     354             : 
     355         737 :     if (form == 0) {
     356           0 :         if (len != 1) {
     357           0 :             ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
     358           0 :             return 0;
     359             :         }
     360             : 
     361           0 :         return EC_POINT_set_to_infinity(group, point);
     362             :     }
     363             : 
     364         737 :     field_len = BN_num_bytes(&group->field);
     365             :     enc_len =
     366             :         (form ==
     367         737 :          POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
     368             : 
     369         737 :     if (len != enc_len) {
     370           0 :         ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
     371           0 :         return 0;
     372             :     }
     373             : 
     374         737 :     if (ctx == NULL) {
     375           0 :         ctx = new_ctx = BN_CTX_new();
     376           0 :         if (ctx == NULL)
     377             :             return 0;
     378             :     }
     379             : 
     380         737 :     BN_CTX_start(ctx);
     381         737 :     x = BN_CTX_get(ctx);
     382         737 :     y = BN_CTX_get(ctx);
     383         737 :     if (y == NULL)
     384             :         goto err;
     385             : 
     386         737 :     if (!BN_bin2bn(buf + 1, field_len, x))
     387             :         goto err;
     388         737 :     if (BN_ucmp(x, &group->field) >= 0) {
     389           0 :         ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
     390           0 :         goto err;
     391             :     }
     392             : 
     393         737 :     if (form == POINT_CONVERSION_COMPRESSED) {
     394           0 :         if (!EC_POINT_set_compressed_coordinates_GFp
     395           0 :             (group, point, x, y_bit, ctx))
     396             :             goto err;
     397             :     } else {
     398         737 :         if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
     399             :             goto err;
     400         737 :         if (BN_ucmp(y, &group->field) >= 0) {
     401           0 :             ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
     402           0 :             goto err;
     403             :         }
     404         737 :         if (form == POINT_CONVERSION_HYBRID) {
     405           0 :             if (y_bit != BN_is_odd(y)) {
     406           0 :                 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
     407           0 :                 goto err;
     408             :             }
     409             :         }
     410             : 
     411         737 :         if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
     412             :             goto err;
     413             :     }
     414             : 
     415             :     /* test required by X9.62 */
     416         737 :     if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
     417           0 :         ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
     418           0 :         goto err;
     419             :     }
     420             : 
     421             :     ret = 1;
     422             : 
     423             :  err:
     424         737 :     BN_CTX_end(ctx);
     425         737 :     if (new_ctx != NULL)
     426           0 :         BN_CTX_free(new_ctx);
     427         737 :     return ret;
     428             : }

Generated by: LCOV version 1.10