static feeReturn feeGenPrivate(pubKeyInst *pkinst,
	const unsigned char *passwd,
	unsigned passwdLen,
	char hashPasswd)
{
	unsigned 		privLen;			// desired size of pkinst->privData
	feeHash 		*hash = NULL;		// a malloc'd array
	unsigned		digestLen;			// size of MD5 digest
	unsigned 		dataSize;			// min(privLen, passwdLen)
	unsigned		numDigests = 0;
	unsigned		i;
	unsigned char	*cp;
	unsigned		toMove;				// for this digest
	unsigned		moved;				// total digested
	unsigned char	*digest = NULL;
	unsigned char	*privData = NULL;	// temp, before modg(curveOrder)
	giant			corder;				// lesser of two curve orders
	
	/*
	 * generate privData which is just larger than the smaller
	 * curve order.
	 * We'll take the result mod the curve order when we're done.
	 * Note we do *not* have to free corder - it's a pointer to a giant
	 * in pkinst->cp.
	 */
	corder = lesserX1Order(pkinst->cp);
	CKASSERT(!isZero(corder));
	privLen = (bitlen(corder) / 8) + 1;

	if(!hashPasswd) {
		/* 
		 * Caller trusts the incoming entropy. Verify it's big enough and proceed. 
		 */
		if(passwdLen < privLen) {
			return FR_ShortPrivData;
		}
		privLen = passwdLen;
		privData = (unsigned char *)passwd;
		goto finishUp;
	}
	if(passwdLen < 2) {
		return FR_IllegalArg;
	}


	/*
	 * Calculate how many MD5 digests we'll generate.
	 */
	if(privLen > passwdLen) {
		dataSize = passwdLen;
	}
	else {
		dataSize = privLen;
	}
	digestLen = feeHashDigestLen();
	numDigests = (dataSize + digestLen - 1) / digestLen;

	hash = (void**) fmalloc(numDigests * sizeof(feeHash));
	for(i=0; i<numDigests; i++) {
		hash[i] = feeHashAlloc();
	}

	/*
	 * fill digests with passwd data, digestLen (or resid length)
	 * at a time. If (passwdLen > privLen), last digest will hash all
	 * remaining passwd data.
	 */
	cp = (unsigned char *)passwd;
	moved = 0;
	for(i=0; i<numDigests; i++) {
		if(i == (numDigests - 1)) {		    // last digest
		    toMove = passwdLen - moved;
		}
		else {
		    toMove = digestLen;
		}
		feeHashAddData(hash[i], cp, toMove);
		cp += toMove;
		moved += toMove;
	}

	/*
	 * copy digests to privData, up to privLen bytes. Pad with
	 * additional copies of digests if necessary.
	 */
	privData = (unsigned char*) fmalloc(privLen);
	cp = privData;
	moved = 0;
	i = 0;			// digest number
	for(moved=0; moved<privLen; ) {
		if((moved + digestLen) > privLen) {
		   toMove = privLen - moved;
		}
		else {
		   toMove = digestLen;
		}
		digest = feeHashDigest(hash[i++]);
		bcopy(digest, cp, toMove);
		cp += toMove;
		moved += toMove;
		if(i == numDigests) {
		    i = 0;		// wrap to 0, start padding
		}
	}
	
finishUp:
	/*
	 * Convert to giant, justify result to within [2, lesserX1Order]
	 */
	pkinst->privGiant = giant_with_data(privData, privLen);

	#if	FEE_DEBUG
	if(isZero(pkinst->privGiant)) {
		printf("feeGenPrivate: privData = 0!\n");
	}
	#endif	// FEE_DEBUG

	lesserX1OrderJustify(pkinst->privGiant, pkinst->cp);
	if(hashPasswd) {
		memset(privData, 0, privLen);
		ffree(privData);
		for(i=0; i<numDigests; i++) {
			feeHashFree(hash[i]);
		}
		ffree(hash);
	}
	return FR_Success;
}
Пример #2
0
key new_public_with_key(key old_key, curveParams *cp)
{
	key result;

	result = new_public(cp, old_key->twist);
	CKASSERT((old_key->x != NULL) && (old_key->y != NULL));
	CKASSERT((result->x != NULL) && (result->y != NULL));
	gtog(old_key->x, result->x);
	gtog(old_key->y, result->y);
	return result;
}
Пример #3
0
/*
 * Specify private data for key created by new_public().
 * Generates k->x.
 */
void set_priv_key_giant(key k, giant privGiant)
{
	curveParams *cp = k->cp;

	/* elliptiy multiply of initial public point times private key */
	#if CRYPTKIT_ELL_PROJ_ENABLE
	if((k->twist == CURVE_PLUS) && (cp->curveType == FCT_Weierstrass)) {
		/* projective */

		pointProj pt1 = newPointProj(cp->maxDigits);

		CKASSERT((cp->y1Plus != NULL) && (!isZero(cp->y1Plus)));
		CKASSERT(k->y != NULL);

		/* pt1 := {x1Plus, y1Plus, 1} */
		gtog(cp->x1Plus, pt1->x);
		gtog(cp->y1Plus, pt1->y);
		int_to_giant(1, pt1->z);

		/* pt1 := pt1 * privateKey */
		ellMulProjSimple(pt1, privGiant, cp);

		/* result back to {k->x, k->y} */
		gtog(pt1->x, k->x);
		gtog(pt1->y, k->y);
		freePointProj(pt1);	// FIXME - clear the giants
	}
	else {
	#else
	{
	#endif	/* CRYPTKIT_ELL_PROJ_ENABLE */
		/* FEE */
		if(k->twist == CURVE_PLUS) {
			gtog(cp->x1Plus, k->x);
		}
		else {
			gtog(cp->x1Minus, k->x);
		}
		elliptic_simple(k->x, privGiant, k->cp);
	}
}

int key_equal(key one, key two) {
    if (keys_inconsistent(one, two)) return 0;
    return !gcompg(one->x, two->x);
}

static void make_base(curveParams *par, giant result)
/* Jams result with 2^q-k. */
{
    gtog(par->basePrime, result);
}
Пример #4
0
/*
 * g := g mod x1OrderPlus. Result may be zero.
 */
void x1OrderPlusMod(giant g, curveParams *cp)
{
	CKASSERT(!isZero(cp->x1OrderPlus));

	/*
	 * Calculate reciprocal if we don't have it
	 */
	calcX1OrderPlusRecip(cp);
	modg_via_recip(cp->x1OrderPlus, cp->x1OrderPlusRecip, g);
}
Пример #5
0
void x1OrderPlusJustify(giant g, curveParams *cp)
{
	CKASSERT(!isZero(cp->x1OrderPlus));

	/*
	 * Calculate reciprocal if we don't have it
	 */
	calcX1OrderPlusRecip(cp);
	curveOrderJustifyWithRecip(g, cp->x1OrderPlus, cp->x1OrderPlusRecip);
}
Пример #6
0
/* destgiant becomes equal to srcgiant */
void gtog(giant srcgiant, giant destgiant) {

    int numbytes;

    CKASSERT(srcgiant != NULL);
    numbytes =  abs(srcgiant->sign) * GIANT_BYTES_PER_DIGIT;
    if (destgiant->capacity < abs(srcgiant->sign))
	CKRaise("gtog overflow!!");
    memcpy((char *)destgiant->n, (char *)srcgiant->n, numbytes);
    destgiant->sign = srcgiant->sign;
}
Пример #7
0
/*
 * Simple projective multiply.
 *
 * pt := pt * k, result normalized.
 */
void ellMulProjSimple(pointProj pt0, giant k, curveParams *cp)
{
	pointProjStruct pt1;	// local, giants borrowed

	CKASSERT(isone(pt0->z));
	CKASSERT(cp->curveType == FCT_Weierstrass);

	/* ellMulProj assumes constant pt0, can't pass as src and dst */
	pt1.x = borrowGiant(cp->maxDigits);
	pt1.y = borrowGiant(cp->maxDigits);
	pt1.z = borrowGiant(cp->maxDigits);
	ellMulProj(pt0, &pt1, k, cp);
	normalizeProj(&pt1, cp);
	CKASSERT(isone(pt1.z));

	ptopProj(&pt1, pt0);
	returnGiant(pt1.x);
	returnGiant(pt1.y);
	returnGiant(pt1.z);
}
Пример #8
0
/*
 * This version is not normally used; it's for when the reciprocal of
 * curveOrder is not known and won't be used again.
 */
void curveOrderJustify(giant g, giant curveOrder)
{
    giant recip;

    CKASSERT(!isZero(curveOrder));

    recip = borrowGiant(2 * abs(g->sign));
    make_recip(curveOrder, recip);
    curveOrderJustifyWithRecip(g, curveOrder, recip);
    returnGiant(recip);
}
Пример #9
0
void make_base_prim(curveParams *cp)
/* Jams cp->basePrime with 2^q-k. Assumes valid maxDigits, q, k. */
{
    giant tmp = borrowGiant(cp->maxDigits);

    CKASSERT(cp->primeType != FPT_General);
    int_to_giant(1, cp->basePrime);
    gshiftleft((int)cp->q, cp->basePrime);
    int_to_giant(cp->k, tmp);
    subg(tmp, cp->basePrime);
    returnGiant(tmp);
}
Пример #10
0
void ellMulProj(pointProj pt0, pointProj pt1, giant k, curveParams *cp)
/* General elliptic multiplication;
   pt1 := k*pt0 on the curve,
   with k an arbitrary integer.
 */
{
	giant x = pt0->x, y = pt0->y, z = pt0->z,
		  xx = pt1->x, yy = pt1->y, zz = pt1->z;
	int ksign, hlen, klen, b, hb, kb;
    	giant t0;

	CKASSERT(cp->curveType == FCT_Weierstrass);
	if(isZero(k)) {
		int_to_giant(1, xx);
		int_to_giant(1, yy);
		int_to_giant(0, zz);
		return;
	}
	t0 = borrowGiant(cp->maxDigits);
    	ksign = k->sign;
	if(ksign < 0) negg(k);
	gtog(x,xx); gtog(y,yy); gtog(z,zz);
	gtog(k, t0); addg(t0, t0); addg(k, t0); /* t0 := 3k. */
	hlen = bitlen(t0);
	klen = bitlen(k);
	for(b = hlen-2; b > 0; b--) {
		ellDoubleProj(pt1,cp);
		hb = bitval(t0, b);
		if(b < klen) kb = bitval(k, b); else kb = 0;
		if((hb != 0) && (kb == 0))
			ellAddProj(pt1, pt0, cp);
		else if((hb == 0) && (kb !=0))
			ellSubProj(pt1, pt0, cp);
	}
	if(ksign < 0) {
		ellNegProj(pt1, cp);
		k->sign = -k->sign;
	}
	returnGiant(t0);
}
Пример #11
0
void normalizeProj(pointProj pt, curveParams *cp)
/* Obtain actual x,y coords via normalization:
   {x,y,z} := {x/z^2, y/z^3, 1}.
 */

{	giant x = pt->x, y = pt->y, z = pt->z;
	giant t1;

	CKASSERT(cp->curveType == FCT_Weierstrass);
	if(isZero(z)) {
		int_to_giant(1,x); int_to_giant(1,y);
		return;
	}
	t1 = borrowGiant(cp->maxDigits);
	binvg_cp(cp, z);		// was binvaux(p, z);
		gtog(z, t1);
	gsquare(z); feemod(cp, z);
	mulg(z, x); feemod(cp, x);
	mulg(t1, z); mulg(z, y); feemod(cp, y);
	int_to_giant(1, z);
	returnGiant(t1);
}
Пример #12
0
/*
 * New optimzation of curveOrderJustify using known reciprocal, 11 June 1997.
 * g is set to be within [2, curveOrder-2].
 */
static void curveOrderJustifyWithRecip(giant g, giant curveOrder, giant recip)
{
    giant tmp;

    CKASSERT(!isZero(curveOrder));

    modg_via_recip(curveOrder, recip, g);	// g now in [0, curveOrder-1]

    if(isZero(g)) {
    	/*
	 * First degenerate case - (g == 0) : set g := 2
	 */
	dbgLog(("curveOrderJustify: case 1\n"));
   	int_to_giant(2, g);
	return;
    }
    if(isone(g)) {
    	/*
	 * Second case - (g == 1) : set g := 2
	 */
 	dbgLog(("curveOrderJustify: case 2\n"));
   	int_to_giant(2, g);
	return;
    }
    tmp = borrowGiant(g->capacity);
    gtog(g, tmp);
    iaddg(1, tmp);
    if(gcompg(tmp, curveOrder) == 0) {
    	/*
	 * Third degenerate case - (g == (curveOrder-1)) : set g -= 1
	 */
	dbgLog(("curveOrderJustify: case 3\n"));
	int_to_giant(1, tmp);
	subg(tmp, g);
    }
    returnGiant(tmp);
    return;
}
Пример #13
0
void findPointProj(pointProj pt, giant seed, curveParams *cp)
/* Starting with seed, finds a random (projective) point {x,y,1} on curve.
 */
{
	giant x = pt->x, y = pt->y, z = pt->z;

	CKASSERT(cp->curveType == FCT_Weierstrass);
	feemod(cp, seed);
    	while(1) {
		gtog(seed, x);
		gsquare(x); feemod(cp, x);	// x := seed^2
		addg(cp->a, x);			// x := seed^2 + a
		mulg(seed,x); 			// x := seed^3 + a*seed
		addg(cp->b, x);
		feemod(cp, x);			// x := seed^3 + a seed + b.
		/* test cubic form for having root. */
		if(sqrtmod(x, cp)) break;
		iaddg(1, seed);
	}
	gtog(x, y);
    	gtog(seed,x);
	int_to_giant(1, z);
}
Пример #14
0
feeReturn feeECDSAVerify(const unsigned char *sigData,
	size_t sigDataLen,
	const unsigned char *data,
	unsigned dataLen,
	feePubKey pubKey,
    feeSigFormat  format)
{
	/* giant integers per IEEE P1363 notation */
	giant 		h;			// s^(-1)
	giant		h1;			// f h
	giant		h2;			// c times h
	giant		littleC;		// newGiant from ECDSA_decode
	giant 		littleD;		// ditto
	giant		c;			// borrowed, full size
	giant		d;			// ditto
	giant		cPrime = NULL;		// i mod r
	pointProj	h1G = NULL;		// h1 'o' G
	pointProj	h2W = NULL;		// h2 'o' W
	key		W;			// i.e., their public key

	unsigned	version;
	feeReturn	frtn;
	curveParams	*cp = feePubKeyCurveParams(pubKey);
    unsigned    groupBytesLen = ((feePubKeyBitsize(pubKey)+7) / 8);
    int		result;

	if(cp == NULL) {
		return FR_BadPubKey;
	}

	/*
	 * First decode the byteRep string.
	 */
	frtn = ECDSA_decode(
        format,
        groupBytesLen,
        sigData,
		sigDataLen,
		&littleC,
		&littleD,
		&version);
	if(frtn) {
		return frtn;
	}

	/*
	 * littleC and littleD have capacity = abs(sign), probably
	 * not big enough....
	 */
	c = borrowGiant(cp->maxDigits);
	d = borrowGiant(cp->maxDigits);
	gtog(littleC, c);
	gtog(littleD, d);
	freeGiant(littleC);
	freeGiant(littleD);

	sigDbg(("ECDSA verify:\n"));

    /*
     * Verify that c and d are within [1,group_order-1]
     */
    if((gcompg(cp->cOrderPlus, c) != 1) || (gcompg(cp->cOrderPlus, d) != 1) ||
       isZero(c) || isZero(d))
    {
        returnGiant(c);
        returnGiant(d);
        return FR_InvalidSignature;
    }

	/*
	 * W = signer's public key
	 */
	W = feePubKeyPlusCurve(pubKey);

	/*
	 * 1) Compute h = d^(-1) (mod x1OrderPlus);
	 */
	SIGPROF_START;
	h = borrowGiant(cp->maxDigits);
	gtog(d, h);
	binvg_x1OrderPlus(cp, h);
	SIGPROF_END(vfyStep1);

	/*
	 * 2) h1 = digest as giant (skips assigning to 'f' in P1363)
	 */
	if(dataLen > (cp->maxDigits * GIANT_BYTES_PER_DIGIT)) {
	    h1 = borrowGiant(BYTES_TO_GIANT_DIGITS(dataLen));
	}
	else {
	    h1 = borrowGiant(cp->maxDigits);
	}
	deserializeGiant(data, h1, dataLen);

	/* 
	 * Certicom SEC1 states that if the digest is larger than the modulus, 
	 * use the left q bits of the digest. 
	 */
	unsigned hashBits = dataLen * 8;
	if(hashBits > cp->q) {
		gshiftright(hashBits - cp->q, h1);
	}
	
	sigLogGiant("  Wx       : ", W->x);
	sigLogGiant("  f        : ", h1);
	sigLogGiant("  c        : ", c);
	sigLogGiant("  d        : ", d);
	sigLogGiant("  s^(-1)   : ", h);

	/*
	 * 3) Compute h1 = f * h mod x1OrderPlus;
	 */
	SIGPROF_START;
	mulg(h, h1);					// h1 := f * h
	x1OrderPlusMod(h1, cp);
	SIGPROF_END(vfyStep3);

	/*
	 * 4) Compute h2 = c * h (mod x1OrderPlus);
	 */
	SIGPROF_START;
	h2 = borrowGiant(cp->maxDigits);
	gtog(c, h2);
	mulg(h, h2);					// h2 := c * h
	x1OrderPlusMod(h2, cp);
	SIGPROF_END(vfyStep4);

     	/*
	 * 5) Compute h2W = h2 'o' W  (W = theirPub)
	 */
	CKASSERT((W->y != NULL) && !isZero(W->y));
	h2W = newPointProj(cp->maxDigits);
	gtog(W->x, h2W->x);
	gtog(W->y, h2W->y);
	int_to_giant(1, h2W->z);
	ellMulProjSimple(h2W, h2, cp);

	/*
	 * 6) Compute h1G = h1 'o' G   (G = {x1Plus, y1Plus, 1} )
	 */
	CKASSERT((cp->y1Plus != NULL) && !isZero(cp->y1Plus));
	h1G = newPointProj(cp->maxDigits);
	gtog(cp->x1Plus, h1G->x);
	gtog(cp->y1Plus, h1G->y);
	int_to_giant(1,  h1G->z);
	ellMulProjSimple(h1G, h1, cp);

	/*
	 * 7) h1G := (h1 'o' G) + (h2  'o' W)
	 */
	ellAddProj(h1G, h2W, cp);

	/*
	 * 8) If elliptic sum is point at infinity, signature is bad; stop.
	 */
	if(isZero(h1G->z)) {
		dbgLog(("feeECDSAVerify: h1 * G = point at infinity\n"));
		result = 1;
		goto vfyDone;
	}
	normalizeProj(h1G, cp);

	/*
	 * 9) cPrime = x coordinate of elliptic sum, mod x1OrderPlus
	 */
	cPrime = borrowGiant(cp->maxDigits);
	gtog(h1G->x, cPrime);
	x1OrderPlusMod(cPrime, cp);

	/*
	 * 10) Good sig iff cPrime == c
	 */
	result = gcompg(c, cPrime);

vfyDone:
	if(result) {
		frtn = FR_InvalidSignature;
		#if	LOG_BAD_SIG
		printf("***yup, bad sig***\n");
		#endif	// LOG_BAD_SIG
	}
	else {
		frtn = FR_Success;
	}

	returnGiant(c);
	returnGiant(d);
	returnGiant(h);
	returnGiant(h1);
	returnGiant(h2);
	if(h1G != NULL) {
		freePointProj(h1G);
	}
	if(h2W != NULL) {
		freePointProj(h2W);
	}
	if(cPrime != NULL) {
		returnGiant(cPrime);
	}
	return frtn;
}
Пример #15
0
feeReturn feeECDSASign(
    feePubKey pubKey,
    feeSigFormat  format,             // Signature format DER 9.62 / RAW
	const unsigned char *data,   		// data to be signed
	unsigned dataLen,					// in bytes
	feeRandFcn randFcn,					// optional
	void *randRef,						// optional 
	unsigned char **sigData,			// malloc'd and RETURNED
	unsigned *sigDataLen)				// RETURNED
{
	curveParams 		*cp;

	/* giant integers per IEEE P1363 notation */

	giant 			c;		// both 1363 'c' and 'i'
						// i.e., x-coord of u's pub key
	giant 			d;
	giant 			u;		// random private key
	giant			s;		// private key as giant
	giant			f;		// data (message) as giant

	feeReturn 		frtn = FR_Success;
	feeRand 		frand;
	unsigned char 	*randBytes;
	unsigned		randBytesLen;
    unsigned        groupBytesLen;
	giant			privGiant;
	#if	ECDSA_SIGN_USE_PROJ
	pointProjStruct	pt;		// pt->x = c
	giant			pty;		// pt->y
	giant			ptz;		// pt->z
	#endif	// ECDSA_SIGN_USE_PROJ

	if(pubKey == NULL) {
		return FR_BadPubKey;
	}
	cp = feePubKeyCurveParams(pubKey);
	if(cp == NULL) {
		return FR_BadPubKey;
	}
	if(cp->curveType != FCT_Weierstrass) {
		return FR_IllegalCurve;
	}

	CKASSERT(!isZero(cp->x1OrderPlus));

	/*
	 * Private key and message to be signed as giants
	 */
	privGiant = feePubKeyPrivData(pubKey);
	if(privGiant == NULL) {
		dbgLog(("Attempt to Sign without private data\n"));
		return FR_IllegalArg;
	}
	s = borrowGiant(cp->maxDigits);
	gtog(privGiant, s);
	if(dataLen > (cp->maxDigits * GIANT_BYTES_PER_DIGIT)) {
	    f = borrowGiant(BYTES_TO_GIANT_DIGITS(dataLen));
	}
	else {
	    f = borrowGiant(cp->maxDigits);
	}
	deserializeGiant(data, f, dataLen);

	/* 
	 * Certicom SEC1 states that if the digest is larger than the modulus, 
	 * use the left q bits of the digest. 
	 */
	unsigned hashBits = dataLen * 8;
	if(hashBits > cp->q) {
		gshiftright(hashBits - cp->q, f);
	}

	sigDbg(("ECDSA sign:\n"));
	sigLogGiant("  s        : ", s);
	sigLogGiant("  f        : ", f);

	c = borrowGiant(cp->maxDigits);
	d = borrowGiant(cp->maxDigits);
	u = borrowGiant(cp->maxDigits);
	if(randFcn == NULL) {
		frand = feeRandAlloc();
	}
	else {
		frand = NULL;
	}
	
	/*
	 * Random size is just larger than base prime
	 */
	groupBytesLen = ((feePubKeyBitsize(pubKey)+7) / 8);
    randBytesLen = groupBytesLen+8;  // +8bytes (64bits)  to reduce the biais when with reduction mod prime. Per FIPS186-4 - "Using Extra Random Bits"
	randBytes = (unsigned char*) fmalloc(randBytesLen);

	#if	ECDSA_SIGN_USE_PROJ
	/* quick temp pointProj */
	pty = borrowGiant(cp->maxDigits);
	ptz = borrowGiant(cp->maxDigits);
	pt.x = c;
	pt.y = pty;
	pt.z = ptz;
	#endif	// ECDSA_SIGN_USE_PROJ

	while(1) {
		/* Repeat this loop until we have a non-zero c and d */

		/*
		 * 1) Obtain random u in [2, x1OrderPlus-2]
		 */
		SIGPROF_START;
		if(randFcn) {
			randFcn(randRef, randBytes, randBytesLen);
		}
		else {
			feeRandBytes(frand, randBytes, randBytesLen);
		}
		deserializeGiant(randBytes, u, randBytesLen);
        sigLogGiant("  raw u        : ", u);
        sigLogGiant("  order        : ", cp->x1OrderPlus);
        x1OrderPlusJustify(u, cp);
		SIGPROF_END(signStep1);
		sigLogGiant("  in range u        : ", u);

    		/*
		 * note 'o' indicates elliptic multiply, * is integer mult.
		 *
    		 * 2) Compute x coordinate, call it c, of u 'o' G
		 * 3) Reduce: c := c mod x1OrderPlus;
   		 * 4) If c == 0, goto (1);
		 */
		SIGPROF_START;
		gtog(cp->x1Plus, c);

		#if	ECDSA_SIGN_USE_PROJ

		/* projective coordinates */
		gtog(cp->y1Plus, pty);
		int_to_giant(1, ptz);
		ellMulProjSimple(&pt, u, cp);

		#else	/* ECDSA_SIGN_USE_PROJ */

		/* the FEE way */
		elliptic_simple(c, u, cp);

		#endif	/* ECDSA_SIGN_USE_PROJ */

		SIGPROF_END(signStep2);
		SIGPROF_START;
		x1OrderPlusMod(c, cp);
		SIGPROF_END(signStep34);
		if(isZero(c)) {
			dbgLog(("feeECDSASign: zero modulo (1)\n"));
			continue;
		}

		/*
		 * 5) Compute u^(-1) mod x1OrderPlus;
		 */
		SIGPROF_START;
		gtog(u, d);
		binvg_x1OrderPlus(cp, d);
		SIGPROF_END(signStep5);
		sigLogGiant("  u^(-1)   : ", d);

		/*
		 * 6) Compute signature d as:
	 	 *    d = [u^(-1) (f + s*c)] (mod x1OrderPlus)
		 */
		SIGPROF_START;
		mulg(c, s);	     	// s *= c
		x1OrderPlusMod(s, cp);
		addg(f, s);   		// s := f + (s * c)
		x1OrderPlusMod(s, cp);
		mulg(s, d);	     	// d := u^(-1) (f + (s * c))
		x1OrderPlusMod(d, cp);
		SIGPROF_END(signStep67);

		/*
		 * 7) If d = 0, goto (1);
		 */
		if(isZero(d)) {
			dbgLog(("feeECDSASign: zero modulo (2)\n"));
			continue;
		}
		sigLogGiant("  c        : ", c);
		sigLogGiant("  d        : ", d);
		break;			// normal successful exit
	}

	/*
	 * 8) signature is now the integer pair (c, d).
	 */

	/*
	 * Cook up raw data representing the signature.
	 */
	SIGPROF_START;
	ECDSA_encode(format,groupBytesLen, c, d, sigData, sigDataLen);
	SIGPROF_END(signStep8);

	if(frand != NULL) {
		feeRandFree(frand);
	}
	ffree(randBytes);
	returnGiant(u);
	returnGiant(d);
	returnGiant(c);
	returnGiant(f);
	returnGiant(s);
	#if	ECDSA_SIGN_USE_PROJ
	returnGiant(pty);
	returnGiant(ptz);
	#endif	/* ECDSA_SIGN_USE_PROJ */
	return frtn;
}