xref: /onnv-gate/usr/src/common/crypto/ecc/ec.c (revision 10500:a10fbcfc2f21)
15697Smcpowers /*
25697Smcpowers  * ***** BEGIN LICENSE BLOCK *****
35697Smcpowers  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
45697Smcpowers  *
55697Smcpowers  * The contents of this file are subject to the Mozilla Public License Version
65697Smcpowers  * 1.1 (the "License"); you may not use this file except in compliance with
75697Smcpowers  * the License. You may obtain a copy of the License at
85697Smcpowers  * http://www.mozilla.org/MPL/
95697Smcpowers  *
105697Smcpowers  * Software distributed under the License is distributed on an "AS IS" basis,
115697Smcpowers  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
125697Smcpowers  * for the specific language governing rights and limitations under the
135697Smcpowers  * License.
145697Smcpowers  *
155697Smcpowers  * The Original Code is the Elliptic Curve Cryptography library.
165697Smcpowers  *
175697Smcpowers  * The Initial Developer of the Original Code is
185697Smcpowers  * Sun Microsystems, Inc.
195697Smcpowers  * Portions created by the Initial Developer are Copyright (C) 2003
205697Smcpowers  * the Initial Developer. All Rights Reserved.
215697Smcpowers  *
225697Smcpowers  * Contributor(s):
235697Smcpowers  *   Dr Vipul Gupta <vipul.gupta@sun.com> and
245697Smcpowers  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
255697Smcpowers  *
265697Smcpowers  * Alternatively, the contents of this file may be used under the terms of
275697Smcpowers  * either the GNU General Public License Version 2 or later (the "GPL"), or
285697Smcpowers  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
295697Smcpowers  * in which case the provisions of the GPL or the LGPL are applicable instead
305697Smcpowers  * of those above. If you wish to allow use of your version of this file only
315697Smcpowers  * under the terms of either the GPL or the LGPL, and not to allow others to
325697Smcpowers  * use your version of this file under the terms of the MPL, indicate your
335697Smcpowers  * decision by deleting the provisions above and replace them with the notice
345697Smcpowers  * and other provisions required by the GPL or the LGPL. If you do not delete
355697Smcpowers  * the provisions above, a recipient may use your version of this file under
365697Smcpowers  * the terms of any one of the MPL, the GPL or the LGPL.
375697Smcpowers  *
385697Smcpowers  * ***** END LICENSE BLOCK ***** */
395697Smcpowers /*
40*10500SHai-May.Chao@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
415697Smcpowers  * Use is subject to license terms.
425697Smcpowers  *
435697Smcpowers  * Sun elects to use this software under the MPL license.
445697Smcpowers  */
455697Smcpowers 
465697Smcpowers 
475697Smcpowers #include "mplogic.h"
485697Smcpowers #include "ec.h"
495697Smcpowers #include "ecl.h"
505697Smcpowers 
515697Smcpowers #include <sys/types.h>
525697Smcpowers #ifndef _KERNEL
535697Smcpowers #include <stdlib.h>
545697Smcpowers #include <string.h>
555697Smcpowers #include <strings.h>
565697Smcpowers #endif
575697Smcpowers #include "ecl-exp.h"
585697Smcpowers #include "mpi.h"
595697Smcpowers #include "ecc_impl.h"
605697Smcpowers 
615697Smcpowers #ifdef _KERNEL
625697Smcpowers #define	PORT_ZFree(p, l)		bzero((p), (l)); kmem_free((p), (l))
635697Smcpowers #else
645697Smcpowers #define	PORT_ZFree(p, l)		bzero((p), (l)); free((p))
655697Smcpowers #endif
665697Smcpowers 
675697Smcpowers /*
685697Smcpowers  * Returns true if pointP is the point at infinity, false otherwise
695697Smcpowers  */
705697Smcpowers PRBool
ec_point_at_infinity(SECItem * pointP)715697Smcpowers ec_point_at_infinity(SECItem *pointP)
725697Smcpowers {
735697Smcpowers     unsigned int i;
745697Smcpowers 
755697Smcpowers     for (i = 1; i < pointP->len; i++) {
765697Smcpowers 	if (pointP->data[i] != 0x00) return PR_FALSE;
775697Smcpowers     }
785697Smcpowers 
795697Smcpowers     return PR_TRUE;
805697Smcpowers }
815697Smcpowers 
825697Smcpowers /*
835697Smcpowers  * Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for
845697Smcpowers  * the curve whose parameters are encoded in params with base point G.
855697Smcpowers  */
865697Smcpowers SECStatus
ec_points_mul(const ECParams * params,const mp_int * k1,const mp_int * k2,const SECItem * pointP,SECItem * pointQ,int kmflag)875697Smcpowers ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
885697Smcpowers              const SECItem *pointP, SECItem *pointQ, int kmflag)
895697Smcpowers {
905697Smcpowers     mp_int Px, Py, Qx, Qy;
915697Smcpowers     mp_int Gx, Gy, order, irreducible, a, b;
925697Smcpowers #if 0 /* currently don't support non-named curves */
935697Smcpowers     unsigned int irr_arr[5];
945697Smcpowers #endif
955697Smcpowers     ECGroup *group = NULL;
965697Smcpowers     SECStatus rv = SECFailure;
975697Smcpowers     mp_err err = MP_OKAY;
985697Smcpowers     int len;
995697Smcpowers 
1005697Smcpowers #if EC_DEBUG
1015697Smcpowers     int i;
1025697Smcpowers     char mpstr[256];
1035697Smcpowers 
1045697Smcpowers     printf("ec_points_mul: params [len=%d]:", params->DEREncoding.len);
1055697Smcpowers     for (i = 0; i < params->DEREncoding.len; i++)
1065697Smcpowers 	    printf("%02x:", params->DEREncoding.data[i]);
1075697Smcpowers     printf("\n");
1085697Smcpowers 
1095697Smcpowers 	if (k1 != NULL) {
1105697Smcpowers 		mp_tohex(k1, mpstr);
1115697Smcpowers 		printf("ec_points_mul: scalar k1: %s\n", mpstr);
1125697Smcpowers 		mp_todecimal(k1, mpstr);
1135697Smcpowers 		printf("ec_points_mul: scalar k1: %s (dec)\n", mpstr);
1145697Smcpowers 	}
1155697Smcpowers 
1165697Smcpowers 	if (k2 != NULL) {
1175697Smcpowers 		mp_tohex(k2, mpstr);
1185697Smcpowers 		printf("ec_points_mul: scalar k2: %s\n", mpstr);
1195697Smcpowers 		mp_todecimal(k2, mpstr);
1205697Smcpowers 		printf("ec_points_mul: scalar k2: %s (dec)\n", mpstr);
1215697Smcpowers 	}
1225697Smcpowers 
1235697Smcpowers 	if (pointP != NULL) {
1245697Smcpowers 		printf("ec_points_mul: pointP [len=%d]:", pointP->len);
1255697Smcpowers 		for (i = 0; i < pointP->len; i++)
1265697Smcpowers 			printf("%02x:", pointP->data[i]);
1275697Smcpowers 		printf("\n");
1285697Smcpowers 	}
1295697Smcpowers #endif
1305697Smcpowers 
1315697Smcpowers 	/* NOTE: We only support uncompressed points for now */
1325697Smcpowers 	len = (params->fieldID.size + 7) >> 3;
1335697Smcpowers 	if (pointP != NULL) {
1345697Smcpowers 		if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
1355697Smcpowers 			(pointP->len != (2 * len + 1))) {
1365697Smcpowers 			return SECFailure;
1375697Smcpowers 		};
1385697Smcpowers 	}
1395697Smcpowers 
1405697Smcpowers 	MP_DIGITS(&Px) = 0;
1415697Smcpowers 	MP_DIGITS(&Py) = 0;
1425697Smcpowers 	MP_DIGITS(&Qx) = 0;
1435697Smcpowers 	MP_DIGITS(&Qy) = 0;
1445697Smcpowers 	MP_DIGITS(&Gx) = 0;
1455697Smcpowers 	MP_DIGITS(&Gy) = 0;
1465697Smcpowers 	MP_DIGITS(&order) = 0;
1475697Smcpowers 	MP_DIGITS(&irreducible) = 0;
1485697Smcpowers 	MP_DIGITS(&a) = 0;
1495697Smcpowers 	MP_DIGITS(&b) = 0;
1505697Smcpowers 	CHECK_MPI_OK( mp_init(&Px, kmflag) );
1515697Smcpowers 	CHECK_MPI_OK( mp_init(&Py, kmflag) );
1525697Smcpowers 	CHECK_MPI_OK( mp_init(&Qx, kmflag) );
1535697Smcpowers 	CHECK_MPI_OK( mp_init(&Qy, kmflag) );
1545697Smcpowers 	CHECK_MPI_OK( mp_init(&Gx, kmflag) );
1555697Smcpowers 	CHECK_MPI_OK( mp_init(&Gy, kmflag) );
1565697Smcpowers 	CHECK_MPI_OK( mp_init(&order, kmflag) );
1575697Smcpowers 	CHECK_MPI_OK( mp_init(&irreducible, kmflag) );
1585697Smcpowers 	CHECK_MPI_OK( mp_init(&a, kmflag) );
1595697Smcpowers 	CHECK_MPI_OK( mp_init(&b, kmflag) );
1605697Smcpowers 
1615697Smcpowers 	if ((k2 != NULL) && (pointP != NULL)) {
1625697Smcpowers 		/* Initialize Px and Py */
1635697Smcpowers 		CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1, (mp_size) len) );
1645697Smcpowers 		CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len, (mp_size) len) );
1655697Smcpowers 	}
1665697Smcpowers 
1675697Smcpowers 	/* construct from named params, if possible */
1685697Smcpowers 	if (params->name != ECCurve_noName) {
1695697Smcpowers 		group = ECGroup_fromName(params->name, kmflag);
1705697Smcpowers 	}
1715697Smcpowers 
1725697Smcpowers #if 0 /* currently don't support non-named curves */
1735697Smcpowers 	if (group == NULL) {
1745697Smcpowers 		/* Set up mp_ints containing the curve coefficients */
1755697Smcpowers 		CHECK_MPI_OK( mp_read_unsigned_octets(&Gx, params->base.data + 1,
1765697Smcpowers 										  (mp_size) len) );
1775697Smcpowers 		CHECK_MPI_OK( mp_read_unsigned_octets(&Gy, params->base.data + 1 + len,
1785697Smcpowers 										  (mp_size) len) );
1795697Smcpowers 		SECITEM_TO_MPINT( params->order, &order );
1805697Smcpowers 		SECITEM_TO_MPINT( params->curve.a, &a );
1815697Smcpowers 		SECITEM_TO_MPINT( params->curve.b, &b );
1825697Smcpowers 		if (params->fieldID.type == ec_field_GFp) {
1835697Smcpowers 			SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible );
1845697Smcpowers 			group = ECGroup_consGFp(&irreducible, &a, &b, &Gx, &Gy, &order, params->cofactor);
1855697Smcpowers 		} else {
1865697Smcpowers 			SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible );
1875697Smcpowers 			irr_arr[0] = params->fieldID.size;
1885697Smcpowers 			irr_arr[1] = params->fieldID.k1;
1895697Smcpowers 			irr_arr[2] = params->fieldID.k2;
1905697Smcpowers 			irr_arr[3] = params->fieldID.k3;
1915697Smcpowers 			irr_arr[4] = 0;
1925697Smcpowers 			group = ECGroup_consGF2m(&irreducible, irr_arr, &a, &b, &Gx, &Gy, &order, params->cofactor);
1935697Smcpowers 		}
1945697Smcpowers 	}
1955697Smcpowers #endif
1965697Smcpowers 	if (group == NULL)
1975697Smcpowers 		goto cleanup;
1985697Smcpowers 
1995697Smcpowers 	if ((k2 != NULL) && (pointP != NULL)) {
2005697Smcpowers 		CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy) );
2015697Smcpowers 	} else {
2025697Smcpowers 		CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy) );
2035697Smcpowers     }
2045697Smcpowers 
2055697Smcpowers     /* Construct the SECItem representation of point Q */
2065697Smcpowers     pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED;
2075697Smcpowers     CHECK_MPI_OK( mp_to_fixlen_octets(&Qx, pointQ->data + 1,
2085697Smcpowers 	                              (mp_size) len) );
2095697Smcpowers     CHECK_MPI_OK( mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len,
2105697Smcpowers 	                              (mp_size) len) );
2115697Smcpowers 
2125697Smcpowers     rv = SECSuccess;
2135697Smcpowers 
2145697Smcpowers #if EC_DEBUG
2155697Smcpowers     printf("ec_points_mul: pointQ [len=%d]:", pointQ->len);
2165697Smcpowers     for (i = 0; i < pointQ->len; i++)
2175697Smcpowers 	    printf("%02x:", pointQ->data[i]);
2185697Smcpowers     printf("\n");
2195697Smcpowers #endif
2205697Smcpowers 
2215697Smcpowers cleanup:
2225697Smcpowers     ECGroup_free(group);
2235697Smcpowers     mp_clear(&Px);
2245697Smcpowers     mp_clear(&Py);
2255697Smcpowers     mp_clear(&Qx);
2265697Smcpowers     mp_clear(&Qy);
2275697Smcpowers     mp_clear(&Gx);
2285697Smcpowers     mp_clear(&Gy);
2295697Smcpowers     mp_clear(&order);
2305697Smcpowers     mp_clear(&irreducible);
2315697Smcpowers     mp_clear(&a);
2325697Smcpowers     mp_clear(&b);
2335697Smcpowers     if (err) {
2345697Smcpowers 	MP_TO_SEC_ERROR(err);
2355697Smcpowers 	rv = SECFailure;
2365697Smcpowers     }
2375697Smcpowers 
2385697Smcpowers     return rv;
2395697Smcpowers }
2405697Smcpowers 
2415697Smcpowers /* Generates a new EC key pair. The private key is a supplied
2425697Smcpowers  * value and the public key is the result of performing a scalar
2435697Smcpowers  * point multiplication of that value with the curve's base point.
2445697Smcpowers  */
2455697Smcpowers SECStatus
ec_NewKey(ECParams * ecParams,ECPrivateKey ** privKey,const unsigned char * privKeyBytes,int privKeyLen,int kmflag)2465697Smcpowers ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
2475697Smcpowers     const unsigned char *privKeyBytes, int privKeyLen, int kmflag)
2485697Smcpowers {
2495697Smcpowers     SECStatus rv = SECFailure;
2505697Smcpowers     PRArenaPool *arena;
2515697Smcpowers     ECPrivateKey *key;
2525697Smcpowers     mp_int k;
2535697Smcpowers     mp_err err = MP_OKAY;
2545697Smcpowers     int len;
2555697Smcpowers 
2565697Smcpowers #if EC_DEBUG
2575697Smcpowers     printf("ec_NewKey called\n");
2585697Smcpowers #endif
2595697Smcpowers 
2605697Smcpowers int printf();
2615697Smcpowers     if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) {
2625697Smcpowers 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
2635697Smcpowers 	return SECFailure;
2645697Smcpowers     }
2655697Smcpowers 
2665697Smcpowers     /* Initialize an arena for the EC key. */
2675697Smcpowers     if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
2685697Smcpowers 	return SECFailure;
2695697Smcpowers 
2705697Smcpowers     key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey),
2715697Smcpowers 	kmflag);
2725697Smcpowers     if (!key) {
2735697Smcpowers 	PORT_FreeArena(arena, PR_TRUE);
2745697Smcpowers 	return SECFailure;
2755697Smcpowers     }
2765697Smcpowers 
2775697Smcpowers     /* Set the version number (SEC 1 section C.4 says it should be 1) */
2785697Smcpowers     SECITEM_AllocItem(arena, &key->version, 1, kmflag);
2795697Smcpowers     key->version.data[0] = 1;
2805697Smcpowers 
2815697Smcpowers     /* Copy all of the fields from the ECParams argument to the
2825697Smcpowers      * ECParams structure within the private key.
2835697Smcpowers      */
2845697Smcpowers     key->ecParams.arena = arena;
2855697Smcpowers     key->ecParams.type = ecParams->type;
2865697Smcpowers     key->ecParams.fieldID.size = ecParams->fieldID.size;
2875697Smcpowers     key->ecParams.fieldID.type = ecParams->fieldID.type;
2885697Smcpowers     if (ecParams->fieldID.type == ec_field_GFp) {
2895697Smcpowers 	CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
2905697Smcpowers 	    &ecParams->fieldID.u.prime, kmflag));
2915697Smcpowers     } else {
2925697Smcpowers 	CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly,
2935697Smcpowers 	    &ecParams->fieldID.u.poly, kmflag));
2945697Smcpowers     }
2955697Smcpowers     key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
2965697Smcpowers     key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
2975697Smcpowers     key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
2985697Smcpowers     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
2995697Smcpowers 	&ecParams->curve.a, kmflag));
3005697Smcpowers     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
3015697Smcpowers 	&ecParams->curve.b, kmflag));
3025697Smcpowers     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
3035697Smcpowers 	&ecParams->curve.seed, kmflag));
3045697Smcpowers     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
3055697Smcpowers 	&ecParams->base, kmflag));
3065697Smcpowers     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
3075697Smcpowers 	&ecParams->order, kmflag));
3085697Smcpowers     key->ecParams.cofactor = ecParams->cofactor;
3095697Smcpowers     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
3105697Smcpowers 	&ecParams->DEREncoding, kmflag));
3115697Smcpowers     key->ecParams.name = ecParams->name;
3125697Smcpowers     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
3135697Smcpowers 	&ecParams->curveOID, kmflag));
3145697Smcpowers 
3155697Smcpowers     len = (ecParams->fieldID.size + 7) >> 3;
3165697Smcpowers     SECITEM_AllocItem(arena, &key->publicValue, 2*len + 1, kmflag);
3175697Smcpowers     len = ecParams->order.len;
3185697Smcpowers     SECITEM_AllocItem(arena, &key->privateValue, len, kmflag);
3195697Smcpowers 
3205697Smcpowers     /* Copy private key */
3215697Smcpowers     if (privKeyLen >= len) {
3225697Smcpowers 	memcpy(key->privateValue.data, privKeyBytes, len);
3235697Smcpowers     } else {
3245697Smcpowers 	memset(key->privateValue.data, 0, (len - privKeyLen));
3255697Smcpowers 	memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
3265697Smcpowers     }
3275697Smcpowers 
3285697Smcpowers     /* Compute corresponding public key */
3295697Smcpowers     MP_DIGITS(&k) = 0;
3305697Smcpowers     CHECK_MPI_OK( mp_init(&k, kmflag) );
3315697Smcpowers     CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data,
3325697Smcpowers 	(mp_size) len) );
3335697Smcpowers 
3345697Smcpowers     rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue), kmflag);
3355697Smcpowers     if (rv != SECSuccess) goto cleanup;
3365697Smcpowers     *privKey = key;
3375697Smcpowers 
3385697Smcpowers cleanup:
3395697Smcpowers     mp_clear(&k);
3405697Smcpowers     if (rv)
3415697Smcpowers 	PORT_FreeArena(arena, PR_TRUE);
3425697Smcpowers 
3435697Smcpowers #if EC_DEBUG
3445697Smcpowers     printf("ec_NewKey returning %s\n",
3455697Smcpowers 	(rv == SECSuccess) ? "success" : "failure");
3465697Smcpowers #endif
3475697Smcpowers 
3485697Smcpowers     return rv;
3495697Smcpowers 
3505697Smcpowers }
3515697Smcpowers 
3525697Smcpowers /* Generates a new EC key pair. The private key is a supplied
3535697Smcpowers  * random value (in seed) and the public key is the result of
3545697Smcpowers  * performing a scalar point multiplication of that value with
3555697Smcpowers  * the curve's base point.
3565697Smcpowers  */
3575697Smcpowers SECStatus
EC_NewKeyFromSeed(ECParams * ecParams,ECPrivateKey ** privKey,const unsigned char * seed,int seedlen,int kmflag)3585697Smcpowers EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
3595697Smcpowers     const unsigned char *seed, int seedlen, int kmflag)
3605697Smcpowers {
3615697Smcpowers     SECStatus rv = SECFailure;
3625697Smcpowers     rv = ec_NewKey(ecParams, privKey, seed, seedlen, kmflag);
3635697Smcpowers     return rv;
3645697Smcpowers }
3655697Smcpowers 
3665697Smcpowers /* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
3675697Smcpowers  * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
3685697Smcpowers  * random number generator.
3695697Smcpowers  *
3705697Smcpowers  * Parameters
3715697Smcpowers  * - order: a buffer that holds the curve's group order
3725697Smcpowers  * - len: the length in octets of the order buffer
3735697Smcpowers  *
3745697Smcpowers  * Return Value
3755697Smcpowers  * Returns a buffer of len octets that holds the private key. The caller
3765697Smcpowers  * is responsible for freeing the buffer with PORT_ZFree.
3775697Smcpowers  */
3785697Smcpowers static unsigned char *
ec_GenerateRandomPrivateKey(const unsigned char * order,int len,int kmflag)3795697Smcpowers ec_GenerateRandomPrivateKey(const unsigned char *order, int len, int kmflag)
3805697Smcpowers {
3815697Smcpowers     SECStatus rv = SECSuccess;
3825697Smcpowers     mp_err err;
3835697Smcpowers     unsigned char *privKeyBytes = NULL;
3845697Smcpowers     mp_int privKeyVal, order_1, one;
3855697Smcpowers 
3865697Smcpowers     MP_DIGITS(&privKeyVal) = 0;
3875697Smcpowers     MP_DIGITS(&order_1) = 0;
3885697Smcpowers     MP_DIGITS(&one) = 0;
3895697Smcpowers     CHECK_MPI_OK( mp_init(&privKeyVal, kmflag) );
3905697Smcpowers     CHECK_MPI_OK( mp_init(&order_1, kmflag) );
3915697Smcpowers     CHECK_MPI_OK( mp_init(&one, kmflag) );
3925697Smcpowers 
3935697Smcpowers     /* Generates 2*len random bytes using the global random bit generator
3945697Smcpowers      * (which implements Algorithm 1 of FIPS 186-2 Change Notice 1) then
3955697Smcpowers      * reduces modulo the group order.
3965697Smcpowers      */
3975697Smcpowers     if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup;
3985697Smcpowers     CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );
3995697Smcpowers     CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2*len) );
4005697Smcpowers     CHECK_MPI_OK( mp_read_unsigned_octets(&order_1, order, len) );
4015697Smcpowers     CHECK_MPI_OK( mp_set_int(&one, 1) );
4025697Smcpowers     CHECK_MPI_OK( mp_sub(&order_1, &one, &order_1) );
4035697Smcpowers     CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) );
4045697Smcpowers     CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) );
4055697Smcpowers     CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) );
4065697Smcpowers     memset(privKeyBytes+len, 0, len);
4075697Smcpowers cleanup:
4085697Smcpowers     mp_clear(&privKeyVal);
4095697Smcpowers     mp_clear(&order_1);
4105697Smcpowers     mp_clear(&one);
4115697Smcpowers     if (err < MP_OKAY) {
4125697Smcpowers 	MP_TO_SEC_ERROR(err);
4135697Smcpowers 	rv = SECFailure;
4145697Smcpowers     }
4155697Smcpowers     if (rv != SECSuccess && privKeyBytes) {
4165697Smcpowers #ifdef _KERNEL
4175697Smcpowers 	kmem_free(privKeyBytes, 2*len);
4185697Smcpowers #else
4195697Smcpowers 	free(privKeyBytes);
4205697Smcpowers #endif
4215697Smcpowers 	privKeyBytes = NULL;
4225697Smcpowers     }
4235697Smcpowers     return privKeyBytes;
4245697Smcpowers }
4255697Smcpowers 
4265697Smcpowers /* Generates a new EC key pair. The private key is a random value and
4275697Smcpowers  * the public key is the result of performing a scalar point multiplication
4285697Smcpowers  * of that value with the curve's base point.
4295697Smcpowers  */
4305697Smcpowers SECStatus
EC_NewKey(ECParams * ecParams,ECPrivateKey ** privKey,int kmflag)4315697Smcpowers EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey, int kmflag)
4325697Smcpowers {
4335697Smcpowers     SECStatus rv = SECFailure;
4345697Smcpowers     int len;
4355697Smcpowers     unsigned char *privKeyBytes = NULL;
4365697Smcpowers 
4375697Smcpowers     if (!ecParams) {
4385697Smcpowers 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
4395697Smcpowers 	return SECFailure;
4405697Smcpowers     }
4415697Smcpowers 
4425697Smcpowers     len = ecParams->order.len;
4435697Smcpowers     privKeyBytes = ec_GenerateRandomPrivateKey(ecParams->order.data, len,
4445697Smcpowers 	kmflag);
4455697Smcpowers     if (privKeyBytes == NULL) goto cleanup;
4465697Smcpowers     /* generate public key */
4475697Smcpowers     CHECK_SEC_OK( ec_NewKey(ecParams, privKey, privKeyBytes, len, kmflag) );
4485697Smcpowers 
4495697Smcpowers cleanup:
4505697Smcpowers     if (privKeyBytes) {
4515697Smcpowers 	PORT_ZFree(privKeyBytes, len * 2);
4525697Smcpowers     }
4535697Smcpowers #if EC_DEBUG
4545697Smcpowers     printf("EC_NewKey returning %s\n",
4555697Smcpowers 	(rv == SECSuccess) ? "success" : "failure");
4565697Smcpowers #endif
4575697Smcpowers 
4585697Smcpowers     return rv;
4595697Smcpowers }
4605697Smcpowers 
4615697Smcpowers /* Validates an EC public key as described in Section 5.2.2 of
4625697Smcpowers  * X9.62. The ECDH primitive when used without the cofactor does
4635697Smcpowers  * not address small subgroup attacks, which may occur when the
4645697Smcpowers  * public key is not valid. These attacks can be prevented by
4655697Smcpowers  * validating the public key before using ECDH.
4665697Smcpowers  */
4675697Smcpowers SECStatus
EC_ValidatePublicKey(ECParams * ecParams,SECItem * publicValue,int kmflag)4685697Smcpowers EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue, int kmflag)
4695697Smcpowers {
4705697Smcpowers     mp_int Px, Py;
4715697Smcpowers     ECGroup *group = NULL;
4725697Smcpowers     SECStatus rv = SECFailure;
4735697Smcpowers     mp_err err = MP_OKAY;
4745697Smcpowers     int len;
4755697Smcpowers 
4765697Smcpowers     if (!ecParams || !publicValue) {
4775697Smcpowers 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
4785697Smcpowers 	return SECFailure;
4795697Smcpowers     }
4805697Smcpowers 
4815697Smcpowers     /* NOTE: We only support uncompressed points for now */
4825697Smcpowers     len = (ecParams->fieldID.size + 7) >> 3;
4835697Smcpowers     if (publicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
4845697Smcpowers 	PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
4855697Smcpowers 	return SECFailure;
4865697Smcpowers     } else if (publicValue->len != (2 * len + 1)) {
4875697Smcpowers 	PORT_SetError(SEC_ERROR_BAD_KEY);
4885697Smcpowers 	return SECFailure;
4895697Smcpowers     }
4905697Smcpowers 
4915697Smcpowers     MP_DIGITS(&Px) = 0;
4925697Smcpowers     MP_DIGITS(&Py) = 0;
4935697Smcpowers     CHECK_MPI_OK( mp_init(&Px, kmflag) );
4945697Smcpowers     CHECK_MPI_OK( mp_init(&Py, kmflag) );
4955697Smcpowers 
4965697Smcpowers     /* Initialize Px and Py */
4975697Smcpowers     CHECK_MPI_OK( mp_read_unsigned_octets(&Px, publicValue->data + 1, (mp_size) len) );
4985697Smcpowers     CHECK_MPI_OK( mp_read_unsigned_octets(&Py, publicValue->data + 1 + len, (mp_size) len) );
4995697Smcpowers 
5005697Smcpowers     /* construct from named params */
5015697Smcpowers     group = ECGroup_fromName(ecParams->name, kmflag);
5025697Smcpowers     if (group == NULL) {
5035697Smcpowers 	/*
5045697Smcpowers 	 * ECGroup_fromName fails if ecParams->name is not a valid
5055697Smcpowers 	 * ECCurveName value, or if we run out of memory, or perhaps
5065697Smcpowers 	 * for other reasons.  Unfortunately if ecParams->name is a
5075697Smcpowers 	 * valid ECCurveName value, we don't know what the right error
5085697Smcpowers 	 * code should be because ECGroup_fromName doesn't return an
5095697Smcpowers 	 * error code to the caller.  Set err to MP_UNDEF because
5105697Smcpowers 	 * that's what ECGroup_fromName uses internally.
5115697Smcpowers 	 */
5125697Smcpowers 	if ((ecParams->name <= ECCurve_noName) ||
5135697Smcpowers 	    (ecParams->name >= ECCurve_pastLastCurve)) {
5145697Smcpowers 	    err = MP_BADARG;
5155697Smcpowers 	} else {
5165697Smcpowers 	    err = MP_UNDEF;
5175697Smcpowers 	}
5185697Smcpowers 	goto cleanup;
5195697Smcpowers     }
5205697Smcpowers 
5215697Smcpowers     /* validate public point */
5225697Smcpowers     if ((err = ECPoint_validate(group, &Px, &Py)) < MP_YES) {
5235697Smcpowers 	if (err == MP_NO) {
5245697Smcpowers 	    PORT_SetError(SEC_ERROR_BAD_KEY);
5255697Smcpowers 	    rv = SECFailure;
5265697Smcpowers 	    err = MP_OKAY;  /* don't change the error code */
5275697Smcpowers 	}
5285697Smcpowers 	goto cleanup;
5295697Smcpowers     }
5305697Smcpowers 
5315697Smcpowers     rv = SECSuccess;
5325697Smcpowers 
5335697Smcpowers cleanup:
5345697Smcpowers     ECGroup_free(group);
5355697Smcpowers     mp_clear(&Px);
5365697Smcpowers     mp_clear(&Py);
5375697Smcpowers     if (err) {
5385697Smcpowers 	MP_TO_SEC_ERROR(err);
5395697Smcpowers 	rv = SECFailure;
5405697Smcpowers     }
5415697Smcpowers     return rv;
5425697Smcpowers }
5435697Smcpowers 
5445697Smcpowers /*
5455697Smcpowers ** Performs an ECDH key derivation by computing the scalar point
5465697Smcpowers ** multiplication of privateValue and publicValue (with or without the
5475697Smcpowers ** cofactor) and returns the x-coordinate of the resulting elliptic
5485697Smcpowers ** curve point in derived secret.  If successful, derivedSecret->data
5495697Smcpowers ** is set to the address of the newly allocated buffer containing the
5505697Smcpowers ** derived secret, and derivedSecret->len is the size of the secret
5515697Smcpowers ** produced. It is the caller's responsibility to free the allocated
5525697Smcpowers ** buffer containing the derived secret.
5535697Smcpowers */
5545697Smcpowers SECStatus
ECDH_Derive(SECItem * publicValue,ECParams * ecParams,SECItem * privateValue,PRBool withCofactor,SECItem * derivedSecret,int kmflag)5555697Smcpowers ECDH_Derive(SECItem  *publicValue,
5565697Smcpowers             ECParams *ecParams,
5575697Smcpowers             SECItem  *privateValue,
5585697Smcpowers             PRBool    withCofactor,
5595697Smcpowers             SECItem  *derivedSecret,
5605697Smcpowers 	    int kmflag)
5615697Smcpowers {
5625697Smcpowers     SECStatus rv = SECFailure;
5635697Smcpowers     unsigned int len = 0;
5645697Smcpowers     SECItem pointQ = {siBuffer, NULL, 0};
5655697Smcpowers     mp_int k; /* to hold the private value */
5665697Smcpowers     mp_int cofactor;
5675697Smcpowers     mp_err err = MP_OKAY;
5685697Smcpowers #if EC_DEBUG
5695697Smcpowers     int i;
5705697Smcpowers #endif
5715697Smcpowers 
5725697Smcpowers     if (!publicValue || !ecParams || !privateValue ||
5735697Smcpowers 	!derivedSecret) {
5745697Smcpowers 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
5755697Smcpowers 	return SECFailure;
5765697Smcpowers     }
5775697Smcpowers 
5785697Smcpowers     memset(derivedSecret, 0, sizeof *derivedSecret);
5795697Smcpowers     len = (ecParams->fieldID.size + 7) >> 3;
5805697Smcpowers     pointQ.len = 2*len + 1;
5815697Smcpowers     if ((pointQ.data = PORT_Alloc(2*len + 1, kmflag)) == NULL) goto cleanup;
5825697Smcpowers 
5835697Smcpowers     MP_DIGITS(&k) = 0;
5845697Smcpowers     CHECK_MPI_OK( mp_init(&k, kmflag) );
5855697Smcpowers     CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data,
5865697Smcpowers 	                                  (mp_size) privateValue->len) );
5875697Smcpowers 
5885697Smcpowers     if (withCofactor && (ecParams->cofactor != 1)) {
5895697Smcpowers 	    /* multiply k with the cofactor */
5905697Smcpowers 	    MP_DIGITS(&cofactor) = 0;
5915697Smcpowers 	    CHECK_MPI_OK( mp_init(&cofactor, kmflag) );
5925697Smcpowers 	    mp_set(&cofactor, ecParams->cofactor);
5935697Smcpowers 	    CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) );
5945697Smcpowers     }
5955697Smcpowers 
5965697Smcpowers     /* Multiply our private key and peer's public point */
5975697Smcpowers     if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ, kmflag) != SECSuccess) ||
5985697Smcpowers 	ec_point_at_infinity(&pointQ))
5995697Smcpowers 	goto cleanup;
6005697Smcpowers 
6015697Smcpowers     /* Allocate memory for the derived secret and copy
6025697Smcpowers      * the x co-ordinate of pointQ into it.
6035697Smcpowers      */
6045697Smcpowers     SECITEM_AllocItem(NULL, derivedSecret, len, kmflag);
6055697Smcpowers     memcpy(derivedSecret->data, pointQ.data + 1, len);
6065697Smcpowers 
6075697Smcpowers     rv = SECSuccess;
6085697Smcpowers 
6095697Smcpowers #if EC_DEBUG
6105697Smcpowers     printf("derived_secret:\n");
6115697Smcpowers     for (i = 0; i < derivedSecret->len; i++)
6125697Smcpowers 	printf("%02x:", derivedSecret->data[i]);
6135697Smcpowers     printf("\n");
6145697Smcpowers #endif
6155697Smcpowers 
6165697Smcpowers cleanup:
6175697Smcpowers     mp_clear(&k);
6185697Smcpowers 
6195697Smcpowers     if (pointQ.data) {
6205697Smcpowers 	PORT_ZFree(pointQ.data, 2*len + 1);
6215697Smcpowers     }
6225697Smcpowers 
6235697Smcpowers     return rv;
6245697Smcpowers }
6255697Smcpowers 
6265697Smcpowers /* Computes the ECDSA signature (a concatenation of two values r and s)
6275697Smcpowers  * on the digest using the given key and the random value kb (used in
6285697Smcpowers  * computing s).
6295697Smcpowers  */
6305697Smcpowers SECStatus
ECDSA_SignDigestWithSeed(ECPrivateKey * key,SECItem * signature,const SECItem * digest,const unsigned char * kb,const int kblen,int kmflag)6315697Smcpowers ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
6325697Smcpowers     const SECItem *digest, const unsigned char *kb, const int kblen, int kmflag)
6335697Smcpowers {
6345697Smcpowers     SECStatus rv = SECFailure;
6355697Smcpowers     mp_int x1;
6365697Smcpowers     mp_int d, k;     /* private key, random integer */
6375697Smcpowers     mp_int r, s;     /* tuple (r, s) is the signature */
6385697Smcpowers     mp_int n;
6395697Smcpowers     mp_err err = MP_OKAY;
6405697Smcpowers     ECParams *ecParams = NULL;
6415697Smcpowers     SECItem kGpoint = { siBuffer, NULL, 0};
6425697Smcpowers     int flen = 0;    /* length in bytes of the field size */
6435697Smcpowers     unsigned olen;   /* length in bytes of the base point order */
6445697Smcpowers 
6455697Smcpowers #if EC_DEBUG
6465697Smcpowers     char mpstr[256];
6475697Smcpowers #endif
6485697Smcpowers 
6495697Smcpowers     /* Initialize MPI integers. */
6505697Smcpowers     /* must happen before the first potential call to cleanup */
6515697Smcpowers     MP_DIGITS(&x1) = 0;
6525697Smcpowers     MP_DIGITS(&d) = 0;
6535697Smcpowers     MP_DIGITS(&k) = 0;
6545697Smcpowers     MP_DIGITS(&r) = 0;
6555697Smcpowers     MP_DIGITS(&s) = 0;
6565697Smcpowers     MP_DIGITS(&n) = 0;
6575697Smcpowers 
6585697Smcpowers     /* Check args */
6595697Smcpowers     if (!key || !signature || !digest || !kb || (kblen < 0)) {
6605697Smcpowers 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
6615697Smcpowers 	goto cleanup;
6625697Smcpowers     }
6635697Smcpowers 
6645697Smcpowers     ecParams = &(key->ecParams);
6655697Smcpowers     flen = (ecParams->fieldID.size + 7) >> 3;
6665697Smcpowers     olen = ecParams->order.len;
6675697Smcpowers     if (signature->data == NULL) {
6685697Smcpowers 	/* a call to get the signature length only */
6695697Smcpowers 	goto finish;
6705697Smcpowers     }
6715697Smcpowers     if (signature->len < 2*olen) {
6725697Smcpowers 	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
6735697Smcpowers 	rv = SECBufferTooSmall;
6745697Smcpowers 	goto cleanup;
6755697Smcpowers     }
6765697Smcpowers 
6775697Smcpowers 
6785697Smcpowers     CHECK_MPI_OK( mp_init(&x1, kmflag) );
6795697Smcpowers     CHECK_MPI_OK( mp_init(&d, kmflag) );
6805697Smcpowers     CHECK_MPI_OK( mp_init(&k, kmflag) );
6815697Smcpowers     CHECK_MPI_OK( mp_init(&r, kmflag) );
6825697Smcpowers     CHECK_MPI_OK( mp_init(&s, kmflag) );
6835697Smcpowers     CHECK_MPI_OK( mp_init(&n, kmflag) );
6845697Smcpowers 
6855697Smcpowers     SECITEM_TO_MPINT( ecParams->order, &n );
6865697Smcpowers     SECITEM_TO_MPINT( key->privateValue, &d );
6875697Smcpowers     CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
6885697Smcpowers     /* Make sure k is in the interval [1, n-1] */
6895697Smcpowers     if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
6905697Smcpowers #if EC_DEBUG
6915697Smcpowers         printf("k is outside [1, n-1]\n");
6925697Smcpowers         mp_tohex(&k, mpstr);
6935697Smcpowers 	printf("k : %s \n", mpstr);
6945697Smcpowers         mp_tohex(&n, mpstr);
6955697Smcpowers 	printf("n : %s \n", mpstr);
6965697Smcpowers #endif
6975697Smcpowers 	PORT_SetError(SEC_ERROR_NEED_RANDOM);
6985697Smcpowers 	goto cleanup;
6995697Smcpowers     }
7005697Smcpowers 
7015697Smcpowers     /*
7025697Smcpowers     ** ANSI X9.62, Section 5.3.2, Step 2
7035697Smcpowers     **
7045697Smcpowers     ** Compute kG
7055697Smcpowers     */
7065697Smcpowers     kGpoint.len = 2*flen + 1;
7075697Smcpowers     kGpoint.data = PORT_Alloc(2*flen + 1, kmflag);
7085697Smcpowers     if ((kGpoint.data == NULL) ||
7095697Smcpowers 	(ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag)
7105697Smcpowers 	    != SECSuccess))
7115697Smcpowers 	goto cleanup;
7125697Smcpowers 
7135697Smcpowers     /*
7145697Smcpowers     ** ANSI X9.62, Section 5.3.3, Step 1
7155697Smcpowers     **
7165697Smcpowers     ** Extract the x co-ordinate of kG into x1
7175697Smcpowers     */
7185697Smcpowers     CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1,
7195697Smcpowers 	                                  (mp_size) flen) );
7205697Smcpowers 
7215697Smcpowers     /*
7225697Smcpowers     ** ANSI X9.62, Section 5.3.3, Step 2
7235697Smcpowers     **
7245697Smcpowers     ** r = x1 mod n  NOTE: n is the order of the curve
7255697Smcpowers     */
7265697Smcpowers     CHECK_MPI_OK( mp_mod(&x1, &n, &r) );
7275697Smcpowers 
7285697Smcpowers     /*
7295697Smcpowers     ** ANSI X9.62, Section 5.3.3, Step 3
7305697Smcpowers     **
7315697Smcpowers     ** verify r != 0
7325697Smcpowers     */
7335697Smcpowers     if (mp_cmp_z(&r) == 0) {
7345697Smcpowers 	PORT_SetError(SEC_ERROR_NEED_RANDOM);
7355697Smcpowers 	goto cleanup;
7365697Smcpowers     }
7375697Smcpowers 
7385697Smcpowers     /*
7395697Smcpowers     ** ANSI X9.62, Section 5.3.3, Step 4
7405697Smcpowers     **
7415697Smcpowers     ** s = (k**-1 * (HASH(M) + d*r)) mod n
7425697Smcpowers     */
7435697Smcpowers     SECITEM_TO_MPINT(*digest, &s);        /* s = HASH(M)     */
7445697Smcpowers 
7455697Smcpowers     /* In the definition of EC signing, digests are truncated
7465697Smcpowers      * to the length of n in bits.
7475697Smcpowers      * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
7485697Smcpowers     if (digest->len*8 > ecParams->fieldID.size) {
7495697Smcpowers 	mpl_rsh(&s,&s,digest->len*8 - ecParams->fieldID.size);
7505697Smcpowers     }
7515697Smcpowers 
7525697Smcpowers #if EC_DEBUG
7535697Smcpowers     mp_todecimal(&n, mpstr);
7545697Smcpowers     printf("n : %s (dec)\n", mpstr);
7555697Smcpowers     mp_todecimal(&d, mpstr);
7565697Smcpowers     printf("d : %s (dec)\n", mpstr);
7575697Smcpowers     mp_tohex(&x1, mpstr);
7585697Smcpowers     printf("x1: %s\n", mpstr);
7595697Smcpowers     mp_todecimal(&s, mpstr);
7605697Smcpowers     printf("digest: %s (decimal)\n", mpstr);
7615697Smcpowers     mp_todecimal(&r, mpstr);
7625697Smcpowers     printf("r : %s (dec)\n", mpstr);
7635697Smcpowers     mp_tohex(&r, mpstr);
7645697Smcpowers     printf("r : %s\n", mpstr);
7655697Smcpowers #endif
7665697Smcpowers 
7675697Smcpowers     CHECK_MPI_OK( mp_invmod(&k, &n, &k) );      /* k = k**-1 mod n */
7685697Smcpowers     CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) );  /* d = d * r mod n */
7695697Smcpowers     CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) );  /* s = s + d mod n */
7705697Smcpowers     CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) );  /* s = s * k mod n */
7715697Smcpowers 
7725697Smcpowers #if EC_DEBUG
7735697Smcpowers     mp_todecimal(&s, mpstr);
7745697Smcpowers     printf("s : %s (dec)\n", mpstr);
7755697Smcpowers     mp_tohex(&s, mpstr);
7765697Smcpowers     printf("s : %s\n", mpstr);
7775697Smcpowers #endif
7785697Smcpowers 
7795697Smcpowers     /*
7805697Smcpowers     ** ANSI X9.62, Section 5.3.3, Step 5
7815697Smcpowers     **
7825697Smcpowers     ** verify s != 0
7835697Smcpowers     */
7845697Smcpowers     if (mp_cmp_z(&s) == 0) {
7855697Smcpowers 	PORT_SetError(SEC_ERROR_NEED_RANDOM);
7865697Smcpowers 	goto cleanup;
7875697Smcpowers     }
7885697Smcpowers 
7895697Smcpowers    /*
7905697Smcpowers     **
7915697Smcpowers     ** Signature is tuple (r, s)
7925697Smcpowers     */
7935697Smcpowers     CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) );
7945697Smcpowers     CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) );
7955697Smcpowers finish:
7965697Smcpowers     signature->len = 2*olen;
7975697Smcpowers 
7985697Smcpowers     rv = SECSuccess;
7995697Smcpowers     err = MP_OKAY;
8005697Smcpowers cleanup:
8015697Smcpowers     mp_clear(&x1);
8025697Smcpowers     mp_clear(&d);
8035697Smcpowers     mp_clear(&k);
8045697Smcpowers     mp_clear(&r);
8055697Smcpowers     mp_clear(&s);
8065697Smcpowers     mp_clear(&n);
8075697Smcpowers 
8085697Smcpowers     if (kGpoint.data) {
8095697Smcpowers 	PORT_ZFree(kGpoint.data, 2*flen + 1);
8105697Smcpowers     }
8115697Smcpowers 
8125697Smcpowers     if (err) {
8135697Smcpowers 	MP_TO_SEC_ERROR(err);
8145697Smcpowers 	rv = SECFailure;
8155697Smcpowers     }
8165697Smcpowers 
8175697Smcpowers #if EC_DEBUG
8185697Smcpowers     printf("ECDSA signing with seed %s\n",
8195697Smcpowers 	(rv == SECSuccess) ? "succeeded" : "failed");
8205697Smcpowers #endif
8215697Smcpowers 
8225697Smcpowers    return rv;
8235697Smcpowers }
8245697Smcpowers 
8255697Smcpowers /*
8265697Smcpowers ** Computes the ECDSA signature on the digest using the given key
8275697Smcpowers ** and a random seed.
8285697Smcpowers */
8295697Smcpowers SECStatus
ECDSA_SignDigest(ECPrivateKey * key,SECItem * signature,const SECItem * digest,int kmflag)8305697Smcpowers ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest,
8315697Smcpowers     int kmflag)
8325697Smcpowers {
8335697Smcpowers     SECStatus rv = SECFailure;
8345697Smcpowers     int len;
8355697Smcpowers     unsigned char *kBytes= NULL;
8365697Smcpowers 
8375697Smcpowers     if (!key) {
8385697Smcpowers 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
8395697Smcpowers 	return SECFailure;
8405697Smcpowers     }
8415697Smcpowers 
8425697Smcpowers     /* Generate random value k */
8435697Smcpowers     len = key->ecParams.order.len;
8445697Smcpowers     kBytes = ec_GenerateRandomPrivateKey(key->ecParams.order.data, len,
8455697Smcpowers 	kmflag);
8465697Smcpowers     if (kBytes == NULL) goto cleanup;
8475697Smcpowers 
8485697Smcpowers     /* Generate ECDSA signature with the specified k value */
8495697Smcpowers     rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len, kmflag);
8505697Smcpowers 
8515697Smcpowers cleanup:
8525697Smcpowers     if (kBytes) {
8535697Smcpowers 	PORT_ZFree(kBytes, len * 2);
8545697Smcpowers     }
8555697Smcpowers 
8565697Smcpowers #if EC_DEBUG
8575697Smcpowers     printf("ECDSA signing %s\n",
8585697Smcpowers 	(rv == SECSuccess) ? "succeeded" : "failed");
8595697Smcpowers #endif
8605697Smcpowers 
8615697Smcpowers     return rv;
8625697Smcpowers }
8635697Smcpowers 
8645697Smcpowers /*
8655697Smcpowers ** Checks the signature on the given digest using the key provided.
8665697Smcpowers */
8675697Smcpowers SECStatus
ECDSA_VerifyDigest(ECPublicKey * key,const SECItem * signature,const SECItem * digest,int kmflag)8685697Smcpowers ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
8695697Smcpowers                  const SECItem *digest, int kmflag)
8705697Smcpowers {
8715697Smcpowers     SECStatus rv = SECFailure;
8725697Smcpowers     mp_int r_, s_;           /* tuple (r', s') is received signature) */
8735697Smcpowers     mp_int c, u1, u2, v;     /* intermediate values used in verification */
8745697Smcpowers     mp_int x1;
8755697Smcpowers     mp_int n;
8765697Smcpowers     mp_err err = MP_OKAY;
8775697Smcpowers     ECParams *ecParams = NULL;
8785697Smcpowers     SECItem pointC = { siBuffer, NULL, 0 };
8795697Smcpowers     int slen;       /* length in bytes of a half signature (r or s) */
8805697Smcpowers     int flen;       /* length in bytes of the field size */
8815697Smcpowers     unsigned olen;  /* length in bytes of the base point order */
8825697Smcpowers 
8835697Smcpowers #if EC_DEBUG
8845697Smcpowers     char mpstr[256];
8855697Smcpowers     printf("ECDSA verification called\n");
8865697Smcpowers #endif
8875697Smcpowers 
8885697Smcpowers     /* Initialize MPI integers. */
8895697Smcpowers     /* must happen before the first potential call to cleanup */
8905697Smcpowers     MP_DIGITS(&r_) = 0;
8915697Smcpowers     MP_DIGITS(&s_) = 0;
8925697Smcpowers     MP_DIGITS(&c) = 0;
8935697Smcpowers     MP_DIGITS(&u1) = 0;
8945697Smcpowers     MP_DIGITS(&u2) = 0;
8955697Smcpowers     MP_DIGITS(&x1) = 0;
8965697Smcpowers     MP_DIGITS(&v)  = 0;
8975697Smcpowers     MP_DIGITS(&n)  = 0;
8985697Smcpowers 
8995697Smcpowers     /* Check args */
9005697Smcpowers     if (!key || !signature || !digest) {
9015697Smcpowers 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
9025697Smcpowers 	goto cleanup;
9035697Smcpowers     }
9045697Smcpowers 
9055697Smcpowers     ecParams = &(key->ecParams);
9065697Smcpowers     flen = (ecParams->fieldID.size + 7) >> 3;
9075697Smcpowers     olen = ecParams->order.len;
9085697Smcpowers     if (signature->len == 0 || signature->len%2 != 0 ||
9095697Smcpowers 	signature->len > 2*olen) {
9105697Smcpowers 	PORT_SetError(SEC_ERROR_INPUT_LEN);
9115697Smcpowers 	goto cleanup;
9125697Smcpowers     }
9135697Smcpowers     slen = signature->len/2;
9145697Smcpowers 
9155697Smcpowers     SECITEM_AllocItem(NULL, &pointC, 2*flen + 1, kmflag);
9165697Smcpowers     if (pointC.data == NULL)
9175697Smcpowers 	goto cleanup;
9185697Smcpowers 
9195697Smcpowers     CHECK_MPI_OK( mp_init(&r_, kmflag) );
9205697Smcpowers     CHECK_MPI_OK( mp_init(&s_, kmflag) );
9215697Smcpowers     CHECK_MPI_OK( mp_init(&c, kmflag)  );
9225697Smcpowers     CHECK_MPI_OK( mp_init(&u1, kmflag) );
9235697Smcpowers     CHECK_MPI_OK( mp_init(&u2, kmflag) );
9245697Smcpowers     CHECK_MPI_OK( mp_init(&x1, kmflag)  );
9255697Smcpowers     CHECK_MPI_OK( mp_init(&v, kmflag)  );
9265697Smcpowers     CHECK_MPI_OK( mp_init(&n, kmflag)  );
9275697Smcpowers 
9285697Smcpowers     /*
9295697Smcpowers     ** Convert received signature (r', s') into MPI integers.
9305697Smcpowers     */
9315697Smcpowers     CHECK_MPI_OK( mp_read_unsigned_octets(&r_, signature->data, slen) );
9325697Smcpowers     CHECK_MPI_OK( mp_read_unsigned_octets(&s_, signature->data + slen, slen) );
9335697Smcpowers 
9345697Smcpowers     /*
9355697Smcpowers     ** ANSI X9.62, Section 5.4.2, Steps 1 and 2
9365697Smcpowers     **
9375697Smcpowers     ** Verify that 0 < r' < n and 0 < s' < n
9385697Smcpowers     */
9395697Smcpowers     SECITEM_TO_MPINT(ecParams->order, &n);
9405697Smcpowers     if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
9415697Smcpowers         mp_cmp(&r_, &n) >= 0 || mp_cmp(&s_, &n) >= 0) {
9425697Smcpowers 	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
9435697Smcpowers 	goto cleanup; /* will return rv == SECFailure */
9445697Smcpowers     }
9455697Smcpowers 
9465697Smcpowers     /*
9475697Smcpowers     ** ANSI X9.62, Section 5.4.2, Step 3
9485697Smcpowers     **
9495697Smcpowers     ** c = (s')**-1 mod n
9505697Smcpowers     */
9515697Smcpowers     CHECK_MPI_OK( mp_invmod(&s_, &n, &c) );      /* c = (s')**-1 mod n */
9525697Smcpowers 
9535697Smcpowers     /*
9545697Smcpowers     ** ANSI X9.62, Section 5.4.2, Step 4
9555697Smcpowers     **
9565697Smcpowers     ** u1 = ((HASH(M')) * c) mod n
9575697Smcpowers     */
9585697Smcpowers     SECITEM_TO_MPINT(*digest, &u1);                  /* u1 = HASH(M)     */
9595697Smcpowers 
9605697Smcpowers     /* In the definition of EC signing, digests are truncated
9615697Smcpowers      * to the length of n in bits.
9625697Smcpowers      * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
9635697Smcpowers     if (digest->len*8 > ecParams->fieldID.size) {  /* u1 = HASH(M')     */
9645697Smcpowers 	mpl_rsh(&u1,&u1,digest->len*8- ecParams->fieldID.size);
9655697Smcpowers     }
9665697Smcpowers 
9675697Smcpowers #if EC_DEBUG
9685697Smcpowers     mp_todecimal(&r_, mpstr);
9695697Smcpowers     printf("r_: %s (dec)\n", mpstr);
9705697Smcpowers     mp_todecimal(&s_, mpstr);
9715697Smcpowers     printf("s_: %s (dec)\n", mpstr);
9725697Smcpowers     mp_todecimal(&c, mpstr);
9735697Smcpowers     printf("c : %s (dec)\n", mpstr);
9745697Smcpowers     mp_todecimal(&u1, mpstr);
9755697Smcpowers     printf("digest: %s (dec)\n", mpstr);
9765697Smcpowers #endif
9775697Smcpowers 
9785697Smcpowers     CHECK_MPI_OK( mp_mulmod(&u1, &c, &n, &u1) );  /* u1 = u1 * c mod n */
9795697Smcpowers 
9805697Smcpowers     /*
9815697Smcpowers     ** ANSI X9.62, Section 5.4.2, Step 4
9825697Smcpowers     **
9835697Smcpowers     ** u2 = ((r') * c) mod n
9845697Smcpowers     */
9855697Smcpowers     CHECK_MPI_OK( mp_mulmod(&r_, &c, &n, &u2) );
9865697Smcpowers 
9875697Smcpowers     /*
9885697Smcpowers     ** ANSI X9.62, Section 5.4.3, Step 1
9895697Smcpowers     **
9905697Smcpowers     ** Compute u1*G + u2*Q
9915697Smcpowers     ** Here, A = u1.G     B = u2.Q    and   C = A + B
9925697Smcpowers     ** If the result, C, is the point at infinity, reject the signature
9935697Smcpowers     */
9945697Smcpowers     if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC, kmflag)
9955697Smcpowers 	!= SECSuccess) {
9965697Smcpowers 	rv = SECFailure;
9975697Smcpowers 	goto cleanup;
9985697Smcpowers     }
9995697Smcpowers     if (ec_point_at_infinity(&pointC)) {
10005697Smcpowers 	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
10015697Smcpowers 	rv = SECFailure;
10025697Smcpowers 	goto cleanup;
10035697Smcpowers     }
10045697Smcpowers 
10055697Smcpowers     CHECK_MPI_OK( mp_read_unsigned_octets(&x1, pointC.data + 1, flen) );
10065697Smcpowers 
10075697Smcpowers     /*
10085697Smcpowers     ** ANSI X9.62, Section 5.4.4, Step 2
10095697Smcpowers     **
10105697Smcpowers     ** v = x1 mod n
10115697Smcpowers     */
10125697Smcpowers     CHECK_MPI_OK( mp_mod(&x1, &n, &v) );
10135697Smcpowers 
10145697Smcpowers #if EC_DEBUG
10155697Smcpowers     mp_todecimal(&r_, mpstr);
10165697Smcpowers     printf("r_: %s (dec)\n", mpstr);
10175697Smcpowers     mp_todecimal(&v, mpstr);
10185697Smcpowers     printf("v : %s (dec)\n", mpstr);
10195697Smcpowers #endif
10205697Smcpowers 
10215697Smcpowers     /*
10225697Smcpowers     ** ANSI X9.62, Section 5.4.4, Step 3
10235697Smcpowers     **
10245697Smcpowers     ** Verification:  v == r'
10255697Smcpowers     */
10265697Smcpowers     if (mp_cmp(&v, &r_)) {
10275697Smcpowers 	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
10285697Smcpowers 	rv = SECFailure; /* Signature failed to verify. */
10295697Smcpowers     } else {
10305697Smcpowers 	rv = SECSuccess; /* Signature verified. */
10315697Smcpowers     }
10325697Smcpowers 
10335697Smcpowers #if EC_DEBUG
10345697Smcpowers     mp_todecimal(&u1, mpstr);
10355697Smcpowers     printf("u1: %s (dec)\n", mpstr);
10365697Smcpowers     mp_todecimal(&u2, mpstr);
10375697Smcpowers     printf("u2: %s (dec)\n", mpstr);
10385697Smcpowers     mp_tohex(&x1, mpstr);
10395697Smcpowers     printf("x1: %s\n", mpstr);
10405697Smcpowers     mp_todecimal(&v, mpstr);
10415697Smcpowers     printf("v : %s (dec)\n", mpstr);
10425697Smcpowers #endif
10435697Smcpowers 
10445697Smcpowers cleanup:
10455697Smcpowers     mp_clear(&r_);
10465697Smcpowers     mp_clear(&s_);
10475697Smcpowers     mp_clear(&c);
10485697Smcpowers     mp_clear(&u1);
10495697Smcpowers     mp_clear(&u2);
10505697Smcpowers     mp_clear(&x1);
10515697Smcpowers     mp_clear(&v);
10525697Smcpowers     mp_clear(&n);
10535697Smcpowers 
10545697Smcpowers     if (pointC.data) SECITEM_FreeItem(&pointC, PR_FALSE);
10555697Smcpowers     if (err) {
10565697Smcpowers 	MP_TO_SEC_ERROR(err);
10575697Smcpowers 	rv = SECFailure;
10585697Smcpowers     }
10595697Smcpowers 
10605697Smcpowers #if EC_DEBUG
10615697Smcpowers     printf("ECDSA verification %s\n",
10625697Smcpowers 	(rv == SECSuccess) ? "succeeded" : "failed");
10635697Smcpowers #endif
10645697Smcpowers 
10655697Smcpowers     return rv;
10665697Smcpowers }
10675697Smcpowers 
1068*10500SHai-May.Chao@Sun.COM /*
1069*10500SHai-May.Chao@Sun.COM  * Copy all of the fields from srcParams into dstParams
1070*10500SHai-May.Chao@Sun.COM  */
1071*10500SHai-May.Chao@Sun.COM SECStatus
EC_CopyParams(PRArenaPool * arena,ECParams * dstParams,const ECParams * srcParams)1072*10500SHai-May.Chao@Sun.COM EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
1073*10500SHai-May.Chao@Sun.COM 	      const ECParams *srcParams)
1074*10500SHai-May.Chao@Sun.COM {
1075*10500SHai-May.Chao@Sun.COM     SECStatus rv = SECFailure;
1076*10500SHai-May.Chao@Sun.COM 
1077*10500SHai-May.Chao@Sun.COM     dstParams->arena = arena;
1078*10500SHai-May.Chao@Sun.COM     dstParams->type = srcParams->type;
1079*10500SHai-May.Chao@Sun.COM     dstParams->fieldID.size = srcParams->fieldID.size;
1080*10500SHai-May.Chao@Sun.COM     dstParams->fieldID.type = srcParams->fieldID.type;
1081*10500SHai-May.Chao@Sun.COM     if (srcParams->fieldID.type == ec_field_GFp) {
1082*10500SHai-May.Chao@Sun.COM 	CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime,
1083*10500SHai-May.Chao@Sun.COM 	    &srcParams->fieldID.u.prime, 0));
1084*10500SHai-May.Chao@Sun.COM     } else {
1085*10500SHai-May.Chao@Sun.COM 	CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.poly,
1086*10500SHai-May.Chao@Sun.COM 	    &srcParams->fieldID.u.poly, 0));
1087*10500SHai-May.Chao@Sun.COM     }
1088*10500SHai-May.Chao@Sun.COM     dstParams->fieldID.k1 = srcParams->fieldID.k1;
1089*10500SHai-May.Chao@Sun.COM     dstParams->fieldID.k2 = srcParams->fieldID.k2;
1090*10500SHai-May.Chao@Sun.COM     dstParams->fieldID.k3 = srcParams->fieldID.k3;
1091*10500SHai-May.Chao@Sun.COM     CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.a,
1092*10500SHai-May.Chao@Sun.COM 	&srcParams->curve.a, 0));
1093*10500SHai-May.Chao@Sun.COM     CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.b,
1094*10500SHai-May.Chao@Sun.COM 	&srcParams->curve.b, 0));
1095*10500SHai-May.Chao@Sun.COM     CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.seed,
1096*10500SHai-May.Chao@Sun.COM 	&srcParams->curve.seed, 0));
1097*10500SHai-May.Chao@Sun.COM     CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->base,
1098*10500SHai-May.Chao@Sun.COM 	&srcParams->base, 0));
1099*10500SHai-May.Chao@Sun.COM     CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->order,
1100*10500SHai-May.Chao@Sun.COM 	&srcParams->order, 0));
1101*10500SHai-May.Chao@Sun.COM     CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->DEREncoding,
1102*10500SHai-May.Chao@Sun.COM 	&srcParams->DEREncoding, 0));
1103*10500SHai-May.Chao@Sun.COM 	dstParams->name = srcParams->name;
1104*10500SHai-May.Chao@Sun.COM     CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curveOID,
1105*10500SHai-May.Chao@Sun.COM  	&srcParams->curveOID, 0));
1106*10500SHai-May.Chao@Sun.COM     dstParams->cofactor = srcParams->cofactor;
1107*10500SHai-May.Chao@Sun.COM 
1108*10500SHai-May.Chao@Sun.COM     return SECSuccess;
1109*10500SHai-May.Chao@Sun.COM 
1110*10500SHai-May.Chao@Sun.COM cleanup:
1111*10500SHai-May.Chao@Sun.COM     return SECFailure;
1112*10500SHai-May.Chao@Sun.COM }
1113