cryptotest.c revision 158886
1134911Ssam/*- 2134911Ssam * Copyright (c) 2004 Sam Leffler, Errno Consulting 3134911Ssam * All rights reserved. 4134911Ssam * 5134911Ssam * Redistribution and use in source and binary forms, with or without 6134911Ssam * modification, are permitted provided that the following conditions 7134911Ssam * are met: 8134911Ssam * 1. Redistributions of source code must retain the above copyright 9134911Ssam * notice, this list of conditions and the following disclaimer, 10134911Ssam * without modification. 11134911Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12134911Ssam * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13134911Ssam * redistribution must be conditioned upon including a substantially 14134911Ssam * similar Disclaimer requirement for further binary redistribution. 15134911Ssam * 3. Neither the names of the above-listed copyright holders nor the names 16134911Ssam * of any contributors may be used to endorse or promote products derived 17134911Ssam * from this software without specific prior written permission. 18134911Ssam * 19134911Ssam * NO WARRANTY 20134911Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21134911Ssam * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22134911Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 23134911Ssam * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 24134911Ssam * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 25134911Ssam * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26134911Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27134911Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28134911Ssam * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29134911Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30134911Ssam * THE POSSIBILITY OF SUCH DAMAGES. 31134911Ssam * 32134911Ssam * $FreeBSD: head/tools/tools/crypto/cryptotest.c 158886 2006-05-24 15:40:46Z mr $ 33134911Ssam */ 34134911Ssam 35134911Ssam/* 36134911Ssam * Simple tool for testing hardware/system crypto support. 37134911Ssam * 38134911Ssam * cryptotest [-czsbv] [-a algorithm] [count] [size ...] 39134911Ssam * 40134911Ssam * Run count iterations of a crypt+decrypt or mac operation on a buffer of 41134911Ssam * size bytes. A random key and iv are used. Options: 42134911Ssam * -c check the results 43134911Ssam * -z run all available algorithms on a variety of buffer sizes 44134911Ssam * -v be verbose 45134911Ssam * -b mark operations for batching 46134911Ssam * -p profile kernel crypto operations (must be root) 47134911Ssam * -t n fork n threads and run tests concurrently 48134911Ssam * Known algorithms are: 49134911Ssam * null null cbc 50134911Ssam * des des cbc 51134911Ssam * 3des 3des cbc 52134911Ssam * blf blowfish cbc 53134911Ssam * cast cast cbc 54134911Ssam * skj skipjack cbc 55134911Ssam * aes rijndael/aes 128-bit cbc 56134911Ssam * aes192 rijndael/aes 192-bit cbc 57134911Ssam * aes256 rijndael/aes 256-bit cbc 58134911Ssam * md5 md5 hmac 59134911Ssam * sha1 sha1 hmac 60134911Ssam * sha256 256-bit sha2 hmac 61134911Ssam * sha384 384-bit sha2 hmac 62134911Ssam * sha512 512--bit sha2 hmac 63134911Ssam * 64134911Ssam * For a test of how fast a crypto card is, use something like: 65134911Ssam * cryptotest -z 1024 66134911Ssam * This will run a series of tests using the available crypto/cipher 67134911Ssam * algorithms over a variety of buffer sizes. The 1024 says to do 1024 68134911Ssam * iterations. Extra arguments can be used to specify one or more buffer 69134911Ssam * sizes to use in doing tests. 70134911Ssam * 71134911Ssam * To fork multiple processes all doing the same work, specify -t X on the 72134911Ssam * command line to get X "threads" running simultaneously. No effort is made 73134911Ssam * to synchronize the threads or otherwise maximize load. 74134911Ssam * 75134911Ssam * If the kernel crypto code is built with CRYPTO_TIMING and you run as root, 76134911Ssam * then you can specify the -p option to get a "profile" of the time spent 77134911Ssam * processing crypto operations. At present this data is only meaningful for 78134911Ssam * symmetric operations. To get meaningful numbers you must run on an idle 79134911Ssam * machine. 80134911Ssam * 81134911Ssam * Expect ~400 Mb/s for a Broadcom 582x for 8K buffers on a reasonable CPU 82134911Ssam * (64-bit PCI helps). Hifn 7811 parts top out at ~110 Mb/s. 83134911Ssam */ 84134911Ssam#include <sys/types.h> 85134911Ssam#include <sys/param.h> 86134911Ssam#include <sys/time.h> 87134911Ssam#include <sys/ioctl.h> 88134911Ssam#include <stdio.h> 89134911Ssam#include <fcntl.h> 90134911Ssam#include <unistd.h> 91134911Ssam#include <sys/wait.h> 92134911Ssam#include <sys/mman.h> 93134911Ssam#include <paths.h> 94134911Ssam#include <stdlib.h> 95134911Ssam 96134911Ssam#include <sys/sysctl.h> 97134911Ssam#include <sys/time.h> 98134911Ssam#include <crypto/cryptodev.h> 99134911Ssam 100134911Ssam#define CHUNK 64 /* how much to display */ 101134911Ssam#define N(a) (sizeof (a) / sizeof (a[0])) 102134911Ssam#define streq(a,b) (strcasecmp(a,b) == 0) 103134911Ssam 104134911Ssamvoid hexdump(char *, int); 105134911Ssam 106134911Ssamint verbose = 0; 107134911Ssamint opflags = 0; 108134911Ssamint verify = 0; 109134911Ssam 110134911Ssamstruct alg { 111134911Ssam const char* name; 112134911Ssam int ishash; 113134911Ssam int blocksize; 114134911Ssam int minkeylen; 115134911Ssam int maxkeylen; 116134911Ssam int code; 117134911Ssam} algorithms[] = { 118134911Ssam#ifdef CRYPTO_NULL_CBC 119134911Ssam { "null", 0, 8, 1, 256, CRYPTO_NULL_CBC }, 120134911Ssam#endif 121134911Ssam { "des", 0, 8, 8, 8, CRYPTO_DES_CBC }, 122134911Ssam { "3des", 0, 8, 24, 24, CRYPTO_3DES_CBC }, 123134911Ssam { "blf", 0, 8, 5, 56, CRYPTO_BLF_CBC }, 124134911Ssam { "cast", 0, 8, 5, 16, CRYPTO_CAST_CBC }, 125134911Ssam { "skj", 0, 8, 10, 10, CRYPTO_SKIPJACK_CBC }, 126134911Ssam { "aes", 0, 16, 16, 16, CRYPTO_RIJNDAEL128_CBC}, 127134911Ssam { "aes192", 0, 16, 24, 24, CRYPTO_RIJNDAEL128_CBC}, 128134911Ssam { "aes256", 0, 16, 32, 32, CRYPTO_RIJNDAEL128_CBC}, 129134911Ssam#ifdef notdef 130134911Ssam { "arc4", 0, 8, 1, 32, CRYPTO_ARC4 }, 131134911Ssam#endif 132134911Ssam { "md5", 1, 8, 16, 16, CRYPTO_MD5_HMAC }, 133134911Ssam { "sha1", 1, 8, 20, 20, CRYPTO_SHA1_HMAC }, 134158886Smr { "sha256", 1, 8, 32, 32, CRYPTO_SHA2_256_HMAC }, 135158886Smr { "sha384", 1, 8, 48, 48, CRYPTO_SHA2_384_HMAC }, 136158886Smr { "sha512", 1, 8, 64, 64, CRYPTO_SHA2_512_HMAC }, 137134911Ssam}; 138134911Ssam 139134911Ssamstatic void 140134911Ssamusage(const char* cmd) 141134911Ssam{ 142134911Ssam printf("usage: %s [-c] [-z] [-s] [-b] [-v] [-a algorithm] [count] [size ...]\n", 143134911Ssam cmd); 144134911Ssam printf("where algorithm is one of:\n"); 145134911Ssam printf(" des 3des (default) blowfish cast skipjack\n"); 146134911Ssam printf(" aes (aka rijndael) aes192 aes256 arc4\n"); 147134911Ssam printf("count is the number of encrypt/decrypt ops to do\n"); 148134911Ssam printf("size is the number of bytes of text to encrypt+decrypt\n"); 149134911Ssam printf("\n"); 150134911Ssam printf("-c check the results (slows timing)\n"); 151134911Ssam printf("-z run all available algorithms on a variety of sizes\n"); 152134911Ssam printf("-v be verbose\n"); 153134911Ssam printf("-b mark operations for batching\n"); 154134911Ssam printf("-p profile kernel crypto operation (must be root)\n"); 155134911Ssam exit(-1); 156134911Ssam} 157134911Ssam 158134911Ssamstatic struct alg* 159134911Ssamgetalgbycode(int cipher) 160134911Ssam{ 161134911Ssam int i; 162134911Ssam 163134911Ssam for (i = 0; i < N(algorithms); i++) 164134911Ssam if (cipher == algorithms[i].code) 165134911Ssam return &algorithms[i]; 166134911Ssam return NULL; 167134911Ssam} 168134911Ssam 169134911Ssamstatic struct alg* 170134911Ssamgetalgbyname(const char* name) 171134911Ssam{ 172134911Ssam int i; 173134911Ssam 174134911Ssam for (i = 0; i < N(algorithms); i++) 175134911Ssam if (streq(name, algorithms[i].name)) 176134911Ssam return &algorithms[i]; 177134911Ssam return NULL; 178134911Ssam} 179134911Ssam 180134911Ssamstatic int 181134911Ssamdevcrypto(void) 182134911Ssam{ 183134911Ssam static int fd = -1; 184134911Ssam 185134911Ssam if (fd < 0) { 186134911Ssam fd = open(_PATH_DEV "crypto", O_RDWR, 0); 187134911Ssam if (fd < 0) 188134911Ssam err(1, _PATH_DEV "crypto"); 189134911Ssam if (fcntl(fd, F_SETFD, 1) == -1) 190134911Ssam err(1, "fcntl(F_SETFD) (devcrypto)"); 191134911Ssam } 192134911Ssam return fd; 193134911Ssam} 194134911Ssam 195134911Ssamstatic int 196134911Ssamcrget(void) 197134911Ssam{ 198134911Ssam int fd; 199134911Ssam 200134911Ssam if (ioctl(devcrypto(), CRIOGET, &fd) == -1) 201134911Ssam err(1, "ioctl(CRIOGET)"); 202134911Ssam if (fcntl(fd, F_SETFD, 1) == -1) 203134911Ssam err(1, "fcntl(F_SETFD) (crget)"); 204134911Ssam return fd; 205134911Ssam} 206134911Ssam 207134911Ssamstatic char 208134911Ssamrdigit(void) 209134911Ssam{ 210134911Ssam const char a[] = { 211134911Ssam 0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41, 212134911Ssam 0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01 213134911Ssam }; 214134911Ssam return 0x20+a[random()%N(a)]; 215134911Ssam} 216134911Ssam 217134911Ssamstatic void 218140407Sphkruntest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) 219134911Ssam{ 220134911Ssam int i, fd = crget(); 221134911Ssam struct timeval start, stop, dt; 222134911Ssam char *cleartext, *ciphertext, *originaltext; 223134911Ssam struct session_op sop; 224134911Ssam struct crypt_op cop; 225134911Ssam char iv[8]; 226134911Ssam 227134911Ssam bzero(&sop, sizeof(sop)); 228134911Ssam if (!alg->ishash) { 229134911Ssam sop.keylen = (alg->minkeylen + alg->maxkeylen)/2; 230134911Ssam sop.key = (char *) malloc(sop.keylen); 231134911Ssam if (sop.key == NULL) 232134911Ssam err(1, "malloc (key)"); 233134911Ssam for (i = 0; i < sop.keylen; i++) 234134911Ssam sop.key[i] = rdigit(); 235134911Ssam sop.cipher = alg->code; 236134911Ssam } else { 237134911Ssam sop.mackeylen = (alg->minkeylen + alg->maxkeylen)/2; 238134911Ssam sop.mackey = (char *) malloc(sop.mackeylen); 239134911Ssam if (sop.mackey == NULL) 240134911Ssam err(1, "malloc (mac)"); 241134911Ssam for (i = 0; i < sop.mackeylen; i++) 242134911Ssam sop.mackey[i] = rdigit(); 243134911Ssam sop.mac = alg->code; 244134911Ssam } 245134911Ssam if (ioctl(fd, cmd, &sop) < 0) { 246134911Ssam if (cmd == CIOCGSESSION) { 247134911Ssam close(fd); 248134911Ssam if (verbose) { 249134911Ssam printf("cipher %s", alg->name); 250134911Ssam if (alg->ishash) 251134911Ssam printf(" mackeylen %u\n", sop.mackeylen); 252134911Ssam else 253134911Ssam printf(" keylen %u\n", sop.keylen); 254134911Ssam perror("CIOCGSESSION"); 255134911Ssam } 256134911Ssam /* hardware doesn't support algorithm; skip it */ 257134911Ssam return; 258134911Ssam } 259134911Ssam printf("cipher %s keylen %u mackeylen %u\n", 260134911Ssam alg->name, sop.keylen, sop.mackeylen); 261134911Ssam err(1, "CIOCGSESSION"); 262134911Ssam } 263134911Ssam 264134911Ssam originaltext = malloc(3*size); 265134911Ssam if (originaltext == NULL) 266134911Ssam err(1, "malloc (text)"); 267134911Ssam cleartext = originaltext+size; 268134911Ssam ciphertext = cleartext+size; 269134911Ssam for (i = 0; i < size; i++) 270134911Ssam cleartext[i] = rdigit(); 271134911Ssam memcpy(originaltext, cleartext, size); 272134911Ssam for (i = 0; i < N(iv); i++) 273134911Ssam iv[i] = rdigit(); 274134911Ssam 275134911Ssam if (verbose) { 276134911Ssam printf("session = 0x%x\n", sop.ses); 277134911Ssam printf("count = %d, size = %d\n", count, size); 278134911Ssam if (!alg->ishash) { 279134911Ssam printf("iv:"); 280134911Ssam hexdump(iv, sizeof iv); 281134911Ssam } 282134911Ssam printf("cleartext:"); 283134911Ssam hexdump(cleartext, MIN(size, CHUNK)); 284134911Ssam } 285134911Ssam 286134911Ssam gettimeofday(&start, NULL); 287134911Ssam if (!alg->ishash) { 288134911Ssam for (i = 0; i < count; i++) { 289134911Ssam cop.ses = sop.ses; 290134911Ssam cop.op = COP_ENCRYPT; 291134911Ssam cop.flags = opflags; 292134911Ssam cop.len = size; 293134911Ssam cop.src = cleartext; 294134911Ssam cop.dst = ciphertext; 295134911Ssam cop.mac = 0; 296134911Ssam cop.iv = iv; 297134911Ssam 298134911Ssam if (ioctl(fd, CIOCCRYPT, &cop) < 0) 299134911Ssam err(1, "ioctl(CIOCCRYPT)"); 300134911Ssam 301134911Ssam if (verify && bcmp(ciphertext, cleartext, size) == 0) { 302134911Ssam printf("cipher text unchanged:"); 303134911Ssam hexdump(ciphertext, size); 304134911Ssam } 305134911Ssam 306134911Ssam memset(cleartext, 'x', MIN(size, CHUNK)); 307134911Ssam cop.ses = sop.ses; 308134911Ssam cop.op = COP_DECRYPT; 309134911Ssam cop.flags = opflags; 310134911Ssam cop.len = size; 311134911Ssam cop.src = ciphertext; 312134911Ssam cop.dst = cleartext; 313134911Ssam cop.mac = 0; 314134911Ssam cop.iv = iv; 315134911Ssam 316134911Ssam if (ioctl(fd, CIOCCRYPT, &cop) < 0) 317134911Ssam err(1, "ioctl(CIOCCRYPT)"); 318134911Ssam 319134911Ssam if (verify && bcmp(cleartext, originaltext, size) != 0) { 320134911Ssam printf("decrypt mismatch:\n"); 321134911Ssam printf("original:"); 322134911Ssam hexdump(originaltext, size); 323134911Ssam printf("cleartext:"); 324134911Ssam hexdump(cleartext, size); 325134911Ssam } 326134911Ssam } 327134911Ssam } else { 328134911Ssam for (i = 0; i < count; i++) { 329134911Ssam cop.ses = sop.ses; 330134911Ssam cop.op = 0; 331134911Ssam cop.flags = opflags; 332134911Ssam cop.len = size; 333134911Ssam cop.src = cleartext; 334134911Ssam cop.dst = 0; 335134911Ssam cop.mac = ciphertext; 336134911Ssam cop.iv = 0; 337134911Ssam 338134911Ssam if (ioctl(fd, CIOCCRYPT, &cop) < 0) 339134911Ssam err(1, "ioctl(CIOCCRYPT)"); 340134911Ssam } 341134911Ssam } 342134911Ssam gettimeofday(&stop, NULL); 343134911Ssam 344134911Ssam if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0) 345134911Ssam perror("ioctl(CIOCFSESSION)"); 346134911Ssam 347134911Ssam if (verbose) { 348134911Ssam printf("cleartext:"); 349134911Ssam hexdump(cleartext, MIN(size, CHUNK)); 350134911Ssam } 351134911Ssam timersub(&stop, &start, tv); 352134911Ssam 353134911Ssam free(originaltext); 354134911Ssam 355134911Ssam close(fd); 356134911Ssam} 357134911Ssam 358134911Ssam#ifdef __FreeBSD__ 359134911Ssamstatic void 360134911Ssamresetstats() 361134911Ssam{ 362134911Ssam struct cryptostats stats; 363134911Ssam size_t slen; 364134911Ssam 365134911Ssam slen = sizeof (stats); 366140407Sphk if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) { 367134911Ssam perror("kern.crypto_stats"); 368134911Ssam return; 369134911Ssam } 370134911Ssam bzero(&stats.cs_invoke, sizeof (stats.cs_invoke)); 371134911Ssam bzero(&stats.cs_done, sizeof (stats.cs_done)); 372134911Ssam bzero(&stats.cs_cb, sizeof (stats.cs_cb)); 373134911Ssam bzero(&stats.cs_finis, sizeof (stats.cs_finis)); 374134911Ssam stats.cs_invoke.min.tv_sec = 10000; 375134911Ssam stats.cs_done.min.tv_sec = 10000; 376134911Ssam stats.cs_cb.min.tv_sec = 10000; 377134911Ssam stats.cs_finis.min.tv_sec = 10000; 378134911Ssam if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0) 379134911Ssam perror("kern.cryptostats"); 380134911Ssam} 381134911Ssam 382134911Ssamstatic void 383134911Ssamprintt(const char* tag, struct cryptotstat *ts) 384134911Ssam{ 385134911Ssam uint64_t avg, min, max; 386134911Ssam 387134911Ssam if (ts->count == 0) 388134911Ssam return; 389134911Ssam avg = (1000000000LL*ts->acc.tv_sec + ts->acc.tv_nsec) / ts->count; 390134911Ssam min = 1000000000LL*ts->min.tv_sec + ts->min.tv_nsec; 391134911Ssam max = 1000000000LL*ts->max.tv_sec + ts->max.tv_nsec; 392134911Ssam printf("%16.16s: avg %6llu ns : min %6llu ns : max %7llu ns [%u samps]\n", 393134911Ssam tag, avg, min, max, ts->count); 394134911Ssam} 395134911Ssam#endif 396134911Ssam 397134911Ssamstatic void 398140407Sphkruntests(struct alg *alg, int count, int size, u_long cmd, int threads, int profile) 399134911Ssam{ 400134911Ssam int i, status; 401134911Ssam double t; 402134911Ssam void *region; 403134911Ssam struct timeval *tvp; 404134911Ssam struct timeval total; 405134911Ssam int otiming; 406134911Ssam 407134911Ssam if (size % alg->blocksize) { 408134911Ssam if (verbose) 409134911Ssam printf("skipping blocksize %u 'cuz not a multiple of " 410134911Ssam "%s blocksize %u\n", 411134911Ssam size, alg->name, alg->blocksize); 412134911Ssam return; 413134911Ssam } 414134911Ssam 415134911Ssam region = mmap(NULL, threads * sizeof (struct timeval), 416134911Ssam PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); 417134911Ssam if (region == MAP_FAILED) { 418134911Ssam perror("mmap"); 419134911Ssam return; 420134911Ssam } 421134911Ssam tvp = (struct timeval *) region; 422134911Ssam#ifdef __FreeBSD__ 423134911Ssam if (profile) { 424134911Ssam size_t tlen = sizeof (otiming); 425134911Ssam int timing = 1; 426134911Ssam 427134911Ssam resetstats(); 428134911Ssam if (sysctlbyname("debug.crypto_timing", &otiming, &tlen, 429134911Ssam &timing, sizeof (timing)) < 0) 430134911Ssam perror("debug.crypto_timing"); 431134911Ssam } 432134911Ssam#endif 433134911Ssam 434134911Ssam if (threads > 1) { 435134911Ssam for (i = 0; i < threads; i++) 436134911Ssam if (fork() == 0) { 437134911Ssam runtest(alg, count, size, cmd, &tvp[i]); 438134911Ssam exit(0); 439134911Ssam } 440134911Ssam while (waitpid(WAIT_MYPGRP, &status, 0) != -1) 441134911Ssam ; 442134911Ssam } else 443134911Ssam runtest(alg, count, size, cmd, tvp); 444134911Ssam 445134911Ssam t = 0; 446134911Ssam for (i = 0; i < threads; i++) 447134911Ssam t += (((double)tvp[i].tv_sec * 1000000 + tvp[i].tv_usec) / 1000000); 448134911Ssam if (t) { 449134911Ssam int nops = alg->ishash ? count : 2*count; 450134911Ssam 451134911Ssam t /= threads; 452134911Ssam printf("%6.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n", 453134911Ssam t, nops, alg->name, size, (double)nops*size / t, 454134911Ssam (double)nops*size / t * 8 / 1024 / 1024); 455134911Ssam } 456134911Ssam#ifdef __FreeBSD__ 457134911Ssam if (profile) { 458134911Ssam struct cryptostats stats; 459134911Ssam size_t slen = sizeof (stats); 460134911Ssam 461134911Ssam if (sysctlbyname("debug.crypto_timing", NULL, NULL, 462134911Ssam &otiming, sizeof (otiming)) < 0) 463134911Ssam perror("debug.crypto_timing"); 464140407Sphk if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) 465134911Ssam perror("kern.cryptostats"); 466134911Ssam if (stats.cs_invoke.count) { 467134911Ssam printt("dispatch->invoke", &stats.cs_invoke); 468134911Ssam printt("invoke->done", &stats.cs_done); 469134911Ssam printt("done->cb", &stats.cs_cb); 470134911Ssam printt("cb->finis", &stats.cs_finis); 471134911Ssam } 472134911Ssam } 473134911Ssam#endif 474134911Ssam fflush(stdout); 475134911Ssam} 476134911Ssam 477134911Ssamint 478134911Ssammain(int argc, char **argv) 479134911Ssam{ 480134911Ssam struct alg *alg = NULL; 481134911Ssam int count = 1; 482134911Ssam int sizes[128], nsizes = 0; 483140407Sphk u_long cmd = CIOCGSESSION; 484134911Ssam int testall = 0; 485134911Ssam int maxthreads = 1; 486134911Ssam int profile = 0; 487134911Ssam int i, ch; 488134911Ssam 489134911Ssam while ((ch = getopt(argc, argv, "cpzsva:bt:")) != -1) { 490134911Ssam switch (ch) { 491134911Ssam#ifdef CIOCGSSESSION 492134911Ssam case 's': 493134911Ssam cmd = CIOCGSSESSION; 494134911Ssam break; 495134911Ssam#endif 496134911Ssam case 'v': 497134911Ssam verbose++; 498134911Ssam break; 499134911Ssam case 'a': 500134911Ssam alg = getalgbyname(optarg); 501134911Ssam if (alg == NULL) { 502134911Ssam if (streq(optarg, "rijndael")) 503134911Ssam alg = getalgbyname("aes"); 504134911Ssam else 505134911Ssam usage(argv[0]); 506134911Ssam } 507134911Ssam break; 508134911Ssam case 't': 509134911Ssam maxthreads = atoi(optarg); 510134911Ssam break; 511134911Ssam case 'z': 512134911Ssam testall = 1; 513134911Ssam break; 514134911Ssam case 'p': 515134911Ssam profile = 1; 516134911Ssam break; 517134911Ssam case 'b': 518134911Ssam opflags |= COP_F_BATCH; 519134911Ssam break; 520134911Ssam case 'c': 521134911Ssam verify = 1; 522134911Ssam break; 523134911Ssam default: 524134911Ssam usage(argv[0]); 525134911Ssam } 526134911Ssam } 527134911Ssam argc -= optind, argv += optind; 528134911Ssam if (argc > 0) 529134911Ssam count = atoi(argv[0]); 530134911Ssam while (argc > 1) { 531134911Ssam int s = atoi(argv[1]); 532134911Ssam if (nsizes < N(sizes)) { 533134911Ssam sizes[nsizes++] = s; 534134911Ssam } else { 535134911Ssam printf("Too many sizes, ignoring %u\n", s); 536134911Ssam } 537134911Ssam argc--, argv++; 538134911Ssam } 539134911Ssam if (nsizes == 0) { 540134911Ssam if (alg) 541134911Ssam sizes[nsizes++] = alg->blocksize; 542134911Ssam else 543134911Ssam sizes[nsizes++] = 8; 544134911Ssam if (testall) { 545134911Ssam while (sizes[nsizes-1] < 8*1024) { 546134911Ssam sizes[nsizes] = sizes[nsizes-1]<<1; 547134911Ssam nsizes++; 548134911Ssam } 549134911Ssam } 550134911Ssam } 551134911Ssam 552134911Ssam if (testall) { 553134911Ssam for (i = 0; i < N(algorithms); i++) { 554134911Ssam int j; 555134911Ssam alg = &algorithms[i]; 556134911Ssam for (j = 0; j < nsizes; j++) 557134911Ssam runtests(alg, count, sizes[j], cmd, maxthreads, profile); 558134911Ssam } 559134911Ssam } else { 560134911Ssam if (alg == NULL) 561134911Ssam alg = getalgbycode(CRYPTO_3DES_CBC); 562134911Ssam for (i = 0; i < nsizes; i++) 563134911Ssam runtests(alg, count, sizes[i], cmd, maxthreads, profile); 564134911Ssam } 565134911Ssam 566134911Ssam return (0); 567134911Ssam} 568134911Ssam 569134911Ssamvoid 570134911Ssamhexdump(char *p, int n) 571134911Ssam{ 572134911Ssam int i, off; 573134911Ssam 574134911Ssam for (off = 0; n > 0; off += 16, n -= 16) { 575134911Ssam printf("%s%04x:", off == 0 ? "\n" : "", off); 576134911Ssam i = (n >= 16 ? 16 : n); 577134911Ssam do { 578134911Ssam printf(" %02x", *p++ & 0xff); 579134911Ssam } while (--i); 580134911Ssam printf("\n"); 581134911Ssam } 582134911Ssam} 583