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; }
/* * 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); }
/* * 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); }
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; }
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); }
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); }
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); }
/* * 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); }
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"); }
/* * 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; }
/* * 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); }
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; }
/* * 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; }
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; }
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. */