-/*
- * atomTime.c - measure performance of mulg, gsquare, feemod,
- * gshift{left,right}, elliptic, ellMulProj
- */
-
-#include "ckconfig.h"
-#include "ckutilsPlatform.h"
-#include "CryptKitSA.h"
-#include "ckutilities.h" /* needs private headers */
-#include "curveParams.h" /* ditto */
-#include "falloc.h" /* ditto */
-#include "elliptic.h"
-#include "ellipticProj.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-
-/* default loops for "fast" and "slow" ops respecitively */
-#define LOOPS_DEF_FAST 10000
-#define LOOPS_DEF_SLOW 100
-
-#define NUM_BORROW 100
-
-/* individual enables - normally all on, disable to zero in on one test */
-#define MULG_ENABLE 1
-#define GSQUARE_ENABLE 1
-#define FEEMOD_ENABLE 1
-#define BORROW_ENABLE 1
-#define SHIFT_ENABLE 1
-#define BINVAUX_ENABLE 1
-#define MAKE_RECIP_ENABLE 1
-#define MODGRECIP_ENABLE 1
-#define KEYGEN_ENABLE 1
-#define ELLIPTIC_ENABLE 1
-#define ELL_SIMPLE_ENABLE 1
-
-static void usage(char **argv)
-{
- printf("Usage: %s [l=loops_fast] [L=loops_slow] [q(uick)] [D=depth]\n", argv[0]);
- exit(1);
-}
-
-/*
- * Fill numGiants with random data of length bits.
- */
-static void genRandGiants(giant *giants,
- unsigned numGiants,
- unsigned bits,
- feeRand rand)
-{
- int i;
- giant g;
- unsigned char *rdata;
- unsigned bytes = (bits + 7) / 8;
- giantDigit mask = 0;
- unsigned giantMsd = 0; // index of MSD
- unsigned log2BitsPerDigit;
- unsigned bitsPerDigit;
-
- /* just to satisfy compiler - make sure it's always called */
- if(giants == NULL) {
- return;
- }
-
- log2BitsPerDigit = GIANT_LOG2_BITS_PER_DIGIT;
- bitsPerDigit = GIANT_BITS_PER_DIGIT;
-
- if((bits & 7) != 0) {
- /*
- * deserializeGiant() has a resolution of one byte. We
- * need more resolution - that is, we'll be creating
- * giants a little larger than we need, and we'll mask off
- * some bits in the giants' m.s. digit.
- * This assumes that data fills the giantDigits such
- * that if bytes mod GIANT_BYTES_PER_DIGIT != 0, the
- * empty byte(s) in the MSD are in the m.s. byte(s).
- */
- giantMsd = bits >> log2BitsPerDigit;
- mask = (1 << (bits & (bitsPerDigit - 1))) - 1;
- }
- rdata = fmalloc(bytes);
- for(i=0; i<numGiants; i++) {
- g = giants[i];
- feeRandBytes(rand, rdata, bytes);
- deserializeGiant(rdata, g, bytes);
- if(mask != 0) {
- int j;
-
- g->n[giantMsd] &= mask;
-
- /*
- * We've zeroed out some bits; we might have to
- * adjust the sign of the giant as well. Note that
- * deserializeGiant always yields positive
- * giants....
- */
- for(j=(g->sign - 1); j!=0; j--) {
- if(g->n[j] == 0) {
- (g->sign)--;
- }
- else {
- break;
- }
- }
- }
- }
- ffree(rdata);
- return;
-}
-
-#if CRYPTKIT_ELL_PROJ_ENABLE
-/*
- * Assumes the presence of numEllPoints items in *points, and that the
- * x coordinate in each point is init'd to a random giant. Uses the x
- * coords as seeds to make normalized points of the entire *points array.
- */
-static void makePoints(pointProjStruct *points,
- unsigned numEllPoints,
- curveParams *cp)
-{
- int i;
- giant seed = newGiant(cp->maxDigits);
-
- for(i=0; i<numEllPoints; i++) {
- gtog(points[i].x, seed);
- findPointProj(&points[i], seed, cp);
- }
- freeGiant(seed);
-}
-
-#endif /* CRYPTKIT_ELL_PROJ_ENABLE */
-
-int main(int argc, char **argv)
-{
- int arg;
- char *argp;
- unsigned loopsFast = LOOPS_DEF_FAST;
- unsigned loopsSlow = LOOPS_DEF_SLOW;
- unsigned maxLoops;
- unsigned depth;
- feeRand rand;
- giant *giants;
- unsigned seed;
- int i;
- int j;
- PLAT_TIME startTime;
- PLAT_TIME endTime;
- double elapsed;
- unsigned numGiants;
- #if CRYPTKIT_ELL_PROJ_ENABLE
- unsigned numEllGiants; // for elliptic ops
- unsigned numEllPoints; // for elliptic ops
- #endif
- curveParams *cp;
- unsigned quick = 0;
- unsigned minDepth = 0;
- unsigned maxDepth = FEE_DEPTH_MAX;
- unsigned basePrimeLen;
- int *shiftCnt;
- char *curveType;
- #if CRYPTKIT_ELL_PROJ_ENABLE
- pointProjStruct *points;
- #endif
- giant z = NULL;
- giant modGiant = NULL;
- giant recip = NULL;
- feePubKey *keyArray = NULL;
- giant gborrow[NUM_BORROW];
-
- /* just to satisfy compiler - make sure it's always called */
- genRandGiants(NULL, 0, 0, 0);
-
- for(arg=1; arg<argc; arg++) {
- argp = argv[arg];
- switch(argp[0]) {
- case 'l':
- loopsFast = atoi(&argp[2]);
- break;
- case 'L':
- loopsSlow = atoi(&argp[2]);
- break;
- case 'q':
- quick = 1;
- break;
- case 'D':
- minDepth = maxDepth = atoi(&argp[2]);
- break;
- default:
- usage(argv);
- break;
- }
- }
-
- /*
- * Common random generator
- */
- time((unsigned long *)&seed);
- rand = feeRandAllocWithSeed(seed);
-
- maxLoops = loopsFast;
- if(loopsSlow > maxLoops) {
- maxLoops = loopsSlow;
- }
-
- /*
- * Alloc array of giants big enough for squaring at the largest
- * key size, enough of them for 'loops' mulgs
- */
- cp = curveParamsForDepth(FEE_DEPTH_LARGEST);
- numGiants = maxLoops * 2; // 2 giants per loop
- if(loopsSlow > (maxLoops / 4)) {
- /* findPointProj needs 4 giants per loop */
- numGiants *= 4;
- }
- #if CRYPTKIT_ELL_PROJ_ENABLE
- numEllGiants = loopsSlow * 2;
- numEllPoints = loopsSlow * 2;
- #endif
- giants = fmalloc(numGiants * sizeof(giant));
- if(giants == NULL) {
- printf("malloc failure\n");
- exit(1);
- }
- for(i=0; i<numGiants; i++) {
- giants[i] = newGiant(cp->maxDigits);
- if(giants[i] == NULL) {
- printf("malloc failure\n");
- exit(1);
- }
- }
- freeCurveParams(cp);
-
- #if CRYPTKIT_ELL_PROJ_ENABLE
- /*
- * Projective points - two per ellLoop. The giants come from
- * giants[]. We reserve an extra giant per point.
- * We're assuming that numEllPoints < (4 * numGiants).
- */
- points = fmalloc(numEllPoints * sizeof(pointProjStruct));
- if(points == NULL) {
- printf("malloc failure\n");
- exit(1);
- }
- j=0;
- for(i=0; i<numEllPoints; i++) {
- points[i].x = giants[j++];
- points[i].y = giants[j++];
- points[i].z = giants[j++];
- j++; // skip a giant
- }
- #endif
-
- /* feePubKey array */
- keyArray = fmalloc(sizeof(feePubKey) * loopsSlow);
- if(keyArray == NULL) {
- printf("malloc failure\n");
- exit(1);
- }
-
- /*
- * Alloc an array of shiftCnt ints
- */
- shiftCnt = fmalloc(maxLoops * sizeof(int));
- if(shiftCnt == NULL) {
- printf("malloc failure\n");
- exit(1);
- }
-
- for(depth=minDepth; depth<=maxDepth; depth++) {
-
- if(quick) {
- if((depth != FEE_DEPTH_127M) &&
- (depth != FEE_DEPTH_161W)) {
- continue;
- }
- }
-
- /*
- * 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);
-
- /*
- * mulg test
- * bitlen(giant) <= bitlen(basePrime);
- * giants[n+1] *= giants[n]
- */
- #if MULG_ENABLE
- genRandGiants(giants, numGiants, basePrimeLen, rand);
- PLAT_GET_TIME(startTime);
- for(i=0; i<numGiants; i+=2) {
- mulg(giants[i], giants[i+1]);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_NS(startTime, endTime);
- printf(" mulg: %12.2f ns per op\n",
- elapsed / (numGiants / 2));
- #endif /* MULG_ENABLE */
-
- /*
- * gsquare test
- * bitlen(giant) <= bitlen(basePrime);
- * gsquare(giants[n])
- */
- #if GSQUARE_ENABLE
- genRandGiants(giants, numGiants, basePrimeLen, rand);
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsFast; i++) {
- gsquare(giants[i]);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_NS(startTime, endTime);
- printf(" gsquare: %12.2f ns per op\n", elapsed / loopsFast);
- #endif /* GSQUARE_ENABLE */
-
- /*
- * feemod test
- * bitlen(giant) <= ((2 * bitlen(basePrime) - 2);
- * feemod(giants[n])
- */
- #if FEEMOD_ENABLE
- genRandGiants(giants, numGiants, (basePrimeLen * 2) - 2,
- rand);
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsFast; i++) {
- feemod(cp, giants[i]);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_NS(startTime, endTime);
- printf(" feemod: %12.2f ns per op\n", elapsed / loopsFast);
- #endif /* FEEMOD_ENABLE */
-
-
- /*
- * borrowGiant test
- */
- #if BORROW_ENABLE
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsFast; i++) {
- for(j=0; j<NUM_BORROW; j++) {
- gborrow[j] = borrowGiant(cp->maxDigits);
- }
- for(j=0; j<NUM_BORROW; j++) {
- returnGiant(gborrow[j]);
- }
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_NS(startTime, endTime);
- printf(" borrow/return: %12.2f ns per op\n",
- elapsed / (loopsFast * NUM_BORROW));
- #endif /* BORROW_ENABLE */
-
- /*
- * shiftright test
- * bitlen(giant) <= bitlen(basePrime)
- * 0 <= shiftCnt <= bitlen(basePrime)
- * gshiftright(giants[i])
- */
- #if SHIFT_ENABLE
- genRandGiants(giants, numGiants, basePrimeLen, rand);
- for(i=0; i<loopsFast; i++) {
- shiftCnt[i] = feeRandNextNum(rand) % basePrimeLen;
- }
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsFast; i++) {
- gshiftright(shiftCnt[i], giants[i]);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_NS(startTime, endTime);
- printf(" gshiftright: %12.2f ns per op\n", elapsed / loopsFast);
-
- /*
- * shiftleft test
- * bitlen(giant) <= bitlen(basePrime)
- * 1 <= shiftCnt <= bitlen(basePrime)
- * gshiftleft(giants[i]
- */
- genRandGiants(giants, numGiants, basePrimeLen, rand);
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsFast; i++) {
- gshiftright(shiftCnt[i], giants[i]);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_NS(startTime, endTime);
- printf(" gshiftleft: %12.2f ns per op\n", elapsed / loopsFast);
- #endif /* SHIFT_ENABLE */
-
- /*
- * binvaux test
- * bitlen(giant) <= bitlen(basePrime);
- * binvaux(basePrime, giants[n+1])
- */
- #if BINVAUX_ENABLE
- genRandGiants(giants, loopsSlow, basePrimeLen, rand);
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsSlow; i++) {
- binvaux(cp->basePrime, giants[i]);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_US(startTime, endTime);
- printf(" binvaux: %12.2f us per op\n",
- elapsed / loopsSlow);
- #endif /* BINVAUX_ENABLE */
-
- /*
- * make_recip test
- * bitlen(giant) <= bitlen(basePrime);
- * make_recip(giants[n], giants[n+1]
- */
- #if MAKE_RECIP_ENABLE
- genRandGiants(giants, numGiants, basePrimeLen, rand);
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsSlow*2; i+=2) {
- make_recip(giants[i], giants[i+1]);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_US(startTime, endTime);
- printf(" make_recip: %12.2f us per op\n",
- elapsed / loopsSlow);
- #endif /* MAKE_RECIP_ENABLE */
-
- /*
- * modg_via_recip test
- * bitlen(giant) <= ((2 * bitlen(basePrime) - 2);
- * bitlen(modGiant) <= bitlen(basePrime)
- * calc recip of modGiant
- * modg_via_recip(giants[i])
- */
- #if MODGRECIP_ENABLE
- genRandGiants(giants, numGiants, (basePrimeLen * 2) - 2,
- rand);
- modGiant = borrowGiant(cp->maxDigits);
- recip = borrowGiant(cp->maxDigits);
- genRandGiants(&modGiant, 1, basePrimeLen, rand);
- make_recip(modGiant, recip);
-
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsSlow; i++) {
- modg_via_recip(modGiant, recip, giants[i]);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_NS(startTime, endTime);
- printf(" modg_via_recip: %12.2f ns per op\n",
- elapsed / loopsSlow);
- returnGiant(modGiant);
- modGiant = NULL;
- returnGiant(recip);
- recip = NULL;
- #endif /* MODGRECIP_ENABLE */
-
- /*
- * key generate test
- * keyArray[n] = feePubKeyAlloc();
- * feePubKeyInitFromPrivData(keyArray[n] );
- */
- #if KEYGEN_ENABLE
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsSlow; i++) {
- keyArray[i] = feePubKeyAlloc();
- if(keyArray[i] == NULL) {
- printf("malloc failure\n");
- exit(1);
- }
- /* fixme how about some better seed data */
- feePubKeyInitFromPrivDataDepth(keyArray[i],
- (unsigned char *)"somePrivData",
- 12,
- depth,
- 1);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_US(startTime, endTime);
- printf(" keygen: %12.2f us per op\n",
- elapsed / loopsSlow);
- for(i=0; i<loopsSlow; i++) {
- feePubKeyFree(keyArray[i]);
- }
- #endif /* KEYGEN_ENABLE*/
-
- /*
- * elliptic test
- * bitlen(giant) <= bitlen(basePrime);
- * {giants[n], 1} *= giants[n+1] (elliptic mult)
- */
- #if ELLIPTIC_ENABLE
- genRandGiants(giants, numGiants, basePrimeLen, rand);
- z = borrowGiant(cp->maxDigits);
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsSlow; i+=2) {
- /* superoptimized int_to_giant(1) */
- z->n[0] = 1;
- z->sign = 1;
- elliptic(giants[i], z, giants[i+1], cp);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_US(startTime, endTime);
- printf(" elliptic: %12.2f us per op\n",
- elapsed / (loopsSlow / 2));
- #endif /* ELLIPTIC_ENABLE*/
-
- /*
- * elliptic_simple test
- * bitlen(giant) <= bitlen(basePrime);
- * giants[n] *= giants[n+1] (elliptic mult)
- */
- #if ELL_SIMPLE_ENABLE
- genRandGiants(giants, numGiants, basePrimeLen, rand);
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsSlow*2; i+=2) {
- elliptic_simple(giants[i], giants[i+1], cp);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_US(startTime, endTime);
- printf(" elliptic_simple: %12.2f us per op\n",
- elapsed / loopsSlow);
- #endif /* ELL_SIMPLE_ENABLE */
-
- if(cp->curveType != FCT_Weierstrass) {
- goto loopEnd;
- }
-
- #if CRYPTKIT_ELL_PROJ_ENABLE
- /*
- * ellMulProj test
- * bitlen(giant) <= bitlen(basePrime);
- * point[n+1] = point[n] * giants[4n+3]
- *
- * note we're cooking up way more giants than we have to;
- * we really only need the x's and k's. But what the heck.
- */
- genRandGiants(giants, 4 * numEllPoints, basePrimeLen, rand);
- makePoints(points, numEllPoints, cp);
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsSlow; i+=2) {
- ellMulProj(&points[i], &points[i+1],
- giants[4*i+3], cp);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_US(startTime, endTime);
- printf(" ellMulProj: %12.2f us per op\n",
- elapsed / (loopsSlow / 2));
-
- /*
- * ellMulProjSimple test
- * bitlen(giant) <= bitlen(basePrime);
- * point[n] *= giants[4n+3] (projective elliptic mult)
- */
- genRandGiants(giants, 4 * numEllPoints, basePrimeLen, rand);
- makePoints(points, numEllPoints, cp);
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsSlow; i++) {
- ellMulProjSimple(&points[i], giants[4*i+3], cp);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_US(startTime, endTime);
- printf(" ellMulProjSimple: %12.2f us per op\n",
- elapsed / loopsSlow);
-
- /*
- * ellAddProj test
- * bitlen(giant) <= bitlen(basePrime);
- * point[n] += point[n+1] (projective elliptic add)
- */
- genRandGiants(giants, 4 * numEllPoints, basePrimeLen, rand);
- makePoints(points, numEllPoints, cp);
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsSlow; i+=2) {
- ellAddProj(&points[i], &points[i+1], cp);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_NS(startTime, endTime);
- printf(" ellAddProj: %12.2f ns per op\n",
- elapsed / loopsSlow);
-
- /*
- * ellDoubleProj test
- * bitlen(giant) <= bitlen(basePrime);
- * ellDoubleProj(point[n])
- */
- genRandGiants(giants, 4 * numEllPoints, basePrimeLen, rand);
- makePoints(points, numEllPoints, cp);
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsSlow; i++) {
- ellDoubleProj(&points[i], cp);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_NS(startTime, endTime);
- printf(" ellDoubleProj: %12.2f ns per op\n",
- elapsed / loopsSlow);
-
- /*
- * findPointProj test
- * bitlen(giant) <= bitlen(basePrime);
- * findPointProj(point[n], giants[4n+3])
- */
- genRandGiants(giants, 4 * loopsSlow, basePrimeLen, rand);
- PLAT_GET_TIME(startTime);
- for(i=0; i<loopsSlow; i++) {
- findPointProj(&points[i], giants[4*i + 3], cp);
- }
- PLAT_GET_TIME(endTime);
- elapsed = PLAT_GET_US(startTime, endTime);
- printf(" findPointProj: %12.2f us per op\n",
- elapsed / loopsSlow);
-
- #endif /* CRYPTKIT_ELL_PROJ_ENABLE */
-
-loopEnd:
- freeCurveParams(cp);
- }
-
- feeRandFree(rand);
- for(i=0; i<numGiants; i++) {
- freeGiant(giants[i]);
- }
- ffree(giants);
- if(z) {
- freeGiant(z);
- }
- if(recip) {
- freeGiant(recip);
- }
- if(modGiant) {
- freeGiant(modGiant);
- }
- return 0;
-}
-