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 2009 Sun Microsystems, Inc. All rights reserved.
41 * Use is subject to license terms.
43 * Sun elects to use this software under the MPL license.
51 #include <sys/types.h>
62 #define PORT_ZFree(p, l) bzero((p), (l)); kmem_free((p), (l))
64 #define PORT_ZFree(p, l) bzero((p), (l)); free((p))
68 * Returns true if pointP is the point at infinity, false otherwise
71 ec_point_at_infinity(SECItem
*pointP
)
75 for (i
= 1; i
< pointP
->len
; i
++) {
76 if (pointP
->data
[i
] != 0x00) return PR_FALSE
;
83 * Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for
84 * the curve whose parameters are encoded in params with base point G.
87 ec_points_mul(const ECParams
*params
, const mp_int
*k1
, const mp_int
*k2
,
88 const SECItem
*pointP
, SECItem
*pointQ
, int kmflag
)
90 mp_int Px
, Py
, Qx
, Qy
;
91 mp_int Gx
, Gy
, order
, irreducible
, a
, b
;
92 #if 0 /* currently don't support non-named curves */
93 unsigned int irr_arr
[5];
95 ECGroup
*group
= NULL
;
96 SECStatus rv
= SECFailure
;
104 printf("ec_points_mul: params [len=%d]:", params
->DEREncoding
.len
);
105 for (i
= 0; i
< params
->DEREncoding
.len
; i
++)
106 printf("%02x:", params
->DEREncoding
.data
[i
]);
111 printf("ec_points_mul: scalar k1: %s\n", mpstr
);
112 mp_todecimal(k1
, mpstr
);
113 printf("ec_points_mul: scalar k1: %s (dec)\n", mpstr
);
118 printf("ec_points_mul: scalar k2: %s\n", mpstr
);
119 mp_todecimal(k2
, mpstr
);
120 printf("ec_points_mul: scalar k2: %s (dec)\n", mpstr
);
123 if (pointP
!= NULL
) {
124 printf("ec_points_mul: pointP [len=%d]:", pointP
->len
);
125 for (i
= 0; i
< pointP
->len
; i
++)
126 printf("%02x:", pointP
->data
[i
]);
131 /* NOTE: We only support uncompressed points for now */
132 len
= (params
->fieldID
.size
+ 7) >> 3;
133 if (pointP
!= NULL
) {
134 if ((pointP
->data
[0] != EC_POINT_FORM_UNCOMPRESSED
) ||
135 (pointP
->len
!= (2 * len
+ 1))) {
146 MP_DIGITS(&order
) = 0;
147 MP_DIGITS(&irreducible
) = 0;
150 CHECK_MPI_OK( mp_init(&Px
, kmflag
) );
151 CHECK_MPI_OK( mp_init(&Py
, kmflag
) );
152 CHECK_MPI_OK( mp_init(&Qx
, kmflag
) );
153 CHECK_MPI_OK( mp_init(&Qy
, kmflag
) );
154 CHECK_MPI_OK( mp_init(&Gx
, kmflag
) );
155 CHECK_MPI_OK( mp_init(&Gy
, kmflag
) );
156 CHECK_MPI_OK( mp_init(&order
, kmflag
) );
157 CHECK_MPI_OK( mp_init(&irreducible
, kmflag
) );
158 CHECK_MPI_OK( mp_init(&a
, kmflag
) );
159 CHECK_MPI_OK( mp_init(&b
, kmflag
) );
161 if ((k2
!= NULL
) && (pointP
!= NULL
)) {
162 /* Initialize Px and Py */
163 CHECK_MPI_OK( mp_read_unsigned_octets(&Px
, pointP
->data
+ 1, (mp_size
) len
) );
164 CHECK_MPI_OK( mp_read_unsigned_octets(&Py
, pointP
->data
+ 1 + len
, (mp_size
) len
) );
167 /* construct from named params, if possible */
168 if (params
->name
!= ECCurve_noName
) {
169 group
= ECGroup_fromName(params
->name
, kmflag
);
172 #if 0 /* currently don't support non-named curves */
174 /* Set up mp_ints containing the curve coefficients */
175 CHECK_MPI_OK( mp_read_unsigned_octets(&Gx
, params
->base
.data
+ 1,
177 CHECK_MPI_OK( mp_read_unsigned_octets(&Gy
, params
->base
.data
+ 1 + len
,
179 SECITEM_TO_MPINT( params
->order
, &order
);
180 SECITEM_TO_MPINT( params
->curve
.a
, &a
);
181 SECITEM_TO_MPINT( params
->curve
.b
, &b
);
182 if (params
->fieldID
.type
== ec_field_GFp
) {
183 SECITEM_TO_MPINT( params
->fieldID
.u
.prime
, &irreducible
);
184 group
= ECGroup_consGFp(&irreducible
, &a
, &b
, &Gx
, &Gy
, &order
, params
->cofactor
);
186 SECITEM_TO_MPINT( params
->fieldID
.u
.poly
, &irreducible
);
187 irr_arr
[0] = params
->fieldID
.size
;
188 irr_arr
[1] = params
->fieldID
.k1
;
189 irr_arr
[2] = params
->fieldID
.k2
;
190 irr_arr
[3] = params
->fieldID
.k3
;
192 group
= ECGroup_consGF2m(&irreducible
, irr_arr
, &a
, &b
, &Gx
, &Gy
, &order
, params
->cofactor
);
199 if ((k2
!= NULL
) && (pointP
!= NULL
)) {
200 CHECK_MPI_OK( ECPoints_mul(group
, k1
, k2
, &Px
, &Py
, &Qx
, &Qy
) );
202 CHECK_MPI_OK( ECPoints_mul(group
, k1
, NULL
, NULL
, NULL
, &Qx
, &Qy
) );
205 /* Construct the SECItem representation of point Q */
206 pointQ
->data
[0] = EC_POINT_FORM_UNCOMPRESSED
;
207 CHECK_MPI_OK( mp_to_fixlen_octets(&Qx
, pointQ
->data
+ 1,
209 CHECK_MPI_OK( mp_to_fixlen_octets(&Qy
, pointQ
->data
+ 1 + len
,
215 printf("ec_points_mul: pointQ [len=%d]:", pointQ
->len
);
216 for (i
= 0; i
< pointQ
->len
; i
++)
217 printf("%02x:", pointQ
->data
[i
]);
230 mp_clear(&irreducible
);
234 MP_TO_SEC_ERROR(err
);
241 /* Generates a new EC key pair. The private key is a supplied
242 * value and the public key is the result of performing a scalar
243 * point multiplication of that value with the curve's base point.
246 ec_NewKey(ECParams
*ecParams
, ECPrivateKey
**privKey
,
247 const unsigned char *privKeyBytes
, int privKeyLen
, int kmflag
)
249 SECStatus rv
= SECFailure
;
253 mp_err err
= MP_OKAY
;
257 printf("ec_NewKey called\n");
261 if (!ecParams
|| !privKey
|| !privKeyBytes
|| (privKeyLen
< 0)) {
262 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
266 /* Initialize an arena for the EC key. */
267 if (!(arena
= PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE
)))
270 key
= (ECPrivateKey
*)PORT_ArenaZAlloc(arena
, sizeof(ECPrivateKey
),
273 PORT_FreeArena(arena
, PR_TRUE
);
277 /* Set the version number (SEC 1 section C.4 says it should be 1) */
278 SECITEM_AllocItem(arena
, &key
->version
, 1, kmflag
);
279 key
->version
.data
[0] = 1;
281 /* Copy all of the fields from the ECParams argument to the
282 * ECParams structure within the private key.
284 key
->ecParams
.arena
= arena
;
285 key
->ecParams
.type
= ecParams
->type
;
286 key
->ecParams
.fieldID
.size
= ecParams
->fieldID
.size
;
287 key
->ecParams
.fieldID
.type
= ecParams
->fieldID
.type
;
288 if (ecParams
->fieldID
.type
== ec_field_GFp
) {
289 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &key
->ecParams
.fieldID
.u
.prime
,
290 &ecParams
->fieldID
.u
.prime
, kmflag
));
292 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &key
->ecParams
.fieldID
.u
.poly
,
293 &ecParams
->fieldID
.u
.poly
, kmflag
));
295 key
->ecParams
.fieldID
.k1
= ecParams
->fieldID
.k1
;
296 key
->ecParams
.fieldID
.k2
= ecParams
->fieldID
.k2
;
297 key
->ecParams
.fieldID
.k3
= ecParams
->fieldID
.k3
;
298 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &key
->ecParams
.curve
.a
,
299 &ecParams
->curve
.a
, kmflag
));
300 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &key
->ecParams
.curve
.b
,
301 &ecParams
->curve
.b
, kmflag
));
302 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &key
->ecParams
.curve
.seed
,
303 &ecParams
->curve
.seed
, kmflag
));
304 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &key
->ecParams
.base
,
305 &ecParams
->base
, kmflag
));
306 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &key
->ecParams
.order
,
307 &ecParams
->order
, kmflag
));
308 key
->ecParams
.cofactor
= ecParams
->cofactor
;
309 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &key
->ecParams
.DEREncoding
,
310 &ecParams
->DEREncoding
, kmflag
));
311 key
->ecParams
.name
= ecParams
->name
;
312 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &key
->ecParams
.curveOID
,
313 &ecParams
->curveOID
, kmflag
));
315 len
= (ecParams
->fieldID
.size
+ 7) >> 3;
316 SECITEM_AllocItem(arena
, &key
->publicValue
, 2*len
+ 1, kmflag
);
317 len
= ecParams
->order
.len
;
318 SECITEM_AllocItem(arena
, &key
->privateValue
, len
, kmflag
);
320 /* Copy private key */
321 if (privKeyLen
>= len
) {
322 memcpy(key
->privateValue
.data
, privKeyBytes
, len
);
324 memset(key
->privateValue
.data
, 0, (len
- privKeyLen
));
325 memcpy(key
->privateValue
.data
+ (len
- privKeyLen
), privKeyBytes
, privKeyLen
);
328 /* Compute corresponding public key */
330 CHECK_MPI_OK( mp_init(&k
, kmflag
) );
331 CHECK_MPI_OK( mp_read_unsigned_octets(&k
, key
->privateValue
.data
,
334 rv
= ec_points_mul(ecParams
, &k
, NULL
, NULL
, &(key
->publicValue
), kmflag
);
335 if (rv
!= SECSuccess
) goto cleanup
;
341 PORT_FreeArena(arena
, PR_TRUE
);
344 printf("ec_NewKey returning %s\n",
345 (rv
== SECSuccess
) ? "success" : "failure");
352 /* Generates a new EC key pair. The private key is a supplied
353 * random value (in seed) and the public key is the result of
354 * performing a scalar point multiplication of that value with
355 * the curve's base point.
358 EC_NewKeyFromSeed(ECParams
*ecParams
, ECPrivateKey
**privKey
,
359 const unsigned char *seed
, int seedlen
, int kmflag
)
361 SECStatus rv
= SECFailure
;
362 rv
= ec_NewKey(ecParams
, privKey
, seed
, seedlen
, kmflag
);
366 /* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
367 * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
368 * random number generator.
371 * - order: a buffer that holds the curve's group order
372 * - len: the length in octets of the order buffer
375 * Returns a buffer of len octets that holds the private key. The caller
376 * is responsible for freeing the buffer with PORT_ZFree.
378 static unsigned char *
379 ec_GenerateRandomPrivateKey(const unsigned char *order
, int len
, int kmflag
)
381 SECStatus rv
= SECSuccess
;
383 unsigned char *privKeyBytes
= NULL
;
384 mp_int privKeyVal
, order_1
, one
;
386 MP_DIGITS(&privKeyVal
) = 0;
387 MP_DIGITS(&order_1
) = 0;
389 CHECK_MPI_OK( mp_init(&privKeyVal
, kmflag
) );
390 CHECK_MPI_OK( mp_init(&order_1
, kmflag
) );
391 CHECK_MPI_OK( mp_init(&one
, kmflag
) );
393 /* Generates 2*len random bytes using the global random bit generator
394 * (which implements Algorithm 1 of FIPS 186-2 Change Notice 1) then
395 * reduces modulo the group order.
397 if ((privKeyBytes
= PORT_Alloc(2*len
, kmflag
)) == NULL
) goto cleanup
;
398 CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes
, 2*len
) );
399 CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal
, privKeyBytes
, 2*len
) );
400 CHECK_MPI_OK( mp_read_unsigned_octets(&order_1
, order
, len
) );
401 CHECK_MPI_OK( mp_set_int(&one
, 1) );
402 CHECK_MPI_OK( mp_sub(&order_1
, &one
, &order_1
) );
403 CHECK_MPI_OK( mp_mod(&privKeyVal
, &order_1
, &privKeyVal
) );
404 CHECK_MPI_OK( mp_add(&privKeyVal
, &one
, &privKeyVal
) );
405 CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal
, privKeyBytes
, len
) );
406 memset(privKeyBytes
+len
, 0, len
);
408 mp_clear(&privKeyVal
);
412 MP_TO_SEC_ERROR(err
);
415 if (rv
!= SECSuccess
&& privKeyBytes
) {
417 kmem_free(privKeyBytes
, 2*len
);
426 /* Generates a new EC key pair. The private key is a random value and
427 * the public key is the result of performing a scalar point multiplication
428 * of that value with the curve's base point.
431 EC_NewKey(ECParams
*ecParams
, ECPrivateKey
**privKey
, int kmflag
)
433 SECStatus rv
= SECFailure
;
435 unsigned char *privKeyBytes
= NULL
;
438 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
442 len
= ecParams
->order
.len
;
443 privKeyBytes
= ec_GenerateRandomPrivateKey(ecParams
->order
.data
, len
,
445 if (privKeyBytes
== NULL
) goto cleanup
;
446 /* generate public key */
447 CHECK_SEC_OK( ec_NewKey(ecParams
, privKey
, privKeyBytes
, len
, kmflag
) );
451 PORT_ZFree(privKeyBytes
, len
* 2);
454 printf("EC_NewKey returning %s\n",
455 (rv
== SECSuccess
) ? "success" : "failure");
461 /* Validates an EC public key as described in Section 5.2.2 of
462 * X9.62. The ECDH primitive when used without the cofactor does
463 * not address small subgroup attacks, which may occur when the
464 * public key is not valid. These attacks can be prevented by
465 * validating the public key before using ECDH.
468 EC_ValidatePublicKey(ECParams
*ecParams
, SECItem
*publicValue
, int kmflag
)
471 ECGroup
*group
= NULL
;
472 SECStatus rv
= SECFailure
;
473 mp_err err
= MP_OKAY
;
476 if (!ecParams
|| !publicValue
) {
477 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
481 /* NOTE: We only support uncompressed points for now */
482 len
= (ecParams
->fieldID
.size
+ 7) >> 3;
483 if (publicValue
->data
[0] != EC_POINT_FORM_UNCOMPRESSED
) {
484 PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM
);
486 } else if (publicValue
->len
!= (2 * len
+ 1)) {
487 PORT_SetError(SEC_ERROR_BAD_KEY
);
493 CHECK_MPI_OK( mp_init(&Px
, kmflag
) );
494 CHECK_MPI_OK( mp_init(&Py
, kmflag
) );
496 /* Initialize Px and Py */
497 CHECK_MPI_OK( mp_read_unsigned_octets(&Px
, publicValue
->data
+ 1, (mp_size
) len
) );
498 CHECK_MPI_OK( mp_read_unsigned_octets(&Py
, publicValue
->data
+ 1 + len
, (mp_size
) len
) );
500 /* construct from named params */
501 group
= ECGroup_fromName(ecParams
->name
, kmflag
);
504 * ECGroup_fromName fails if ecParams->name is not a valid
505 * ECCurveName value, or if we run out of memory, or perhaps
506 * for other reasons. Unfortunately if ecParams->name is a
507 * valid ECCurveName value, we don't know what the right error
508 * code should be because ECGroup_fromName doesn't return an
509 * error code to the caller. Set err to MP_UNDEF because
510 * that's what ECGroup_fromName uses internally.
512 if ((ecParams
->name
<= ECCurve_noName
) ||
513 (ecParams
->name
>= ECCurve_pastLastCurve
)) {
521 /* validate public point */
522 if ((err
= ECPoint_validate(group
, &Px
, &Py
)) < MP_YES
) {
524 PORT_SetError(SEC_ERROR_BAD_KEY
);
526 err
= MP_OKAY
; /* don't change the error code */
538 MP_TO_SEC_ERROR(err
);
545 ** Performs an ECDH key derivation by computing the scalar point
546 ** multiplication of privateValue and publicValue (with or without the
547 ** cofactor) and returns the x-coordinate of the resulting elliptic
548 ** curve point in derived secret. If successful, derivedSecret->data
549 ** is set to the address of the newly allocated buffer containing the
550 ** derived secret, and derivedSecret->len is the size of the secret
551 ** produced. It is the caller's responsibility to free the allocated
552 ** buffer containing the derived secret.
555 ECDH_Derive(SECItem
*publicValue
,
557 SECItem
*privateValue
,
559 SECItem
*derivedSecret
,
562 SECStatus rv
= SECFailure
;
563 unsigned int len
= 0;
564 SECItem pointQ
= {siBuffer
, NULL
, 0};
565 mp_int k
; /* to hold the private value */
567 mp_err err
= MP_OKAY
;
572 if (!publicValue
|| !ecParams
|| !privateValue
||
574 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
578 memset(derivedSecret
, 0, sizeof *derivedSecret
);
579 len
= (ecParams
->fieldID
.size
+ 7) >> 3;
580 pointQ
.len
= 2*len
+ 1;
581 if ((pointQ
.data
= PORT_Alloc(2*len
+ 1, kmflag
)) == NULL
) goto cleanup
;
584 CHECK_MPI_OK( mp_init(&k
, kmflag
) );
585 CHECK_MPI_OK( mp_read_unsigned_octets(&k
, privateValue
->data
,
586 (mp_size
) privateValue
->len
) );
588 if (withCofactor
&& (ecParams
->cofactor
!= 1)) {
589 /* multiply k with the cofactor */
590 MP_DIGITS(&cofactor
) = 0;
591 CHECK_MPI_OK( mp_init(&cofactor
, kmflag
) );
592 mp_set(&cofactor
, ecParams
->cofactor
);
593 CHECK_MPI_OK( mp_mul(&k
, &cofactor
, &k
) );
596 /* Multiply our private key and peer's public point */
597 if ((ec_points_mul(ecParams
, NULL
, &k
, publicValue
, &pointQ
, kmflag
) != SECSuccess
) ||
598 ec_point_at_infinity(&pointQ
))
601 /* Allocate memory for the derived secret and copy
602 * the x co-ordinate of pointQ into it.
604 SECITEM_AllocItem(NULL
, derivedSecret
, len
, kmflag
);
605 memcpy(derivedSecret
->data
, pointQ
.data
+ 1, len
);
610 printf("derived_secret:\n");
611 for (i
= 0; i
< derivedSecret
->len
; i
++)
612 printf("%02x:", derivedSecret
->data
[i
]);
620 PORT_ZFree(pointQ
.data
, 2*len
+ 1);
626 /* Computes the ECDSA signature (a concatenation of two values r and s)
627 * on the digest using the given key and the random value kb (used in
631 ECDSA_SignDigestWithSeed(ECPrivateKey
*key
, SECItem
*signature
,
632 const SECItem
*digest
, const unsigned char *kb
, const int kblen
, int kmflag
)
634 SECStatus rv
= SECFailure
;
636 mp_int d
, k
; /* private key, random integer */
637 mp_int r
, s
; /* tuple (r, s) is the signature */
639 mp_err err
= MP_OKAY
;
640 ECParams
*ecParams
= NULL
;
641 SECItem kGpoint
= { siBuffer
, NULL
, 0};
642 int flen
= 0; /* length in bytes of the field size */
643 unsigned olen
; /* length in bytes of the base point order */
649 /* Initialize MPI integers. */
650 /* must happen before the first potential call to cleanup */
659 if (!key
|| !signature
|| !digest
|| !kb
|| (kblen
< 0)) {
660 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
664 ecParams
= &(key
->ecParams
);
665 flen
= (ecParams
->fieldID
.size
+ 7) >> 3;
666 olen
= ecParams
->order
.len
;
667 if (signature
->data
== NULL
) {
668 /* a call to get the signature length only */
671 if (signature
->len
< 2*olen
) {
672 PORT_SetError(SEC_ERROR_OUTPUT_LEN
);
673 rv
= SECBufferTooSmall
;
678 CHECK_MPI_OK( mp_init(&x1
, kmflag
) );
679 CHECK_MPI_OK( mp_init(&d
, kmflag
) );
680 CHECK_MPI_OK( mp_init(&k
, kmflag
) );
681 CHECK_MPI_OK( mp_init(&r
, kmflag
) );
682 CHECK_MPI_OK( mp_init(&s
, kmflag
) );
683 CHECK_MPI_OK( mp_init(&n
, kmflag
) );
685 SECITEM_TO_MPINT( ecParams
->order
, &n
);
686 SECITEM_TO_MPINT( key
->privateValue
, &d
);
687 CHECK_MPI_OK( mp_read_unsigned_octets(&k
, kb
, kblen
) );
688 /* Make sure k is in the interval [1, n-1] */
689 if ((mp_cmp_z(&k
) <= 0) || (mp_cmp(&k
, &n
) >= 0)) {
691 printf("k is outside [1, n-1]\n");
693 printf("k : %s \n", mpstr
);
695 printf("n : %s \n", mpstr
);
697 PORT_SetError(SEC_ERROR_NEED_RANDOM
);
702 ** ANSI X9.62, Section 5.3.2, Step 2
706 kGpoint
.len
= 2*flen
+ 1;
707 kGpoint
.data
= PORT_Alloc(2*flen
+ 1, kmflag
);
708 if ((kGpoint
.data
== NULL
) ||
709 (ec_points_mul(ecParams
, &k
, NULL
, NULL
, &kGpoint
, kmflag
)
714 ** ANSI X9.62, Section 5.3.3, Step 1
716 ** Extract the x co-ordinate of kG into x1
718 CHECK_MPI_OK( mp_read_unsigned_octets(&x1
, kGpoint
.data
+ 1,
722 ** ANSI X9.62, Section 5.3.3, Step 2
724 ** r = x1 mod n NOTE: n is the order of the curve
726 CHECK_MPI_OK( mp_mod(&x1
, &n
, &r
) );
729 ** ANSI X9.62, Section 5.3.3, Step 3
733 if (mp_cmp_z(&r
) == 0) {
734 PORT_SetError(SEC_ERROR_NEED_RANDOM
);
739 ** ANSI X9.62, Section 5.3.3, Step 4
741 ** s = (k**-1 * (HASH(M) + d*r)) mod n
743 SECITEM_TO_MPINT(*digest
, &s
); /* s = HASH(M) */
745 /* In the definition of EC signing, digests are truncated
746 * to the length of n in bits.
747 * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
748 if (digest
->len
*8 > ecParams
->fieldID
.size
) {
749 mpl_rsh(&s
,&s
,digest
->len
*8 - ecParams
->fieldID
.size
);
753 mp_todecimal(&n
, mpstr
);
754 printf("n : %s (dec)\n", mpstr
);
755 mp_todecimal(&d
, mpstr
);
756 printf("d : %s (dec)\n", mpstr
);
757 mp_tohex(&x1
, mpstr
);
758 printf("x1: %s\n", mpstr
);
759 mp_todecimal(&s
, mpstr
);
760 printf("digest: %s (decimal)\n", mpstr
);
761 mp_todecimal(&r
, mpstr
);
762 printf("r : %s (dec)\n", mpstr
);
764 printf("r : %s\n", mpstr
);
767 CHECK_MPI_OK( mp_invmod(&k
, &n
, &k
) ); /* k = k**-1 mod n */
768 CHECK_MPI_OK( mp_mulmod(&d
, &r
, &n
, &d
) ); /* d = d * r mod n */
769 CHECK_MPI_OK( mp_addmod(&s
, &d
, &n
, &s
) ); /* s = s + d mod n */
770 CHECK_MPI_OK( mp_mulmod(&s
, &k
, &n
, &s
) ); /* s = s * k mod n */
773 mp_todecimal(&s
, mpstr
);
774 printf("s : %s (dec)\n", mpstr
);
776 printf("s : %s\n", mpstr
);
780 ** ANSI X9.62, Section 5.3.3, Step 5
784 if (mp_cmp_z(&s
) == 0) {
785 PORT_SetError(SEC_ERROR_NEED_RANDOM
);
791 ** Signature is tuple (r, s)
793 CHECK_MPI_OK( mp_to_fixlen_octets(&r
, signature
->data
, olen
) );
794 CHECK_MPI_OK( mp_to_fixlen_octets(&s
, signature
->data
+ olen
, olen
) );
796 signature
->len
= 2*olen
;
809 PORT_ZFree(kGpoint
.data
, 2*flen
+ 1);
813 MP_TO_SEC_ERROR(err
);
818 printf("ECDSA signing with seed %s\n",
819 (rv
== SECSuccess
) ? "succeeded" : "failed");
826 ** Computes the ECDSA signature on the digest using the given key
827 ** and a random seed.
830 ECDSA_SignDigest(ECPrivateKey
*key
, SECItem
*signature
, const SECItem
*digest
,
833 SECStatus rv
= SECFailure
;
835 unsigned char *kBytes
= NULL
;
838 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
842 /* Generate random value k */
843 len
= key
->ecParams
.order
.len
;
844 kBytes
= ec_GenerateRandomPrivateKey(key
->ecParams
.order
.data
, len
,
846 if (kBytes
== NULL
) goto cleanup
;
848 /* Generate ECDSA signature with the specified k value */
849 rv
= ECDSA_SignDigestWithSeed(key
, signature
, digest
, kBytes
, len
, kmflag
);
853 PORT_ZFree(kBytes
, len
* 2);
857 printf("ECDSA signing %s\n",
858 (rv
== SECSuccess
) ? "succeeded" : "failed");
865 ** Checks the signature on the given digest using the key provided.
868 ECDSA_VerifyDigest(ECPublicKey
*key
, const SECItem
*signature
,
869 const SECItem
*digest
, int kmflag
)
871 SECStatus rv
= SECFailure
;
872 mp_int r_
, s_
; /* tuple (r', s') is received signature) */
873 mp_int c
, u1
, u2
, v
; /* intermediate values used in verification */
876 mp_err err
= MP_OKAY
;
877 ECParams
*ecParams
= NULL
;
878 SECItem pointC
= { siBuffer
, NULL
, 0 };
879 int slen
; /* length in bytes of a half signature (r or s) */
880 int flen
; /* length in bytes of the field size */
881 unsigned olen
; /* length in bytes of the base point order */
885 printf("ECDSA verification called\n");
888 /* Initialize MPI integers. */
889 /* must happen before the first potential call to cleanup */
900 if (!key
|| !signature
|| !digest
) {
901 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
905 ecParams
= &(key
->ecParams
);
906 flen
= (ecParams
->fieldID
.size
+ 7) >> 3;
907 olen
= ecParams
->order
.len
;
908 if (signature
->len
== 0 || signature
->len
%2 != 0 ||
909 signature
->len
> 2*olen
) {
910 PORT_SetError(SEC_ERROR_INPUT_LEN
);
913 slen
= signature
->len
/2;
915 SECITEM_AllocItem(NULL
, &pointC
, 2*flen
+ 1, kmflag
);
916 if (pointC
.data
== NULL
)
919 CHECK_MPI_OK( mp_init(&r_
, kmflag
) );
920 CHECK_MPI_OK( mp_init(&s_
, kmflag
) );
921 CHECK_MPI_OK( mp_init(&c
, kmflag
) );
922 CHECK_MPI_OK( mp_init(&u1
, kmflag
) );
923 CHECK_MPI_OK( mp_init(&u2
, kmflag
) );
924 CHECK_MPI_OK( mp_init(&x1
, kmflag
) );
925 CHECK_MPI_OK( mp_init(&v
, kmflag
) );
926 CHECK_MPI_OK( mp_init(&n
, kmflag
) );
929 ** Convert received signature (r', s') into MPI integers.
931 CHECK_MPI_OK( mp_read_unsigned_octets(&r_
, signature
->data
, slen
) );
932 CHECK_MPI_OK( mp_read_unsigned_octets(&s_
, signature
->data
+ slen
, slen
) );
935 ** ANSI X9.62, Section 5.4.2, Steps 1 and 2
937 ** Verify that 0 < r' < n and 0 < s' < n
939 SECITEM_TO_MPINT(ecParams
->order
, &n
);
940 if (mp_cmp_z(&r_
) <= 0 || mp_cmp_z(&s_
) <= 0 ||
941 mp_cmp(&r_
, &n
) >= 0 || mp_cmp(&s_
, &n
) >= 0) {
942 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
943 goto cleanup
; /* will return rv == SECFailure */
947 ** ANSI X9.62, Section 5.4.2, Step 3
949 ** c = (s')**-1 mod n
951 CHECK_MPI_OK( mp_invmod(&s_
, &n
, &c
) ); /* c = (s')**-1 mod n */
954 ** ANSI X9.62, Section 5.4.2, Step 4
956 ** u1 = ((HASH(M')) * c) mod n
958 SECITEM_TO_MPINT(*digest
, &u1
); /* u1 = HASH(M) */
960 /* In the definition of EC signing, digests are truncated
961 * to the length of n in bits.
962 * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
963 if (digest
->len
*8 > ecParams
->fieldID
.size
) { /* u1 = HASH(M') */
964 mpl_rsh(&u1
,&u1
,digest
->len
*8- ecParams
->fieldID
.size
);
968 mp_todecimal(&r_
, mpstr
);
969 printf("r_: %s (dec)\n", mpstr
);
970 mp_todecimal(&s_
, mpstr
);
971 printf("s_: %s (dec)\n", mpstr
);
972 mp_todecimal(&c
, mpstr
);
973 printf("c : %s (dec)\n", mpstr
);
974 mp_todecimal(&u1
, mpstr
);
975 printf("digest: %s (dec)\n", mpstr
);
978 CHECK_MPI_OK( mp_mulmod(&u1
, &c
, &n
, &u1
) ); /* u1 = u1 * c mod n */
981 ** ANSI X9.62, Section 5.4.2, Step 4
983 ** u2 = ((r') * c) mod n
985 CHECK_MPI_OK( mp_mulmod(&r_
, &c
, &n
, &u2
) );
988 ** ANSI X9.62, Section 5.4.3, Step 1
990 ** Compute u1*G + u2*Q
991 ** Here, A = u1.G B = u2.Q and C = A + B
992 ** If the result, C, is the point at infinity, reject the signature
994 if (ec_points_mul(ecParams
, &u1
, &u2
, &key
->publicValue
, &pointC
, kmflag
)
999 if (ec_point_at_infinity(&pointC
)) {
1000 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
1005 CHECK_MPI_OK( mp_read_unsigned_octets(&x1
, pointC
.data
+ 1, flen
) );
1008 ** ANSI X9.62, Section 5.4.4, Step 2
1012 CHECK_MPI_OK( mp_mod(&x1
, &n
, &v
) );
1015 mp_todecimal(&r_
, mpstr
);
1016 printf("r_: %s (dec)\n", mpstr
);
1017 mp_todecimal(&v
, mpstr
);
1018 printf("v : %s (dec)\n", mpstr
);
1022 ** ANSI X9.62, Section 5.4.4, Step 3
1024 ** Verification: v == r'
1026 if (mp_cmp(&v
, &r_
)) {
1027 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
1028 rv
= SECFailure
; /* Signature failed to verify. */
1030 rv
= SECSuccess
; /* Signature verified. */
1034 mp_todecimal(&u1
, mpstr
);
1035 printf("u1: %s (dec)\n", mpstr
);
1036 mp_todecimal(&u2
, mpstr
);
1037 printf("u2: %s (dec)\n", mpstr
);
1038 mp_tohex(&x1
, mpstr
);
1039 printf("x1: %s\n", mpstr
);
1040 mp_todecimal(&v
, mpstr
);
1041 printf("v : %s (dec)\n", mpstr
);
1054 if (pointC
.data
) SECITEM_FreeItem(&pointC
, PR_FALSE
);
1056 MP_TO_SEC_ERROR(err
);
1061 printf("ECDSA verification %s\n",
1062 (rv
== SECSuccess
) ? "succeeded" : "failed");
1069 * Copy all of the fields from srcParams into dstParams
1072 EC_CopyParams(PRArenaPool
*arena
, ECParams
*dstParams
,
1073 const ECParams
*srcParams
)
1075 SECStatus rv
= SECFailure
;
1077 dstParams
->arena
= arena
;
1078 dstParams
->type
= srcParams
->type
;
1079 dstParams
->fieldID
.size
= srcParams
->fieldID
.size
;
1080 dstParams
->fieldID
.type
= srcParams
->fieldID
.type
;
1081 if (srcParams
->fieldID
.type
== ec_field_GFp
) {
1082 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &dstParams
->fieldID
.u
.prime
,
1083 &srcParams
->fieldID
.u
.prime
, 0));
1085 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &dstParams
->fieldID
.u
.poly
,
1086 &srcParams
->fieldID
.u
.poly
, 0));
1088 dstParams
->fieldID
.k1
= srcParams
->fieldID
.k1
;
1089 dstParams
->fieldID
.k2
= srcParams
->fieldID
.k2
;
1090 dstParams
->fieldID
.k3
= srcParams
->fieldID
.k3
;
1091 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &dstParams
->curve
.a
,
1092 &srcParams
->curve
.a
, 0));
1093 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &dstParams
->curve
.b
,
1094 &srcParams
->curve
.b
, 0));
1095 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &dstParams
->curve
.seed
,
1096 &srcParams
->curve
.seed
, 0));
1097 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &dstParams
->base
,
1098 &srcParams
->base
, 0));
1099 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &dstParams
->order
,
1100 &srcParams
->order
, 0));
1101 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &dstParams
->DEREncoding
,
1102 &srcParams
->DEREncoding
, 0));
1103 dstParams
->name
= srcParams
->name
;
1104 CHECK_SEC_OK(SECITEM_CopyItem(arena
, &dstParams
->curveOID
,
1105 &srcParams
->curveOID
, 0));
1106 dstParams
->cofactor
= srcParams
->cofactor
;