#include "ckconfig.h"
#include "ckutilsPlatform.h"
#include "CryptKitSA.h"
#include "ckutilities.h"
#include "curveParams.h"
#include "falloc.h"
#include "elliptic.h"
#include "ellipticProj.h"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define LOOPS_DEF_FAST 10000
#define LOOPS_DEF_SLOW 100
#define NUM_BORROW 100
#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);
}
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; unsigned log2BitsPerDigit;
unsigned bitsPerDigit;
if(giants == NULL) {
return;
}
log2BitsPerDigit = GIANT_LOG2_BITS_PER_DIGIT;
bitsPerDigit = GIANT_BITS_PER_DIGIT;
if((bits & 7) != 0) {
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;
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
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
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; unsigned numEllPoints; #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];
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;
}
}
time((unsigned long *)&seed);
rand = feeRandAllocWithSeed(seed);
maxLoops = loopsFast;
if(loopsSlow > maxLoops) {
maxLoops = loopsSlow;
}
cp = curveParamsForDepth(FEE_DEPTH_LARGEST);
numGiants = maxLoops * 2; if(loopsSlow > (maxLoops / 4)) {
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
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++; }
#endif
keyArray = fmalloc(sizeof(feePubKey) * loopsSlow);
if(keyArray == NULL) {
printf("malloc failure\n");
exit(1);
}
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;
}
}
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);
#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
#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
#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
#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
#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);
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
#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
#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
#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
#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);
}
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
#if ELLIPTIC_ENABLE
genRandGiants(giants, numGiants, basePrimeLen, rand);
z = borrowGiant(cp->maxDigits);
PLAT_GET_TIME(startTime);
for(i=0; i<loopsSlow; i+=2) {
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
#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
if(cp->curveType != FCT_Weierstrass) {
goto loopEnd;
}
#if CRYPTKIT_ELL_PROJ_ENABLE
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));
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);
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);
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);
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
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;
}