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