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