/*
 * Create new feeSig object, including a random large integer 'randGiant' for
 * possible use in salting a feeHash object, and 'PmX', equal to
 * randGiant 'o' P1. Note that this is not called when *verifying* a
 * signature, only when signing.
 */
feeSig feeSigNewWithKey(
	feePubKey 		pubKey,
	feeRandFcn		randFcn,		/* optional */
	void			*randRef)
{
	sigInst 	*sinst = sinstAlloc();
	feeRand 	frand;
	unsigned char 	*randBytes;
	unsigned	randBytesLen;
	curveParams	*cp;

	if(pubKey == NULL) {
		return NULL;
	}
	cp = feePubKeyCurveParams(pubKey);
	if(cp == NULL) {
		return NULL;
	}

	/*
	 * Generate random m, a little larger than key size, save as randGiant
	 */
	randBytesLen = (feePubKeyBitsize(pubKey) / 8) + 1;
	randBytes = (unsigned char*) fmalloc(randBytesLen);
	if(randFcn) {
		randFcn(randRef, randBytes, randBytesLen);
	}
	else {
		frand = feeRandAlloc();
		feeRandBytes(frand, randBytes, randBytesLen);
		feeRandFree(frand);
	}
	sinst->randGiant = giant_with_data(randBytes, randBytesLen);
	memset(randBytes, 0, randBytesLen);
	ffree(randBytes);

	#if	FEE_DEBUG
	if(isZero(sinst->randGiant)) {
		printf("feeSigNewWithKey: randGiant = 0!\n");
	}
	#endif	// FEE_DEBUG

	/*
	 * Justify randGiant to be in [2, x1OrderPlus]
	 */
	x1OrderPlusJustify(sinst->randGiant, cp);

	/* PmX := randGiant 'o' P1 */
	sinst->PmX = newGiant(cp->maxDigits);

	#if 	CRYPTKIT_ELL_PROJ_ENABLE

	if(cp->curveType == FCT_Weierstrass) {

		pointProjStruct pt0;

		sinst->PmY = newGiant(cp->maxDigits);

		/* cook up pt0 as P1 */
		pt0.x = sinst->PmX;
		pt0.y = sinst->PmY;
		pt0.z = borrowGiant(cp->maxDigits);
		gtog(cp->x1Plus, pt0.x);
		gtog(cp->y1Plus, pt0.y);
		int_to_giant(1, pt0.z);

		/* pt0 := P1 'o' randGiant */
		ellMulProjSimple(&pt0, sinst->randGiant, cp);

		returnGiant(pt0.z);
	}
	else {
		if(SIG_CURVE == CURVE_PLUS) {
			gtog(cp->x1Plus, sinst->PmX);
		}
		else {
			gtog(cp->x1Minus, sinst->PmX);
		}
		elliptic_simple(sinst->PmX, sinst->randGiant, cp);
	}
	#else	/* CRYPTKIT_ELL_PROJ_ENABLE */

	if(SIG_CURVE == CURVE_PLUS) {
		gtog(cp->x1Plus, sinst->PmX);
	}
	else {
		gtog(cp->x1Minus, sinst->PmX);
	}
	elliptic_simple(sinst->PmX, sinst->randGiant, cp);

	#endif	/* CRYPTKIT_ELL_PROJ_ENABLE */

	return sinst;
}
Пример #2
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;
}