Example #1
0
void subg(giant a, giant b)
/* b := b - a, any signs, any result. */
{
	int 		asgn = a->sign, bsgn = b->sign;

	if (asgn == 0)
		return;
	if (bsgn == 0)
	{
		gtog(a, b);
		negg(b);
		return;
	}
	if ((asgn < 0) != (bsgn < 0))
	{
		if (bsgn > 0)
		{
			negg(a);
			normal_addg(a, b);
			negg(a);
			return;
		}
		negg(b);
		normal_addg(a, b);
		negg(b);
		return;
	}
	if (bsgn > 0)
	{
		if (gcompg(b, a) >= 0)
		{
			normal_subg(a, b);
			return;
		}
		reverse_subg(a, b);
		negg(b);
		return;
	}
	negg(a);
	negg(b);
	if (gcompg(b, a) >= 0)
	{
		normal_subg(a, b);
		negg(a);
		negg(b);
		return;
	}
	reverse_subg(a, b);
	negg(a);
	return;
}
Example #2
0
/*
 * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style
 * curveParameters.
 */
int which_curve(giant x, curveParams *par)
 /* Returns (+-1) depending on whether x is on curve
   (+-)y^2 = x^3 + c x^2 + a x + b.
 */
{
    giant t1;
    giant t2;
    giant t3;
    int result;
    PROF_START;

    t1 = borrowGiant(par->maxDigits);
    t2 = borrowGiant(par->maxDigits);
    t3 = borrowGiant(par->maxDigits);

   /* First, set t2:= x^3 + c x^2 + a x + b. */
    gtog(x, t2); addg(par->c, t2);
    mulg(x, t2); addg(par->a, t2);  /* t2 := x^2 + c x + a. */
    feemod(par, t2);
    mulg(x, t2); addg(par->b, t2);
    feemod(par, t2);
    /* Next, test whether t2 is a square. */
    gtog(t2, t1);
    make_base(par, t3); iaddg(1, t3); gshiftright(1, t3); /* t3 = (p+1)/2. */
    feepowermodg(par, t1, t3); 		      /* t1 := t2^((p+1)/2) (mod p). */
    if(gcompg(t1, t2) == 0)
            result = CURVE_PLUS;
    else
            result = CURVE_MINUS;
    returnGiant(t1);
    returnGiant(t2);
    returnGiant(t3);
    PROF_END(whichCurveTime);
    return result;
}
void
gmersennemod(
	int 	n,
	giant 	g
)
/* g := g (mod 2^n - 1) */
{
    int the_sign;
    giant scratch3 = borrowGiant(g->capacity);
    giant scratch4 = borrowGiant(1);

    if ((the_sign = gsign(g)) < 0) absg(g);
    while (bitlen(g) > n) {
	gtog(g,scratch3);
	gshiftright(n,scratch3);
	addg(scratch3,g);
	gshiftleft(n,scratch3);
	subg(scratch3,g);
    }
    if(isZero(g)) goto out;
    int_to_giant(1,scratch3);
    gshiftleft(n,scratch3);
    int_to_giant(1,scratch4);
    subg(scratch4,scratch3);
    if(gcompg(g,scratch3) >= 0) subg(scratch3,g);
    if (the_sign < 0) {
	g->sign = -g->sign;
	addg(scratch3,g);
    }
out:
    returnGiant(scratch3);
    returnGiant(scratch4);
}
Example #4
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);
}
Example #5
0
void modg_via_recip(giant d, giant r, giant n)
/* This is the fastest mod of the present collection.
* n := n % d, where r is the precalculated
* steady-state reciprocal of d. */
{
	int		s = (bitlen(r) - 1), sign = n->sign;
	giant 	tmp, tmp2;

	if (isZero(d) || (d->sign < 0))
	{
		exit(SIGN);
	}

	tmp = popg();
	tmp2 = popg();

	n->sign = abs(n->sign);
	while (1)
	{
		gtog(n, tmp); gshiftright(s - 1, tmp);
		mulg(r, tmp);
		gshiftright(s + 1, tmp);
		mulg(d, tmp);
		subg(tmp, n);
		if (gcompg(n, d) >= 0)
			subg(d, n);
		if (gcompg(n, d) < 0)
			break;
	}
	if (sign >= 0)
		goto done;
	if (isZero(n))
		goto done;
	negg(n);
	addg(d, n);
done:
	pushg(2);
	return;
}
void addg(giant a, giant b)
/* b := b + a, any signs any result. */
{   int asgn = a->sign, bsgn = b->sign;
    if(asgn == 0) return;
    if(bsgn == 0) {
    	gtog(a,b);
	return;
    }
    if((asgn < 0) == (bsgn < 0)) {
    	if(bsgn > 0) {
		normal_addg(a,b);
		return;
	}
	negg(a); if(a != b) negg(b); normal_addg(a,b);  /* Fix REC 1 Dec 98. */
	negg(a); if(a != b) negg(b); return;  /* Fix REC 1 Dec 98. */
    }
    if(bsgn > 0) {
        negg(a);
	if(gcompg(b,a) >= 0) {
		normal_subg(a,b);
		negg(a);
		return;
	}
	reverse_subg(a,b);
	negg(a);
	negg(b);
	return;
    }
    negg(b);
    if(gcompg(b,a) < 0) {
    	reverse_subg(a,b);
	return;
    }
    normal_subg(a,b);
    negg(b);
    return;
}
Example #7
0
void modg(giant d, giant n)
/* n becomes n%d. n is arbitrary, but the denominator d must be positive! */
{
	if (cur_recip == NULL) {
		cur_recip = newgiant(current_max_size);
		cur_den = newgiant(current_max_size);
		gtog(d, cur_den);
		make_recip(d, cur_recip);
	}
	else if (gcompg(d, cur_den)) {
		gtog(d, cur_den);
		make_recip(d, cur_recip);
	}
	modg_via_recip(d, cur_recip, n);
}
Example #8
0
int signature_compare(giant p0x, giant p1x, giant p2x, curveParams *par)
/* Returns non-zero iff p0x cannot be the x-coordinate of the sum of two points whose respective x-coordinates are p1x, p2x. */
{
        int ret = 0;
        giant t1;
	giant t2;
        giant t3;
        giant t4;
        giant t5;

	PROF_START;

        t1 = borrowGiant(par->maxDigits);
	t2 = borrowGiant(par->maxDigits);
        t3 = borrowGiant(par->maxDigits);
        t4 = borrowGiant(par->maxDigits);
        t5 = borrowGiant(par->maxDigits);

        if(gcompg(p1x, p2x) == 0) {
		int_to_giant(1, t1);
		numer_double(p1x, t1, t2, par);
		denom_double(p1x, t1, t3, par);
		mulg(p0x, t3); subg(t3, t2);
		feemod(par, t2);
        } else {
		numer_plus(p1x, p2x, t1, par);
		gshiftleft(1, t1); feemod(par, t1);
		int_to_giant(1, t3);
		numer_times(p1x, t3, p2x, t3, t2, par);
		int_to_giant(1, t4); int_to_giant(1, t5);
		denom_times(p1x, t4 , p2x, t5, t3, par);
		/* Now we require t3 x0^2 - t1 x0 + t2 == 0. */
		mulg(p0x, t3); feemod(par, t3);
		subg(t1, t3); mulg(p0x, t3);
		feemod(par, t3);
		addg(t3, t2);
		feemod(par, t2);
        }

	if(!isZero(t2)) ret = SIGNATURE_INVALID;
        returnGiant(t1);
        returnGiant(t2);
        returnGiant(t3);
        returnGiant(t4);
        returnGiant(t5);
	PROF_END(sigCompTime);
	return(ret);
}
Example #9
0
void make_recip(giant d, giant r)
/* r becomes the steady-state reciprocal
* 2^(2b)/d, where b = bit-length of d-1. */
{
	int		b;
	giant 	tmp, tmp2;

	if (isZero(d) || (d->sign < 0))
	{
		exit(SIGN);
	}
	tmp = popg();
	tmp2 = popg();
	itog(1, r);
	subg(r, d);
	b = bitlen(d);
	addg(r, d);
	gshiftleft(b, r);
	gtog(r, tmp2);
	while (1)
	{
		gtog(r, tmp);
		squareg(tmp);
		gshiftright(b, tmp);
		mulg(d, tmp);
		gshiftright(b, tmp);
		addg(r, r);
		subg(tmp, r);
		if (gcompg(r, tmp2) <= 0)
			break;
		gtog(r, tmp2);
	}
	itog(1, tmp);
	gshiftleft(2 * b, tmp);
	gtog(r, tmp2);
	mulg(d, tmp2);
	subg(tmp2, tmp);
	itog(1, tmp2);
	while (tmp->sign < 0)
	{
		subg(tmp2, r);
		addg(d, tmp);
	}
	pushg(2);
}
Example #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;
}
static void bdivg(giant v, giant u)
/* u becomes greatest power of two not exceeding u/v. */
{
    int diff = bitlen(u) - bitlen(v);
    giant scratch7;

    if (diff<0) {
        int_to_giant(0,u);
        return;
    }
    scratch7 = borrowGiant(u->capacity);
    gtog(v, scratch7);
    gshiftleft(diff,scratch7);
    if(gcompg(u,scratch7) < 0) diff--;
    if(diff<0) {
        int_to_giant(0,u);
    	returnGiant(scratch7);
        return;
    }
    int_to_giant(1,u);
    gshiftleft(diff,u);
    returnGiant(scratch7);
}
Example #12
0
void
main(
	void
)
{
	giant 		x = newgiant(INFINITY), y = newgiant(INFINITY),
				p = newgiant(INFINITY), r = newgiant(100);
	int 		j;

   	printf("Give two integers x, y on separate lines:\n");
   	gin(x); 
   	gin(y); 

   	gtog(y, p);  /* p := y */
   	mulg(x, p);
   	printf("y * x = "); 
   	gout(p);

  	gtog(y, p);
   	subg(x, p);
   	printf("y - x = "); 
   	gout(p);

   	gtog(y, p);
   	addg(x, p);
   	printf("y + x = "); 
   	gout(p);

   	gtog(y, p);
   	divg(x, p);
   	printf("y div x = "); 
   	gout(p);

   	gtog(y, p);
   	modg(x, p);
   	printf("y mod x = "); 
   	gout(p);

   	gtog(y, p);
   	gcdg(x, p);
   	printf("GCD(x, y) = "); 
   	gout(p);
 
	/* Next, test which of x, y is greater. */
   	if (gcompg(x, y) < 0 ) 
   		printf("y is greater\n");
	else if (gcompg(x,y) == 0) 
		printf("x, y equal\n");
	else 
		printf("x is greater\n");

	/* Next, we see how a giant struct is comprised.
   	 * We make a random, bipolar number of about 100 
   	 * digits in base 65536. 
   	 */
	for (j=0; j < 100; j++) 
	{  /* Fill 100 digits randomly. */
		r->n[j] = (unsigned short)rand();
   	}
   	r->sign = 100 * (1 - 2*(rand()%2));

	/* Next, don't forget to check for leading zero digits,
     * even though such are unlikely. 
     */
   	j = abs(r->sign) - 1;
   	while ((r->n[j] == 0) && (j > 0)) 
   	{
   		--j;
   	}
   	r->sign = (j+1) * ((r->sign > 0) ? 1: -1);
   	printf("The random number: "); gout(r);

	/* Next, compare a large-FFT multiply with a standard,
     * grammar-school multiply. 
     */
   	itog(1, x); 
   	gshiftleft(65536, x); 
   	iaddg(1, x);
   	itog(5, y); 
   	gshiftleft(30000, y); 
   	itog(1, p); 
   	subg(p, y); 
	/* Now we multiply (2^65536 + 1)*(5*(2^30000) - 1). */
   	gtog(y, p);
   	mulg(x, p);  /* Actually invokes FFT method because
					bit lengths of x, y are sufficiently large. */
   	printf("High digit of (2^65536 + 1)*(5*(2^30000) - 1) via FFT mul: %d\n", (int) p->n[abs(p->sign)-1]);
   	fflush(stdout);
   	gtog(y, p);
   	grammarmulg(x, p);  /* Grammar-school method. */
   	printf("High digit via grammar-school mul: %d\n", (int) p->n[abs(p->sign)-1]);
   	fflush(stdout);

	/* Next, perform Fermat test for pseudoprimality. */
   	printf("Give prime candidate p:\n");
   	gin(p); 
   	gtog(p, y);
   	itog(1, x); subg(x, y);
   	itog(2, x);
   	powermodg(x, y, p);
   	if (isone(x)) 
   		printf("p is probably prime.\n");
	else 
		printf("p is composite.\n");
}
Example #13
0
/*
 * Encrypt a block or less of data. Caller malloc's cipherText.
 */
feeReturn feeFEEDExpEncryptBlock(feeFEEDExp feed,
	const unsigned char *plainText,
	unsigned plainTextLen,
	unsigned char *cipherText,
	unsigned *cipherTextLen,		// RETURNED
	int finalBlock)
{
	feedInst 		*finst = (feedInst *) feed;
	int 			index;				/* which curve (+/- 1) */
	char 			g = 0;				/* parity, which_curve bits in ciphertext */
	key 			B;
	unsigned char	*ptext;				/* for final block */
	unsigned		ctextLen;
	feeReturn		frtn = FR_Success;
	giant			x1;
	unsigned		randLen;
	curveParams		*cp = finst->cp;
    randLen = cp->minBytes+8; // +8bytes (64bits)  to reduce the biais when with reduction mod prime. Per FIPS186-4 - "Using Extra Random Bits"

	if(plainTextLen > finst->plainBlockSize) {
		return FR_IllegalArg;
	}
	else if ((plainTextLen < finst->plainBlockSize) && !finalBlock) {
		return FR_IllegalArg;
	}

	/*
	 * Init only on first encrypt
	 */
	if((finst->randFcn == NULL) && (finst->rand == NULL)) {
		finst->rand = feeRandAlloc();
	}
	if(finst->randData == NULL) {
		finst->randData = (unsigned char*) fmalloc(randLen);
	}
	
	/*
	 * plaintext as giant xp
	 */
	if(finalBlock) {
		ptext = (unsigned char*) fmalloc(finst->plainBlockSize);
		bzero(ptext, finst->plainBlockSize);
		if(plainTextLen) {
			/*
			 * 0 for empty block with resid length 0
			 */
			bcopy(plainText, ptext, plainTextLen);
		}
		if(plainTextLen < finst->plainBlockSize) {
		    if(plainTextLen == 0) {
		    	/*
				 * Special case - can't actually write zero here;
				 * it screws up deserializing the giant during
				 * decrypt
				 */
		        ptext[finst->plainBlockSize - 1] = RESID_ZERO;
		    }
		    else {
				ptext[finst->plainBlockSize - 1] = plainTextLen;
		    }
			#if FEED_DEBUG
			printf("encrypt: resid 0x%x\n", ptext[finst->plainBlockSize - 1]);
			#endif
		}
		/*
		 * else handle evenly aligned case below...
		 */
		deserializeGiant(ptext, finst->xp, finst->plainBlockSize);
		ffree(ptext);
	}
	else {
		deserializeGiant(plainText, finst->xp, plainTextLen);
	}
	#if	FEED_DEBUG
	printf("encrypt:\n");
	printf("  xp : "); PRINT_GIANT(finst->xp);
	#endif	// FEED_DEBUG

	/*
	 * pick curve B? that data lies upon
	 */
	index = which_curve(finst->xp, finst->cp);
	if(index == CURVE_PLUS) {
		B = finst->plus;
		x1 = finst->cp->x1Plus;
	}
	else {
		B = finst->minus;
		x1 = finst->cp->x1Minus;
	}
	#if	FEED_DEBUG
	printf("  which_curve: %s\n", 
		(index == CURVE_PLUS) ? "CURVE_PLUS" : "CURVE_MINUS");
	#endif

	/*
	 * random number as giant xaux
	 */
	if(finst->randFcn != NULL) {
		finst->randFcn(finst->randRef, finst->randData, randLen);
	}
	else {
		feeRandBytes(finst->rand, finst->randData, randLen);
	}
	deserializeGiant(finst->randData, finst->xaux, randLen);
	
	#if	FEE_DEBUG
	if(isZero(finst->xaux)) {
		printf("feeFEEDExpEncryptBlock: random xaux = 0!\n");
	}
	#endif	// FEE_DEBUG
	/*
	 * Justify random # to be in [2, minimumX1Order].
	 */
	lesserX1OrderJustify(finst->xaux, cp);
	#if		FEED_DEBUG
	printf(" xaux: "); PRINT_GIANT(finst->xaux);
	#endif	// FEED_DEBUG

	gtog(B->x, finst->xq);				// xq = pubB?
    elliptic_simple(finst->xq, finst->xaux, cp);
										// xq = r(pubB?)
	#if		FEED_DEBUG
	printf(" r(pubB?): "); PRINT_GIANT(finst->xq);
	#endif
	elliptic_add(finst->xp, finst->xq, finst->xm, cp, SIGN_PLUS);
										// xm = data + r(pubB?)
	gtog(x1, finst->xc);
    elliptic_simple(finst->xc, finst->xaux, cp);
										// xc = r(P1?)
	elliptic_add(finst->xm, finst->xq, finst->xaux, cp, SIGN_PLUS);
										// xaux = xm + xq (for curve +1)
										//      = (data + r(pubB?)) + r(pubB?)
	if(gcompg(finst->xaux, finst->xp) == 0) {
		g |= CLUE_ELL_ADD_SIGN_PLUS;
	}
	else {
		g |= CLUE_ELL_ADD_SIGN_MINUS;
		#if	FEED_DEBUG
		/* this better be true.... */
		elliptic_add(finst->xm, finst->xq, finst->xaux, cp, SIGN_MINUS);
		if(gcompg(finst->xaux, finst->xp)) {
			printf("*******elliptic_add(xm, xq, -1) != xp! *************\n");
			printf("  xq : "); PRINT_GIANT(finst->xq);
			printf("  ell_add(xm, xq, -1) : "); PRINT_GIANT(finst->xaux);
		}
		#endif
	}									// g = (xaux == data) ? add : subtract

	/*
	 * Ciphertext = (xm, xc, g)
	 */
	serializeGiant(finst->xm, cipherText, cp->minBytes);
	cipherText += cp->minBytes;
	serializeGiant(finst->xc, cipherText, cp->minBytes);
	cipherText += cp->minBytes;
	*cipherText++ = g;
	ctextLen = finst->cipherBlockSize;
	#if	FEED_DEBUG
	printf("  xm : "); PRINT_GIANT(finst->xm);
	printf("  xc : "); PRINT_GIANT(finst->xc);
	printf("   g : %d\n", g);
	#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

		#if FEED_DEBUG
		printf("encrypt: one more empty block\n");
		#endif
		frtn = feeFEEDExpEncryptBlock(feed,
			NULL,				// plainText not used
			0,				// resid
			cipherText,			// append...
			&moreCipher,
			1);
		if(frtn == FR_Success) {
			ctextLen += moreCipher;
		}
	}

	*cipherTextLen = ctextLen;
	return frtn;
}
Example #14
0
/*
 * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style
 * curveParameters.
 */
void elliptic_add(giant x1, giant x2, giant x3, curveParams *par, int s) {

 /* Addition algorithm for x3 = x1 + x2 on the curve, with sign ambiguity s.
    From theory, we know that if {x1,1} and {x2,1} are on a curve, then
    their elliptic sum (x1,1} + {x2,1} = {x3,1} must have x3 as one of two
    values:

       x3 = U/2 + s*Sqrt[U^2/4 - V]

    where sign s = +-1, and U,V are functions of x1,x2.  Tho present function
    is called a maximum of twice, to settle which of +- is s.  When a call
    is made, it is guaranteed already that x1, x2 both lie on the same curve
    (+- curve); i.e., which curve (+-) is not connected at all with sign s of
    the x3 relation.
  */

    giant cur_n;
    giant t1;
    giant t2;
    giant t3;
    giant t4;
    giant t5;

    PROF_START;
    cur_n = borrowGiant(par->maxDigits);
    t1 = borrowGiant(par->maxDigits);
    t2 = borrowGiant(par->maxDigits);
    t3 = borrowGiant(par->maxDigits);
    t4 = borrowGiant(par->maxDigits);
    t5 = borrowGiant(par->maxDigits);

    if(gcompg(x1, x2)==0) {
	int_to_giant(1, t1);
	numer_double(x1, t1, x3, par);
	denom_double(x1, t1, t2, par);
	binvg_cp(par, t2);
	mulg(t2, x3); feemod(par, x3);
	goto out;
    }
    numer_plus(x1, x2, t1, par);
    int_to_giant(1, t3);
    numer_times(x1, t3, x2, t3, t2, par);
    int_to_giant(1, t4); int_to_giant(1, t5);
    denom_times(x1, t4, x2, t5, t3, par);
    binvg_cp(par, t3);
    mulg(t3, t1); feemod(par, t1); /* t1 := U/2. */
    mulg(t3, t2); feemod(par, t2); /* t2 := V. */
    /* Now x3 will be t1 +- Sqrt[t1^2 - t2]. */
    gtog(t1, t4); gsquare(t4); feemod(par, t4);
    subg(t2, t4);
    make_base(par, cur_n); iaddg(1, cur_n); gshiftright(2, cur_n);
    	/* cur_n := (p+1)/4. */
    feepowermodg(par, t4, cur_n);      /* t4 := t2^((p+1)/4) (mod p). */
    gtog(t1, x3);
    if(s != SIGN_PLUS) negg(t4);
    addg(t4, x3);
    feemod(par, x3);

out:
    returnGiant(cur_n);
    returnGiant(t1);
    returnGiant(t2);
    returnGiant(t3);
    returnGiant(t4);
    returnGiant(t5);

    PROF_END(ellAddTime);
}
Example #15
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;
}
Example #16
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;
}
Example #17
0
static int sqrtmod(giant x, curveParams *cp)
/* If Sqrt[x] (mod p) exists, function returns 1, else 0.
   In either case x is modified, but if 1 is returned,
   x:= Sqrt[x] (mod p).
 */
{
	int rtn;
	giant t0 = borrowGiant(cp->maxDigits);
	giant t1 = borrowGiant(cp->maxDigits);
	giant t2 = borrowGiant(cp->maxDigits);
	giant t3 = borrowGiant(cp->maxDigits);
	giant t4 = borrowGiant(cp->maxDigits);

	giant p = cp->basePrime;

    	feemod(cp, x);			/* Justify the argument. */
    	gtog(x, t0);  /* Store x for eventual validity check on square root. */
    	if((p->n[0] & 3) == 3) {  /* The case p = 3 (mod 4). */
		gtog(p, t1);
		iaddg(1, t1); gshiftright(2, t1);
		powermodg(x, t1, cp);
		goto resolve;
    	}
	/* Next, handle case p = 5 (mod 8). */
    	if((p->n[0] & 7) == 5) {
		gtog(p, t1); int_to_giant(1, t2);
		subg(t2, t1); gshiftright(2, t1);
		gtog(x, t2);
		powermodg(t2, t1, cp);  /* t2 := x^((p-1)/4) % p. */
		iaddg(1, t1);
		gshiftright(1, t1); /* t1 := (p+3)/8. */
		if(isone(t2)) {
			powermodg(x, t1, cp);  /* x^((p+3)/8) is root. */
			goto resolve;
		} else {
			int_to_giant(1, t2); subg(t2, t1);
				/* t1 := (p-5)/8. */
			gshiftleft(2,x);
			powermodg(x, t1, cp);
			mulg(t0, x); addg(x, x); feemod(cp, x);
				/* 2x (4x)^((p-5)/8. */
			goto resolve;
		}
	}

	/* Next, handle tougher case: p = 1 (mod 8). */
	int_to_giant(2, t1);
	while(1) {  /* Find appropriate nonresidue. */
		gtog(t1, t2);
		gsquare(t2); subg(x, t2); feemod(cp, t2);
		if(jacobi_symbol(t2, cp) == -1) break;
		iaddg(1, t1);
	}  /* t2 is now w^2 in F_p^2. */
   	int_to_giant(1, t3);
   	gtog(p, t4); iaddg(1, t4); gshiftright(1, t4);
	powFp2(t1, t3, t2, t4, cp);
	gtog(t1, x);

resolve:
   	gtog(x,t1); gsquare(t1); feemod(cp, t1);
    	if(gcompg(t0, t1) == 0) {
		rtn = 1; 	/* Success. */
	}
	else {
		rtn = 0;	/* no square root */
	}
	returnGiant(t0);
	returnGiant(t1);
	returnGiant(t2);
	returnGiant(t3);
	returnGiant(t4);
	return rtn;
}
Example #18
0
void
feemod(curveParams *par, giant x)
{
    int sign, sign2;
    giant t1;
    giant t3;
    giant t4;
    giant t5;
    #if		FEEMOD_LOOP_TEST
    unsigned feemodLoops = 0;
    #endif	// FEEMOD_LOOP_TEST

    FEEMOD_CALL_INCR;		// for FEEMOD_LOOP_TEST
    INCR_FEEMODS;		// for ellipticMeasure
    PROF_INCR(numFeemod);	// for general profiling

    switch(par->primeType) {
        case FPT_Mersenne:
	    /*
	     * Super-optimized Mersenne prime modulus case
	     */
	    gmersennemod(par->q, x);
	    break;

        case FPT_FEE:
	    /*
	     * General 2**q-k case
	     */
	    sign = (x->sign < 0) ? -1 : 1;
	    sign2 = 1;
	    x->sign = abs(x->sign);
	    if(gcompg(par->basePrime, x) >= 0) {
	    	goto outFee;
	    }
	    t1 = borrowGiant(par->maxDigits);
	    t3 = borrowGiant(par->maxDigits);
	    t4 = borrowGiant(par->maxDigits);
	    t5 = borrowGiant(par->maxDigits);

	    /* Begin OPT: 11 Jan 98 REC. */
	    if( ((par->q & (GIANT_BITS_PER_DIGIT - 1)) == 0) &&
	        (par->k >= 0) &&
		(par->k < GIANT_DIGIT_MASK)) {

		/*
		 * Microscopic mod for certain regions of {q,k}
		 * parameter space.
		 */
		int j, digits, excess, max;
		giantDigit carry;
		giantDigit termHi;	// double precision
		giantDigit termLo;
		giantDigit *p1, *p2;

		digits = par->q >> GIANT_LOG2_BITS_PER_DIGIT;
		while(bitlen(x) > par->q) {
		    excess = (x->sign) - digits;
		    max = (excess > digits) ? excess : digits;
		    carry = 0;

		    p1 = &x->n[0];
		    p2 = &x->n[digits];

		    if(excess <= digits) {
			carry = VectorMultiply(par->k,
				p2,
				excess,
				p1);

			/* propagate final carry */
			p1 += excess;
			for(j = excess; j < digits; j++) {

			    /*
			     * term = *p1 + carry;
			     * *p1++ = term & 65535;
			     * carry = term >> 16;
			     */
			    termLo = giantAddDigits(*p1, carry, &carry);
			    *p1++ = termLo;
			}
		    } else {
			carry = VectorMultiply(par->k,
				p2,
				digits,
				p1);
			p1 += digits;
			p2 += digits;
			for(j = digits; j < excess; j++) {
			    /*
			     * term = (par->k)*(*p2++) + carry;
			     */
			    giantMulDigits(par->k,
			    	*p2++,
				&termLo,
				&termHi);
			    giantAddDouble(&termLo, &termHi, carry);

			    /*
			     * *p1++ = term & 65535;
			     * carry = term >> 16;
			     */
			    *p1++ = termLo;
			    carry = termHi;
			}
		    }

		    if(carry > 0) {
			x->n[max] = carry;
		    } else {
			while(--max){
			    if(x->n[max] != 0) break;
			}
		    }
		    x->sign = max + 1;
		    FEEMOD_LOOP_INCR;
		}
	    } else { /* Macroscopic mod for general PT_FEE case. */