xref: /illumos-gate/usr/src/common/crypto/ecc/ecdecode.c (revision 4f364e7c95ee7fd9d5bbeddc1940e92405bb0e72)
1 /*
2  * ***** BEGIN LICENSE BLOCK *****
3  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  * http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  *
15  * The Original Code is the Elliptic Curve Cryptography library.
16  *
17  * The Initial Developer of the Original Code is
18  * Sun Microsystems, Inc.
19  * Portions created by the Initial Developer are Copyright (C) 2003
20  * the Initial Developer. All Rights Reserved.
21  *
22  * Contributor(s):
23  *   Dr Vipul Gupta <vipul.gupta@sun.com> and
24  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
25  *
26  * Alternatively, the contents of this file may be used under the terms of
27  * either the GNU General Public License Version 2 or later (the "GPL"), or
28  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29  * in which case the provisions of the GPL or the LGPL are applicable instead
30  * of those above. If you wish to allow use of your version of this file only
31  * under the terms of either the GPL or the LGPL, and not to allow others to
32  * use your version of this file under the terms of the MPL, indicate your
33  * decision by deleting the provisions above and replace them with the notice
34  * and other provisions required by the GPL or the LGPL. If you do not delete
35  * the provisions above, a recipient may use your version of this file under
36  * the terms of any one of the MPL, the GPL or the LGPL.
37  *
38  * ***** END LICENSE BLOCK ***** */
39 /*
40  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
41  * Use is subject to license terms.
42  *
43  * Sun elects to use this software under the MPL license.
44  */
45 
46 #pragma ident	"%Z%%M%	%I%	%E% SMI"
47 
48 #include <sys/types.h>
49 #include <sys/systm.h>
50 #include <sys/param.h>
51 #ifdef _KERNEL
52 #include <sys/kmem.h>
53 #else
54 #include <string.h>
55 #endif
56 #include "ec.h"
57 #include "ecl-curve.h"
58 #include "ecc_impl.h"
59 
60 #define MAX_ECKEY_LEN		72
61 #define SEC_ASN1_OBJECT_ID	0x06
62 
63 /*
64  * Initializes a SECItem from a hexadecimal string
65  *
66  * Warning: This function ignores leading 00's, so any leading 00's
67  * in the hexadecimal string must be optional.
68  */
69 static SECItem *
70 hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str,
71     int kmflag)
72 {
73     int i = 0;
74     int byteval = 0;
75     int tmp = strlen(str);
76 
77     if ((tmp % 2) != 0) return NULL;
78 
79     /* skip leading 00's unless the hex string is "00" */
80     while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
81         str += 2;
82         tmp -= 2;
83     }
84 
85     item->data = (unsigned char *) PORT_ArenaAlloc(arena, tmp/2, kmflag);
86     if (item->data == NULL) return NULL;
87     item->len = tmp/2;
88 
89     while (str[i]) {
90         if ((str[i] >= '0') && (str[i] <= '9'))
91 	    tmp = str[i] - '0';
92 	else if ((str[i] >= 'a') && (str[i] <= 'f'))
93 	    tmp = str[i] - 'a' + 10;
94 	else if ((str[i] >= 'A') && (str[i] <= 'F'))
95 	    tmp = str[i] - 'A' + 10;
96 	else
97 	    return NULL;
98 
99 	byteval = byteval * 16 + tmp;
100 	if ((i % 2) != 0) {
101 	    item->data[i/2] = byteval;
102 	    byteval = 0;
103 	}
104 	i++;
105     }
106 
107     return item;
108 }
109 
110 static SECStatus
111 gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params,
112     int kmflag)
113 {
114     SECStatus rv = SECFailure;
115     const ECCurveParams *curveParams;
116     /* 2 ['0'+'4'] + MAX_ECKEY_LEN * 2 [x,y] * 2 [hex string] + 1 ['\0'] */
117     char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
118 
119     if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve)) goto cleanup;
120     params->name = name;
121     curveParams = ecCurve_map[params->name];
122     CHECK_OK(curveParams);
123     params->fieldID.size = curveParams->size;
124     params->fieldID.type = field_type;
125     if (field_type == ec_field_GFp) {
126 	CHECK_OK(hexString2SECItem(NULL, &params->fieldID.u.prime,
127 	    curveParams->irr, kmflag));
128     } else {
129 	CHECK_OK(hexString2SECItem(NULL, &params->fieldID.u.poly,
130 	    curveParams->irr, kmflag));
131     }
132     CHECK_OK(hexString2SECItem(NULL, &params->curve.a,
133 	curveParams->curvea, kmflag));
134     CHECK_OK(hexString2SECItem(NULL, &params->curve.b,
135 	curveParams->curveb, kmflag));
136     genenc[0] = '0';
137     genenc[1] = '4';
138     genenc[2] = '\0';
139     strcat(genenc, curveParams->genx);
140     strcat(genenc, curveParams->geny);
141     CHECK_OK(hexString2SECItem(NULL, &params->base, genenc, kmflag));
142     CHECK_OK(hexString2SECItem(NULL, &params->order,
143     	curveParams->order, kmflag));
144     params->cofactor = curveParams->cofactor;
145 
146     rv = SECSuccess;
147 
148 cleanup:
149     return rv;
150 }
151 
152 ECCurveName SECOID_FindOIDTag(const SECItem *);
153 
154 SECStatus
155 EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
156     ECParams *params, int kmflag)
157 {
158     SECStatus rv = SECFailure;
159     ECCurveName tag;
160     SECItem oid = { siBuffer, NULL, 0};
161 
162 #if EC_DEBUG
163     int i;
164 
165     printf("Encoded params in EC_DecodeParams: ");
166     for (i = 0; i < encodedParams->len; i++) {
167 	    printf("%02x:", encodedParams->data[i]);
168     }
169     printf("\n");
170 #endif
171 
172     if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) &&
173 	(encodedParams->len != SECG_CURVE_OID_TOTAL_LEN)) {
174 	    PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
175 	    return SECFailure;
176     };
177 
178     oid.len = encodedParams->len - 2;
179     oid.data = encodedParams->data + 2;
180     if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
181 	((tag = SECOID_FindOIDTag(&oid)) == ECCurve_noName)) {
182 	    PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
183 	    return SECFailure;
184     }
185 
186     params->arena = arena;
187     params->cofactor = 0;
188     params->type = ec_params_named;
189     params->name = ECCurve_noName;
190 
191     /* For named curves, fill out curveOID */
192     params->curveOID.len = oid.len;
193     params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(NULL, oid.len,
194 	kmflag);
195     if (params->curveOID.data == NULL) goto cleanup;
196     memcpy(params->curveOID.data, oid.data, oid.len);
197 
198 #if EC_DEBUG
199     printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag));
200 #endif
201 
202     switch (tag) {
203 
204     /* Binary curves */
205 
206     case ECCurve_X9_62_CHAR2_PNB163V1:
207 	/* Populate params for c2pnb163v1 */
208 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V1, ec_field_GF2m,
209 	    params, kmflag) );
210 	break;
211 
212     case ECCurve_X9_62_CHAR2_PNB163V2:
213 	/* Populate params for c2pnb163v2 */
214 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V2, ec_field_GF2m,
215 	    params, kmflag) );
216 	break;
217 
218     case ECCurve_X9_62_CHAR2_PNB163V3:
219 	/* Populate params for c2pnb163v3 */
220 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V3, ec_field_GF2m,
221 	    params, kmflag) );
222 	break;
223 
224     case ECCurve_X9_62_CHAR2_PNB176V1:
225 	/* Populate params for c2pnb176v1 */
226 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB176V1, ec_field_GF2m,
227 	    params, kmflag) );
228 	break;
229 
230     case ECCurve_X9_62_CHAR2_TNB191V1:
231 	/* Populate params for c2tnb191v1 */
232 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V1, ec_field_GF2m,
233 	    params, kmflag) );
234 	break;
235 
236     case ECCurve_X9_62_CHAR2_TNB191V2:
237 	/* Populate params for c2tnb191v2 */
238 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V2, ec_field_GF2m,
239 	    params, kmflag) );
240 	break;
241 
242     case ECCurve_X9_62_CHAR2_TNB191V3:
243 	/* Populate params for c2tnb191v3 */
244 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V3, ec_field_GF2m,
245 	    params, kmflag) );
246 	break;
247 
248     case ECCurve_X9_62_CHAR2_PNB208W1:
249 	/* Populate params for c2pnb208w1 */
250 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB208W1, ec_field_GF2m,
251 	    params, kmflag) );
252 	break;
253 
254     case ECCurve_X9_62_CHAR2_TNB239V1:
255 	/* Populate params for c2tnb239v1 */
256 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V1, ec_field_GF2m,
257 	    params, kmflag) );
258 	break;
259 
260     case ECCurve_X9_62_CHAR2_TNB239V2:
261 	/* Populate params for c2tnb239v2 */
262 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V2, ec_field_GF2m,
263 	    params, kmflag) );
264 	break;
265 
266     case ECCurve_X9_62_CHAR2_TNB239V3:
267 	/* Populate params for c2tnb239v3 */
268 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V3, ec_field_GF2m,
269 	    params, kmflag) );
270 	break;
271 
272     case ECCurve_X9_62_CHAR2_PNB272W1:
273 	/* Populate params for c2pnb272w1 */
274 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB272W1, ec_field_GF2m,
275 	    params, kmflag) );
276 	break;
277 
278     case ECCurve_X9_62_CHAR2_PNB304W1:
279 	/* Populate params for c2pnb304w1 */
280 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB304W1, ec_field_GF2m,
281 	    params, kmflag) );
282 	break;
283 
284     case ECCurve_X9_62_CHAR2_TNB359V1:
285 	/* Populate params for c2tnb359v1 */
286 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB359V1, ec_field_GF2m,
287 	    params, kmflag) );
288 	break;
289 
290     case ECCurve_X9_62_CHAR2_PNB368W1:
291 	/* Populate params for c2pnb368w1 */
292 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB368W1, ec_field_GF2m,
293 	    params, kmflag) );
294 	break;
295 
296     case ECCurve_X9_62_CHAR2_TNB431R1:
297 	/* Populate params for c2tnb431r1 */
298 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB431R1, ec_field_GF2m,
299 	    params, kmflag) );
300 	break;
301 
302     case ECCurve_SECG_CHAR2_113R1:
303 	/* Populate params for sect113r1 */
304 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R1, ec_field_GF2m,
305 	    params, kmflag) );
306 	break;
307 
308     case ECCurve_SECG_CHAR2_113R2:
309 	/* Populate params for sect113r2 */
310 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R2, ec_field_GF2m,
311 	    params, kmflag) );
312 	break;
313 
314     case ECCurve_SECG_CHAR2_131R1:
315 	/* Populate params for sect131r1 */
316 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R1, ec_field_GF2m,
317 	    params, kmflag) );
318 	break;
319 
320     case ECCurve_SECG_CHAR2_131R2:
321 	/* Populate params for sect131r2 */
322 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R2, ec_field_GF2m,
323 	    params, kmflag) );
324 	break;
325 
326     case ECCurve_SECG_CHAR2_163K1:
327 	/* Populate params for sect163k1
328 	 * (the NIST K-163 curve)
329 	 */
330 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163K1, ec_field_GF2m,
331 	    params, kmflag) );
332 	break;
333 
334     case ECCurve_SECG_CHAR2_163R1:
335 	/* Populate params for sect163r1 */
336 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R1, ec_field_GF2m,
337 	    params, kmflag) );
338 	break;
339 
340     case ECCurve_SECG_CHAR2_163R2:
341 	/* Populate params for sect163r2
342 	 * (the NIST B-163 curve)
343 	 */
344 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R2, ec_field_GF2m,
345 	    params, kmflag) );
346 	break;
347 
348     case ECCurve_SECG_CHAR2_193R1:
349 	/* Populate params for sect193r1 */
350 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R1, ec_field_GF2m,
351 	    params, kmflag) );
352 	break;
353 
354     case ECCurve_SECG_CHAR2_193R2:
355 	/* Populate params for sect193r2 */
356 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R2, ec_field_GF2m,
357 	    params, kmflag) );
358 	break;
359 
360     case ECCurve_SECG_CHAR2_233K1:
361 	/* Populate params for sect233k1
362 	 * (the NIST K-233 curve)
363 	 */
364 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233K1, ec_field_GF2m,
365 	    params, kmflag) );
366 	break;
367 
368     case ECCurve_SECG_CHAR2_233R1:
369 	/* Populate params for sect233r1
370 	 * (the NIST B-233 curve)
371 	 */
372 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233R1, ec_field_GF2m,
373 	    params, kmflag) );
374 	break;
375 
376     case ECCurve_SECG_CHAR2_239K1:
377 	/* Populate params for sect239k1 */
378 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_239K1, ec_field_GF2m,
379 	    params, kmflag) );
380 	break;
381 
382     case ECCurve_SECG_CHAR2_283K1:
383         /* Populate params for sect283k1
384 	 * (the NIST K-283 curve)
385 	 */
386 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283K1, ec_field_GF2m,
387 	    params, kmflag) );
388 	break;
389 
390     case ECCurve_SECG_CHAR2_283R1:
391 	/* Populate params for sect283r1
392 	 * (the NIST B-283 curve)
393 	 */
394 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283R1, ec_field_GF2m,
395 	    params, kmflag) );
396 	break;
397 
398     case ECCurve_SECG_CHAR2_409K1:
399 	/* Populate params for sect409k1
400 	 * (the NIST K-409 curve)
401 	 */
402 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409K1, ec_field_GF2m,
403 	    params, kmflag) );
404 	break;
405 
406     case ECCurve_SECG_CHAR2_409R1:
407 	/* Populate params for sect409r1
408 	 * (the NIST B-409 curve)
409 	 */
410 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409R1, ec_field_GF2m,
411 	    params, kmflag) );
412 	break;
413 
414     case ECCurve_SECG_CHAR2_571K1:
415 	/* Populate params for sect571k1
416 	 * (the NIST K-571 curve)
417 	 */
418 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571K1, ec_field_GF2m,
419 	    params, kmflag) );
420 	break;
421 
422     case ECCurve_SECG_CHAR2_571R1:
423 	/* Populate params for sect571r1
424 	 * (the NIST B-571 curve)
425 	 */
426 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571R1, ec_field_GF2m,
427 	    params, kmflag) );
428 	break;
429 
430     /* Prime curves */
431 
432     case ECCurve_X9_62_PRIME_192V1:
433 	/* Populate params for prime192v1 aka secp192r1
434 	 * (the NIST P-192 curve)
435 	 */
436 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V1, ec_field_GFp,
437 	    params, kmflag) );
438 	break;
439 
440     case ECCurve_X9_62_PRIME_192V2:
441 	/* Populate params for prime192v2 */
442 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V2, ec_field_GFp,
443 	    params, kmflag) );
444 	break;
445 
446     case ECCurve_X9_62_PRIME_192V3:
447 	/* Populate params for prime192v3 */
448 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V3, ec_field_GFp,
449 	    params, kmflag) );
450 	break;
451 
452     case ECCurve_X9_62_PRIME_239V1:
453 	/* Populate params for prime239v1 */
454 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V1, ec_field_GFp,
455 	    params, kmflag) );
456 	break;
457 
458     case ECCurve_X9_62_PRIME_239V2:
459 	/* Populate params for prime239v2 */
460 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V2, ec_field_GFp,
461 	    params, kmflag) );
462 	break;
463 
464     case ECCurve_X9_62_PRIME_239V3:
465 	/* Populate params for prime239v3 */
466 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V3, ec_field_GFp,
467 	    params, kmflag) );
468 	break;
469 
470     case ECCurve_X9_62_PRIME_256V1:
471 	/* Populate params for prime256v1 aka secp256r1
472 	 * (the NIST P-256 curve)
473 	 */
474 	CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp,
475 	    params, kmflag) );
476 	break;
477 
478     case ECCurve_SECG_PRIME_112R1:
479         /* Populate params for secp112r1 */
480 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R1, ec_field_GFp,
481 	    params, kmflag) );
482 	break;
483 
484     case ECCurve_SECG_PRIME_112R2:
485         /* Populate params for secp112r2 */
486 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R2, ec_field_GFp,
487 	    params, kmflag) );
488 	break;
489 
490     case ECCurve_SECG_PRIME_128R1:
491         /* Populate params for secp128r1 */
492 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R1, ec_field_GFp,
493 	    params, kmflag) );
494 	break;
495 
496     case ECCurve_SECG_PRIME_128R2:
497         /* Populate params for secp128r2 */
498 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R2, ec_field_GFp,
499 	    params, kmflag) );
500 	break;
501 
502     case ECCurve_SECG_PRIME_160K1:
503         /* Populate params for secp160k1 */
504 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160K1, ec_field_GFp,
505 	    params, kmflag) );
506 	break;
507 
508     case ECCurve_SECG_PRIME_160R1:
509         /* Populate params for secp160r1 */
510 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R1, ec_field_GFp,
511 	    params, kmflag) );
512 	break;
513 
514     case ECCurve_SECG_PRIME_160R2:
515 	/* Populate params for secp160r1 */
516 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R2, ec_field_GFp,
517 	    params, kmflag) );
518 	break;
519 
520     case ECCurve_SECG_PRIME_192K1:
521 	/* Populate params for secp192k1 */
522 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_192K1, ec_field_GFp,
523 	    params, kmflag) );
524 	break;
525 
526     case ECCurve_SECG_PRIME_224K1:
527 	/* Populate params for secp224k1 */
528 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224K1, ec_field_GFp,
529 	    params, kmflag) );
530 	break;
531 
532     case ECCurve_SECG_PRIME_224R1:
533 	/* Populate params for secp224r1
534 	 * (the NIST P-224 curve)
535 	 */
536 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224R1, ec_field_GFp,
537 	    params, kmflag) );
538 	break;
539 
540     case ECCurve_SECG_PRIME_256K1:
541 	/* Populate params for secp256k1 */
542 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_256K1, ec_field_GFp,
543 	    params, kmflag) );
544 	break;
545 
546     case ECCurve_SECG_PRIME_384R1:
547 	/* Populate params for secp384r1
548 	 * (the NIST P-384 curve)
549 	 */
550 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp,
551 	    params, kmflag) );
552 	break;
553 
554     case ECCurve_SECG_PRIME_521R1:
555 	/* Populate params for secp521r1
556 	 * (the NIST P-521 curve)
557 	 */
558 	CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp,
559 	    params, kmflag) );
560 	break;
561 
562     default:
563 	break;
564     };
565 
566 cleanup:
567     if (!params->cofactor) {
568 	PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
569 #if EC_DEBUG
570 	printf("Unrecognized curve, returning NULL params\n");
571 #endif
572     }
573 
574     return rv;
575 }
576 
577 SECStatus
578 EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams, int kmflag)
579 {
580     PRArenaPool *arena;
581     ECParams *params;
582     SECStatus rv = SECFailure;
583 
584     /* Initialize an arena for the ECParams structure */
585     if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
586 	return SECFailure;
587 
588     params = (ECParams *)PORT_ArenaZAlloc(NULL, sizeof(ECParams), kmflag);
589     if (!params) {
590 	PORT_FreeArena(NULL, B_TRUE);
591 	return SECFailure;
592     }
593 
594     /* Copy the encoded params */
595     SECITEM_AllocItem(arena, &(params->DEREncoding), encodedParams->len,
596 	kmflag);
597     memcpy(params->DEREncoding.data, encodedParams->data, encodedParams->len);
598 
599     /* Fill out the rest of the ECParams structure based on
600      * the encoded params
601      */
602     rv = EC_FillParams(NULL, encodedParams, params, kmflag);
603     if (rv == SECFailure) {
604 	PORT_FreeArena(NULL, B_TRUE);
605 	return SECFailure;
606     } else {
607 	*ecparams = params;;
608 	return SECSuccess;
609     }
610 }
611