예제 #1
0
pointProj newPointProj(unsigned numDigits)
{
	pointProj pt;

	pt = (pointProj) fmalloc(sizeof(pointProjStruct));
	pt->x = newGiant(numDigits);
	pt->y = newGiant(numDigits);
	pt->z = newGiant(numDigits);
	return(pt);
}
/*
 * Create a giant, initialized with specified char[] data.
 */
giant giant_with_data(const unsigned char *d, int len) {
    int numDigits = BYTES_TO_GIANT_DIGITS(len);
    giant result;

    result = newGiant(numDigits);
    deserializeGiant(d, result, len);
    return result;
}
예제 #3
0
/*
 * Key exchange atom.
 */
giant make_pad(giant privGiant, key publicKey) {
    curveParams *par = publicKey->cp;
    giant result = newGiant(par->maxDigits);

    gtog(publicKey->x, result);
    elliptic_simple(result, privGiant, par);
    return result;
}
예제 #4
0
key new_public(curveParams *cp, int twist) {
    key k;

    k = (key) fmalloc(sizeof(keystruct));
    k->cp = cp;
    k->twist = twist;

    k->x = newGiant(cp->maxDigits);
    if((twist == CURVE_PLUS) && (cp->curveType == FCT_Weierstrass)) {
		k->y = newGiant(cp->maxDigits);
    }
    else {
    	/*
		 * no projective algebra. We could optimize and save a few bytes
		 * here by setting y to NULL, but that really complicates things
		 * in may other places. Best to have a real giant.
		 */
		k->y = newGiant(1);
    }
    return(k);
}
예제 #5
0
giant copyGiant(giant x)
{
	int bytes;

	giant result = newGiant(x->capacity);

	/*
	 * 13 Jun 1997
	 * NO! this assumes packed alignment
	 */
	bytes = sizeof(giantstruct) +
		((x->capacity - 1) * GIANT_BYTES_PER_DIGIT);
	bcopy(x, result, bytes);
	return result;
}
/*
 * Init an empty feePubKey from a DER-encoded blob, public and private key versions. 
 */
feeReturn feePubKeyInitFromDERPubBlob(feePubKey pubKey,
	unsigned char *keyBlob,
	size_t keyBlobLen)
{
	pubKeyInst	*pkinst = (pubKeyInst *) pubKey;
	feeReturn	frtn;
	int			version;
	
	if(pkinst == NULL) {
		return FR_BadPubKey;
	}
	
	/* kind of messy, maybe we should clean this up. But new_public() does too
	 * much - e.g., it allocates the x and y which we really don't want */
	 memset(pkinst, 0, sizeof(pubKeyInst));
	 pkinst->plus = (key) fmalloc(sizeof(keystruct));
	 pkinst->minus = (key) fmalloc(sizeof(keystruct));
	 if((pkinst->plus == NULL) || (pkinst->minus == NULL)) {
		return FR_Memory;
	 }
	 memset(pkinst->plus, 0, sizeof(keystruct));
	 memset(pkinst->minus, 0, sizeof(keystruct));
	 pkinst->cp = NULL;
	 pkinst->privGiant = NULL;
	 pkinst->plus->twist  = CURVE_PLUS;
	 pkinst->minus->twist = CURVE_MINUS;
	 frtn = feeDERDecodePublicKey(keyBlob, 
		(unsigned)keyBlobLen,
		&version,			// currently unused
		&pkinst->cp,
		&pkinst->plus->x,
		&pkinst->minus->x,
		&pkinst->plus->y);
	if(frtn) {
		return frtn;
	}
	/* minus curve, y is not used */
	pkinst->minus->y = newGiant(1);
	int_to_giant(0, pkinst->minus->y);
	pkinst->plus->cp = pkinst->minus->cp = pkinst->cp;
	return FR_Success;
}
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;
}
예제 #8
0
/*
 * Alloc and init a feeFEEDExp object associated with specified feePubKey.
 */
feeFEEDExp feeFEEDExpNewWithPubKey(
	feePubKey pubKey,
	feeRandFcn randFcn,		// optional 
	void *randRef)
{
	feedInst 		*finst = (feedInst *) fmalloc(sizeof(feedInst));
	giant 			privGiant;

	finst->cp = curveParamsCopy(feePubKeyCurveParams(pubKey));
	finst->plus = new_public_with_key(feePubKeyPlusCurve(pubKey),
		finst->cp);
	finst->minus = new_public_with_key(feePubKeyMinusCurve(pubKey),
		finst->cp);

	/*
	 * These might yield NULL data; we can only encrypt in that case.
	 */
	privGiant = feePubKeyPrivData(pubKey);
	if(privGiant) {
		finst->gPriv = newGiant(finst->cp->maxDigits);
		gtog(privGiant, finst->gPriv);
	}
	else {
		finst->gPriv = NULL;
	}

	/*
	 * Conservative, rounding down, on plaintext blocks since we don't
	 * want to split bytes.
	 */
	if(finst->cp->primeType == FPT_General) {
	    unsigned blen = bitlen(finst->cp->basePrime);

	    finst->plainBlockSize = blen / 8;
	    if((blen % 8) == 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--;
	    }
	}

	/*
	 * One block of ciphertext - two giants (with implied sign) and a
	 * parity byte
	 */
	finst->cipherBlockSize = (2 * finst->cp->minBytes) + 1;

	finst->xp = newGiant(finst->cp->maxDigits);
	finst->xc = newGiant(finst->cp->maxDigits);
	finst->xq = newGiant(finst->cp->maxDigits);
	finst->xm = newGiant(finst->cp->maxDigits);
	finst->xaux = newGiant(finst->cp->maxDigits);
	finst->rand = NULL;
	finst->randData = NULL;
	finst->randFcn = randFcn;
	finst->randRef = randRef;
	return finst;
}
/*
 * 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;
}
/*
 * 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;
}
/*
 * 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;
}
예제 #12
0
giant borrowGiant(unsigned numDigits)
{
	giant 		result;

	#if	GIANTS_VIA_STACK

	unsigned 	stackNum;
	gstack 		*gs = gstacks;

	#if 	WARN_ZERO_GIANT_SIZE
	if(numDigits == 0) {
		printf("borrowGiant(0)\n");
		numDigits = gstacks[numGstacks-1].numDigits;
	}
	#endif	// WARN_ZERO_GIANT_SIZE

	/*
	 * Find appropriate stack
	 */
	if(numDigits <= MIN_GIANT_SIZE)
	        stackNum = 0;
	else if (numDigits <= (MIN_GIANT_SIZE << GIANT_SIZE_INCR))
	        stackNum = 1;
	else if (numDigits <= (MIN_GIANT_SIZE << (2 * GIANT_SIZE_INCR)))
	        stackNum = 2;
	else if (numDigits <= (MIN_GIANT_SIZE << (3 * GIANT_SIZE_INCR)))
	        stackNum = 3;
	else if (numDigits <= (MIN_GIANT_SIZE << (4 * GIANT_SIZE_INCR)))
	        stackNum = 4;
	else
		stackNum = numGstacks;

	if(stackNum >= numGstacks) {
		/*
		 * out of bounds; just malloc
		 */
		#if	LOG_GIANT_STACK_OVERFLOW
		gstackDbg(("giantFromStack overflow; numDigits %d\n",
			numDigits));
		#endif	// LOG_GIANT_STACK_OVERFLOW
		return newGiant(numDigits);
	}
 	gs = &gstacks[stackNum];

	#if	GIANT_MAC_DEBUG
	if((gs->numFree != 0) && (gs->stack == NULL)) {
		dblog0("borrowGiant: null stack!\n");
	}
	#endif
 
   	if(gs->numFree != 0) {
        	result = gs->stack[--gs->numFree];
	}
    	else {
		/*
		 * Stack empty; malloc
		 */
    		result = newGiant(gs->numDigits);
	}

	#else	/* GIANTS_VIA_STACK */

	result = newGiant(numDigits);

	#endif	/* GIANTS_VIA_STACK */

	PROF_INCR(numBorrows);
	return result;
}
예제 #13
0
int main(int argc, char **argv)
{
	int		arg;
	char		*argp;
	giant		*g1;
	giant		*g2;		// ditto
	unsigned char	*buf;		// random data
	unsigned	numDigits;
	unsigned	i;
	unsigned	numBytes;
	unsigned	mulgElapsed;
	unsigned	sqrElapsed;
	
	int 		loops = LOOPS_DEF;
	int		seedSpec = 0;
	unsigned	seed = 0;
	unsigned	maxSize = MAX_SIZE_DEF;
	unsigned	minSize = MIN_SIZE_DEF;
	int 		useOld = 0;
	
	initCryptKit();
	
	#if	macintosh
	argc = ccommand(&argv);
	#endif
	
	for(arg=1; arg<argc; arg++) {
		argp = argv[arg];
		switch(argp[0]) {
		    case 'x':
		    	maxSize = atoi(&argp[2]);
			break;
		    case 'n':
		    	minSize = atoi(&argp[2]);
			break;
		    case 'l':
		    	loops = atoi(&argp[2]);
			break;
		    case 'o':
		    	useOld = 1;
			break;
		    case 's':
			seed = atoi(&argp[2]);
			seedSpec = 1;
			break;
		    case 'h':
		    default:
		    	usage(argv);
		}
	}
	buf = malloc(maxSize);

	if(!seedSpec) {
		unsigned long	tim;
		time(&tim);
		seed = (unsigned)tim;
	}
	SRAND(seed);

	/*
	 * Scratch giants, big enough for anything. Malloc here, init with
	 * random data before each test
	 * note these mallocs will be too big in the useOld case...
	 */
	g1 = malloc(sizeof(giant) * loops);
	g2 = malloc(sizeof(giant) * loops);
    if((g1 == NULL) || (g2 == NULL)) {
    	printf("malloc error\n");
    	exit(1);
    }
	if(useOld) {
	    numDigits = ((2 * maxSize) + 1) / 2;
	}
	else {
	    numDigits = BYTES_TO_GIANT_DIGITS(2 * maxSize);
	}
	for(i=0; i<loops; i++) {
	    g1[i] = newGiant(numDigits);
	    g2[i] = newGiant(numDigits);
	    if((g1[i] == NULL) || (g2[i] == NULL)) {
	    	printf("malloc error\n");
	    	exit(1);
	    }
	}

	printf("Starting giants test: seed %d\n", seed);
	for(numBytes=minSize; numBytes<=maxSize; numBytes*=2) {
		    
		initRandGiants(numBytes, 
			buf,
			loops,
			g1, 
			g2);

		mulgElapsed = mulgTest(loops, g1, g2);
		initRandGiants(numBytes, 
			buf,
			loops,
			g1, 
			g2);

		sqrElapsed = squareTest(loops, g1, g2);
		printf("  bits : %4d   mulg : %3d ns   gsquare : %3d ns\n", 
			numBytes * 8, 
			mulgElapsed / loops,
			sqrElapsed / loops);

	} /* for numBytes */
	return 0;
}
예제 #14
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;
}
예제 #15
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;
}