xref: /onnv-gate/usr/src/common/crypto/ecc/ecl.c (revision 5697:324be5104707)
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