--- /dev/null
+/*
+ * Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+#include "giantIntegers.h"
+#include "ckutilities.h"
+#include "feeFunctions.h"
+#include "feeDebug.h"
+#include <stdlib.h>
+#include "ckutilsPlatform.h"
+#include <stdio.h>
+#include <time.h>
+
+#define LOOPS_DEF 100
+#define MIN_SIZE_DEF 4 /* min giant size in bytes */
+#define MAX_SIZE_DEF 32 /* max in bytes */
+#define LOOP_NOTIFY 100
+
+
+static void usage(char **argv)
+{
+ printf("usage: %s [options]\n", argv[0]);
+ printf(" Options:\n");
+ printf(" l=loops (default = %d)\n", LOOPS_DEF);
+ printf(" n=maxBytes (default = %d\n", MIN_SIZE_DEF);
+ printf(" x=maxBytes (default = %d\n", MAX_SIZE_DEF);
+ printf(" o (use old 16-bit CryptKit\n");
+ printf(" s=seed\n");
+ printf(" h(elp)\n");
+ exit(1);
+}
+
+/*
+ * Fill buffer with random data.
+ */
+static void fillData(unsigned bufSize,
+ unsigned char *buf)
+{
+ unsigned *ip;
+ unsigned intCount;
+ unsigned residue;
+ unsigned char *cp;
+ int i;
+
+ intCount = bufSize >> 2;
+ ip = (unsigned *)buf;
+ for(i=0; i<intCount; i++) {
+ *ip++ = RAND();
+ }
+
+ residue = bufSize & 0x3;
+ cp = (unsigned char *)ip;
+ for(i=0; i<residue; i++) {
+ *cp++ = (unsigned char)RAND();
+ }
+}
+
+/*
+ * fill a pre-allocd giant with specified number of bytes of random
+ * data. *Buf is mallocd and uninitialized and will change here.
+ */
+static void genGiant(giant g,
+ unsigned numBytes,
+ unsigned char *buf)
+{
+ int i;
+
+ fillData(numBytes, buf);
+ deserializeGiant(buf, g, numBytes);
+
+ /* set random sign; deserializeGiant() is always positive */
+ i = RAND();
+ if(i & 1) {
+ g->sign = -g->sign;
+ }
+
+ /* avoid zero data - too many pitfalls with mod and div */
+ while(isZero(g)) {
+ g->sign = 1;
+ g->n[0] = RAND();
+ }
+}
+
+/*
+ * Init giant arrays with random data.
+ */
+static void initRandGiants(unsigned numBytes,
+ unsigned char *buf,
+ unsigned numGiants,
+ giant *g1,
+ giant *g2)
+{
+ int i;
+
+ for(i=0; i<numGiants; i++) {
+ genGiant(g1[i], numBytes, buf);
+ genGiant(g2[i], numBytes, buf);
+ }
+}
+
+/*
+ * Individual tests. API is identical for all tests.
+ *
+ * loops : number of ops to perform.
+ * g1, g2 : arrays of giants with random data and sign. Tests may modify
+ * these. Size of array = 'loops'. Capacity big enough for all
+ * conceivable ops.
+ * Return : total microseconds to do 'loops' ops.
+ */
+
+static int mulgTest(unsigned loops,
+ giant *g1,
+ giant *g2)
+{
+ int loop;
+ PLAT_TIME startTime;
+ PLAT_TIME endTime;
+
+ PLAT_GET_TIME(startTime);
+ for(loop=0; loop<loops; loop++) {
+ mulg(*g1++, *g2++);
+ }
+ PLAT_GET_TIME(endTime);
+ return PLAT_GET_NS(startTime, endTime);
+}
+
+static int squareTest(unsigned loops,
+ giant *g1,
+ giant *g2)
+{
+ int loop;
+ PLAT_TIME startTime;
+ PLAT_TIME endTime;
+
+ PLAT_GET_TIME(startTime);
+ for(loop=0; loop<loops; loop++) {
+ gsquare(*g1++);
+ }
+ PLAT_GET_TIME(endTime);
+ return PLAT_GET_NS(startTime, endTime);
+}
+
+
+int main(int argc, char **argv)
+{
+ int arg;
+ char *argp;
+ giant *g1;
+ giant *g2; // ditto
+ unsigned char *buf; // random data
+ unsigned numDigits;
+ unsigned i;
+ unsigned numBytes;
+ unsigned mulgElapsed;
+ unsigned sqrElapsed;
+
+ int loops = LOOPS_DEF;
+ int seedSpec = 0;
+ unsigned seed = 0;
+ unsigned maxSize = MAX_SIZE_DEF;
+ unsigned minSize = MIN_SIZE_DEF;
+ int useOld = 0;
+
+ initCryptKit();
+
+ #if macintosh
+ argc = ccommand(&argv);
+ #endif
+
+ for(arg=1; arg<argc; arg++) {
+ argp = argv[arg];
+ switch(argp[0]) {
+ case 'x':
+ maxSize = atoi(&argp[2]);
+ break;
+ case 'n':
+ minSize = atoi(&argp[2]);
+ break;
+ case 'l':
+ loops = atoi(&argp[2]);
+ break;
+ case 'o':
+ useOld = 1;
+ break;
+ case 's':
+ seed = atoi(&argp[2]);
+ seedSpec = 1;
+ break;
+ case 'h':
+ default:
+ usage(argv);
+ }
+ }
+ buf = malloc(maxSize);
+
+ if(!seedSpec) {
+ unsigned long tim;
+ time(&tim);
+ seed = (unsigned)tim;
+ }
+ SRAND(seed);
+
+ /*
+ * Scratch giants, big enough for anything. Malloc here, init with
+ * random data before each test
+ * note these mallocs will be too big in the useOld case...
+ */
+ g1 = malloc(sizeof(giant) * loops);
+ g2 = malloc(sizeof(giant) * loops);
+ if((g1 == NULL) || (g2 == NULL)) {
+ printf("malloc error\n");
+ exit(1);
+ }
+ if(useOld) {
+ numDigits = ((2 * maxSize) + 1) / 2;
+ }
+ else {
+ numDigits = BYTES_TO_GIANT_DIGITS(2 * maxSize);
+ }
+ for(i=0; i<loops; i++) {
+ g1[i] = newGiant(numDigits);
+ g2[i] = newGiant(numDigits);
+ if((g1[i] == NULL) || (g2[i] == NULL)) {
+ printf("malloc error\n");
+ exit(1);
+ }
+ }
+
+ printf("Starting giants test: seed %d\n", seed);
+ for(numBytes=minSize; numBytes<=maxSize; numBytes*=2) {
+
+ initRandGiants(numBytes,
+ buf,
+ loops,
+ g1,
+ g2);
+
+ mulgElapsed = mulgTest(loops, g1, g2);
+ initRandGiants(numBytes,
+ buf,
+ loops,
+ g1,
+ g2);
+
+ sqrElapsed = squareTest(loops, g1, g2);
+ printf(" bits : %4d mulg : %3d ns gsquare : %3d ns\n",
+ numBytes * 8,
+ mulgElapsed / loops,
+ sqrElapsed / loops);
+
+ } /* for numBytes */
+ return 0;
+}