Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/security/ec/impl/ecl.c
38918 views
/*1* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.2* Use is subject to license terms.3*4* This library is free software; you can redistribute it and/or5* modify it under the terms of the GNU Lesser General Public6* License as published by the Free Software Foundation; either7* version 2.1 of the License, or (at your option) any later version.8*9* This library is distributed in the hope that it will be useful,10* but WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12* Lesser General Public License for more details.13*14* You should have received a copy of the GNU Lesser General Public License15* along with this library; if not, write to the Free Software Foundation,16* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/* *********************************************************************24*25* The Original Code is the elliptic curve math library.26*27* The Initial Developer of the Original Code is28* Sun Microsystems, Inc.29* Portions created by the Initial Developer are Copyright (C) 200330* the Initial Developer. All Rights Reserved.31*32* Contributor(s):33* Douglas Stebila <[email protected]>, Sun Microsystems Laboratories34*35*********************************************************************** */3637#include "mpi.h"38#include "mplogic.h"39#include "ecl.h"40#include "ecl-priv.h"41#include "ec2.h"42#include "ecp.h"43#ifndef _KERNEL44#include <stdlib.h>45#include <string.h>46#endif4748/* Allocate memory for a new ECGroup object. */49ECGroup *50ECGroup_new(int kmflag)51{52mp_err res = MP_OKAY;53ECGroup *group;54#ifdef _KERNEL55group = (ECGroup *) kmem_alloc(sizeof(ECGroup), kmflag);56#else57group = (ECGroup *) malloc(sizeof(ECGroup));58#endif59if (group == NULL)60return NULL;61group->constructed = MP_YES;62group->meth = NULL;63group->text = NULL;64MP_DIGITS(&group->curvea) = 0;65MP_DIGITS(&group->curveb) = 0;66MP_DIGITS(&group->genx) = 0;67MP_DIGITS(&group->geny) = 0;68MP_DIGITS(&group->order) = 0;69group->base_point_mul = NULL;70group->points_mul = NULL;71group->validate_point = NULL;72group->extra1 = NULL;73group->extra2 = NULL;74group->extra_free = NULL;75MP_CHECKOK(mp_init(&group->curvea, kmflag));76MP_CHECKOK(mp_init(&group->curveb, kmflag));77MP_CHECKOK(mp_init(&group->genx, kmflag));78MP_CHECKOK(mp_init(&group->geny, kmflag));79MP_CHECKOK(mp_init(&group->order, kmflag));8081CLEANUP:82if (res != MP_OKAY) {83ECGroup_free(group);84return NULL;85}86return group;87}8889/* Construct a generic ECGroup for elliptic curves over prime fields. */90ECGroup *91ECGroup_consGFp(const mp_int *irr, const mp_int *curvea,92const mp_int *curveb, const mp_int *genx,93const mp_int *geny, const mp_int *order, int cofactor)94{95mp_err res = MP_OKAY;96ECGroup *group = NULL;9798group = ECGroup_new(FLAG(irr));99if (group == NULL)100return NULL;101102group->meth = GFMethod_consGFp(irr);103if (group->meth == NULL) {104res = MP_MEM;105goto CLEANUP;106}107MP_CHECKOK(mp_copy(curvea, &group->curvea));108MP_CHECKOK(mp_copy(curveb, &group->curveb));109MP_CHECKOK(mp_copy(genx, &group->genx));110MP_CHECKOK(mp_copy(geny, &group->geny));111MP_CHECKOK(mp_copy(order, &group->order));112group->cofactor = cofactor;113group->point_add = &ec_GFp_pt_add_aff;114group->point_sub = &ec_GFp_pt_sub_aff;115group->point_dbl = &ec_GFp_pt_dbl_aff;116group->point_mul = &ec_GFp_pt_mul_jm_wNAF;117group->base_point_mul = NULL;118group->points_mul = &ec_GFp_pts_mul_jac;119group->validate_point = &ec_GFp_validate_point;120121CLEANUP:122if (res != MP_OKAY) {123ECGroup_free(group);124return NULL;125}126return group;127}128129/* Construct a generic ECGroup for elliptic curves over prime fields with130* field arithmetic implemented in Montgomery coordinates. */131ECGroup *132ECGroup_consGFp_mont(const mp_int *irr, const mp_int *curvea,133const mp_int *curveb, const mp_int *genx,134const mp_int *geny, const mp_int *order, int cofactor)135{136mp_err res = MP_OKAY;137ECGroup *group = NULL;138139group = ECGroup_new(FLAG(irr));140if (group == NULL)141return NULL;142143group->meth = GFMethod_consGFp_mont(irr);144if (group->meth == NULL) {145res = MP_MEM;146goto CLEANUP;147}148MP_CHECKOK(group->meth->149field_enc(curvea, &group->curvea, group->meth));150MP_CHECKOK(group->meth->151field_enc(curveb, &group->curveb, group->meth));152MP_CHECKOK(group->meth->field_enc(genx, &group->genx, group->meth));153MP_CHECKOK(group->meth->field_enc(geny, &group->geny, group->meth));154MP_CHECKOK(mp_copy(order, &group->order));155group->cofactor = cofactor;156group->point_add = &ec_GFp_pt_add_aff;157group->point_sub = &ec_GFp_pt_sub_aff;158group->point_dbl = &ec_GFp_pt_dbl_aff;159group->point_mul = &ec_GFp_pt_mul_jm_wNAF;160group->base_point_mul = NULL;161group->points_mul = &ec_GFp_pts_mul_jac;162group->validate_point = &ec_GFp_validate_point;163164CLEANUP:165if (res != MP_OKAY) {166ECGroup_free(group);167return NULL;168}169return group;170}171172#ifdef NSS_ECC_MORE_THAN_SUITE_B173/* Construct a generic ECGroup for elliptic curves over binary polynomial174* fields. */175ECGroup *176ECGroup_consGF2m(const mp_int *irr, const unsigned int irr_arr[5],177const mp_int *curvea, const mp_int *curveb,178const mp_int *genx, const mp_int *geny,179const mp_int *order, int cofactor)180{181mp_err res = MP_OKAY;182ECGroup *group = NULL;183184group = ECGroup_new(FLAG(irr));185if (group == NULL)186return NULL;187188group->meth = GFMethod_consGF2m(irr, irr_arr);189if (group->meth == NULL) {190res = MP_MEM;191goto CLEANUP;192}193MP_CHECKOK(mp_copy(curvea, &group->curvea));194MP_CHECKOK(mp_copy(curveb, &group->curveb));195MP_CHECKOK(mp_copy(genx, &group->genx));196MP_CHECKOK(mp_copy(geny, &group->geny));197MP_CHECKOK(mp_copy(order, &group->order));198group->cofactor = cofactor;199group->point_add = &ec_GF2m_pt_add_aff;200group->point_sub = &ec_GF2m_pt_sub_aff;201group->point_dbl = &ec_GF2m_pt_dbl_aff;202group->point_mul = &ec_GF2m_pt_mul_mont;203group->base_point_mul = NULL;204group->points_mul = &ec_pts_mul_basic;205group->validate_point = &ec_GF2m_validate_point;206207CLEANUP:208if (res != MP_OKAY) {209ECGroup_free(group);210return NULL;211}212return group;213}214#endif215216/* Construct ECGroup from hex parameters and name, if any. Called by217* ECGroup_fromHex and ECGroup_fromName. */218ECGroup *219ecgroup_fromNameAndHex(const ECCurveName name,220const ECCurveParams * params, int kmflag)221{222mp_int irr, curvea, curveb, genx, geny, order;223int bits;224ECGroup *group = NULL;225mp_err res = MP_OKAY;226227/* initialize values */228MP_DIGITS(&irr) = 0;229MP_DIGITS(&curvea) = 0;230MP_DIGITS(&curveb) = 0;231MP_DIGITS(&genx) = 0;232MP_DIGITS(&geny) = 0;233MP_DIGITS(&order) = 0;234MP_CHECKOK(mp_init(&irr, kmflag));235MP_CHECKOK(mp_init(&curvea, kmflag));236MP_CHECKOK(mp_init(&curveb, kmflag));237MP_CHECKOK(mp_init(&genx, kmflag));238MP_CHECKOK(mp_init(&geny, kmflag));239MP_CHECKOK(mp_init(&order, kmflag));240MP_CHECKOK(mp_read_radix(&irr, params->irr, 16));241MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16));242MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16));243MP_CHECKOK(mp_read_radix(&genx, params->genx, 16));244MP_CHECKOK(mp_read_radix(&geny, params->geny, 16));245MP_CHECKOK(mp_read_radix(&order, params->order, 16));246247/* determine number of bits */248bits = mpl_significant_bits(&irr) - 1;249if (bits < MP_OKAY) {250res = bits;251goto CLEANUP;252}253254/* determine which optimizations (if any) to use */255if (params->field == ECField_GFp) {256#ifdef NSS_ECC_MORE_THAN_SUITE_B257switch (name) {258#ifdef ECL_USE_FP259case ECCurve_SECG_PRIME_160R1:260group =261ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,262&order, params->cofactor);263if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }264MP_CHECKOK(ec_group_set_secp160r1_fp(group));265break;266#endif267case ECCurve_SECG_PRIME_192R1:268#ifdef ECL_USE_FP269group =270ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,271&order, params->cofactor);272if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }273MP_CHECKOK(ec_group_set_nistp192_fp(group));274#else275group =276ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,277&order, params->cofactor);278if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }279MP_CHECKOK(ec_group_set_gfp192(group, name));280#endif281break;282case ECCurve_SECG_PRIME_224R1:283#ifdef ECL_USE_FP284group =285ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,286&order, params->cofactor);287if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }288MP_CHECKOK(ec_group_set_nistp224_fp(group));289#else290group =291ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,292&order, params->cofactor);293if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }294MP_CHECKOK(ec_group_set_gfp224(group, name));295#endif296break;297case ECCurve_SECG_PRIME_256R1:298group =299ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,300&order, params->cofactor);301if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }302MP_CHECKOK(ec_group_set_gfp256(group, name));303break;304case ECCurve_SECG_PRIME_521R1:305group =306ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,307&order, params->cofactor);308if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }309MP_CHECKOK(ec_group_set_gfp521(group, name));310break;311default:312/* use generic arithmetic */313#endif314group =315ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,316&order, params->cofactor);317if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }318#ifdef NSS_ECC_MORE_THAN_SUITE_B319}320} else if (params->field == ECField_GF2m) {321group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor);322if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }323if ((name == ECCurve_NIST_K163) ||324(name == ECCurve_NIST_B163) ||325(name == ECCurve_SECG_CHAR2_163R1)) {326MP_CHECKOK(ec_group_set_gf2m163(group, name));327} else if ((name == ECCurve_SECG_CHAR2_193R1) ||328(name == ECCurve_SECG_CHAR2_193R2)) {329MP_CHECKOK(ec_group_set_gf2m193(group, name));330} else if ((name == ECCurve_NIST_K233) ||331(name == ECCurve_NIST_B233)) {332MP_CHECKOK(ec_group_set_gf2m233(group, name));333}334#endif335} else {336res = MP_UNDEF;337goto CLEANUP;338}339340/* set name, if any */341if ((group != NULL) && (params->text != NULL)) {342#ifdef _KERNEL343int n = strlen(params->text) + 1;344345group->text = kmem_alloc(n, kmflag);346if (group->text == NULL) {347res = MP_MEM;348goto CLEANUP;349}350bcopy(params->text, group->text, n);351group->text_len = n;352#else353group->text = strdup(params->text);354if (group->text == NULL) {355res = MP_MEM;356}357#endif358}359360CLEANUP:361mp_clear(&irr);362mp_clear(&curvea);363mp_clear(&curveb);364mp_clear(&genx);365mp_clear(&geny);366mp_clear(&order);367if (res != MP_OKAY) {368ECGroup_free(group);369return NULL;370}371return group;372}373374/* Construct ECGroup from hexadecimal representations of parameters. */375ECGroup *376ECGroup_fromHex(const ECCurveParams * params, int kmflag)377{378return ecgroup_fromNameAndHex(ECCurve_noName, params, kmflag);379}380381/* Construct ECGroup from named parameters. */382ECGroup *383ECGroup_fromName(const ECCurveName name, int kmflag)384{385ECGroup *group = NULL;386ECCurveParams *params = NULL;387mp_err res = MP_OKAY;388389params = EC_GetNamedCurveParams(name, kmflag);390if (params == NULL) {391res = MP_UNDEF;392goto CLEANUP;393}394395/* construct actual group */396group = ecgroup_fromNameAndHex(name, params, kmflag);397if (group == NULL) {398res = MP_UNDEF;399goto CLEANUP;400}401402CLEANUP:403EC_FreeCurveParams(params);404if (res != MP_OKAY) {405ECGroup_free(group);406return NULL;407}408return group;409}410411/* Validates an EC public key as described in Section 5.2.2 of X9.62. */412mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const413mp_int *py)414{415/* 1: Verify that publicValue is not the point at infinity */416/* 2: Verify that the coordinates of publicValue are elements417* of the field.418*/419/* 3: Verify that publicValue is on the curve. */420/* 4: Verify that the order of the curve times the publicValue421* is the point at infinity.422*/423return group->validate_point(px, py, group);424}425426/* Free the memory allocated (if any) to an ECGroup object. */427void428ECGroup_free(ECGroup *group)429{430if (group == NULL)431return;432GFMethod_free(group->meth);433if (group->constructed == MP_NO)434return;435mp_clear(&group->curvea);436mp_clear(&group->curveb);437mp_clear(&group->genx);438mp_clear(&group->geny);439mp_clear(&group->order);440if (group->text != NULL)441#ifdef _KERNEL442kmem_free(group->text, group->text_len);443#else444free(group->text);445#endif446if (group->extra_free != NULL)447group->extra_free(group);448#ifdef _KERNEL449kmem_free(group, sizeof (ECGroup));450#else451free(group);452#endif453}454455456