📄 ec2_smpl.c
字号:
/* crypto/ec/ec2_smpl.c *//* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. * * The Elliptic Curve Public-Key Crypto Library (ECC Code) included * herein is developed by SUN MICROSYSTEMS, INC., and is contributed * to the OpenSSL project. * * The ECC Code is licensed pursuant to the OpenSSL open source * license provided below. * * The software is originally written by Sheueling Chang Shantz and * Douglas Stebila of Sun Microsystems Laboratories. * *//* ==================================================================== * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */#include <openssl/err.h>#include "ec_lcl.h"const EC_METHOD *EC_GF2m_simple_method(void) { static const EC_METHOD ret = { NID_X9_62_characteristic_two_field, ec_GF2m_simple_group_init, ec_GF2m_simple_group_finish, ec_GF2m_simple_group_clear_finish, ec_GF2m_simple_group_copy, ec_GF2m_simple_group_set_curve, ec_GF2m_simple_group_get_curve, ec_GF2m_simple_group_get_degree, ec_GF2m_simple_group_check_discriminant, ec_GF2m_simple_point_init, ec_GF2m_simple_point_finish, ec_GF2m_simple_point_clear_finish, ec_GF2m_simple_point_copy, ec_GF2m_simple_point_set_to_infinity, 0 /* set_Jprojective_coordinates_GFp */, 0 /* get_Jprojective_coordinates_GFp */, ec_GF2m_simple_point_set_affine_coordinates, ec_GF2m_simple_point_get_affine_coordinates, ec_GF2m_simple_set_compressed_coordinates, ec_GF2m_simple_point2oct, ec_GF2m_simple_oct2point, ec_GF2m_simple_add, ec_GF2m_simple_dbl, ec_GF2m_simple_invert, ec_GF2m_simple_is_at_infinity, ec_GF2m_simple_is_on_curve, ec_GF2m_simple_cmp, ec_GF2m_simple_make_affine, ec_GF2m_simple_points_make_affine, /* the following three method functions are defined in ec2_mult.c */ ec_GF2m_simple_mul, ec_GF2m_precompute_mult, ec_GF2m_have_precompute_mult, ec_GF2m_simple_field_mul, ec_GF2m_simple_field_sqr, ec_GF2m_simple_field_div, 0 /* field_encode */, 0 /* field_decode */, 0 /* field_set_to_one */ }; return &ret; }/* Initialize a GF(2^m)-based EC_GROUP structure. * Note that all other members are handled by EC_GROUP_new. */int ec_GF2m_simple_group_init(EC_GROUP *group) { BN_init(&group->field); BN_init(&group->a); BN_init(&group->b); return 1; }/* Free a GF(2^m)-based EC_GROUP structure. * Note that all other members are handled by EC_GROUP_free. */void ec_GF2m_simple_group_finish(EC_GROUP *group) { BN_free(&group->field); BN_free(&group->a); BN_free(&group->b); }/* Clear and free a GF(2^m)-based EC_GROUP structure. * Note that all other members are handled by EC_GROUP_clear_free. */void ec_GF2m_simple_group_clear_finish(EC_GROUP *group) { BN_clear_free(&group->field); BN_clear_free(&group->a); BN_clear_free(&group->b); group->poly[0] = 0; group->poly[1] = 0; group->poly[2] = 0; group->poly[3] = 0; group->poly[4] = 0; }/* Copy a GF(2^m)-based EC_GROUP structure. * Note that all other members are handled by EC_GROUP_copy. */int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) { int i; if (!BN_copy(&dest->field, &src->field)) return 0; if (!BN_copy(&dest->a, &src->a)) return 0; if (!BN_copy(&dest->b, &src->b)) return 0; dest->poly[0] = src->poly[0]; dest->poly[1] = src->poly[1]; dest->poly[2] = src->poly[2]; dest->poly[3] = src->poly[3]; dest->poly[4] = src->poly[4]; bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2); bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2); for (i = dest->a.top; i < dest->a.dmax; i++) dest->a.d[i] = 0; for (i = dest->b.top; i < dest->b.dmax; i++) dest->b.d[i] = 0; return 1; }/* Set the curve parameters of an EC_GROUP structure. */int ec_GF2m_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { int ret = 0, i; /* group->field */ if (!BN_copy(&group->field, p)) goto err; i = BN_GF2m_poly2arr(&group->field, group->poly, 5); if ((i != 5) && (i != 3)) { ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD); goto err; } /* group->a */ if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) goto err; bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2); for (i = group->a.top; i < group->a.dmax; i++) group->a.d[i] = 0; /* group->b */ if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) goto err; bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2); for (i = group->b.top; i < group->b.dmax; i++) group->b.d[i] = 0; ret = 1; err: return ret; }/* Get the curve parameters of an EC_GROUP structure. * If p, a, or b are NULL then there values will not be set but the method will return with success. */int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) { int ret = 0; if (p != NULL) { if (!BN_copy(p, &group->field)) return 0; } if (a != NULL) { if (!BN_copy(a, &group->a)) goto err; } if (b != NULL) { if (!BN_copy(b, &group->b)) goto err; } ret = 1; err: return ret; }/* Gets the degree of the field. For a curve over GF(2^m) this is the value m. */int ec_GF2m_simple_group_get_degree(const EC_GROUP *group) { return BN_num_bits(&group->field)-1; }/* Checks the discriminant of the curve. * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) */int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) { int ret = 0; BIGNUM *b; BN_CTX *new_ctx = NULL; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE); goto err; } } BN_CTX_start(ctx); b = BN_CTX_get(ctx); if (b == NULL) goto err; if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) goto err; /* check the discriminant: * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) */ if (BN_is_zero(b)) goto err; ret = 1;err: if (ctx != NULL) BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }/* Initializes an EC_POINT. */int ec_GF2m_simple_point_init(EC_POINT *point) { BN_init(&point->X); BN_init(&point->Y); BN_init(&point->Z); return 1; }/* Frees an EC_POINT. */void ec_GF2m_simple_point_finish(EC_POINT *point) { BN_free(&point->X); BN_free(&point->Y); BN_free(&point->Z); }/* Clears and frees an EC_POINT. */void ec_GF2m_simple_point_clear_finish(EC_POINT *point) { BN_clear_free(&point->X); BN_clear_free(&point->Y); BN_clear_free(&point->Z); point->Z_is_one = 0; }/* Copy the contents of one EC_POINT into another. Assumes dest is initialized. */int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src) { if (!BN_copy(&dest->X, &src->X)) return 0; if (!BN_copy(&dest->Y, &src->Y)) return 0; if (!BN_copy(&dest->Z, &src->Z)) return 0; dest->Z_is_one = src->Z_is_one; return 1; }/* Set an EC_POINT to the point at infinity. * A point at infinity is represented by having Z=0. */int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) { point->Z_is_one = 0; BN_zero(&point->Z); return 1; }/* Set the coordinates of an EC_POINT using affine coordinates. * Note that the simple implementation only uses affine coordinates. */int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) { int ret = 0; if (x == NULL || y == NULL) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (!BN_copy(&point->X, x)) goto err; BN_set_negative(&point->X, 0); if (!BN_copy(&point->Y, y)) goto err; BN_set_negative(&point->Y, 0); if (!BN_copy(&point->Z, BN_value_one())) goto err; BN_set_negative(&point->Z, 0); point->Z_is_one = 1; ret = 1; err: return ret; }/* Gets the affine coordinates of an EC_POINT. * Note that the simple implementation only uses affine coordinates. */int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) { int ret = 0; if (EC_POINT_is_at_infinity(group, point)) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY); return 0; } if (BN_cmp(&point->Z, BN_value_one())) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (x != NULL) { if (!BN_copy(x, &point->X)) goto err; BN_set_negative(x, 0); } if (y != NULL) { if (!BN_copy(y, &point->Y)) goto err; BN_set_negative(y, 0); } ret = 1; err: return ret; }/* Include patented algorithms. */#include "ec2_smpt.c"/* Converts an EC_POINT to an octet string. * If buf is NULL, the encoded length will be returned. * If the length len of buf is smaller than required an error will be returned. * * The point compression section of this function is patented by Certicom Corp. * under US Patent 6,141,420. Point compression is disabled by default and can * be enabled by defining the preprocessor macro OPENSSL_EC_BIN_PT_COMP at * Configure-time. */size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, unsigned char *buf, size_t len, BN_CTX *ctx) { size_t ret; BN_CTX *new_ctx = NULL; int used_ctx = 0; BIGNUM *x, *y, *yxi; size_t field_len, i, skip;#ifndef OPENSSL_EC_BIN_PT_COMP if ((form == POINT_CONVERSION_COMPRESSED) || (form == POINT_CONVERSION_HYBRID)) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_DISABLED); goto err; }#endif if ((form != POINT_CONVERSION_COMPRESSED) && (form != POINT_CONVERSION_UNCOMPRESSED) && (form != POINT_CONVERSION_HYBRID)) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); goto err; } if (EC_POINT_is_at_infinity(group, point)) { /* encodes to a single 0 octet */ if (buf != NULL) { if (len < 1) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); return 0; } buf[0] = 0; } return 1; } /* ret := required output buffer length */ field_len = (EC_GROUP_get_degree(group) + 7) / 8; ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len; /* if 'buf' is NULL, just return required length */ if (buf != NULL) { if (len < ret) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); goto err; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } BN_CTX_start(ctx); used_ctx = 1; x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); yxi = BN_CTX_get(ctx); if (yxi == NULL) goto err;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -