static feeReturn feeGenPrivate(pubKeyInst *pkinst, const unsigned char *passwd, unsigned passwdLen, char hashPasswd) { unsigned privLen; // desired size of pkinst->privData feeHash *hash = NULL; // a malloc'd array unsigned digestLen; // size of MD5 digest unsigned dataSize; // min(privLen, passwdLen) unsigned numDigests = 0; unsigned i; unsigned char *cp; unsigned toMove; // for this digest unsigned moved; // total digested unsigned char *digest = NULL; unsigned char *privData = NULL; // temp, before modg(curveOrder) giant corder; // lesser of two curve orders /* * generate privData which is just larger than the smaller * curve order. * We'll take the result mod the curve order when we're done. * Note we do *not* have to free corder - it's a pointer to a giant * in pkinst->cp. */ corder = lesserX1Order(pkinst->cp); CKASSERT(!isZero(corder)); privLen = (bitlen(corder) / 8) + 1; if(!hashPasswd) { /* * Caller trusts the incoming entropy. Verify it's big enough and proceed. */ if(passwdLen < privLen) { return FR_ShortPrivData; } privLen = passwdLen; privData = (unsigned char *)passwd; goto finishUp; } if(passwdLen < 2) { return FR_IllegalArg; } /* * Calculate how many MD5 digests we'll generate. */ if(privLen > passwdLen) { dataSize = passwdLen; } else { dataSize = privLen; } digestLen = feeHashDigestLen(); numDigests = (dataSize + digestLen - 1) / digestLen; hash = (void**) fmalloc(numDigests * sizeof(feeHash)); for(i=0; i<numDigests; i++) { hash[i] = feeHashAlloc(); } /* * fill digests with passwd data, digestLen (or resid length) * at a time. If (passwdLen > privLen), last digest will hash all * remaining passwd data. */ cp = (unsigned char *)passwd; moved = 0; for(i=0; i<numDigests; i++) { if(i == (numDigests - 1)) { // last digest toMove = passwdLen - moved; } else { toMove = digestLen; } feeHashAddData(hash[i], cp, toMove); cp += toMove; moved += toMove; } /* * copy digests to privData, up to privLen bytes. Pad with * additional copies of digests if necessary. */ privData = (unsigned char*) fmalloc(privLen); cp = privData; moved = 0; i = 0; // digest number for(moved=0; moved<privLen; ) { if((moved + digestLen) > privLen) { toMove = privLen - moved; } else { toMove = digestLen; } digest = feeHashDigest(hash[i++]); bcopy(digest, cp, toMove); cp += toMove; moved += toMove; if(i == numDigests) { i = 0; // wrap to 0, start padding } } finishUp: /* * Convert to giant, justify result to within [2, lesserX1Order] */ pkinst->privGiant = giant_with_data(privData, privLen); #if FEE_DEBUG if(isZero(pkinst->privGiant)) { printf("feeGenPrivate: privData = 0!\n"); } #endif // FEE_DEBUG lesserX1OrderJustify(pkinst->privGiant, pkinst->cp); if(hashPasswd) { memset(privData, 0, privLen); ffree(privData); for(i=0; i<numDigests; i++) { feeHashFree(hash[i]); } ffree(hash); } return FR_Success; }
/* * Obtain size of the modulus of privKey in bytes. */ size_t sslPrivKeyLengthInBytes(SSLPrivKey *privKey) { #if 0 /* Get the length of p + q (which is the size of the modulus) in bits. */ gi_uint16 bitLen = bitlen(&privKey->rsaKey.p.g) + bitlen(&privKey->rsaKey.q.g); /* Convert it to bytes. */ return (bitLen + 7) / 8; #else return SecKeyGetBlockSize(SECKEYREF(privKey)); #endif }
static void powermodg( giant x, giant n, curveParams *cp ) /* x becomes x^n (mod basePrime). */ { int len, pos; giant scratch2 = borrowGiant(cp->maxDigits); gtog(x, scratch2); int_to_giant(1, x); len = bitlen(n); pos = 0; while (1) { if (bitval(n, pos++)) { mulg(scratch2, x); feemod(cp, x); } if (pos>=len) break; gsquare(scratch2); feemod(cp, scratch2); } returnGiant(scratch2); }
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); }
/* * New, 13 Jan 1997. */ static void feepowermodg(curveParams *par, giant x, giant n) /* Power ladder. x := x^n (mod 2^q-k) */ { int len, pos; giant t1; PROF_START; t1 = borrowGiant(par->maxDigits); gtog(x, t1); int_to_giant(1, x); len = bitlen(n); pos = 0; while(1) { if(bitval(n, pos++)) { mulg(t1, x); feemod(par, x); } if(pos>=len) break; gsquare(t1); feemod(par, t1); } returnGiant(t1); PROF_END(powerModTime); }
void ellMulProj(pointProj pt0, pointProj pt1, giant k, curveParams *cp) /* General elliptic multiplication; pt1 := k*pt0 on the curve, with k an arbitrary integer. */ { giant x = pt0->x, y = pt0->y, z = pt0->z, xx = pt1->x, yy = pt1->y, zz = pt1->z; int ksign, hlen, klen, b, hb, kb; giant t0; CKASSERT(cp->curveType == FCT_Weierstrass); if(isZero(k)) { int_to_giant(1, xx); int_to_giant(1, yy); int_to_giant(0, zz); return; } t0 = borrowGiant(cp->maxDigits); ksign = k->sign; if(ksign < 0) negg(k); gtog(x,xx); gtog(y,yy); gtog(z,zz); gtog(k, t0); addg(t0, t0); addg(k, t0); /* t0 := 3k. */ hlen = bitlen(t0); klen = bitlen(k); for(b = hlen-2; b > 0; b--) { ellDoubleProj(pt1,cp); hb = bitval(t0, b); if(b < klen) kb = bitval(k, b); else kb = 0; if((hb != 0) && (kb == 0)) ellAddProj(pt1, pt0, cp); else if((hb == 0) && (kb !=0)) ellSubProj(pt1, pt0, cp); } if(ksign < 0) { ellNegProj(pt1, cp); k->sign = -k->sign; } returnGiant(t0); }
unsigned feePubKeyBitsize(feePubKey pubKey) { pubKeyInst *pkinst = (pubKeyInst *) pubKey; switch(pkinst->cp->primeType) { case FPT_General: /* cp->q is here for just this purpose */ case FPT_Mersenne: return pkinst->cp->q; case FPT_FEE: /* could be larger or smaller than 2^q-1 */ default: return bitlen(pkinst->cp->basePrime); } /* NOT REACHED */ return 0; }
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 gmersennemod(int n, giant g) { /* g becomes g mod ((2^n)-1) 31 Jul 96 modified REC. 17 Jan 97 modified REC. */ unsigned bits = n & (GIANT_BITS_PER_DIGIT - 1); unsigned digits = 1 + ((n-1) >> GIANT_LOG2_BITS_PER_DIGIT); int isPositive = (g->sign > 0); int j; int b; int size; int foundzero; giantDigit mask = (bits == 0) ? GIANT_DIGIT_MASK : (giantDigit)((1<<bits)-1); giant scratch1; b = bitlen(g); if(b < n) { unsigned numDigits = (n + GIANT_BITS_PER_DIGIT - 1) >> GIANT_LOG2_BITS_PER_DIGIT; giantDigit lastWord = 0; giantDigit bits = 1; if(g->sign >= 0) return; /* * Cons up ((2**n)-1), add to g. */ scratch1 = borrowGiant(numDigits + 1); scratch1->sign = numDigits; for(j=0; j<(int)(numDigits-1); j++) { scratch1->n[j] = GIANT_DIGIT_MASK; } /* * Last word has lower (n & (GIANT_BITS_PER_DIGIT-1)) bits set. */ for(j=0; j < (int)(n & (GIANT_BITS_PER_DIGIT-1)); j++) { lastWord |= bits; bits <<= 1; } scratch1->n[numDigits-1] = lastWord; addg(g, scratch1); /* One version. */ gtog(scratch1, g); returnGiant(scratch1); return; }
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); }
static void powFp2(giant a, giant b, giant w2, giant n, curveParams *cp) /* Perform powering in the field F_p^2: a + b w := (a + b w)^n (mod p), where parameter w2 is a quadratic nonresidue (formally equal to w^2). */ { int j; giant t6; giant t7; giant t8; giant t9; if(isZero(n)) { int_to_giant(1,a); int_to_giant(0,b); return; } t6 = borrowGiant(cp->maxDigits); t7 = borrowGiant(cp->maxDigits); t8 = borrowGiant(cp->maxDigits); t9 = borrowGiant(cp->maxDigits); gtog(a, t8); gtog(b, t9); for(j = bitlen(n)-2; j >= 0; j--) { gtog(b, t6); mulg(a, b); addg(b,b); feemod(cp, b); /* b := 2 a b. */ gsquare(t6); feemod(cp, t6); mulg(w2, t6); feemod(cp, t6); gsquare(a); addg(t6, a); feemod(cp, a); /* a := a^2 + b^2 w2. */ if(bitval(n, j)) { gtog(b, t6); mulg(t8, b); feemod(cp, b); gtog(a, t7); mulg(t9, a); addg(a, b); feemod(cp, b); mulg(t9, t6); feemod(cp, t6); mulg(w2, t6); feemod(cp, t6); mulg(t8, a); addg(t6, a); feemod(cp, a); } } returnGiant(t6); returnGiant(t7); returnGiant(t8); returnGiant(t9); return; }
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 powermodg(giant x, giant n, giant g) /* x becomes x^n (mod g). */ { int len, pos; giant scratch2 = popg(); gtog(x, scratch2); itog(1, x); len = bitlen(n); pos = 0; while (1) { if (bitval(n, pos++)) { mulg(scratch2, x); modg(g, x); } if (pos >= len) break; squareg(scratch2); modg(g, scratch2); } pushg(1); }
/* * General elliptic multiply. * * {xx, zz} := k * {xx, zz} */ void elliptic(giant xx, giant zz, giant k, curveParams *par) { int len = bitlen(k); int pos = len - 2; giant xs; giant zs; giant xorg; giant zorg; PROF_START; if(sequalg(1,k)) return; if(sequalg(2,k)) { ell_even(xx, zz, xx, zz, par); goto out; } zs = borrowGiant(par->maxDigits); xs = borrowGiant(par->maxDigits); zorg = borrowGiant(par->maxDigits); xorg = borrowGiant(par->maxDigits); gtog(xx, xorg); gtog(zz, zorg); ell_even(xx, zz, xs, zs, par); do { if(bitval(k, pos--)) { ell_odd(xs, zs, xx, zz, xorg, zorg, par); ell_even(xs, zs, xs, zs, par); } else { ell_odd(xx, zz, xs, zs, xorg, zorg, par); ell_even(xx, zz, xx, zz, par); } } while (pos >= 0); // REC fix 9/23/94 returnGiant(xs); returnGiant(zs); returnGiant(xorg); returnGiant(zorg); out: PROF_END(ellipticTime); }
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. */
/* * 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; }
/* * 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; }
int main(int argc, char **argv) { int arg; char *argp; unsigned sigLoops = SIGN_LOOPS_DEF; unsigned vfyLoops = VFY_LOOPS_DEF; unsigned numKeys = NUM_KEYS; // might be less for very small loops unsigned depth; feeRand rand; feePubKey keys[NUM_KEYS]; /* sigLoops copies of each of {digestData, sigData} */ FeeData *digestData; FeeData *sigData; unsigned seed; unsigned i; PLAT_TIME startTime; PLAT_TIME endTime; double elapsed; curveParams *cp; unsigned minDepth = 0; unsigned maxDepth = FEE_DEPTH_MAX; unsigned basePrimeLen; char *curveType; feeReturn frtn; for(arg=1; arg<argc; arg++) { argp = argv[arg]; switch(argp[0]) { case 's': sigLoops = atoi(&argp[2]); break; case 'v': vfyLoops = atoi(&argp[2]); break; case 'D': minDepth = maxDepth = atoi(&argp[2]); break; default: usage(argv); break; } } /* * Common random generator */ time((time_t *)&seed); rand = feeRandAllocWithSeed(seed); if(numKeys > sigLoops) { numKeys = sigLoops; } digestData = (FeeData *)fmalloc(sizeof(FeeData) * sigLoops); sigData = (FeeData *)fmalloc(sizeof(FeeData) * sigLoops); /* alloc the data, once, for largest private key or "digest" we'll use */ for(i=0; i<sigLoops; i++) { mallocData(&digestData[i], PRIV_KEY_SIZE_BYTES); } for(depth=minDepth; depth<=maxDepth; depth++) { /* * Get curve params for this depth */ cp = curveParamsForDepth(depth); if(cp == NULL) { printf("malloc failure\n"); exit(1); } switch(cp->curveType) { case FCT_Montgomery: curveType = "FCT_Montgomery"; break; case FCT_Weierstrass: curveType = "FCT_Weierstrass"; break; case FCT_General: curveType = "FCT_General"; break; default: printf("***Unknown curveType!\n"); exit(1); } switch(cp->primeType) { case FPT_General: printf("depth=%d; FPT_General, %s; keysize=%d;\n", depth, curveType, bitlen(cp->basePrime)); break; case FPT_Mersenne: printf("depth=%d; FPT_Mersenne, %s; q=%d\n", depth, curveType, cp->q); break; default: printf("depth=%d; FPT_FEE, %s; q=%d k=%d\n", depth, curveType, cp->q, cp->k); break; } basePrimeLen = bitlen(cp->basePrime); /* one set of random data as private keys */ unsigned privSize = (basePrimeLen + 8) / 8; genRandData(digestData, numKeys, privSize, rand); /* generate the keys (no hash - we've got that covered) */ for(i=0; i<numKeys; i++) { keys[i] = feePubKeyAlloc(); feePubKeyInitFromPrivDataDepth(keys[i], digestData[i].data, privSize, depth, 0); } /* now different data to actually sign */ genRandData(digestData, sigLoops, DIGEST_SIZE_BYTES, rand); /* * sign */ PLAT_GET_TIME(startTime); for(i=0; i<sigLoops; i++) { FeeData *digst = &digestData[i]; FeeData *sig = &sigData[i]; feePubKey fkey = keys[i % numKeys]; feeSig fs = feeSigNewWithKey(fkey, randCallback, rand); frtn = feeSigSign(fs, digst->data, digst->length, fkey); if(frtn) { printf("***Error %d on feeSigSign\n", (int)frtn); break; } frtn = feeSigData(fs, &sig->data, &sig->length); if(frtn) { printf("***Error %d on feeSigData\n", (int)frtn); break; } feeSigFree(fs); } PLAT_GET_TIME(endTime); elapsed = PLAT_GET_US(startTime, endTime); printf(" sign: %12.2f us per op\n", elapsed / sigLoops); /* * verify - might be doing more of these than we have * valid signatures..... */ unsigned dex=0; PLAT_GET_TIME(startTime); for(i=0; i<vfyLoops; i++) { FeeData *digst = &digestData[dex]; FeeData *sig = &sigData[dex]; feePubKey fkey = keys[dex % numKeys]; feeSig fs; frtn = feeSigParse(sig->data, sig->length, &fs); if(frtn) { printf("***Error %d on feeSigParse\n", (int)frtn); break; } frtn = feeSigVerify(fs, digst->data, digst->length, fkey); if(frtn) { printf("***Error %d on feeSigVerify\n", (int)frtn); break; } feeSigFree(fs); dex++; if(dex == sigLoops) { /* that's all the data we have, recycle */ dex = 0; } } PLAT_GET_TIME(endTime); elapsed = PLAT_GET_US(startTime, endTime); printf(" verify: %12.2f us per op\n", elapsed / vfyLoops); freeCurveParams(cp); /* possibly limited number of signatures.... */ for(i=0; i<sigLoops; i++) { ffree(sigData[i].data); // mallocd by feeSigData() } for(i=0; i<numKeys; i++) { feePubKeyFree(keys[i]); } } feeRandFree(rand); for(i=0; i<sigLoops; i++) { ffree(digestData[i].data); } ffree(digestData); ffree(sigData); return 0; }