1/* 2 * atomTime.c - measure performance of digital signature primitives (not incluing 3 * digest) 4 */ 5 6#include "ckconfig.h" 7#include "ckutilsPlatform.h" 8#include "CryptKitSA.h" 9#include "curveParams.h" 10#include "falloc.h" 11#include <stdlib.h> 12#include <stdio.h> 13#include <time.h> 14 15#define SIGN_LOOPS_DEF 100 16#define VFY_LOOPS_DEF 100 17#define PRIV_KEY_SIZE_BYTES 32 18#define DIGEST_SIZE_BYTES 20 /* e.g., SHA1 */ 19#define NUM_KEYS 10 20 21static void usage(char **argv) 22{ 23 printf("Usage: %s [option...]\n", argv[0]); 24 printf("Options:\n"); 25 printf(" s=signLoops -- default %d\n", SIGN_LOOPS_DEF); 26 printf(" v=verifyLoops -- default %d\n", VFY_LOOPS_DEF); 27 printf(" D=depth -- default is ALL\n"); 28 exit(1); 29} 30 31typedef struct { 32 unsigned char *data; 33 unsigned length; 34} FeeData; 35 36/* 37 * Fill numDatas with random data of length bits. Caller has mallocd referents. 38 */ 39static void genRandData(FeeData *datas, 40 unsigned numDatas, 41 unsigned numBytes, 42 feeRand rand) 43{ 44 unsigned i; 45 FeeData *fd; 46 for(i=0; i<numDatas; i++) { 47 fd = &datas[i]; 48 fd->length = numBytes; 49 feeRandBytes(rand, fd->data, numBytes); 50 } 51 return; 52} 53 54static void mallocData( 55 FeeData *fd, 56 unsigned numBytes) 57{ 58 fd->data = (unsigned char *)fmalloc(numBytes); 59 fd->length = numBytes; 60} 61 62/* common random callback */ 63feeReturn randCallback( 64 void *ref, 65 unsigned char *bytes, 66 unsigned numBytes) 67{ 68 feeRand frand = (feeRand)ref; 69 feeRandBytes(frand, bytes, numBytes); 70 return FR_Success; 71} 72 73int main(int argc, char **argv) 74{ 75 int arg; 76 char *argp; 77 unsigned sigLoops = SIGN_LOOPS_DEF; 78 unsigned vfyLoops = VFY_LOOPS_DEF; 79 unsigned numKeys = NUM_KEYS; // might be less for very small loops 80 unsigned depth; 81 feeRand rand; 82 83 feePubKey keys[NUM_KEYS]; 84 /* sigLoops copies of each of {digestData, sigData} */ 85 FeeData *digestData; 86 FeeData *sigData; 87 88 unsigned seed; 89 unsigned i; 90 PLAT_TIME startTime; 91 PLAT_TIME endTime; 92 double elapsed; 93 curveParams *cp; 94 unsigned minDepth = 0; 95 unsigned maxDepth = FEE_DEPTH_MAX; 96 unsigned basePrimeLen; 97 char *curveType; 98 feeReturn frtn; 99 100 for(arg=1; arg<argc; arg++) { 101 argp = argv[arg]; 102 switch(argp[0]) { 103 case 's': 104 sigLoops = atoi(&argp[2]); 105 break; 106 case 'v': 107 vfyLoops = atoi(&argp[2]); 108 break; 109 case 'D': 110 minDepth = maxDepth = atoi(&argp[2]); 111 break; 112 default: 113 usage(argv); 114 break; 115 } 116 } 117 118 /* 119 * Common random generator 120 */ 121 time((time_t *)&seed); 122 rand = feeRandAllocWithSeed(seed); 123 124 if(numKeys > sigLoops) { 125 numKeys = sigLoops; 126 } 127 digestData = (FeeData *)fmalloc(sizeof(FeeData) * sigLoops); 128 sigData = (FeeData *)fmalloc(sizeof(FeeData) * sigLoops); 129 130 /* alloc the data, once, for largest private key or "digest" we'll use */ 131 for(i=0; i<sigLoops; i++) { 132 mallocData(&digestData[i], PRIV_KEY_SIZE_BYTES); 133 } 134 for(depth=minDepth; depth<=maxDepth; depth++) { 135 136 /* 137 * Get curve params for this depth 138 */ 139 cp = curveParamsForDepth(depth); 140 if(cp == NULL) { 141 printf("malloc failure\n"); 142 exit(1); 143 } 144 switch(cp->curveType) { 145 case FCT_Montgomery: 146 curveType = "FCT_Montgomery"; 147 break; 148 case FCT_Weierstrass: 149 curveType = "FCT_Weierstrass"; 150 break; 151 case FCT_General: 152 curveType = "FCT_General"; 153 break; 154 default: 155 printf("***Unknown curveType!\n"); 156 exit(1); 157 } 158 159 switch(cp->primeType) { 160 case FPT_General: 161 printf("depth=%d; FPT_General, %s; keysize=%d;\n", 162 depth, curveType, bitlen(cp->basePrime)); 163 break; 164 case FPT_Mersenne: 165 printf("depth=%d; FPT_Mersenne, %s; q=%d\n", 166 depth, curveType, cp->q); 167 break; 168 default: 169 printf("depth=%d; FPT_FEE, %s; q=%d k=%d\n", 170 depth, curveType, cp->q, cp->k); 171 break; 172 } 173 basePrimeLen = bitlen(cp->basePrime); 174 175 /* one set of random data as private keys */ 176 unsigned privSize = (basePrimeLen + 8) / 8; 177 genRandData(digestData, numKeys, privSize, rand); 178 179 /* generate the keys (no hash - we've got that covered) */ 180 for(i=0; i<numKeys; i++) { 181 keys[i] = feePubKeyAlloc(); 182 feePubKeyInitFromPrivDataDepth(keys[i], digestData[i].data, privSize, 183 depth, 0); 184 } 185 186 /* now different data to actually sign */ 187 genRandData(digestData, sigLoops, DIGEST_SIZE_BYTES, rand); 188 189 /* 190 * sign 191 */ 192 PLAT_GET_TIME(startTime); 193 for(i=0; i<sigLoops; i++) { 194 FeeData *digst = &digestData[i]; 195 FeeData *sig = &sigData[i]; 196 feePubKey fkey = keys[i % numKeys]; 197 198 feeSig fs = feeSigNewWithKey(fkey, randCallback, rand); 199 frtn = feeSigSign(fs, digst->data, digst->length, fkey); 200 if(frtn) { 201 printf("***Error %d on feeSigSign\n", (int)frtn); 202 break; 203 } 204 frtn = feeSigData(fs, &sig->data, &sig->length); 205 if(frtn) { 206 printf("***Error %d on feeSigData\n", (int)frtn); 207 break; 208 } 209 feeSigFree(fs); 210 } 211 PLAT_GET_TIME(endTime); 212 elapsed = PLAT_GET_US(startTime, endTime); 213 printf(" sign: %12.2f us per op\n", 214 elapsed / sigLoops); 215 216 /* 217 * verify - might be doing more of these than we have 218 * valid signatures..... 219 */ 220 unsigned dex=0; 221 PLAT_GET_TIME(startTime); 222 for(i=0; i<vfyLoops; i++) { 223 FeeData *digst = &digestData[dex]; 224 FeeData *sig = &sigData[dex]; 225 feePubKey fkey = keys[dex % numKeys]; 226 227 feeSig fs; 228 frtn = feeSigParse(sig->data, sig->length, &fs); 229 if(frtn) { 230 printf("***Error %d on feeSigParse\n", (int)frtn); 231 break; 232 } 233 frtn = feeSigVerify(fs, digst->data, digst->length, fkey); 234 if(frtn) { 235 printf("***Error %d on feeSigVerify\n", (int)frtn); 236 break; 237 } 238 feeSigFree(fs); 239 dex++; 240 if(dex == sigLoops) { 241 /* that's all the data we have, recycle */ 242 dex = 0; 243 } 244 } 245 PLAT_GET_TIME(endTime); 246 elapsed = PLAT_GET_US(startTime, endTime); 247 printf(" verify: %12.2f us per op\n", 248 elapsed / vfyLoops); 249 250 freeCurveParams(cp); 251 /* possibly limited number of signatures.... */ 252 for(i=0; i<sigLoops; i++) { 253 ffree(sigData[i].data); // mallocd by feeSigData() 254 } 255 for(i=0; i<numKeys; i++) { 256 feePubKeyFree(keys[i]); 257 } 258 } 259 260 feeRandFree(rand); 261 for(i=0; i<sigLoops; i++) { 262 ffree(digestData[i].data); 263 } 264 ffree(digestData); 265 ffree(sigData); 266 267 return 0; 268} 269 270