Unleashed v1.4
[unleashed.git] / usr / src / common / crypto / ecc / ecdecode.c
blobfd42ffa98e621257ef81b0b98c44b30df0c8e8e0
1 /*
2 * ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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.
15 * The Original Code is the Elliptic Curve Cryptography library.
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.
22 * Contributor(s):
23 * Dr Vipul Gupta <vipul.gupta@sun.com> and
24 * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
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.
38 * ***** END LICENSE BLOCK ***** */
40 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
41 * Use is subject to license terms.
43 * Sun elects to use this software under the MPL license.
46 #pragma ident "%Z%%M% %I% %E% SMI"
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"
60 #define MAX_ECKEY_LEN 72
61 #define SEC_ASN1_OBJECT_ID 0x06
64 * Initializes a SECItem from a hexadecimal string
66 * Warning: This function ignores leading 00's, so any leading 00's
67 * in the hexadecimal string must be optional.
69 static SECItem *
70 hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str,
71 int kmflag)
73 int i = 0;
74 int byteval = 0;
75 int tmp = strlen(str);
77 if ((tmp % 2) != 0) return NULL;
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;
85 item->data = (unsigned char *) PORT_ArenaAlloc(arena, tmp/2, kmflag);
86 if (item->data == NULL) return NULL;
87 item->len = tmp/2;
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;
99 byteval = byteval * 16 + tmp;
100 if ((i % 2) != 0) {
101 item->data[i/2] = byteval;
102 byteval = 0;
104 i++;
107 return item;
110 static SECStatus
111 gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params,
112 int kmflag)
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];
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));
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;
146 rv = SECSuccess;
148 cleanup:
149 return rv;
152 ECCurveName SECOID_FindOIDTag(const SECItem *);
154 SECStatus
155 EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
156 ECParams *params, int kmflag)
158 SECStatus rv = SECFailure;
159 ECCurveName tag;
160 SECItem oid = { siBuffer, NULL, 0};
162 #if EC_DEBUG
163 int i;
165 printf("Encoded params in EC_DecodeParams: ");
166 for (i = 0; i < encodedParams->len; i++) {
167 printf("%02x:", encodedParams->data[i]);
169 printf("\n");
170 #endif
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;
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;
186 params->arena = arena;
187 params->cofactor = 0;
188 params->type = ec_params_named;
189 params->name = ECCurve_noName;
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);
198 #if EC_DEBUG
199 printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag));
200 #endif
202 switch (tag) {
204 /* Binary curves */
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
326 case ECCurve_SECG_CHAR2_163K1:
327 /* Populate params for sect163k1
328 * (the NIST K-163 curve)
330 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163K1, ec_field_GF2m,
331 params, kmflag) );
332 break;
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;
340 case ECCurve_SECG_CHAR2_163R2:
341 /* Populate params for sect163r2
342 * (the NIST B-163 curve)
344 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R2, ec_field_GF2m,
345 params, kmflag) );
346 break;
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;
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;
360 case ECCurve_SECG_CHAR2_233K1:
361 /* Populate params for sect233k1
362 * (the NIST K-233 curve)
364 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233K1, ec_field_GF2m,
365 params, kmflag) );
366 break;
368 case ECCurve_SECG_CHAR2_233R1:
369 /* Populate params for sect233r1
370 * (the NIST B-233 curve)
372 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233R1, ec_field_GF2m,
373 params, kmflag) );
374 break;
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;
382 case ECCurve_SECG_CHAR2_283K1:
383 /* Populate params for sect283k1
384 * (the NIST K-283 curve)
386 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283K1, ec_field_GF2m,
387 params, kmflag) );
388 break;
390 case ECCurve_SECG_CHAR2_283R1:
391 /* Populate params for sect283r1
392 * (the NIST B-283 curve)
394 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283R1, ec_field_GF2m,
395 params, kmflag) );
396 break;
398 case ECCurve_SECG_CHAR2_409K1:
399 /* Populate params for sect409k1
400 * (the NIST K-409 curve)
402 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409K1, ec_field_GF2m,
403 params, kmflag) );
404 break;
406 case ECCurve_SECG_CHAR2_409R1:
407 /* Populate params for sect409r1
408 * (the NIST B-409 curve)
410 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409R1, ec_field_GF2m,
411 params, kmflag) );
412 break;
414 case ECCurve_SECG_CHAR2_571K1:
415 /* Populate params for sect571k1
416 * (the NIST K-571 curve)
418 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571K1, ec_field_GF2m,
419 params, kmflag) );
420 break;
422 case ECCurve_SECG_CHAR2_571R1:
423 /* Populate params for sect571r1
424 * (the NIST B-571 curve)
426 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571R1, ec_field_GF2m,
427 params, kmflag) );
428 break;
430 /* Prime curves */
432 case ECCurve_X9_62_PRIME_192V1:
433 /* Populate params for prime192v1 aka secp192r1
434 * (the NIST P-192 curve)
436 CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V1, ec_field_GFp,
437 params, kmflag) );
438 break;
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;
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;
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;
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;
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;
470 case ECCurve_X9_62_PRIME_256V1:
471 /* Populate params for prime256v1 aka secp256r1
472 * (the NIST P-256 curve)
474 CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp,
475 params, kmflag) );
476 break;
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;
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;
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;
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;
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;
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;
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;
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;
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;
532 case ECCurve_SECG_PRIME_224R1:
533 /* Populate params for secp224r1
534 * (the NIST P-224 curve)
536 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224R1, ec_field_GFp,
537 params, kmflag) );
538 break;
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;
546 case ECCurve_SECG_PRIME_384R1:
547 /* Populate params for secp384r1
548 * (the NIST P-384 curve)
550 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp,
551 params, kmflag) );
552 break;
554 case ECCurve_SECG_PRIME_521R1:
555 /* Populate params for secp521r1
556 * (the NIST P-521 curve)
558 CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp,
559 params, kmflag) );
560 break;
562 default:
563 break;
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
574 return rv;
577 SECStatus
578 EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams, int kmflag)
580 PRArenaPool *arena;
581 ECParams *params;
582 SECStatus rv = SECFailure;
584 /* Initialize an arena for the ECParams structure */
585 if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
586 return SECFailure;
588 params = (ECParams *)PORT_ArenaZAlloc(NULL, sizeof(ECParams), kmflag);
589 if (!params) {
590 PORT_FreeArena(NULL, B_TRUE);
591 return SECFailure;
594 /* Copy the encoded params */
595 SECITEM_AllocItem(arena, &(params->DEREncoding), encodedParams->len,
596 kmflag);
597 memcpy(params->DEREncoding.data, encodedParams->data, encodedParams->len);
599 /* Fill out the rest of the ECParams structure based on
600 * the encoded params
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;