1*f9fbec18Smcpowers /* 2*f9fbec18Smcpowers * ***** BEGIN LICENSE BLOCK ***** 3*f9fbec18Smcpowers * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4*f9fbec18Smcpowers * 5*f9fbec18Smcpowers * The contents of this file are subject to the Mozilla Public License Version 6*f9fbec18Smcpowers * 1.1 (the "License"); you may not use this file except in compliance with 7*f9fbec18Smcpowers * the License. You may obtain a copy of the License at 8*f9fbec18Smcpowers * http://www.mozilla.org/MPL/ 9*f9fbec18Smcpowers * 10*f9fbec18Smcpowers * Software distributed under the License is distributed on an "AS IS" basis, 11*f9fbec18Smcpowers * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12*f9fbec18Smcpowers * for the specific language governing rights and limitations under the 13*f9fbec18Smcpowers * License. 14*f9fbec18Smcpowers * 15*f9fbec18Smcpowers * The Original Code is the elliptic curve math library. 16*f9fbec18Smcpowers * 17*f9fbec18Smcpowers * The Initial Developer of the Original Code is 18*f9fbec18Smcpowers * Sun Microsystems, Inc. 19*f9fbec18Smcpowers * Portions created by the Initial Developer are Copyright (C) 2003 20*f9fbec18Smcpowers * the Initial Developer. All Rights Reserved. 21*f9fbec18Smcpowers * 22*f9fbec18Smcpowers * Contributor(s): 23*f9fbec18Smcpowers * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories 24*f9fbec18Smcpowers * 25*f9fbec18Smcpowers * Alternatively, the contents of this file may be used under the terms of 26*f9fbec18Smcpowers * either the GNU General Public License Version 2 or later (the "GPL"), or 27*f9fbec18Smcpowers * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28*f9fbec18Smcpowers * in which case the provisions of the GPL or the LGPL are applicable instead 29*f9fbec18Smcpowers * of those above. If you wish to allow use of your version of this file only 30*f9fbec18Smcpowers * under the terms of either the GPL or the LGPL, and not to allow others to 31*f9fbec18Smcpowers * use your version of this file under the terms of the MPL, indicate your 32*f9fbec18Smcpowers * decision by deleting the provisions above and replace them with the notice 33*f9fbec18Smcpowers * and other provisions required by the GPL or the LGPL. If you do not delete 34*f9fbec18Smcpowers * the provisions above, a recipient may use your version of this file under 35*f9fbec18Smcpowers * the terms of any one of the MPL, the GPL or the LGPL. 36*f9fbec18Smcpowers * 37*f9fbec18Smcpowers * ***** END LICENSE BLOCK ***** */ 38*f9fbec18Smcpowers /* 39*f9fbec18Smcpowers * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 40*f9fbec18Smcpowers * Use is subject to license terms. 41*f9fbec18Smcpowers * 42*f9fbec18Smcpowers * Sun elects to use this software under the MPL license. 43*f9fbec18Smcpowers */ 44*f9fbec18Smcpowers 45*f9fbec18Smcpowers #pragma ident "%Z%%M% %I% %E% SMI" 46*f9fbec18Smcpowers 47*f9fbec18Smcpowers #include "mpi.h" 48*f9fbec18Smcpowers #include "mplogic.h" 49*f9fbec18Smcpowers #include "ecl.h" 50*f9fbec18Smcpowers #include "ecl-priv.h" 51*f9fbec18Smcpowers #include "ec2.h" 52*f9fbec18Smcpowers #include "ecp.h" 53*f9fbec18Smcpowers #ifndef _KERNEL 54*f9fbec18Smcpowers #include <stdlib.h> 55*f9fbec18Smcpowers #include <string.h> 56*f9fbec18Smcpowers #endif 57*f9fbec18Smcpowers 58*f9fbec18Smcpowers /* Allocate memory for a new ECGroup object. */ 59*f9fbec18Smcpowers ECGroup * 60*f9fbec18Smcpowers ECGroup_new(int kmflag) 61*f9fbec18Smcpowers { 62*f9fbec18Smcpowers mp_err res = MP_OKAY; 63*f9fbec18Smcpowers ECGroup *group; 64*f9fbec18Smcpowers #ifdef _KERNEL 65*f9fbec18Smcpowers group = (ECGroup *) kmem_alloc(sizeof(ECGroup), kmflag); 66*f9fbec18Smcpowers #else 67*f9fbec18Smcpowers group = (ECGroup *) malloc(sizeof(ECGroup)); 68*f9fbec18Smcpowers #endif 69*f9fbec18Smcpowers if (group == NULL) 70*f9fbec18Smcpowers return NULL; 71*f9fbec18Smcpowers group->constructed = MP_YES; 72*f9fbec18Smcpowers group->meth = NULL; 73*f9fbec18Smcpowers group->text = NULL; 74*f9fbec18Smcpowers MP_DIGITS(&group->curvea) = 0; 75*f9fbec18Smcpowers MP_DIGITS(&group->curveb) = 0; 76*f9fbec18Smcpowers MP_DIGITS(&group->genx) = 0; 77*f9fbec18Smcpowers MP_DIGITS(&group->geny) = 0; 78*f9fbec18Smcpowers MP_DIGITS(&group->order) = 0; 79*f9fbec18Smcpowers group->base_point_mul = NULL; 80*f9fbec18Smcpowers group->points_mul = NULL; 81*f9fbec18Smcpowers group->validate_point = NULL; 82*f9fbec18Smcpowers group->extra1 = NULL; 83*f9fbec18Smcpowers group->extra2 = NULL; 84*f9fbec18Smcpowers group->extra_free = NULL; 85*f9fbec18Smcpowers MP_CHECKOK(mp_init(&group->curvea, kmflag)); 86*f9fbec18Smcpowers MP_CHECKOK(mp_init(&group->curveb, kmflag)); 87*f9fbec18Smcpowers MP_CHECKOK(mp_init(&group->genx, kmflag)); 88*f9fbec18Smcpowers MP_CHECKOK(mp_init(&group->geny, kmflag)); 89*f9fbec18Smcpowers MP_CHECKOK(mp_init(&group->order, kmflag)); 90*f9fbec18Smcpowers 91*f9fbec18Smcpowers CLEANUP: 92*f9fbec18Smcpowers if (res != MP_OKAY) { 93*f9fbec18Smcpowers ECGroup_free(group); 94*f9fbec18Smcpowers return NULL; 95*f9fbec18Smcpowers } 96*f9fbec18Smcpowers return group; 97*f9fbec18Smcpowers } 98*f9fbec18Smcpowers 99*f9fbec18Smcpowers /* Construct a generic ECGroup for elliptic curves over prime fields. */ 100*f9fbec18Smcpowers ECGroup * 101*f9fbec18Smcpowers ECGroup_consGFp(const mp_int *irr, const mp_int *curvea, 102*f9fbec18Smcpowers const mp_int *curveb, const mp_int *genx, 103*f9fbec18Smcpowers const mp_int *geny, const mp_int *order, int cofactor) 104*f9fbec18Smcpowers { 105*f9fbec18Smcpowers mp_err res = MP_OKAY; 106*f9fbec18Smcpowers ECGroup *group = NULL; 107*f9fbec18Smcpowers 108*f9fbec18Smcpowers group = ECGroup_new(FLAG(irr)); 109*f9fbec18Smcpowers if (group == NULL) 110*f9fbec18Smcpowers return NULL; 111*f9fbec18Smcpowers 112*f9fbec18Smcpowers group->meth = GFMethod_consGFp(irr); 113*f9fbec18Smcpowers if (group->meth == NULL) { 114*f9fbec18Smcpowers res = MP_MEM; 115*f9fbec18Smcpowers goto CLEANUP; 116*f9fbec18Smcpowers } 117*f9fbec18Smcpowers MP_CHECKOK(mp_copy(curvea, &group->curvea)); 118*f9fbec18Smcpowers MP_CHECKOK(mp_copy(curveb, &group->curveb)); 119*f9fbec18Smcpowers MP_CHECKOK(mp_copy(genx, &group->genx)); 120*f9fbec18Smcpowers MP_CHECKOK(mp_copy(geny, &group->geny)); 121*f9fbec18Smcpowers MP_CHECKOK(mp_copy(order, &group->order)); 122*f9fbec18Smcpowers group->cofactor = cofactor; 123*f9fbec18Smcpowers group->point_add = &ec_GFp_pt_add_aff; 124*f9fbec18Smcpowers group->point_sub = &ec_GFp_pt_sub_aff; 125*f9fbec18Smcpowers group->point_dbl = &ec_GFp_pt_dbl_aff; 126*f9fbec18Smcpowers group->point_mul = &ec_GFp_pt_mul_jm_wNAF; 127*f9fbec18Smcpowers group->base_point_mul = NULL; 128*f9fbec18Smcpowers group->points_mul = &ec_GFp_pts_mul_jac; 129*f9fbec18Smcpowers group->validate_point = &ec_GFp_validate_point; 130*f9fbec18Smcpowers 131*f9fbec18Smcpowers CLEANUP: 132*f9fbec18Smcpowers if (res != MP_OKAY) { 133*f9fbec18Smcpowers ECGroup_free(group); 134*f9fbec18Smcpowers return NULL; 135*f9fbec18Smcpowers } 136*f9fbec18Smcpowers return group; 137*f9fbec18Smcpowers } 138*f9fbec18Smcpowers 139*f9fbec18Smcpowers /* Construct a generic ECGroup for elliptic curves over prime fields with 140*f9fbec18Smcpowers * field arithmetic implemented in Montgomery coordinates. */ 141*f9fbec18Smcpowers ECGroup * 142*f9fbec18Smcpowers ECGroup_consGFp_mont(const mp_int *irr, const mp_int *curvea, 143*f9fbec18Smcpowers const mp_int *curveb, const mp_int *genx, 144*f9fbec18Smcpowers const mp_int *geny, const mp_int *order, int cofactor) 145*f9fbec18Smcpowers { 146*f9fbec18Smcpowers mp_err res = MP_OKAY; 147*f9fbec18Smcpowers ECGroup *group = NULL; 148*f9fbec18Smcpowers 149*f9fbec18Smcpowers group = ECGroup_new(FLAG(irr)); 150*f9fbec18Smcpowers if (group == NULL) 151*f9fbec18Smcpowers return NULL; 152*f9fbec18Smcpowers 153*f9fbec18Smcpowers group->meth = GFMethod_consGFp_mont(irr); 154*f9fbec18Smcpowers if (group->meth == NULL) { 155*f9fbec18Smcpowers res = MP_MEM; 156*f9fbec18Smcpowers goto CLEANUP; 157*f9fbec18Smcpowers } 158*f9fbec18Smcpowers MP_CHECKOK(group->meth-> 159*f9fbec18Smcpowers field_enc(curvea, &group->curvea, group->meth)); 160*f9fbec18Smcpowers MP_CHECKOK(group->meth-> 161*f9fbec18Smcpowers field_enc(curveb, &group->curveb, group->meth)); 162*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_enc(genx, &group->genx, group->meth)); 163*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_enc(geny, &group->geny, group->meth)); 164*f9fbec18Smcpowers MP_CHECKOK(mp_copy(order, &group->order)); 165*f9fbec18Smcpowers group->cofactor = cofactor; 166*f9fbec18Smcpowers group->point_add = &ec_GFp_pt_add_aff; 167*f9fbec18Smcpowers group->point_sub = &ec_GFp_pt_sub_aff; 168*f9fbec18Smcpowers group->point_dbl = &ec_GFp_pt_dbl_aff; 169*f9fbec18Smcpowers group->point_mul = &ec_GFp_pt_mul_jm_wNAF; 170*f9fbec18Smcpowers group->base_point_mul = NULL; 171*f9fbec18Smcpowers group->points_mul = &ec_GFp_pts_mul_jac; 172*f9fbec18Smcpowers group->validate_point = &ec_GFp_validate_point; 173*f9fbec18Smcpowers 174*f9fbec18Smcpowers CLEANUP: 175*f9fbec18Smcpowers if (res != MP_OKAY) { 176*f9fbec18Smcpowers ECGroup_free(group); 177*f9fbec18Smcpowers return NULL; 178*f9fbec18Smcpowers } 179*f9fbec18Smcpowers return group; 180*f9fbec18Smcpowers } 181*f9fbec18Smcpowers 182*f9fbec18Smcpowers #ifdef NSS_ECC_MORE_THAN_SUITE_B 183*f9fbec18Smcpowers /* Construct a generic ECGroup for elliptic curves over binary polynomial 184*f9fbec18Smcpowers * fields. */ 185*f9fbec18Smcpowers ECGroup * 186*f9fbec18Smcpowers ECGroup_consGF2m(const mp_int *irr, const unsigned int irr_arr[5], 187*f9fbec18Smcpowers const mp_int *curvea, const mp_int *curveb, 188*f9fbec18Smcpowers const mp_int *genx, const mp_int *geny, 189*f9fbec18Smcpowers const mp_int *order, int cofactor) 190*f9fbec18Smcpowers { 191*f9fbec18Smcpowers mp_err res = MP_OKAY; 192*f9fbec18Smcpowers ECGroup *group = NULL; 193*f9fbec18Smcpowers 194*f9fbec18Smcpowers group = ECGroup_new(FLAG(irr)); 195*f9fbec18Smcpowers if (group == NULL) 196*f9fbec18Smcpowers return NULL; 197*f9fbec18Smcpowers 198*f9fbec18Smcpowers group->meth = GFMethod_consGF2m(irr, irr_arr); 199*f9fbec18Smcpowers if (group->meth == NULL) { 200*f9fbec18Smcpowers res = MP_MEM; 201*f9fbec18Smcpowers goto CLEANUP; 202*f9fbec18Smcpowers } 203*f9fbec18Smcpowers MP_CHECKOK(mp_copy(curvea, &group->curvea)); 204*f9fbec18Smcpowers MP_CHECKOK(mp_copy(curveb, &group->curveb)); 205*f9fbec18Smcpowers MP_CHECKOK(mp_copy(genx, &group->genx)); 206*f9fbec18Smcpowers MP_CHECKOK(mp_copy(geny, &group->geny)); 207*f9fbec18Smcpowers MP_CHECKOK(mp_copy(order, &group->order)); 208*f9fbec18Smcpowers group->cofactor = cofactor; 209*f9fbec18Smcpowers group->point_add = &ec_GF2m_pt_add_aff; 210*f9fbec18Smcpowers group->point_sub = &ec_GF2m_pt_sub_aff; 211*f9fbec18Smcpowers group->point_dbl = &ec_GF2m_pt_dbl_aff; 212*f9fbec18Smcpowers group->point_mul = &ec_GF2m_pt_mul_mont; 213*f9fbec18Smcpowers group->base_point_mul = NULL; 214*f9fbec18Smcpowers group->points_mul = &ec_pts_mul_basic; 215*f9fbec18Smcpowers group->validate_point = &ec_GF2m_validate_point; 216*f9fbec18Smcpowers 217*f9fbec18Smcpowers CLEANUP: 218*f9fbec18Smcpowers if (res != MP_OKAY) { 219*f9fbec18Smcpowers ECGroup_free(group); 220*f9fbec18Smcpowers return NULL; 221*f9fbec18Smcpowers } 222*f9fbec18Smcpowers return group; 223*f9fbec18Smcpowers } 224*f9fbec18Smcpowers #endif 225*f9fbec18Smcpowers 226*f9fbec18Smcpowers /* Construct ECGroup from hex parameters and name, if any. Called by 227*f9fbec18Smcpowers * ECGroup_fromHex and ECGroup_fromName. */ 228*f9fbec18Smcpowers ECGroup * 229*f9fbec18Smcpowers ecgroup_fromNameAndHex(const ECCurveName name, 230*f9fbec18Smcpowers const ECCurveParams * params, int kmflag) 231*f9fbec18Smcpowers { 232*f9fbec18Smcpowers mp_int irr, curvea, curveb, genx, geny, order; 233*f9fbec18Smcpowers int bits; 234*f9fbec18Smcpowers ECGroup *group = NULL; 235*f9fbec18Smcpowers mp_err res = MP_OKAY; 236*f9fbec18Smcpowers 237*f9fbec18Smcpowers /* initialize values */ 238*f9fbec18Smcpowers MP_DIGITS(&irr) = 0; 239*f9fbec18Smcpowers MP_DIGITS(&curvea) = 0; 240*f9fbec18Smcpowers MP_DIGITS(&curveb) = 0; 241*f9fbec18Smcpowers MP_DIGITS(&genx) = 0; 242*f9fbec18Smcpowers MP_DIGITS(&geny) = 0; 243*f9fbec18Smcpowers MP_DIGITS(&order) = 0; 244*f9fbec18Smcpowers MP_CHECKOK(mp_init(&irr, kmflag)); 245*f9fbec18Smcpowers MP_CHECKOK(mp_init(&curvea, kmflag)); 246*f9fbec18Smcpowers MP_CHECKOK(mp_init(&curveb, kmflag)); 247*f9fbec18Smcpowers MP_CHECKOK(mp_init(&genx, kmflag)); 248*f9fbec18Smcpowers MP_CHECKOK(mp_init(&geny, kmflag)); 249*f9fbec18Smcpowers MP_CHECKOK(mp_init(&order, kmflag)); 250*f9fbec18Smcpowers MP_CHECKOK(mp_read_radix(&irr, params->irr, 16)); 251*f9fbec18Smcpowers MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16)); 252*f9fbec18Smcpowers MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16)); 253*f9fbec18Smcpowers MP_CHECKOK(mp_read_radix(&genx, params->genx, 16)); 254*f9fbec18Smcpowers MP_CHECKOK(mp_read_radix(&geny, params->geny, 16)); 255*f9fbec18Smcpowers MP_CHECKOK(mp_read_radix(&order, params->order, 16)); 256*f9fbec18Smcpowers 257*f9fbec18Smcpowers /* determine number of bits */ 258*f9fbec18Smcpowers bits = mpl_significant_bits(&irr) - 1; 259*f9fbec18Smcpowers if (bits < MP_OKAY) { 260*f9fbec18Smcpowers res = bits; 261*f9fbec18Smcpowers goto CLEANUP; 262*f9fbec18Smcpowers } 263*f9fbec18Smcpowers 264*f9fbec18Smcpowers /* determine which optimizations (if any) to use */ 265*f9fbec18Smcpowers if (params->field == ECField_GFp) { 266*f9fbec18Smcpowers #ifdef NSS_ECC_MORE_THAN_SUITE_B 267*f9fbec18Smcpowers switch (name) { 268*f9fbec18Smcpowers #ifdef ECL_USE_FP 269*f9fbec18Smcpowers case ECCurve_SECG_PRIME_160R1: 270*f9fbec18Smcpowers group = 271*f9fbec18Smcpowers ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, 272*f9fbec18Smcpowers &order, params->cofactor); 273*f9fbec18Smcpowers if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } 274*f9fbec18Smcpowers MP_CHECKOK(ec_group_set_secp160r1_fp(group)); 275*f9fbec18Smcpowers break; 276*f9fbec18Smcpowers #endif 277*f9fbec18Smcpowers case ECCurve_SECG_PRIME_192R1: 278*f9fbec18Smcpowers #ifdef ECL_USE_FP 279*f9fbec18Smcpowers group = 280*f9fbec18Smcpowers ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, 281*f9fbec18Smcpowers &order, params->cofactor); 282*f9fbec18Smcpowers if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } 283*f9fbec18Smcpowers MP_CHECKOK(ec_group_set_nistp192_fp(group)); 284*f9fbec18Smcpowers #else 285*f9fbec18Smcpowers group = 286*f9fbec18Smcpowers ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, 287*f9fbec18Smcpowers &order, params->cofactor); 288*f9fbec18Smcpowers if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } 289*f9fbec18Smcpowers MP_CHECKOK(ec_group_set_gfp192(group, name)); 290*f9fbec18Smcpowers #endif 291*f9fbec18Smcpowers break; 292*f9fbec18Smcpowers case ECCurve_SECG_PRIME_224R1: 293*f9fbec18Smcpowers #ifdef ECL_USE_FP 294*f9fbec18Smcpowers group = 295*f9fbec18Smcpowers ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, 296*f9fbec18Smcpowers &order, params->cofactor); 297*f9fbec18Smcpowers if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } 298*f9fbec18Smcpowers MP_CHECKOK(ec_group_set_nistp224_fp(group)); 299*f9fbec18Smcpowers #else 300*f9fbec18Smcpowers group = 301*f9fbec18Smcpowers ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, 302*f9fbec18Smcpowers &order, params->cofactor); 303*f9fbec18Smcpowers if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } 304*f9fbec18Smcpowers MP_CHECKOK(ec_group_set_gfp224(group, name)); 305*f9fbec18Smcpowers #endif 306*f9fbec18Smcpowers break; 307*f9fbec18Smcpowers case ECCurve_SECG_PRIME_256R1: 308*f9fbec18Smcpowers group = 309*f9fbec18Smcpowers ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, 310*f9fbec18Smcpowers &order, params->cofactor); 311*f9fbec18Smcpowers if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } 312*f9fbec18Smcpowers MP_CHECKOK(ec_group_set_gfp256(group, name)); 313*f9fbec18Smcpowers break; 314*f9fbec18Smcpowers case ECCurve_SECG_PRIME_521R1: 315*f9fbec18Smcpowers group = 316*f9fbec18Smcpowers ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, 317*f9fbec18Smcpowers &order, params->cofactor); 318*f9fbec18Smcpowers if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } 319*f9fbec18Smcpowers MP_CHECKOK(ec_group_set_gfp521(group, name)); 320*f9fbec18Smcpowers break; 321*f9fbec18Smcpowers default: 322*f9fbec18Smcpowers /* use generic arithmetic */ 323*f9fbec18Smcpowers #endif 324*f9fbec18Smcpowers group = 325*f9fbec18Smcpowers ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, 326*f9fbec18Smcpowers &order, params->cofactor); 327*f9fbec18Smcpowers if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } 328*f9fbec18Smcpowers #ifdef NSS_ECC_MORE_THAN_SUITE_B 329*f9fbec18Smcpowers } 330*f9fbec18Smcpowers } else if (params->field == ECField_GF2m) { 331*f9fbec18Smcpowers group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor); 332*f9fbec18Smcpowers if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } 333*f9fbec18Smcpowers if ((name == ECCurve_NIST_K163) || 334*f9fbec18Smcpowers (name == ECCurve_NIST_B163) || 335*f9fbec18Smcpowers (name == ECCurve_SECG_CHAR2_163R1)) { 336*f9fbec18Smcpowers MP_CHECKOK(ec_group_set_gf2m163(group, name)); 337*f9fbec18Smcpowers } else if ((name == ECCurve_SECG_CHAR2_193R1) || 338*f9fbec18Smcpowers (name == ECCurve_SECG_CHAR2_193R2)) { 339*f9fbec18Smcpowers MP_CHECKOK(ec_group_set_gf2m193(group, name)); 340*f9fbec18Smcpowers } else if ((name == ECCurve_NIST_K233) || 341*f9fbec18Smcpowers (name == ECCurve_NIST_B233)) { 342*f9fbec18Smcpowers MP_CHECKOK(ec_group_set_gf2m233(group, name)); 343*f9fbec18Smcpowers } 344*f9fbec18Smcpowers #endif 345*f9fbec18Smcpowers } else { 346*f9fbec18Smcpowers res = MP_UNDEF; 347*f9fbec18Smcpowers goto CLEANUP; 348*f9fbec18Smcpowers } 349*f9fbec18Smcpowers 350*f9fbec18Smcpowers /* set name, if any */ 351*f9fbec18Smcpowers if ((group != NULL) && (params->text != NULL)) { 352*f9fbec18Smcpowers #ifdef _KERNEL 353*f9fbec18Smcpowers int n = strlen(params->text) + 1; 354*f9fbec18Smcpowers 355*f9fbec18Smcpowers group->text = kmem_alloc(n, kmflag); 356*f9fbec18Smcpowers if (group->text == NULL) { 357*f9fbec18Smcpowers res = MP_MEM; 358*f9fbec18Smcpowers goto CLEANUP; 359*f9fbec18Smcpowers } 360*f9fbec18Smcpowers bcopy(params->text, group->text, n); 361*f9fbec18Smcpowers group->text_len = n; 362*f9fbec18Smcpowers #else 363*f9fbec18Smcpowers group->text = strdup(params->text); 364*f9fbec18Smcpowers if (group->text == NULL) { 365*f9fbec18Smcpowers res = MP_MEM; 366*f9fbec18Smcpowers } 367*f9fbec18Smcpowers #endif 368*f9fbec18Smcpowers } 369*f9fbec18Smcpowers 370*f9fbec18Smcpowers CLEANUP: 371*f9fbec18Smcpowers mp_clear(&irr); 372*f9fbec18Smcpowers mp_clear(&curvea); 373*f9fbec18Smcpowers mp_clear(&curveb); 374*f9fbec18Smcpowers mp_clear(&genx); 375*f9fbec18Smcpowers mp_clear(&geny); 376*f9fbec18Smcpowers mp_clear(&order); 377*f9fbec18Smcpowers if (res != MP_OKAY) { 378*f9fbec18Smcpowers ECGroup_free(group); 379*f9fbec18Smcpowers return NULL; 380*f9fbec18Smcpowers } 381*f9fbec18Smcpowers return group; 382*f9fbec18Smcpowers } 383*f9fbec18Smcpowers 384*f9fbec18Smcpowers /* Construct ECGroup from hexadecimal representations of parameters. */ 385*f9fbec18Smcpowers ECGroup * 386*f9fbec18Smcpowers ECGroup_fromHex(const ECCurveParams * params, int kmflag) 387*f9fbec18Smcpowers { 388*f9fbec18Smcpowers return ecgroup_fromNameAndHex(ECCurve_noName, params, kmflag); 389*f9fbec18Smcpowers } 390*f9fbec18Smcpowers 391*f9fbec18Smcpowers /* Construct ECGroup from named parameters. */ 392*f9fbec18Smcpowers ECGroup * 393*f9fbec18Smcpowers ECGroup_fromName(const ECCurveName name, int kmflag) 394*f9fbec18Smcpowers { 395*f9fbec18Smcpowers ECGroup *group = NULL; 396*f9fbec18Smcpowers ECCurveParams *params = NULL; 397*f9fbec18Smcpowers mp_err res = MP_OKAY; 398*f9fbec18Smcpowers 399*f9fbec18Smcpowers params = EC_GetNamedCurveParams(name, kmflag); 400*f9fbec18Smcpowers if (params == NULL) { 401*f9fbec18Smcpowers res = MP_UNDEF; 402*f9fbec18Smcpowers goto CLEANUP; 403*f9fbec18Smcpowers } 404*f9fbec18Smcpowers 405*f9fbec18Smcpowers /* construct actual group */ 406*f9fbec18Smcpowers group = ecgroup_fromNameAndHex(name, params, kmflag); 407*f9fbec18Smcpowers if (group == NULL) { 408*f9fbec18Smcpowers res = MP_UNDEF; 409*f9fbec18Smcpowers goto CLEANUP; 410*f9fbec18Smcpowers } 411*f9fbec18Smcpowers 412*f9fbec18Smcpowers CLEANUP: 413*f9fbec18Smcpowers EC_FreeCurveParams(params); 414*f9fbec18Smcpowers if (res != MP_OKAY) { 415*f9fbec18Smcpowers ECGroup_free(group); 416*f9fbec18Smcpowers return NULL; 417*f9fbec18Smcpowers } 418*f9fbec18Smcpowers return group; 419*f9fbec18Smcpowers } 420*f9fbec18Smcpowers 421*f9fbec18Smcpowers /* Validates an EC public key as described in Section 5.2.2 of X9.62. */ 422*f9fbec18Smcpowers mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const 423*f9fbec18Smcpowers mp_int *py) 424*f9fbec18Smcpowers { 425*f9fbec18Smcpowers /* 1: Verify that publicValue is not the point at infinity */ 426*f9fbec18Smcpowers /* 2: Verify that the coordinates of publicValue are elements 427*f9fbec18Smcpowers * of the field. 428*f9fbec18Smcpowers */ 429*f9fbec18Smcpowers /* 3: Verify that publicValue is on the curve. */ 430*f9fbec18Smcpowers /* 4: Verify that the order of the curve times the publicValue 431*f9fbec18Smcpowers * is the point at infinity. 432*f9fbec18Smcpowers */ 433*f9fbec18Smcpowers return group->validate_point(px, py, group); 434*f9fbec18Smcpowers } 435*f9fbec18Smcpowers 436*f9fbec18Smcpowers /* Free the memory allocated (if any) to an ECGroup object. */ 437*f9fbec18Smcpowers void 438*f9fbec18Smcpowers ECGroup_free(ECGroup *group) 439*f9fbec18Smcpowers { 440*f9fbec18Smcpowers if (group == NULL) 441*f9fbec18Smcpowers return; 442*f9fbec18Smcpowers GFMethod_free(group->meth); 443*f9fbec18Smcpowers if (group->constructed == MP_NO) 444*f9fbec18Smcpowers return; 445*f9fbec18Smcpowers mp_clear(&group->curvea); 446*f9fbec18Smcpowers mp_clear(&group->curveb); 447*f9fbec18Smcpowers mp_clear(&group->genx); 448*f9fbec18Smcpowers mp_clear(&group->geny); 449*f9fbec18Smcpowers mp_clear(&group->order); 450*f9fbec18Smcpowers if (group->text != NULL) 451*f9fbec18Smcpowers #ifdef _KERNEL 452*f9fbec18Smcpowers kmem_free(group->text, group->text_len); 453*f9fbec18Smcpowers #else 454*f9fbec18Smcpowers free(group->text); 455*f9fbec18Smcpowers #endif 456*f9fbec18Smcpowers if (group->extra_free != NULL) 457*f9fbec18Smcpowers group->extra_free(group); 458*f9fbec18Smcpowers #ifdef _KERNEL 459*f9fbec18Smcpowers kmem_free(group, sizeof (ECGroup)); 460*f9fbec18Smcpowers #else 461*f9fbec18Smcpowers free(group); 462*f9fbec18Smcpowers #endif 463*f9fbec18Smcpowers } 464