1/* 2 * Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25#include "giantIntegers.h" 26#include "ckutilities.h" 27#include "feeFunctions.h" 28#include "feeDebug.h" 29#include <stdlib.h> 30#include "ckutilsPlatform.h" 31#include <stdio.h> 32#include <time.h> 33 34#define LOOPS_DEF 100 35#define MIN_SIZE_DEF 4 /* min giant size in bytes */ 36#define MAX_SIZE_DEF 32 /* max in bytes */ 37#define LOOP_NOTIFY 100 38 39 40static void usage(char **argv) 41{ 42 printf("usage: %s [options]\n", argv[0]); 43 printf(" Options:\n"); 44 printf(" l=loops (default = %d)\n", LOOPS_DEF); 45 printf(" n=maxBytes (default = %d\n", MIN_SIZE_DEF); 46 printf(" x=maxBytes (default = %d\n", MAX_SIZE_DEF); 47 printf(" o (use old 16-bit CryptKit\n"); 48 printf(" s=seed\n"); 49 printf(" h(elp)\n"); 50 exit(1); 51} 52 53/* 54 * Fill buffer with random data. 55 */ 56static void fillData(unsigned bufSize, 57 unsigned char *buf) 58{ 59 unsigned *ip; 60 unsigned intCount; 61 unsigned residue; 62 unsigned char *cp; 63 int i; 64 65 intCount = bufSize >> 2; 66 ip = (unsigned *)buf; 67 for(i=0; i<intCount; i++) { 68 *ip++ = RAND(); 69 } 70 71 residue = bufSize & 0x3; 72 cp = (unsigned char *)ip; 73 for(i=0; i<residue; i++) { 74 *cp++ = (unsigned char)RAND(); 75 } 76} 77 78/* 79 * fill a pre-allocd giant with specified number of bytes of random 80 * data. *Buf is mallocd and uninitialized and will change here. 81 */ 82static void genGiant(giant g, 83 unsigned numBytes, 84 unsigned char *buf) 85{ 86 int i; 87 88 fillData(numBytes, buf); 89 deserializeGiant(buf, g, numBytes); 90 91 /* set random sign; deserializeGiant() is always positive */ 92 i = RAND(); 93 if(i & 1) { 94 g->sign = -g->sign; 95 } 96 97 /* avoid zero data - too many pitfalls with mod and div */ 98 while(isZero(g)) { 99 g->sign = 1; 100 g->n[0] = RAND(); 101 } 102} 103 104/* 105 * Init giant arrays with random data. 106 */ 107static void initRandGiants(unsigned numBytes, 108 unsigned char *buf, 109 unsigned numGiants, 110 giant *g1, 111 giant *g2) 112{ 113 int i; 114 115 for(i=0; i<numGiants; i++) { 116 genGiant(g1[i], numBytes, buf); 117 genGiant(g2[i], numBytes, buf); 118 } 119} 120 121/* 122 * Individual tests. API is identical for all tests. 123 * 124 * loops : number of ops to perform. 125 * g1, g2 : arrays of giants with random data and sign. Tests may modify 126 * these. Size of array = 'loops'. Capacity big enough for all 127 * conceivable ops. 128 * Return : total microseconds to do 'loops' ops. 129 */ 130 131static int mulgTest(unsigned loops, 132 giant *g1, 133 giant *g2) 134{ 135 int loop; 136 PLAT_TIME startTime; 137 PLAT_TIME endTime; 138 139 PLAT_GET_TIME(startTime); 140 for(loop=0; loop<loops; loop++) { 141 mulg(*g1++, *g2++); 142 } 143 PLAT_GET_TIME(endTime); 144 return PLAT_GET_NS(startTime, endTime); 145} 146 147static int squareTest(unsigned loops, 148 giant *g1, 149 giant *g2) 150{ 151 int loop; 152 PLAT_TIME startTime; 153 PLAT_TIME endTime; 154 155 PLAT_GET_TIME(startTime); 156 for(loop=0; loop<loops; loop++) { 157 gsquare(*g1++); 158 } 159 PLAT_GET_TIME(endTime); 160 return PLAT_GET_NS(startTime, endTime); 161} 162 163 164int main(int argc, char **argv) 165{ 166 int arg; 167 char *argp; 168 giant *g1; 169 giant *g2; // ditto 170 unsigned char *buf; // random data 171 unsigned numDigits; 172 unsigned i; 173 unsigned numBytes; 174 unsigned mulgElapsed; 175 unsigned sqrElapsed; 176 177 int loops = LOOPS_DEF; 178 int seedSpec = 0; 179 unsigned seed = 0; 180 unsigned maxSize = MAX_SIZE_DEF; 181 unsigned minSize = MIN_SIZE_DEF; 182 int useOld = 0; 183 184 initCryptKit(); 185 186 #if macintosh 187 argc = ccommand(&argv); 188 #endif 189 190 for(arg=1; arg<argc; arg++) { 191 argp = argv[arg]; 192 switch(argp[0]) { 193 case 'x': 194 maxSize = atoi(&argp[2]); 195 break; 196 case 'n': 197 minSize = atoi(&argp[2]); 198 break; 199 case 'l': 200 loops = atoi(&argp[2]); 201 break; 202 case 'o': 203 useOld = 1; 204 break; 205 case 's': 206 seed = atoi(&argp[2]); 207 seedSpec = 1; 208 break; 209 case 'h': 210 default: 211 usage(argv); 212 } 213 } 214 buf = malloc(maxSize); 215 216 if(!seedSpec) { 217 unsigned long tim; 218 time(&tim); 219 seed = (unsigned)tim; 220 } 221 SRAND(seed); 222 223 /* 224 * Scratch giants, big enough for anything. Malloc here, init with 225 * random data before each test 226 * note these mallocs will be too big in the useOld case... 227 */ 228 g1 = malloc(sizeof(giant) * loops); 229 g2 = malloc(sizeof(giant) * loops); 230 if((g1 == NULL) || (g2 == NULL)) { 231 printf("malloc error\n"); 232 exit(1); 233 } 234 if(useOld) { 235 numDigits = ((2 * maxSize) + 1) / 2; 236 } 237 else { 238 numDigits = BYTES_TO_GIANT_DIGITS(2 * maxSize); 239 } 240 for(i=0; i<loops; i++) { 241 g1[i] = newGiant(numDigits); 242 g2[i] = newGiant(numDigits); 243 if((g1[i] == NULL) || (g2[i] == NULL)) { 244 printf("malloc error\n"); 245 exit(1); 246 } 247 } 248 249 printf("Starting giants test: seed %d\n", seed); 250 for(numBytes=minSize; numBytes<=maxSize; numBytes*=2) { 251 252 initRandGiants(numBytes, 253 buf, 254 loops, 255 g1, 256 g2); 257 258 mulgElapsed = mulgTest(loops, g1, g2); 259 initRandGiants(numBytes, 260 buf, 261 loops, 262 g1, 263 g2); 264 265 sqrElapsed = squareTest(loops, g1, g2); 266 printf(" bits : %4d mulg : %3d ns gsquare : %3d ns\n", 267 numBytes * 8, 268 mulgElapsed / loops, 269 sqrElapsed / loops); 270 271 } /* for numBytes */ 272 return 0; 273} 274