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
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.
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>
57 #include "ecl-curve.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.
70 hexString2SECItem(PRArenaPool
*arena
, SECItem
*item
, const char *str
,
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')) {
85 item
->data
= (unsigned char *) PORT_ArenaAlloc(arena
, tmp
/2, kmflag
);
86 if (item
->data
== NULL
) return NULL
;
90 if ((str
[i
] >= '0') && (str
[i
] <= '9'))
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;
99 byteval
= byteval
* 16 + tmp
;
101 item
->data
[i
/2] = byteval
;
111 gf_populate_params(ECCurveName name
, ECFieldType field_type
, ECParams
*params
,
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
;
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
, ¶ms
->fieldID
.u
.prime
,
127 curveParams
->irr
, kmflag
));
129 CHECK_OK(hexString2SECItem(NULL
, ¶ms
->fieldID
.u
.poly
,
130 curveParams
->irr
, kmflag
));
132 CHECK_OK(hexString2SECItem(NULL
, ¶ms
->curve
.a
,
133 curveParams
->curvea
, kmflag
));
134 CHECK_OK(hexString2SECItem(NULL
, ¶ms
->curve
.b
,
135 curveParams
->curveb
, kmflag
));
139 strcat(genenc
, curveParams
->genx
);
140 strcat(genenc
, curveParams
->geny
);
141 CHECK_OK(hexString2SECItem(NULL
, ¶ms
->base
, genenc
, kmflag
));
142 CHECK_OK(hexString2SECItem(NULL
, ¶ms
->order
,
143 curveParams
->order
, kmflag
));
144 params
->cofactor
= curveParams
->cofactor
;
152 ECCurveName
SECOID_FindOIDTag(const SECItem
*);
155 EC_FillParams(PRArenaPool
*arena
, const SECItem
*encodedParams
,
156 ECParams
*params
, int kmflag
)
158 SECStatus rv
= SECFailure
;
160 SECItem oid
= { siBuffer
, NULL
, 0};
165 printf("Encoded params in EC_DecodeParams: ");
166 for (i
= 0; i
< encodedParams
->len
; i
++) {
167 printf("%02x:", encodedParams
->data
[i
]);
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
);
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
);
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
,
195 if (params
->curveOID
.data
== NULL
) goto cleanup
;
196 memcpy(params
->curveOID
.data
, oid
.data
, oid
.len
);
199 printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag
));
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
567 if (!params
->cofactor
) {
568 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE
);
570 printf("Unrecognized curve, returning NULL params\n");
578 EC_DecodeParams(const SECItem
*encodedParams
, ECParams
**ecparams
, int kmflag
)
582 SECStatus rv
= SECFailure
;
584 /* Initialize an arena for the ECParams structure */
585 if (!(arena
= PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE
)))
588 params
= (ECParams
*)PORT_ArenaZAlloc(NULL
, sizeof(ECParams
), kmflag
);
590 PORT_FreeArena(NULL
, B_TRUE
);
594 /* Copy the encoded params */
595 SECITEM_AllocItem(arena
, &(params
->DEREncoding
), encodedParams
->len
,
597 memcpy(params
->DEREncoding
.data
, encodedParams
->data
, encodedParams
->len
);
599 /* Fill out the rest of the ECParams structure based on
602 rv
= EC_FillParams(NULL
, encodedParams
, params
, kmflag
);
603 if (rv
== SECFailure
) {
604 PORT_FreeArena(NULL
, B_TRUE
);