/* Caller determines depth from other sources (e.g. AlgId.Params) */
feeReturn feePubKeyInitFromECDSAPubBlob(feePubKey pubKey,
	const unsigned char *keyBlob,
	unsigned keyBlobLen,
	feeDepth depth)
{
	pubKeyInst *pkinst = (pubKeyInst *)pubKey;
	if(pkinst == NULL) {
		return FR_BadPubKey;
	}
	curveParams *cp = curveParamsForDepth(depth);
	if(cp == NULL) {
		return FR_IllegalDepth;
	}
	unsigned giantBytes = (cp->q + 7) / 8;
	unsigned blobSize = 1 + (2 * giantBytes);
	if(keyBlobLen != blobSize) {
		dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blobLen\n"));
		return FR_BadKeyBlob;
	}
	if(*keyBlob != 0x04) {
		dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blob leader\n"));
		return FR_BadKeyBlob;
	}
	
	pkinst->cp = cp;
	pkinst->plus = new_public(cp, CURVE_PLUS);
	deserializeGiant(keyBlob+1, pkinst->plus->x, giantBytes);
	deserializeGiant(keyBlob+1+giantBytes, pkinst->plus->y, giantBytes);
	return FR_Success;
}
Ejemplo n.º 2
0
Archivo: main.c Proyecto: crond/qc
int init(void)
{
	static char fn[]="init()";
	
	errno = 0;
	if( (atexit(&doProperClose)) != 0){
		snprintf(mainDbgBuffer,sizeof(mainDbgBuffer),"atexit reg failed. err:%d %s",errno,strerror(errno));
		dbgLog(FATAL,fn,__LINE__,mainDbgBuffer);
		return -1;
	}

	if((installSignalHdlr()) < 0){
		dbgLog(FATAL,fn,__LINE__,"Signal Hdlr Install Failed.");
		return -1;
	}

	if((i2cFd=openI2CBus(I2C_CHA_2,devAddr)) <= 0){
		dbgLog(FATAL,fn,__LINE__," I2C Init Failed.");
		return -1;
	}
	if((mcUartFd=openSerPort(BB_MC_UART_NUM)) <= 0){
		dbgLog(FATAL,fn,__LINE__,"Serial Port Init Failed");
		return -1;
	}
	
	if( (initSock(QC_LISTN_PORT)) < 0){
		dbgLog(FATAL,fn,__LINE__,"Socket Init Failed");
		return -1;
	}
	return 0;
}
Ejemplo n.º 3
0
Archivo: i2c.c Proyecto: crond/qc
const unsigned int	openI2CBus(const char *devName,const int devAddr)
{
	static char fn[]="openI2CBus()";
	static int fd= 0;
	
	errno=0;
	fd =-1;

	if((fd	= open(devName,O_RDWR)) <= 0){
		snprintf(i2cDbgBuffer,sizeof(i2cDbgBuffer),"I2CDev : %s Open Failed",devName);
		dbgLog(FATAL,fn,__LINE__,i2cDbgBuffer);
		return -1;
	}
	else{
		snprintf(i2cDbgBuffer,sizeof(i2cDbgBuffer),"I2CDev : %s Open Success",devName);
		dbgLog(INFORM,fn,__LINE__,"Opening I2C-[ OK ] ");
	}
	errno = 0;
	if((ioctl(fd,I2C_SLAVE,devAddr)) < 0) {
		snprintf(i2cDbgBuffer,sizeof(i2cDbgBuffer),"I2CDev;%s Dev:%d Access Failed",devName,devAddr);
		dbgLog(FATAL,fn,__LINE__,i2cDbgBuffer);
		return -1;
	}
	else{
		snprintf(i2cDbgBuffer,sizeof(i2cDbgBuffer),"I2CDev:%s Dev:%d Access Success",devName,devAddr);
		dbgLog(INFORM,fn,__LINE__,i2cDbgBuffer);
	}
	return fd;
}
Ejemplo n.º 4
0
int main(int argc,char *argv)
{
    static char fnName[]="main():";	
     
     errno=0;	
    
     if(argc == 2)
     {
        msgQType = atoi(argv[1]);
     }
     else
         msgQType   = 0;

     keyValue = ftok(FILE_PATH,PROJ_ID);
	 if(keyValue <= 0)
     {
        snprintf(dbgLogStr,sizeof(dbgLogStr),
                    "%s:%s:%d: ftok failed. Err:%d",
                        __FILE__,fnName,__LINE__,errno);
        dbgLog(INFORM,dbgLogStr);
        return 0;
     }  
#if 1     
    errno=0;
     msgQId  =   msgget(keyValue, IPC_CREAT|0644);
    if(msgQId < 0)
    {
        snprintf(dbgLogStr,
                    sizeof(dbgLogStr),
                    "%s:%s:%d msgget error:%d",
                    __FILE__,fnName,__LINE__,errno);
        dbgLog(INFORM,dbgLogStr);
        return 0;
    }     
    snprintf(dbgLogStr,sizeof(dbgLogStr),"%s: MSG Q ID:%d",fnName,msgQId);
 
    dbgLog(INFORM,dbgLogStr);
#endif    
    errno =0;
    int ret =0;
    if((ret = msgrcv(msgQId,(char *)buffer,sizeof(buffer),msgQType,IPC_NOWAIT)) < 0)
//    if((msgrcv(msgQId,(char *)&mqstructVar,sizeof(mqstructVar),2,IPC_NOWAIT)) < 0)
    {
        snprintf(dbgLogStr,sizeof(dbgLogStr),"%s:%s:%d msgrecv error:%d. %s",__FILE__,fnName,__LINE__,errno,strerror(errno));
        dbgLog(INFORM,dbgLogStr);
    }
    else
    {
      //  snprintf(dbgLogStr,sizeof(dbgLogStr),"%s Msg Recvd: %s",fnName,mqstructVar.msg);
        snprintf(dbgLogStr,sizeof(dbgLogStr),"%s Msg Recvd:%d: %s",
                                                        fnName,ret,&buffer[4]);
        dbgLog(INFORM,dbgLogStr);
    }
//    stopService(0);
    return 0;
}
Ejemplo n.º 5
0
Archivo: i2c.c Proyecto: crond/qc
int writeToI2CBus(const unsigned int fd,const unsigned char *buffer,const unsigned int len)
{
	static char fn[]="readFromI2CBus()";
	int ret= 0;
	errno = 0;
	if((ret = write(fd,buffer,len)) <= 0){
		sprintf(i2cDbgBuffer,"write failed. Err:%d:%s",errno,strerror(errno));
		dbgLog(REPORT,fn,__LINE__,i2cDbgBuffer);	
	}
	else{
		sprintf(i2cDbgBuffer,"Write Success. wrote:%d bytes",ret);
		dbgLog(REPORT,fn,__LINE__,i2cDbgBuffer);	
	}
	return ret;
}
Ejemplo n.º 6
0
int stopService(char flag)
{
    static char fnName[]="stopService():";
    errno =0;
    if( (msgctl(msgQId,IPC_RMID,NULL)) < 0)
    {
        sprintf(dbgLogStr,
                    "%s:%s:%d: Err while removing MSG-Q. Err:%d",
                            __FILE__,fnName,__LINE__,errno);
        dbgLog(INFORM,dbgLogStr);
        return -1;
    }
    snprintf(dbgLogStr,sizeof(dbgLogStr),"%s: MSG Q remove-SUCCESS",fnName);
    dbgLog(INFORM,dbgLogStr);
    return 0;
}
/*
 * Obtain Pm after feeSigNewWithKey() or feeSigParse()
 */
unsigned char *feeSigPm(feeSig sig,
	unsigned *PmLen)
{
	sigInst *sinst = (sigInst*) sig;
	unsigned char *Pm;

	if(sinst->PmX == NULL) {
		dbgLog(("feeSigPm: no PmX!\n"));
		return NULL;
	}
	else {
		Pm = mem_from_giant(sinst->PmX, PmLen);
		#if	SIG_DEBUG
		if(sigDebug)
		{
		    int i;

		    printf("Pm : "); printGiant(sinst->PmX);
		    printf("PmData: ");
		    for(i=0; i<*PmLen; i++) {
		        printf("%x:", Pm[i]);
		    }
		    printf("\n");
		}
		#endif	// SIG_DEBUG
	}
	return Pm;
}
/*
 * Generate digital signature, ECDSA style.
 */
feeReturn feePubKeyCreateECDSASignature(feePubKey pubKey,
	const unsigned char *data,
	unsigned dataLen,
	unsigned char **signature,	/* fmalloc'd and RETURNED */
	unsigned *signatureLen)		/* RETURNED */
{
	pubKeyInst	*pkinst = (pubKeyInst *) pubKey;
	sha1Obj 	sha1;
	feeReturn	frtn;

	if(pkinst->privGiant == NULL) {
		dbgLog(("feePubKeyCreateECDSASignature: Attempt to Sign "
			"without private data\n"));
		return FR_BadPubKey;
	}
	sha1 = sha1Alloc();
	sha1AddData(sha1, data, dataLen);
	frtn = feeECDSASign(pubKey,
		sha1Digest(sha1),
		sha1DigestLen(),
		NULL,			// randFcn
		NULL,
		signature,
		signatureLen);
	sha1Free(sha1);
	return frtn;
}
/*
 * Init feePubKey from curve parameters matching existing oldKey.
 */
feeReturn feePubKeyInitFromKey(feePubKey pubKey,
	const unsigned char *privData,
	unsigned privDataLen,
	feePubKey oldKey,
	char hashPrivData)
{
	pubKeyInst *pkinst = (pubKeyInst *) pubKey;
	pubKeyInst *oldInst = (pubKeyInst *) oldKey;
	feeReturn  frtn;

	if(oldKey == NULL) {
		dbgLog(("NULL existing key\n"));
		return FR_BadPubKey;
	}

	pkinst->cp = curveParamsCopy(oldInst->cp);
	if(pkinst->cp->x1Minus != NULL) {
		pkinst->minus = new_public(pkinst->cp, CURVE_MINUS);
		if(pkinst->minus == NULL) {
			goto abort;
		}
	}
	/* else this curve only usable for ECDSA */
	
	pkinst->plus = new_public(pkinst->cp, CURVE_PLUS);
	if(pkinst->plus == NULL) {
		goto abort;
	}
	frtn = feeGenPrivate(pkinst, privData, privDataLen, hashPrivData);
	if(frtn) {
		return frtn;
	}
	set_priv_key_giant(pkinst->plus, pkinst->privGiant);
	if(pkinst->cp->x1Minus != NULL) {
		set_priv_key_giant(pkinst->minus, pkinst->privGiant);
	}
	return FR_Success;

abort:
	dbgLog(("Bad Existing Public Key\n"));
	return FR_BadPubKey;
}
Ejemplo n.º 10
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;
}
/*
 * Generate digital signature, ElGamal style.
 */
feeReturn feePubKeyCreateSignature(feePubKey pubKey,
	const unsigned char *data,
	unsigned dataLen,
	unsigned char **signature,	/* fmalloc'd and RETURNED */
	unsigned *signatureLen)		/* RETURNED */
{
	pubKeyInst	*pkinst = (pubKeyInst *) pubKey;
	feeHash 	hash;
	feeSig 		sig;
	unsigned char 	*Pm = NULL;
	unsigned 	PmLen;
	feeReturn	frtn;

	if(pkinst->privGiant == NULL) {
		dbgLog(("feePubKeyCreateSignature: Attempt to Sign without"
			" private data\n"));
		return FR_BadPubKey;
	}
	hash = feeHashAlloc();
	sig = feeSigNewWithKey(pubKey, NULL, NULL);
	if(sig == NULL) {
		/*
		 * Shouldn't happen, but...
		 */
		feeHashFree(hash);
		return FR_BadPubKey;
	}

	/*
	 * Get Pm to salt hash object
	 */
	Pm = feeSigPm(sig, &PmLen);
	feeHashAddData(hash, Pm, PmLen);

	/*
	 * Now hash the data proper, then sign the hash
	 */
	feeHashAddData(hash, data, dataLen);
	frtn = feeSigSign(sig,
		feeHashDigest(hash),
		feeHashDigestLen(),
		pubKey);
	if(frtn == FR_Success) {
		frtn = feeSigData(sig, signature, signatureLen);
	}
	feeHashFree(hash);
	feeSigFree(sig);
	ffree(Pm);
	return frtn;
}
feeReturn feePubKeyInitFromPrivDataDepth(feePubKey pubKey,
	const unsigned char *privData,
	unsigned privDataLen,
	feeDepth depth,
	char hashPrivData)
{
	pubKeyInst *pkinst = (pubKeyInst *) pubKey;
	feeReturn  frtn;

	#if	ENGINE_127_BITS
	if(depth != FEE_DEPTH_127_1) {
		dbgLog(("Illegal Depth\n"));
		return FR_IllegalDepth;
	}
	#endif	// ENGINE_127_BITS
	if(depth > FEE_DEPTH_MAX) {
		dbgLog(("Illegal Depth\n"));
		return FR_IllegalDepth;
	}

	pkinst->cp = curveParamsForDepth(depth);
	pkinst->plus  = new_public(pkinst->cp, CURVE_PLUS);
	if(pkinst->cp->x1Minus != NULL) {
		pkinst->minus = new_public(pkinst->cp, CURVE_MINUS);
	}
	/* else only usable for ECDSA */
	
	frtn = feeGenPrivate(pkinst, privData, privDataLen, hashPrivData);
	if(frtn) {
		return frtn;
	}
	set_priv_key_giant(pkinst->plus, pkinst->privGiant);
	if(pkinst->cp->x1Minus != NULL) {
		set_priv_key_giant(pkinst->minus, pkinst->privGiant);
	}
	return FR_Success;
}
Ejemplo n.º 13
0
Archivo: main.c Proyecto: crond/qc
void doProperClose(void)
{
	static char fn[]="doProperClose()";

	if(i2cFd != 0)
		close(i2cFd);
	if(mcUartFd != 0)
		close(mcUartFd);
	if(sockWaitFd != 0)
		close(sockWaitFd);
	if(eamSockFd != 0)
		close(eamSockFd);
	dbgLog(FATAL,fn,__LINE__,"Finished Proper Closing. Exitting..");
	return;	
}
/***
 *** Common native blob support 
 ***/
static feeReturn createKeyBlob(pubKeyInst *pkinst,
	int 			isPrivate,		// 0 : public   1 : private
	unsigned char 	**keyBlob,		// mallocd and RETURNED
	unsigned 		*keyBlobLen)	// RETURNED
{
	unsigned char 	*s;		// running ptr into *origS
	unsigned		sLen;
	int				magic;

	/* common blob elements */
	sLen = (4 * sizeof(int)) +		// magic, version, minVersion,
									// spare
	    lengthOfByteRepCurveParams(pkinst->cp);
	if(isPrivate) {
	    /* private only */
	    sLen += lengthOfByteRepGiant(pkinst->privGiant);
	    magic = PUBLIC_KEY_BLOB_MAGIC_PRIV;
	}
	else {
	    /* public only */
	    sLen += (lengthOfByteRepKey(pkinst->plus) +
		     lengthOfByteRepKey(pkinst->minus));
	    magic = PUBLIC_KEY_BLOB_MAGIC_PUB;
	}
	*keyBlob = s = (unsigned char*) fmalloc(sLen);
	s += intToByteRep(magic, s);
	s += intToByteRep(PUBLIC_KEY_BLOB_VERSION, s);
	s += intToByteRep(PUBLIC_KEY_BLOB_MINVERSION, s);
	s += intToByteRep(0, s);			// spare
	s += curveParamsToByteRep(pkinst->cp, s);
	if(isPrivate) {
	    s += giantToByteRep(pkinst->privGiant, s);
	}
	else {
	    /* keyToByteRep writes y for plus curve only */
	    s += keyToByteRep(pkinst->plus, s);
		if(pkinst->minus != NULL) {
			s += keyToByteRep(pkinst->minus, s);
		}
		else {
			/* TBD */
			dbgLog(("work needed here for blobs with no minus key\n"));
		}
	}
	*keyBlobLen = sLen;
	return FR_Success;
}
/*
 * Init feePubKey from a public key string.
 *
 * See ByteRep.doc for info on the format of the public key string and blobs;
 * PLEASE UPDATE THIS DOCUMENT WHEN YOU MAKE CHANGES TO THE STRING FORMAT.
 */
feeReturn feePubKeyInitFromKeyString(feePubKey pubKey,
	const char *keyStr,
	unsigned keyStrLen)
{
	unsigned char 	*blob = NULL;
	unsigned		blobLen;
	feeReturn		frtn;

	blob = dec64((unsigned char *)keyStr, keyStrLen, &blobLen);
	if(blob == NULL) {
		dbgLog(("Bad Public Key String (not enc64)\n"));
		return FR_BadPubKeyString;
	}
	frtn = feePubKeyInitFromKeyBlob(pubKey, blob, blobLen);
	ffree(blob);
	return frtn;
}
feeReturn feePubKeyInitFromECDSAPrivBlob(feePubKey pubKey,
	const unsigned char *keyBlob,
	unsigned keyBlobLen,
	feeDepth depth)
{
	pubKeyInst *pkinst = (pubKeyInst *)pubKey;
	if(pkinst == NULL) {
		return FR_BadPubKey;
	}
	curveParams *cp = curveParamsForDepth(depth);
	if(cp == NULL) {
		return FR_IllegalDepth;
	}
	unsigned giantDigits = cp->basePrime->sign;
	unsigned giantBytes = (cp->q + 7) / 8;

	/* 
	 * The specified private key can be one byte smaller than the modulus */
	if((keyBlobLen > giantBytes) || (keyBlobLen < (giantBytes - 1))) {
		dbgLog(("feePubKeyInitFromECDSAPrivBlob: bad blobLen\n"));
		return FR_BadKeyBlob;
	}
	
	pkinst->cp = cp;
	
	/* cook up a new private giant */
	pkinst->privGiant = newGiant(giantDigits);
	if(pkinst->privGiant == NULL) {
		return FR_Memory;
	}
	deserializeGiant(keyBlob, pkinst->privGiant, keyBlobLen);

	/* since this blob only had the private data, infer the remaining fields */
	pkinst->plus  = new_public(pkinst->cp, CURVE_PLUS);
	set_priv_key_giant(pkinst->plus, pkinst->privGiant);
	return FR_Success;
}
/*
 * FEE_SIG_USING_PROJ true  : this is the "no Weierstrass" case
 * feeSigVerifyNoProj false : this is redefined to feeSigVerify
 */
feeReturn feeSigVerifyNoProj(feeSig sig,
	const unsigned char *data,
	unsigned dataLen,
	feePubKey pubKey)
{
	giant 		Q = NULL;
	giant 		messageGiant = NULL;
	giant 		scratch = NULL;
	sigInst 	*sinst = (sigInst*) sig;
	feeReturn	frtn;
	curveParams	*cp;
	key		origKey;		// may be plus or minus key

	if(sinst->PmX == NULL) {
		dbgLog(("sigVerify without parse!\n"));
		frtn = FR_IllegalArg;
		goto out;
	}

	cp = feePubKeyCurveParams(pubKey);
	Q = newGiant(cp->maxDigits);

	/*
	 * pick a key (+/-)
	 * Q := P1
	 */
	if(SIG_CURVE == CURVE_PLUS) {
		origKey = feePubKeyPlusCurve(pubKey);
		gtog(cp->x1Plus, Q);
	}
	else {
		origKey = feePubKeyMinusCurve(pubKey);
		gtog(cp->x1Minus, Q);
	}

	messageGiant = 	giant_with_data(data, dataLen);	// M(ciphertext)

	/* Q := u 'o' P1 */
	elliptic_simple(Q, sinst->u, cp);

	/* scratch := theirPub */
	scratch = newGiant(cp->maxDigits);
	gtog(origKey->x, scratch);

	#if	SIG_DEBUG
	if(sigDebug) {
		printf("verify origKey:\n");
		printKey(origKey);
		printf("messageGiant: ");
		printGiant(messageGiant);
		printf("curveParams:\n");
		printCurveParams(cp);
	}
	#endif	// SIG_DEBUG

	/* scratch := M 'o' theirPub */
	elliptic_simple(scratch, messageGiant, cp);

	#if	SIG_DEBUG
	if(sigDebug) {
		printf("signature_compare, with\n");
		printf("p0 = Q:\n");
		printGiant(Q);
		printf("p1 = Pm:\n");
		printGiant(sinst->PmX);
		printf("p2 = scratch = R:\n");
		printGiant(scratch);
	}
	#endif	// SIG_DEBUG

	if(signature_compare(Q, sinst->PmX, scratch, cp)) {

		frtn = FR_InvalidSignature;
		#if	LOG_BAD_SIG
		printf("***yup, bad sig***\n");
		#endif	// LOG_BAD_SIG
	}
	else {
		frtn = FR_Success;
	}
out:
	if(messageGiant != NULL) {
	    freeGiant(messageGiant);
	}
	if(Q != NULL) {
	    freeGiant(Q);
	}
	if(scratch != NULL) {
	    freeGiant(scratch);
	}
	return frtn;
}
Ejemplo n.º 18
0
/*
 * cons up:
 * 	cluePlus(0)
 *	clueMinus(0)
 *	sPlus
 *	sMinus
 *	r
 * Assumes:
 *	cluePlus = clueMinus = ourPriv * theirPub
 *	initialRS
 * 	initialRSSize
 *	cp
 *
 * Called at feeFEEDNewWithPubKey while encrypting, or upon decrypting
 * first block of data.
 */
static feeReturn initFromRS(feedInst *finst)
{
	giant s;
	unsigned rSize = finst->initialRSSize / 2;

	#if	FEED_DEBUG
	if((finst->initialRS == NULL) ||
	   (finst->cp == NULL) ||
	   (finst->cluePlus == NULL) ||
	   (finst->clueMinus == NULL) ||
	   (finst->initialRSSize == 0)) {
	    	dbgLog(("initFromRS: resource shortage\n"));
	    	return FR_Internal;
	}
	#endif	// FEED_DEBUG

	finst->r = giant_with_data(finst->initialRS, rSize);
	s = giant_with_data(finst->initialRS+rSize, rSize);

	#if	FEED_DEBUG
	if(isZero(finst->r)) {
		printf("initFromRS: r = 0! initialRSSize = %d; encr = %s\n",
			finst->initialRSSize,
			(finst->rsCtext == NULL) ? "TRUE" : "FALSE");
	}
	if(isZero(s)) {
		printf("initFromRS: s = 0! initialRSSize = %d; encr = %s\n",
			finst->initialRSSize,
			(finst->rsCtext == NULL) ? "TRUE" : "FALSE");
	}
	#endif	// FEE_DEBUG
	/*
	 * Justify r and s to be in [2, minimumX1Order].
	 */
	lesserX1OrderJustify(finst->r, finst->cp);
	lesserX1OrderJustify(s, finst->cp);

	/*
	 * sPlus  = s * x1Plus
	 * sMinus = s * x1Minus
	 */
	finst->sPlus = newGiant(finst->cp->maxDigits);
	finst->sMinus = newGiant(finst->cp->maxDigits);
	gtog(finst->cp->x1Plus, finst->sPlus);
	elliptic_simple(finst->sPlus, s, finst->cp);
	gtog(finst->cp->x1Minus, finst->sMinus);
	elliptic_simple(finst->sMinus, s, finst->cp);

	/*
	 * And finally, the initial clues. They are currently set to
	 * ourPriv * theirPub.
	 */
	#if	FEED_DEBUG
	printf("cluePlus : "); printGiant(finst->cluePlus);
	printf("clueMinus: "); printGiant(finst->clueMinus);
	#endif	// FEED_EEBUG

	elliptic_simple(finst->cluePlus, finst->r, finst->cp);
	elliptic_simple(finst->clueMinus, finst->r, finst->cp);

	#if	FEED_DEBUG
	printf("r        : "); printGiant(finst->r);
	printf("s        : "); printGiant(s);
	printf("sPlus    : "); printGiant(finst->sPlus);
	printf("sMinus   : "); printGiant(finst->sMinus);
	printf("cluePlus : "); printGiant(finst->cluePlus);
	printf("clueMinus: "); printGiant(finst->clueMinus);
	#endif	// FEED_DEBUG

	freeGiant(s);
	return FR_Success;
}
Ejemplo n.º 19
0
/*
 * Alloc and init a feeFEED object associated with specified public and
 * private keys.
 */
feeFEED feeFEEDNewWithPubKey(feePubKey myPrivKey,
	feePubKey theirPubKey,
	int forEncrypt,			// 0 ==> decrypt   1 ==> encrypt
	feeRandFcn randFcn,		// optional 
	void *randRef)
{
	feedInst 		*finst;
	giant			privGiant;
	key				k;
	unsigned 		expPlainSize;
	unsigned 		expCipherSize;
	unsigned 		expBlocks;

	if(!curveParamsEquivalent(feePubKeyCurveParams(theirPubKey),
		    feePubKeyCurveParams(myPrivKey))) {
		dbgLog(("feeFEEDNewWithPubKey: Incompatible Keys\n"));
		return NULL;
	}
	finst = (feedInst*) fmalloc(sizeof(feedInst));
	bzero(finst, sizeof(feedInst));
	finst->forEncrypt = forEncrypt;
	finst->cp = curveParamsCopy(feePubKeyCurveParams(theirPubKey));
	finst->rsBlockCount = 0;
	finst->xp = newGiant(finst->cp->maxDigits);
	finst->xm = newGiant(finst->cp->maxDigits);
	finst->tmp1 = newGiant(finst->cp->maxDigits);
	if(forEncrypt) {
	    finst->tmp2 = newGiant(finst->cp->maxDigits);
	}

	/*
	 * cluePlus  = ourPriv * theirPub+
	 * clueMinus = ourPriv * theirPub-
	 */
	finst->cluePlus  = newGiant(finst->cp->maxDigits);
	finst->clueMinus = newGiant(finst->cp->maxDigits);
	privGiant = feePubKeyPrivData(myPrivKey);
	if(privGiant == NULL) {
		dbgLog(("feeFEEDNewWithPubKey: no private key\n"));
		goto abort;
	}
	k = feePubKeyPlusCurve(theirPubKey);
	gtog(k->x, finst->cluePlus);			// cluePlus = theirPub+
	elliptic_simple(finst->cluePlus, privGiant, finst->cp);
	k = feePubKeyMinusCurve(theirPubKey);
	gtog(k->x, finst->clueMinus);			// theirPub-
	elliptic_simple(finst->clueMinus, privGiant, finst->cp);

	/*
	 * Set up block sizes.
	 */
	if(finst->cp->primeType == FPT_General) {
	    unsigned blen = bitlen(finst->cp->basePrime);

	    finst->plainBlockSize = blen / 8;
	    if((blen & 0x7) == 0) {
	    	/*
		 * round down some more...
		 */
		finst->plainBlockSize--;
	    }
	}
	else {
	    finst->plainBlockSize = finst->cp->q / 8;
	    if(((finst->cp->q & 0x7) == 0) && (finst->cp->k > 0)) {
		/*
		 * Special case, with q mod 8 == 0. Here we have to
		 * trim back the plainBlockSize by one byte.
		 */
		finst->plainBlockSize--;
	    }
	}
	finst->cipherBlockSize = finst->cp->minBytes + 1;

	/*
	 * the size of initialRS is subject to tweaking - if we make it
	 * not a multiple of plainBlockSize, we save one FEEDExp cipherBlock
	 * in our ciphertext.
	 */
	finst->initialRSSize = finst->plainBlockSize * 2;
	if(finst->initialRSSize > RS_MIN_SIZE) {
	    unsigned minPlainBlocks;
	    unsigned maxSize;

	    /*
	     * How many plainblocks to hold RS_MIN_SIZE?
	     */
	    minPlainBlocks = (RS_MIN_SIZE + finst->plainBlockSize - 1) /
	    	finst->plainBlockSize;

	    /*
	     * Max size = that many plainblocks, less 2 bytes (to avoid
	     * extra residue block).
	     */
	    maxSize = minPlainBlocks * finst->plainBlockSize - 2;

	    /*
	     * But don't bother with more than 2 plainblocks worth
	     */
	    if(finst->initialRSSize > maxSize) {
	        finst->initialRSSize = maxSize;
	    }
	}
	/* else leave it alone, that's small enough */

	if(forEncrypt) {
		feeRand frand = NULL;

		/*
		 * Encrypt-capable FEEDExp object
		 */
		finst->feedExp = feeFEEDExpNewWithPubKey(theirPubKey,
			randFcn,
			randRef);
		if(finst->feedExp == NULL) {
			goto abort;
		}

		/*
		 * Generate initial r and s data.
		 */
		finst->initialRS = (unsigned char*) fmalloc(finst->initialRSSize);
		if(randFcn != NULL) {
			randFcn(randRef, finst->initialRS, finst->initialRSSize);
		}
		else {
			frand = feeRandAlloc();
			feeRandBytes(frand, finst->initialRS, finst->initialRSSize);
			feeRandFree(frand);
		}
		if(initFromRS(finst)) {
			goto abort;
		}
	}
	else {
		/*
		 * Decrypt-capable FEEDExp object
		 */
		finst->feedExp = feeFEEDExpNewWithPubKey(myPrivKey,
			randFcn,
			randRef);
		if(finst->feedExp == NULL) {
			goto abort;
		}

	}

	/*
	 * Figure out how many of our cipherblocks it takes to hold
	 * a FEEDExp-encrypted initialRS. If initialRSSize is an exact
	 * multiple of expPlainSize, we get an additional feedExp
	 * residue block.
	 */
	expPlainSize = feeFEEDExpPlainBlockSize(finst->feedExp);
	expCipherSize = feeFEEDExpCipherBlockSize(finst->feedExp);
	expBlocks = (finst->initialRSSize + expPlainSize - 1) /
		expPlainSize;
	if((finst->initialRSSize % expPlainSize) == 0) {
		expBlocks++;
	}

	/*
	 * Total meaningful bytes of encrypted initialRS
	 */
	finst->rsCtextSize = expBlocks * expCipherSize;

	/*
	 * Number of our cipherblocks it takes to hold rsCtextSize
	 */
	finst->rsSizeCipherBlocks = (finst->rsCtextSize +
		finst->cipherBlockSize - 1) / finst->cipherBlockSize;
	if(!forEncrypt) {
	    finst->rsCtext = (unsigned char*) fmalloc(finst->rsSizeCipherBlocks *
		finst->cipherBlockSize);
	}

	/*
	 * Sanity check...
	 */
	#if	FEED_DEBUG
	{
	    unsigned fexpBlockSize = feeFEEDExpCipherBlockSize(finst->feedExp);

	    /*
	     * FEEDExp has one more giant in ciphertext, plaintext is
	     * same size
	     */
	    if((finst->cipherBlockSize + finst->cp->minBytes) !=
			fexpBlockSize) {
		dbgLog(("feeFEEDNewWithPubKey: FEEDExp CBlock Size "
			"screwup\n"));
		goto abort;
	    }
	    fexpBlockSize = feeFEEDExpPlainBlockSize(finst->feedExp);
	    if(fexpBlockSize != finst->plainBlockSize) {
		dbgLog(("feeFEEDNewWithPubKey: FEEDExp PBlock Size "
			"screwup\n"));
		goto abort;
	    }
	}
	#endif	// FEED_DEBUG

	return finst;

abort:
	feeFEEDFree(finst);
	return NULL;
}
Ejemplo n.º 20
0
/*
 * Encrypt a block or less of data. Caller malloc's cipherText.
 * Generates up to feeFEEDCipherBufSize() bytes of ciphertext.
 */
feeReturn feeFEEDEncryptBlock(feeFEED feed,
	const unsigned char *plainText,
	unsigned plainTextLen,
	unsigned char *cipherText,
	unsigned *cipherTextLen,		// RETURNED
	int finalBlock)
{
	feedInst 		*finst = (feedInst *) feed;
	unsigned		ctextLen = 0;
	feeReturn		frtn = FR_Success;
	int				whichCurve;
	giant			thisClue;		// not alloc'd or freed
	giant			thisS;			// ditto
	unsigned char	clueByte;

	if(plainTextLen > finst->plainBlockSize) {
		return FR_IllegalArg;
	}
	if((plainTextLen < finst->plainBlockSize) && !finalBlock) {
		return FR_IllegalArg;
	}
	if(finst->initialRS == NULL) {
		/*
		 * Init'd for decrypt?
		 */
		return FR_IllegalArg;
	}

	/*
	 * First block - encrypt initialRS via FEEDExp
	 */
	if(finst->rsBlockCount == 0) {
	    unsigned char *thisCtext;	// malloc's by FEEDExp
	    unsigned padLen;

	    if(finst->initialRS == NULL) {
		/*
		 * init'd for decrypt or reused
		 */
		dbgLog(("feeFEEDEncryptBlock: NULL initialRS!\n"));
		return FR_IllegalArg;
	    }

	    frtn = feeFEEDExpEncrypt(finst->feedExp,
		    finst->initialRS,
		    finst->initialRSSize,
		    &thisCtext,
		    &ctextLen);
	    if(frtn) {
		    /*
		     * Should never happen...
		     */
		    dbgLog(("feeFEEDEncryptBlock: error writing encrypted"
			    " initialRS (%s)\n", feeReturnString(frtn)));
		    return FR_Internal;
	    }
	    bcopy(thisCtext, cipherText, ctextLen);
	    cipherText += ctextLen;
	    ffree(thisCtext);

	    finst->rsBlockCount = finst->rsSizeCipherBlocks;
	    padLen = finst->cipherBlockSize -
	    	(ctextLen % finst->cipherBlockSize);	// zeros to write

	    #if		0	/* FEED_DEBUG */

	    /*
	     * Hard-coded assumptions and tests about initRSSize...
	     * Currently we assume that initRSSize % expBlockSize = 0
	     */
	    if((ctextLen / finst->cipherBlockSize) != 5) {
		dbgLog(("feeFEEDEncryptBlock: cipherblock size screwup (1)\n"));
		return FR_Internal;
	    }
	    if(padLen != 3) {
		dbgLog(("feeFEEDEncryptBlock: cipherblock size screwup (2)\n"));
		return FR_Internal;
	    }
	    #endif	// FEED_DEBUG

	    /*
	     * pad to multiple of (our) cipherblock size.
	     */
	    while(padLen) {
		*cipherText++ = 0;
		ctextLen++;
		padLen--;
	    }
	}

	/*
	 * plaintext to giant xp
	 */
	if(finalBlock) {
		unsigned char *ptext = (unsigned char*) fmalloc(finst->plainBlockSize);
		bzero(ptext, finst->plainBlockSize);
		if(plainTextLen) {
			/*
			 * skip for empty block with resid length 0
			 */
			bcopy(plainText, ptext, plainTextLen);
		}
		if(plainTextLen < finst->plainBlockSize) {
		    if(plainTextLen == 0) {
		    	/*
			 * Special case - resid block with no actual plaintext.
			 * Can't actually write zero here; it screws up
			 * deserializing the giant during decrypt
			 */
		        ptext[finst->plainBlockSize - 1] = RESID_ZERO;
				bprintf(("=== FEED encrypt: RESID_ZERO\n"));
		    }
		    else {
				ptext[finst->plainBlockSize - 1] = plainTextLen;
				bprintf(("=== FEED encrypt: resid len 0x%x\n", plainTextLen));
		    }
		}
		/*
		 * else handle evenly aligned case (i.e., finalBlock true
		 * and (plainTextLen ==  plainBlockSize)) below...
		 */
		deserializeGiant(ptext, finst->xp, finst->plainBlockSize);
		ffree(ptext);
	}
	else {
		deserializeGiant(plainText, finst->xp, plainTextLen);
	}

	/*
	 * encrypt xp
	 *     xm = xp + clue(+/-)
	 * determine parity needed to restore xp
	 *     parity = ((xm + clue(+/-) == xp) ? 1 : -1
	 * and adjust clue
	 *     clue[n+1] = r * clue[n] + (s * P1)
	 */
	whichCurve = which_curve(finst->xp, finst->cp);
	if(whichCurve == CURVE_PLUS) {
		thisClue = finst->cluePlus;
		thisS    = finst->sPlus;
		clueByte = CLUE_PLUS;
	}
	else {
		thisClue = finst->clueMinus;
		thisS    = finst->sMinus;
		clueByte = CLUE_MINUS;
	}
	// calculate xm
	elliptic_add(thisClue, finst->xp, finst->xm, finst->cp, SIGN_PLUS);
	// save xm + clue in tmp1
	elliptic_add(finst->xm, thisClue, finst->tmp1, finst->cp, SIGN_PLUS);
	// Adjust clue
	elliptic_simple(thisClue, finst->r, finst->cp);
	gtog(thisClue, finst->tmp2);
	elliptic_add(finst->tmp2, thisS, thisClue, finst->cp, SIGN_PLUS);

	/*
	 * Calculate parity
	 */
	if(gcompg(finst->tmp1, finst->xp) == 0) {
		clueByte |= PARITY_PLUS;
	}

	/*
	 * Ciphertext = (xm, clueByte)
	 */
	serializeGiant(finst->xm, cipherText, finst->cp->minBytes);
	cipherText += finst->cp->minBytes;
	ctextLen += finst->cp->minBytes;
	*cipherText++ = clueByte;
	ctextLen++;

	#if	FEED_DEBUG
	printf("encrypt  clue %d\n", clueByte);
	printf("  xp : "); printGiant(finst->xp);
	printf("  xm : "); printGiant(finst->xm);
	printf("  cluePlus  :"); printGiant(finst->cluePlus);
	printf("  clueMinus :"); printGiant(finst->clueMinus);
	#endif	// FEED_DEBUG

	if(finalBlock && (plainTextLen == finst->plainBlockSize)) {
	       /*
		* Special case: finalBlock true, plainTextLen == blockSize.
		* In this case we generate one more block of ciphertext,
		* with a resid length of zero.
		*/
		unsigned moreCipher;			// additional cipherLen

		frtn = feeFEEDEncryptBlock(feed,
			NULL,				// plainText not used
			0,				// resid
			cipherText,			// append...
			&moreCipher,
			1);
		if(frtn == FR_Success) {
			ctextLen += moreCipher;
		}
	}
	bprintf(("=== FEED encryptBlock ptextLen 0x%x  ctextLen 0x%x\n",
		plainTextLen, ctextLen));
		
	*cipherTextLen = ctextLen;
	return frtn;
}
/*
 * Init an empty feePubKey from a native blob (non-DER format).
 */
static feeReturn feePubKeyInitFromKeyBlob(feePubKey pubKey,
	unsigned char *keyBlob,
	unsigned keyBlobLen)
{
	pubKeyInst		*pkinst = (pubKeyInst *) pubKey;
	unsigned char	*s;		// running pointer
	unsigned		sLen;		// bytes remaining in *s
	int				magic;
	unsigned		len;		// for length of individual components
	int 			minVersion;
	int				version;
	int				isPrivate;

	s = keyBlob;
	sLen = keyBlobLen;
	if(sLen < (4 * sizeof(int))) {	// magic, version, minVersion, spare
		/*
		 * Too short for all the ints we need
		 */
		dbgLog(("feePublicKey: key blob (1)\n"));
		return FR_BadKeyBlob;
	}

	magic = byteRepToInt(s);
	s += sizeof(int);
	sLen -= sizeof(int);
	switch(magic) {
	    case PUBLIC_KEY_BLOB_MAGIC_PUB:
	    	isPrivate = 0;
		break;
	    case PUBLIC_KEY_BLOB_MAGIC_PRIV:
	    	isPrivate = 1;
		break;
	    default:
		dbgLog(("feePublicKey: Bad Public Key Magic Number\n"));
		return FR_BadKeyBlob;
	}

	/*
	 * Switch on this for version-specific cases
	 */
	version = byteRepToInt(s);
	s += sizeof(int);
	sLen -= sizeof(int);

	minVersion = byteRepToInt(s);
	s += sizeof(int);
	sLen -= sizeof(int);
	if(minVersion > PUBLIC_KEY_BLOB_VERSION) {
		/*
		 * old code, newer key blob - can't parse
		 */
		dbgLog(("feePublicKey: Incompatible Public Key (1)\n"));
		return FR_BadKeyBlob;
	}

	s += sizeof(int);			// skip spare
	sLen -= sizeof(int);

	pkinst->cp = byteRepToCurveParams(s, sLen, &len);
	if(pkinst->cp == NULL) {
		dbgLog(("feePublicKey: Bad Key Blob(2)\n"));
		return FR_BadKeyBlob;
	}
	s += len;
	sLen -= len;

	/*
	 * Private key blob: privGiant.
	 * Public Key blob:  plusX, minusX, plusY.
	 */
	if(isPrivate) {
		pkinst->privGiant = byteRepToGiant(s, sLen, &len);
		if(pkinst->privGiant == NULL) {
			dbgLog(("feePublicKey: Bad Key Blob(3)\n"));
			return FR_BadKeyBlob;
		}
		s += len;
		sLen -= len;
	}
	else {
		/* this writes x and y */
		pkinst->plus = byteRepToKey(s,
			sLen,
			CURVE_PLUS,		// twist
			pkinst->cp,
			&len);
		if(pkinst->plus == NULL) {
			dbgLog(("feePublicKey: Bad Key Blob(4)\n"));
			return FR_BadKeyBlob;
		}
		s += len;
		sLen -= len;

		/* this only writes x */
		pkinst->minus = byteRepToKey(s,
			sLen,
			CURVE_MINUS,		// twist
			pkinst->cp,
			&len);
		if(pkinst->minus == NULL) {
			dbgLog(("feePublicKey: Bad Key Blob(5)\n"));
			return FR_BadKeyBlob;
		}
		s += len;
		sLen -= len;
	}

	/*
	 * One more thing: cook up public plusX and minusX for private key
	 * blob case.
	 */
	if(isPrivate) {
		pkinst->plus  = new_public(pkinst->cp, CURVE_PLUS);
		pkinst->minus = new_public(pkinst->cp, CURVE_MINUS);
		set_priv_key_giant(pkinst->plus, pkinst->privGiant);
		set_priv_key_giant(pkinst->minus, pkinst->privGiant);
	}
	return FR_Success;

}
Ejemplo n.º 22
0
feeReturn feeFEEDDecrypt(feeFEED feed,
	const unsigned char *cipherText,
	unsigned cipherTextLen,
	unsigned char **plainText,		// malloc'd and RETURNED
	unsigned *plainTextLen)			// RETURNED
{
	const unsigned char	*ctext;
	unsigned		ctextLen;		// total to go
	unsigned char		*ptext;			// per block
	unsigned		ptextLen;		// per block
	unsigned char		*ptextResult;		// to return
	unsigned char		*ptextPtr;
	unsigned 		ptextLenTotal;		// running total
	feeReturn		frtn = FR_Success;
	int			finalBlock;
	unsigned		numBlocks;
	unsigned		plainBlockSize = feeFEEDPlainBlockSize(feed);
	unsigned		cipherBlockSize = feeFEEDCipherBlockSize(feed);

	if(cipherTextLen % cipherBlockSize) {
		dbgLog(("feeFEEDDecrypt: unaligned cipherText\n"));
		return FR_BadCipherText;
	}
	if(cipherTextLen == 0) {
		dbgLog(("feeFEEDDecrypt: NULL cipherText\n"));
		return FR_BadCipherText;
	}

	ptext = (unsigned char*) fmalloc(plainBlockSize);
	ctext = cipherText;
	ctextLen = cipherTextLen;
	numBlocks = cipherTextLen / cipherBlockSize;
	ptextResult = (unsigned char*) fmalloc(plainBlockSize * numBlocks);
	ptextPtr = ptextResult;
	ptextLenTotal = 0;

	while(ctextLen) {
		if(ctextLen == cipherBlockSize) {
		    finalBlock = 1;
		}
		else {
		    finalBlock = 0;
		}
		frtn = feeFEEDDecryptBlock(feed,
			ctext,
			cipherBlockSize,
			ptext,
			&ptextLen,
			finalBlock);
		if(frtn) {
			dbgLog(("feeFEEDDecryptBlock: %s\n",
				feeReturnString(frtn)));
			break;
		}
		if(ptextLen) {
			if(ptextLen > plainBlockSize) {
			    dbgLog(("feeFEEDDecrypt: ptext overflow!\n"));
			    frtn = FR_Internal;
			    break;
			}
			bcopy(ptext, ptextPtr, ptextLen);
			ptextPtr += ptextLen;
			ptextLenTotal += ptextLen;
		}
		/*
		 * note ptextLen == 0 is normal termination case for
		 * plainTextLen % plainBlockSize == 0.
		 * Also expected for first 4 blocks of ciphertext;
		 * proceed (we break when ctextLen is exhausted).
		 */
		ctext += cipherBlockSize;
		ctextLen -= cipherBlockSize;
	}

	ffree(ptext);
	if(frtn) {
		ffree(ptextResult);
		*plainText = NULL;
		*plainTextLen = 0;
	}
	else {
		*plainText = ptextResult;
		*plainTextLen = ptextLenTotal;
	}
	return frtn;

}
Ejemplo n.º 23
0
/*
 * Decrypt (exactly) a block of data. Caller malloc's plainText. Always
 * generates feeFEEDPlainBlockSize of plaintext, unless finalBlock is
 * non-zero (in which case feeFEEDPlainBlockSize or less bytes of plainText are
 * generated).
 */
feeReturn feeFEEDDecryptBlock(feeFEED feed,
	const unsigned char *cipherText,
	unsigned cipherTextLen,
	unsigned char *plainText,
	unsigned *plainTextLen,			// RETURNED
	int finalBlock)
{
	feedInst 	*finst = (feedInst *) feed;
	feeReturn	frtn = FR_Success;
	unsigned char	clueByte;
	giant		thisClue;		// not alloc'd
	giant		thisS;			// ditto
	int 		parity;

	if(finst->rsCtext == NULL) {
		/*
		 * Init'd for encrypt?
		 */
		return FR_IllegalArg;
	}
	if(cipherTextLen != finst->cipherBlockSize) {
	 	dbgLog(("feeFEEDDecryptBlock: bad cipherTextLen\n"));
		return FR_IllegalArg;
	}
	if(finst->rsBlockCount < finst->rsSizeCipherBlocks) {
		/*
		 * Processing initialRS, FEEDExp-encrypted
		 */
		unsigned char *rsPtr = finst->rsCtext +
			(finst->rsBlockCount * finst->cipherBlockSize);
		unsigned feedExpCipherSize;

		if(finalBlock) {
		    dbgLog(("feeFEEDDecryptBlock: incomplete initialRS\n"));
		    return FR_BadCipherText;
		}
		bcopy(cipherText, rsPtr, finst->cipherBlockSize);
		finst->rsBlockCount++;
		if(finst->rsBlockCount < finst->rsSizeCipherBlocks) {
		    /*
		     * Not done with this yet...
		     */
			bprintf(("=== FEED Decrypt: gobbled 0x%x bytes ctext, no ptext (1)\n", 
				cipherTextLen));
		    *plainTextLen = 0;
		    return FR_Success;
		}

		#if	FEED_DEBUG
		if((finst->rsBlockCount * finst->cipherBlockSize) <
				finst->rsCtextSize) {
		    dbgLog(("feeFEEDDecryptBlock: rsCtextSize underflow!\n"));
		    return FR_Internal;
		}
		#endif	// FEED_DEBUG

		/*
		 * OK, we should have the FEEDExp ciphertext for initialRS
		 * in rsCtext. Note the last few bytes are extra; we don't
		 * pass them to FEEDExp.
		 */
		feedExpCipherSize = feeFEEDCipherBlockSize(finst->feedExp);
		frtn = feeFEEDExpDecrypt(finst->feedExp,
			finst->rsCtext,
			finst->rsCtextSize,
			&finst->initialRS,
			&finst->initialRSSize);
		if(frtn) {
   		    dbgLog(("feeFEEDDecryptBlock: error decrypting "
		    	"initialRS (%s)\n", feeReturnString(frtn)));
		    return FR_BadCipherText;
		}

		/*
		 * we already know how long this should be...
		 */
		if(finst->initialRSSize != finst->initialRSSize) {
   		    dbgLog(("feeFEEDDecryptBlock: initialRS sync error\n"));
		    return FR_BadCipherText;
		}

		/*
		 * Set up clues
		 */
		if(initFromRS(finst)) {
   		    dbgLog(("feeFEEDDecryptBlock: bad initialRS\n"));
		    return FR_BadCipherText;
		}
		else {
		    /*
		     * Normal completion of last cipherblock containing
		     * initialRS.
		     */
			bprintf(("=== FEED Decrypt: gobbled 0x%x bytes ctext, no ptext (2)\n", 
				cipherTextLen));
		    *plainTextLen = 0;
		    return FR_Success;
		}
	}

	/*
	 * grab xm and clueByte from cipherText
	 */
	deserializeGiant(cipherText, finst->xm, finst->cp->minBytes);
	cipherText += finst->cp->minBytes;
	clueByte = *cipherText;

	if((clueByte & CLUE_BIT) == CLUE_PLUS) {
		thisClue = finst->cluePlus;
		thisS = finst->sPlus;
	}
	else {
		thisClue = finst->clueMinus;
		thisS = finst->sMinus;
	}
	if((clueByte & PARITY_BIT) == PARITY_PLUS) {
		parity = SIGN_PLUS;
	}
	else {
		parity = SIGN_MINUS;
	}

	/*
	 * recover xp
	 *     xp = xm + clue(+/-) w/parity
	 * adjust clue
	 *     clue[n+1] = r * clue[n] + (s * P1)
	 */
	elliptic_add(thisClue, finst->xm, finst->xp, finst->cp, parity);

	elliptic_simple(thisClue, finst->r, finst->cp);
	gtog(thisClue, finst->tmp1);
	elliptic_add(finst->tmp1, thisS, thisClue, finst->cp, SIGN_PLUS);

	/*
	 * plaintext in xp
	 */
	#if	FEED_DEBUG
	printf("decrypt  clue %d\n", clueByte);
	printf("  xp : "); printGiant(finst->xp);
	printf("  xm : "); printGiant(finst->xm);
	printf("  cluePlus  :"); printGiant(finst->cluePlus);
	printf("  clueMinus :"); printGiant(finst->clueMinus);
	#endif	// FEED_DEBUG

	if(finalBlock) {
		/*
		 * Snag data from xp in order to find out how much to move to
		 * *plainText
		 */
		unsigned char *ptext = (unsigned char*) fmalloc(finst->plainBlockSize);

		serializeGiant(finst->xp, ptext, finst->plainBlockSize);
		*plainTextLen = ptext[finst->plainBlockSize - 1];
		if(*plainTextLen == RESID_ZERO) {
			bprintf(("=== FEED Decrypt: RESID_ZERO\n"));
			*plainTextLen = 0;
		}
		else if(*plainTextLen > (finst->plainBlockSize - 1)) {
			dbgLog(("feeFEEDDecryptBlock: ptext overflow!\n"));
			bprintf(("feeFEEDDecryptBlock: ptext overflow!\n"));
			frtn = FR_BadCipherText;
		}
		else {
			bprintf(("=== FEED Decrypt: resid len 0x%x\n", *plainTextLen));
			bcopy(ptext, plainText, *plainTextLen);
		}
		ffree(ptext);
	}
	else {
		*plainTextLen = finst->plainBlockSize;
		serializeGiant(finst->xp, plainText, *plainTextLen);
	}
	bprintf(("=== FEED decryptBlock ptextLen 0x%x  ctextLen 0x%x\n",
		*plainTextLen, cipherTextLen));

	return frtn;
}
Ejemplo n.º 24
0
/*
 * Convenience routines to encrypt & decrypt multi-block data.
 */
feeReturn feeFEEDExpEncrypt(feeFEEDExp feed,
	const unsigned char *plainText,
	unsigned plainTextLen,
	unsigned char **cipherText,		// malloc'd and RETURNED
	unsigned *cipherTextLen)		// RETURNED
{
	const unsigned char	*ptext;			// per block
	unsigned		ptextLen;		// total to go
	unsigned		thisPtextLen;		// per block
	unsigned char		*ctext;			// per block
	unsigned		ctextLen;		// per block
	unsigned char		*ctextResult;		// to return
	unsigned		ctextResultLen;
	unsigned char		*ctextPtr;
	unsigned 		ctextLenTotal;		// running total
	feeReturn		frtn;
	int			finalBlock;
	unsigned		numBlocks;
	unsigned		plainBlockSize;

	if(plainTextLen == 0) {
		dbgLog(("feeFEEDExpDecrypt: NULL plainText\n"));
		return FR_IllegalArg;
	}

	ptext = plainText;
	ptextLen = plainTextLen;
	ctext = (unsigned char*) fmalloc(feeFEEDExpCipherBufSize(feed));
	plainBlockSize = feeFEEDExpPlainBlockSize(feed);
	numBlocks = (plainTextLen + plainBlockSize - 1)/plainBlockSize;
	ctextResultLen = (numBlocks + 1) * feeFEEDExpCipherBlockSize(feed);
	ctextResult = (unsigned char*) fmalloc(ctextResultLen);
	ctextPtr = ctextResult;
	ctextLenTotal = 0;

	while(1) {
		if(ptextLen <= plainBlockSize) {
			finalBlock = 1;
			thisPtextLen = ptextLen;
		}
		else {
			finalBlock = 0;
			thisPtextLen = plainBlockSize;
		}
		frtn = feeFEEDExpEncryptBlock(feed,
			ptext,
			thisPtextLen,
			ctext,
			&ctextLen,
			finalBlock);
		if(frtn) {
			dbgLog(("feeFEEDExpEncrypt: encrypt error: %s\n",
				feeReturnString(frtn)));
			break;
		}
		if(ctextLen == 0) {
			dbgLog(("feeFEEDExpEncrypt: null ciphertext\n"));
			frtn = FR_Internal;
			break;
		}
		bcopy(ctext, ctextPtr, ctextLen);
		ctextLenTotal += ctextLen;
		if(ctextLenTotal > ctextResultLen) {
			dbgLog(("feeFEEDExpEncrypt: ciphertext overflow\n"));
			frtn = FR_Internal;
			break;
		}
		if(finalBlock) {
			break;
		}
		ctextPtr += ctextLen;
		ptext += thisPtextLen;
		ptextLen -= thisPtextLen;
	}

	ffree(ctext);
	if(frtn) {
		ffree(ctextResult);
		*cipherText = NULL;
		*cipherTextLen = 0;
	}
	else {
		*cipherText = ctextResult;
		*cipherTextLen = ctextLenTotal;
		#if	FEE_DEBUG
		if(feeFEEDExpCipherTextSize(feed, plainTextLen) !=
			    ctextLenTotal) {
		    printf("feeFEEDExpEncrypt: feeFEEDCipherTextSize "
		    	"error!\n");
		    printf("ptext %d  exp ctext %d  actual ctext %d\n",
		    	plainTextLen,
			feeFEEDExpCipherTextSize(feed, plainTextLen),
			ctextLenTotal);
		}
		#endif	// FEE_DEBUG
	}
	return frtn;

}
/* 
 * Diffie-Hellman. Public key is specified either as a feePubKey or 
 * a ANSI X9.62 format public key string (0x04 | x | y). In either case
 * the caller must ensure that the two keys are on the same curve. 
 * Output data is fmalloc'd here; caller must free. Output data is 
 * exactly the size of the curve's modulus in bytes. 
 */
feeReturn feePubKeyECDH(
	feePubKey privKey,
	/* one of the following two is non-NULL */
	feePubKey pubKey,
	const unsigned char *pubKeyStr,
	unsigned pubKeyStrLen,
	/* output fmallocd and RETURNED here */
	unsigned char **output,
	unsigned *outputLen)
{
	feePubKey theirPub = pubKey;
	feeReturn frtn = FR_Success;
	pubKeyInst *privInst = (pubKeyInst *) privKey;
	
	if(privInst->privGiant == NULL) {
		dbgLog(("feePubKeyECDH: privKey not a private key\n"));
		return FR_IncompatibleKey;
	}
	
	if(theirPub == NULL) {
		if(pubKeyStr == NULL) {
			return FR_IllegalArg;
		}
		
		/* Cook up a public key with the same curveParams as the private key */
		feeDepth depth;
		frtn = curveParamsDepth(privInst->cp, &depth);
		if(frtn) {
			return frtn;
		}
		theirPub = feePubKeyAlloc();
		if(theirPub == NULL) {
			return FR_Memory;
		}
		frtn = feePubKeyInitFromECDSAPubBlob(theirPub, pubKeyStr, pubKeyStrLen, depth);
		if(frtn) {
			goto errOut;
		}
	}
	
	pubKeyInst *pubInst = (pubKeyInst *) theirPub;
	
	giant outputGiant = make_pad(privInst->privGiant, pubInst->plus);
	if(outputGiant == NULL) {
		dbgLog(("feePubKeyECDH: make_pad error\n"));
		frtn = FR_Internal;
	}
	else {
		*outputLen = (privInst->cp->q + 7) / 8;
		*output = (unsigned char *)fmalloc(*outputLen);
		if(*output == NULL) {
			frtn = FR_Memory;
			goto errOut;
		}
		serializeGiant(outputGiant, *output, *outputLen);
		freeGiant(outputGiant);
	}
errOut:
	if((pubKey == NULL) && (theirPub != NULL)) {
		feePubKeyFree(theirPub);
	}
	return frtn;
}
Ejemplo n.º 26
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;
}
Ejemplo n.º 27
0
/*
 * Decrypt (exactly) a block of data. Caller malloc's plainText. Always
 * generates feeFEEDExpPlainBlockSize of plaintext, unless finalBlock is
 * non-zero (in which case feeFEEDExpPlainBlockSize or less bytes of
 * plainText are generated).
 */
feeReturn feeFEEDExpDecryptBlock(feeFEEDExp feed,
	const unsigned char *cipherText,
	unsigned cipherTextLen,
	unsigned char *plainText,
	unsigned *plainTextLen,			// RETURNED
	int finalBlock)
{
	feedInst 	*finst = (feedInst *) feed;
	char 		g;
	int 		s;
	feeReturn	frtn = FR_Success;
	curveParams	*cp = finst->cp;
	
	if(finst->gPriv == NULL) {
		/*
		 * Can't decrypt without private data
		 */
		return FR_BadPubKey;
	}

	/*
	 * grab xm, xc, and g from cipherText
	 */
	deserializeGiant(cipherText, finst->xm, finst->cp->minBytes);
	cipherText += finst->cp->minBytes;
	deserializeGiant(cipherText, finst->xc, finst->cp->minBytes);
	cipherText += finst->cp->minBytes;
	g = *cipherText;
	#if	FEED_DEBUG
	printf("decrypt g=%d\n", g);
	printf("  privKey : "); PRINT_GIANT(finst->gPriv);
	printf("  xm : "); PRINT_GIANT(finst->xm);
	printf("  xc : "); PRINT_GIANT(finst->xc);
	#endif	// FEED_DEBUG

	if((g & CLUE_ELL_ADD_SIGN) == CLUE_ELL_ADD_SIGN_PLUS) {
		s = SIGN_PLUS;
	}
	else {
		s = SIGN_MINUS;
	}

	/*
	 * xc = r(P1?)
	 * xc := r(P1?)(pri) = xq
	 * xp = data + r(priB+) +/- pri(rB?)
	 */
	elliptic_simple(finst->xc, finst->gPriv, cp);
	#if	FEED_DEBUG
	printf(" xc1 : "); PRINT_GIANT(finst->xc);
	#endif
	elliptic_add(finst->xm, finst->xc, finst->xp, cp, s);

	/*
	 * plaintext in xp
	 */
	#if	FEED_DEBUG
	printf("  xp : "); PRINT_GIANT(finst->xp);
	#endif	// FEED_DEBUG

	if(finalBlock) {
		/*
		 * Snag data from xp in order to find out how much to move to
		 * *plainText
		 */
		unsigned char *ptext = (unsigned char*) fmalloc(finst->plainBlockSize);

		serializeGiant(finst->xp, ptext, finst->plainBlockSize);
		*plainTextLen = ptext[finst->plainBlockSize - 1];
		#if FEED_DEBUG
		printf("decrypt: resid 0x%x\n", *plainTextLen);
		#endif
		if(*plainTextLen == RESID_ZERO) {
			*plainTextLen = 0;
		}
		else if(*plainTextLen > (finst->plainBlockSize - 1)) {
		    dbgLog(("feeFEEDExpDecryptBlock: ptext overflow!\n"));
		    frtn = FR_BadCipherText;
		}
		else {
			bcopy(ptext, plainText, *plainTextLen);
		}
		ffree(ptext);
	}
	else {
		*plainTextLen = finst->plainBlockSize;
		serializeGiant(finst->xp, plainText, *plainTextLen);
	}
	return frtn;
}
/*
 * Sign specified block of data (most likely a hash result) using
 * specified feePubKey.
 */
feeReturn feeSigSign(feeSig sig,
	const unsigned char *data,   		// data to be signed
	unsigned dataLen,			// in bytes
	feePubKey pubKey)
{
	sigInst 		*sinst = (sigInst*) sig;
	giant 			messageGiant = NULL;
	unsigned 		maxlen;
	giant 			privGiant;
	unsigned		privGiantBytes;
	feeReturn 		frtn = FR_Success;
	unsigned		randBytesLen;
	unsigned		uDigits;	// alloc'd digits in sinst->u
	curveParams		*cp;

	if(pubKey == NULL) {
		return FR_BadPubKey;
	}
	cp = feePubKeyCurveParams(pubKey);
	if(cp == NULL) {
		return FR_BadPubKey;
	}
	
	privGiant = feePubKeyPrivData(pubKey);
	if(privGiant == NULL) {
		dbgLog(("Attempt to Sign without private data\n"));
		frtn = FR_IllegalArg;
		goto abort;
	}
	privGiantBytes = abs(privGiant->sign) * GIANT_BYTES_PER_DIGIT;

	/*
	 * Note PmX = m 'o' P1.
	 * Get message/digest as giant. May be significantly different
	 * in size from pubKey's basePrime.
	 */
	messageGiant = giant_with_data(data, dataLen);	    // M(text)
	randBytesLen = feePubKeyBitsize(pubKey) / 8;
	maxlen = max(randBytesLen, dataLen);

	/* leave plenty of room.... */
	uDigits = (3 * (privGiantBytes + maxlen)) / GIANT_BYTES_PER_DIGIT;
	sinst->u = newGiant(uDigits);
	gtog(privGiant, sinst->u);			    // u := ourPri
	mulg(messageGiant, sinst->u);			    // u *= M(text)
	addg(sinst->randGiant, sinst->u);		    // u += m

	/*
	 * Paranoia: we're using the curveParams from the caller's pubKey;
	 * this cp will have a valid x1OrderPlusRecip if pubKey is the same
	 * as the one passed to feeSigNewWithKey() (since feeSigNewWithKey
	 * called x1OrderPlusJustify()). But the caller could conceivably be
	 * using a different instance of their pubKey, in which case
	 * the key's cp->x1OrderPlusRecip may not be valid.
	 */
	calcX1OrderPlusRecip(cp);

	/* u := u mod x1OrderPlus */
	#if	SIG_DEBUG
	if(sigDebug) {
		printf("sigSign:\n");
		printf("u pre-modg  : ");
		printGiant(sinst->u);
	}
	#endif
	modg_via_recip(cp->x1OrderPlus, cp->x1OrderPlusRecip, sinst->u);

	#if	SIG_DEBUG
	if(sigDebug) {
		printf("privGiant   : ");
		printGiant(privGiant);
		printf("u           : ");
		printGiant(sinst->u);
		printf("messageGiant: ");
		printGiant(messageGiant);
		printf("curveParams :\n");
		printCurveParams(cp);
	}
	#endif	// SIG_DEBUG
abort:
	if(messageGiant) {
		freeGiant(messageGiant);
	}
	return frtn;
}
Ejemplo n.º 29
0
feeReturn feeFEEDExpDecrypt(feeFEEDExp feed,
	const unsigned char *cipherText,
	unsigned cipherTextLen,
	unsigned char **plainText,		// malloc'd and RETURNED
	unsigned *plainTextLen)			// RETURNED
{
	const unsigned char	*ctext;
	unsigned		ctextLen;		// total to go
	unsigned char		*ptext;			// per block
	unsigned		ptextLen;		// per block
	unsigned char		*ptextResult;		// to return
	unsigned char		*ptextPtr;
	unsigned 		ptextLenTotal;		// running total
	feeReturn		frtn = FR_Success;
	int			finalBlock;
	unsigned		numBlocks;
	unsigned		plainBlockSize =
					feeFEEDExpPlainBlockSize(feed);
	unsigned		cipherBlockSize =
					feeFEEDExpCipherBlockSize(feed);

	if(cipherTextLen % cipherBlockSize) {
		dbgLog(("feeFEEDExpDecrypt: unaligned cipherText\n"));
		return FR_BadCipherText;
	}
	if(cipherTextLen == 0) {
		dbgLog(("feeFEEDExpDecrypt: NULL cipherText\n"));
		return FR_BadCipherText;
	}

	ptext = (unsigned char*) fmalloc(plainBlockSize);
	ctext = cipherText;
	ctextLen = cipherTextLen;
	numBlocks = cipherTextLen / cipherBlockSize;
	ptextResult = (unsigned char*) fmalloc(plainBlockSize * numBlocks);
	ptextPtr = ptextResult;
	ptextLenTotal = 0;

	while(ctextLen) {
		if(ctextLen == cipherBlockSize) {
		    finalBlock = 1;
		}
		else {
		    finalBlock = 0;
		}
		frtn = feeFEEDExpDecryptBlock(feed,
			ctext,
			cipherBlockSize,
			ptext,
			&ptextLen,
			finalBlock);
		if(frtn) {
			dbgLog(("feeFEEDExpDecryptBlock: %s\n",
				feeReturnString(frtn)));
			break;
		}
		if(ptextLen == 0) {
			/*
			 * Normal termination case for
			 * plainTextLen % plainBlockSize == 0
			 */
			if(!finalBlock) {
			    dbgLog(("feeFEEDExpDecrypt: decrypt sync"
			    	" error!\n"));
			    frtn = FR_BadCipherText;
			}
			break;
		}
		else if(ptextLen > plainBlockSize) {
			dbgLog(("feeFEEDExpDecrypt: ptext overflow!\n"));
			frtn = FR_Internal;
			break;
		}
		else {
			bcopy(ptext, ptextPtr, ptextLen);
			ptextPtr += ptextLen;
			ptextLenTotal += ptextLen;
		}
		ctext += cipherBlockSize;
		ctextLen -= cipherBlockSize;
	}

	ffree(ptext);
	if(frtn) {
		ffree(ptextResult);
		*plainText = NULL;
		*plainTextLen = 0;
	}
	else {
		*plainText = ptextResult;
		*plainTextLen = ptextLenTotal;
	}
	return frtn;

}
feeReturn feeSigVerify(feeSig sig,
	const unsigned char *data,
	unsigned dataLen,
	feePubKey pubKey)
{
	pointProjStruct Q;
	giant 		messageGiant = NULL;
	pointProjStruct	scratch;
	sigInst 	*sinst = (sigInst*) sig;
	feeReturn	frtn;
	curveParams	*cp;
	key		origKey;		// may be plus or minus key

	if(sinst->PmX == NULL) {
		dbgLog(("sigVerify without parse!\n"));
		return FR_IllegalArg;
	}

	cp = feePubKeyCurveParams(pubKey);
	if(cp->curveType != FCT_Weierstrass) {
		return feeSigVerifyNoProj(sig, data, dataLen, pubKey);
	}

	borrowPointProj(&Q, cp->maxDigits);
	borrowPointProj(&scratch, cp->maxDigits);

	/*
	 * Q := P1
	 */
	gtog(cp->x1Plus, Q.x);
	gtog(cp->y1Plus, Q.y);
	int_to_giant(1, Q.z);

	messageGiant = 	giant_with_data(data, dataLen);	// M(ciphertext)

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

	/* scratch := theirPub */
	origKey = feePubKeyPlusCurve(pubKey);
	gtog(origKey->x, scratch.x);
	gtog(origKey->y, scratch.y);
	int_to_giant(1, scratch.z);

	#if	SIG_DEBUG
	if(sigDebug) {
		printf("verify origKey:\n");
		printKey(origKey);
		printf("messageGiant: ");
		printGiant(messageGiant);
		printf("curveParams:\n");
		printCurveParams(cp);
	}
	#endif	// SIG_DEBUG

	/* scratch := M 'o' theirPub */
	ellMulProjSimple(&scratch, messageGiant, cp);

	#if	SIG_DEBUG
	if(sigDebug) {
		printf("signature_compare, with\n");
		printf("p0 = Q:\n");
		printGiant(Q.x);
		printf("p1 = Pm:\n");
		printGiant(sinst->PmX);
		printf("p2 = scratch = R:\n");
		printGiant(scratch.x);
	}
	#endif	// SIG_DEBUG

	if(signature_compare(Q.x, sinst->PmX, scratch.x, cp)) {

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

    	returnPointProj(&Q);
    	returnPointProj(&scratch);
	return frtn;
}