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$ 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 43167755Ssam * -d dev pin work on device dev 44134911Ssam * -z run all available algorithms on a variety of buffer sizes 45134911Ssam * -v be verbose 46134911Ssam * -b mark operations for batching 47134911Ssam * -p profile kernel crypto operations (must be root) 48134911Ssam * -t n fork n threads and run tests concurrently 49134911Ssam * Known algorithms are: 50134911Ssam * null null cbc 51134911Ssam * des des cbc 52134911Ssam * 3des 3des cbc 53134911Ssam * blf blowfish cbc 54134911Ssam * cast cast cbc 55134911Ssam * skj skipjack cbc 56134911Ssam * aes rijndael/aes 128-bit cbc 57134911Ssam * aes192 rijndael/aes 192-bit cbc 58134911Ssam * aes256 rijndael/aes 256-bit cbc 59134911Ssam * md5 md5 hmac 60134911Ssam * sha1 sha1 hmac 61134911Ssam * sha256 256-bit sha2 hmac 62134911Ssam * sha384 384-bit sha2 hmac 63134911Ssam * sha512 512--bit sha2 hmac 64134911Ssam * 65134911Ssam * For a test of how fast a crypto card is, use something like: 66134911Ssam * cryptotest -z 1024 67134911Ssam * This will run a series of tests using the available crypto/cipher 68134911Ssam * algorithms over a variety of buffer sizes. The 1024 says to do 1024 69134911Ssam * iterations. Extra arguments can be used to specify one or more buffer 70134911Ssam * sizes to use in doing tests. 71134911Ssam * 72134911Ssam * To fork multiple processes all doing the same work, specify -t X on the 73134911Ssam * command line to get X "threads" running simultaneously. No effort is made 74134911Ssam * to synchronize the threads or otherwise maximize load. 75134911Ssam * 76134911Ssam * If the kernel crypto code is built with CRYPTO_TIMING and you run as root, 77134911Ssam * then you can specify the -p option to get a "profile" of the time spent 78134911Ssam * processing crypto operations. At present this data is only meaningful for 79134911Ssam * symmetric operations. To get meaningful numbers you must run on an idle 80134911Ssam * machine. 81134911Ssam * 82134911Ssam * Expect ~400 Mb/s for a Broadcom 582x for 8K buffers on a reasonable CPU 83134911Ssam * (64-bit PCI helps). Hifn 7811 parts top out at ~110 Mb/s. 84134911Ssam */ 85134911Ssam#include <sys/types.h> 86134911Ssam#include <sys/param.h> 87134911Ssam#include <sys/time.h> 88134911Ssam#include <sys/ioctl.h> 89134911Ssam#include <stdio.h> 90134911Ssam#include <fcntl.h> 91134911Ssam#include <unistd.h> 92134911Ssam#include <sys/wait.h> 93134911Ssam#include <sys/mman.h> 94134911Ssam#include <paths.h> 95134911Ssam#include <stdlib.h> 96175979Smatteo#include <string.h> 97134911Ssam 98134911Ssam#include <sys/sysctl.h> 99134911Ssam#include <sys/time.h> 100134911Ssam#include <crypto/cryptodev.h> 101134911Ssam 102134911Ssam#define CHUNK 64 /* how much to display */ 103134911Ssam#define N(a) (sizeof (a) / sizeof (a[0])) 104134911Ssam#define streq(a,b) (strcasecmp(a,b) == 0) 105134911Ssam 106134911Ssamvoid hexdump(char *, int); 107134911Ssam 108134911Ssamint verbose = 0; 109134911Ssamint opflags = 0; 110134911Ssamint verify = 0; 111167755Ssamint crid = CRYPTO_FLAG_HARDWARE; 112134911Ssam 113134911Ssamstruct alg { 114134911Ssam const char* name; 115134911Ssam int ishash; 116134911Ssam int blocksize; 117134911Ssam int minkeylen; 118134911Ssam int maxkeylen; 119134911Ssam int code; 120134911Ssam} algorithms[] = { 121134911Ssam#ifdef CRYPTO_NULL_CBC 122134911Ssam { "null", 0, 8, 1, 256, CRYPTO_NULL_CBC }, 123134911Ssam#endif 124134911Ssam { "des", 0, 8, 8, 8, CRYPTO_DES_CBC }, 125134911Ssam { "3des", 0, 8, 24, 24, CRYPTO_3DES_CBC }, 126134911Ssam { "blf", 0, 8, 5, 56, CRYPTO_BLF_CBC }, 127134911Ssam { "cast", 0, 8, 5, 16, CRYPTO_CAST_CBC }, 128134911Ssam { "skj", 0, 8, 10, 10, CRYPTO_SKIPJACK_CBC }, 129134911Ssam { "aes", 0, 16, 16, 16, CRYPTO_RIJNDAEL128_CBC}, 130134911Ssam { "aes192", 0, 16, 24, 24, CRYPTO_RIJNDAEL128_CBC}, 131134911Ssam { "aes256", 0, 16, 32, 32, CRYPTO_RIJNDAEL128_CBC}, 132134911Ssam#ifdef notdef 133134911Ssam { "arc4", 0, 8, 1, 32, CRYPTO_ARC4 }, 134134911Ssam#endif 135134911Ssam { "md5", 1, 8, 16, 16, CRYPTO_MD5_HMAC }, 136134911Ssam { "sha1", 1, 8, 20, 20, CRYPTO_SHA1_HMAC }, 137158886Smr { "sha256", 1, 8, 32, 32, CRYPTO_SHA2_256_HMAC }, 138158886Smr { "sha384", 1, 8, 48, 48, CRYPTO_SHA2_384_HMAC }, 139158886Smr { "sha512", 1, 8, 64, 64, CRYPTO_SHA2_512_HMAC }, 140134911Ssam}; 141134911Ssam 142134911Ssamstatic void 143134911Ssamusage(const char* cmd) 144134911Ssam{ 145167755Ssam printf("usage: %s [-czsbv] [-d dev] [-a algorithm] [count] [size ...]\n", 146134911Ssam cmd); 147134911Ssam printf("where algorithm is one of:\n"); 148134911Ssam printf(" des 3des (default) blowfish cast skipjack\n"); 149134911Ssam printf(" aes (aka rijndael) aes192 aes256 arc4\n"); 150134911Ssam printf("count is the number of encrypt/decrypt ops to do\n"); 151134911Ssam printf("size is the number of bytes of text to encrypt+decrypt\n"); 152134911Ssam printf("\n"); 153134911Ssam printf("-c check the results (slows timing)\n"); 154167755Ssam printf("-d use specific device\n"); 155134911Ssam printf("-z run all available algorithms on a variety of sizes\n"); 156134911Ssam printf("-v be verbose\n"); 157134911Ssam printf("-b mark operations for batching\n"); 158134911Ssam printf("-p profile kernel crypto operation (must be root)\n"); 159134911Ssam exit(-1); 160134911Ssam} 161134911Ssam 162134911Ssamstatic struct alg* 163134911Ssamgetalgbycode(int cipher) 164134911Ssam{ 165134911Ssam int i; 166134911Ssam 167134911Ssam for (i = 0; i < N(algorithms); i++) 168134911Ssam if (cipher == algorithms[i].code) 169134911Ssam return &algorithms[i]; 170134911Ssam return NULL; 171134911Ssam} 172134911Ssam 173134911Ssamstatic struct alg* 174134911Ssamgetalgbyname(const char* name) 175134911Ssam{ 176134911Ssam int i; 177134911Ssam 178134911Ssam for (i = 0; i < N(algorithms); i++) 179134911Ssam if (streq(name, algorithms[i].name)) 180134911Ssam return &algorithms[i]; 181134911Ssam return NULL; 182134911Ssam} 183134911Ssam 184134911Ssamstatic int 185134911Ssamdevcrypto(void) 186134911Ssam{ 187134911Ssam static int fd = -1; 188134911Ssam 189134911Ssam if (fd < 0) { 190134911Ssam fd = open(_PATH_DEV "crypto", O_RDWR, 0); 191134911Ssam if (fd < 0) 192134911Ssam err(1, _PATH_DEV "crypto"); 193134911Ssam if (fcntl(fd, F_SETFD, 1) == -1) 194134911Ssam err(1, "fcntl(F_SETFD) (devcrypto)"); 195134911Ssam } 196134911Ssam return fd; 197134911Ssam} 198134911Ssam 199134911Ssamstatic int 200167755Ssamcrlookup(const char *devname) 201167755Ssam{ 202167755Ssam struct crypt_find_op find; 203167755Ssam 204167755Ssam find.crid = -1; 205167755Ssam strlcpy(find.name, devname, sizeof(find.name)); 206167755Ssam if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) 207167755Ssam err(1, "ioctl(CIOCFINDDEV)"); 208167755Ssam return find.crid; 209167755Ssam} 210167755Ssam 211167755Ssamstatic const char * 212167755Ssamcrfind(int crid) 213167755Ssam{ 214167755Ssam static struct crypt_find_op find; 215167755Ssam 216167755Ssam bzero(&find, sizeof(find)); 217167755Ssam find.crid = crid; 218167755Ssam if (ioctl(devcrypto(), CRIOFINDDEV, &find) == -1) 219167755Ssam err(1, "ioctl(CIOCFINDDEV): crid %d", crid); 220167755Ssam return find.name; 221167755Ssam} 222167755Ssam 223167755Ssamstatic int 224134911Ssamcrget(void) 225134911Ssam{ 226134911Ssam int fd; 227134911Ssam 228134911Ssam if (ioctl(devcrypto(), CRIOGET, &fd) == -1) 229134911Ssam err(1, "ioctl(CRIOGET)"); 230134911Ssam if (fcntl(fd, F_SETFD, 1) == -1) 231134911Ssam err(1, "fcntl(F_SETFD) (crget)"); 232134911Ssam return fd; 233134911Ssam} 234134911Ssam 235134911Ssamstatic char 236134911Ssamrdigit(void) 237134911Ssam{ 238134911Ssam const char a[] = { 239134911Ssam 0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41, 240134911Ssam 0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01 241134911Ssam }; 242134911Ssam return 0x20+a[random()%N(a)]; 243134911Ssam} 244134911Ssam 245134911Ssamstatic void 246140407Sphkruntest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) 247134911Ssam{ 248134911Ssam int i, fd = crget(); 249134911Ssam struct timeval start, stop, dt; 250134911Ssam char *cleartext, *ciphertext, *originaltext; 251167755Ssam struct session2_op sop; 252134911Ssam struct crypt_op cop; 253181965Sraj char iv[EALG_MAX_BLOCK_LEN]; 254134911Ssam 255134911Ssam bzero(&sop, sizeof(sop)); 256134911Ssam if (!alg->ishash) { 257134911Ssam sop.keylen = (alg->minkeylen + alg->maxkeylen)/2; 258134911Ssam sop.key = (char *) malloc(sop.keylen); 259134911Ssam if (sop.key == NULL) 260134911Ssam err(1, "malloc (key)"); 261134911Ssam for (i = 0; i < sop.keylen; i++) 262134911Ssam sop.key[i] = rdigit(); 263134911Ssam sop.cipher = alg->code; 264134911Ssam } else { 265134911Ssam sop.mackeylen = (alg->minkeylen + alg->maxkeylen)/2; 266134911Ssam sop.mackey = (char *) malloc(sop.mackeylen); 267134911Ssam if (sop.mackey == NULL) 268134911Ssam err(1, "malloc (mac)"); 269134911Ssam for (i = 0; i < sop.mackeylen; i++) 270134911Ssam sop.mackey[i] = rdigit(); 271134911Ssam sop.mac = alg->code; 272134911Ssam } 273167755Ssam sop.crid = crid; 274134911Ssam if (ioctl(fd, cmd, &sop) < 0) { 275167755Ssam if (cmd == CIOCGSESSION || cmd == CIOCGSESSION2) { 276134911Ssam close(fd); 277134911Ssam if (verbose) { 278134911Ssam printf("cipher %s", alg->name); 279134911Ssam if (alg->ishash) 280134911Ssam printf(" mackeylen %u\n", sop.mackeylen); 281134911Ssam else 282134911Ssam printf(" keylen %u\n", sop.keylen); 283134911Ssam perror("CIOCGSESSION"); 284134911Ssam } 285134911Ssam /* hardware doesn't support algorithm; skip it */ 286134911Ssam return; 287134911Ssam } 288134911Ssam printf("cipher %s keylen %u mackeylen %u\n", 289134911Ssam alg->name, sop.keylen, sop.mackeylen); 290134911Ssam err(1, "CIOCGSESSION"); 291134911Ssam } 292134911Ssam 293134911Ssam originaltext = malloc(3*size); 294134911Ssam if (originaltext == NULL) 295134911Ssam err(1, "malloc (text)"); 296134911Ssam cleartext = originaltext+size; 297134911Ssam ciphertext = cleartext+size; 298134911Ssam for (i = 0; i < size; i++) 299134911Ssam cleartext[i] = rdigit(); 300134911Ssam memcpy(originaltext, cleartext, size); 301134911Ssam for (i = 0; i < N(iv); i++) 302134911Ssam iv[i] = rdigit(); 303134911Ssam 304134911Ssam if (verbose) { 305134911Ssam printf("session = 0x%x\n", sop.ses); 306167755Ssam printf("device = %s\n", crfind(sop.crid)); 307134911Ssam printf("count = %d, size = %d\n", count, size); 308134911Ssam if (!alg->ishash) { 309134911Ssam printf("iv:"); 310134911Ssam hexdump(iv, sizeof iv); 311134911Ssam } 312134911Ssam printf("cleartext:"); 313134911Ssam hexdump(cleartext, MIN(size, CHUNK)); 314134911Ssam } 315134911Ssam 316134911Ssam gettimeofday(&start, NULL); 317134911Ssam if (!alg->ishash) { 318134911Ssam for (i = 0; i < count; i++) { 319134911Ssam cop.ses = sop.ses; 320134911Ssam cop.op = COP_ENCRYPT; 321134911Ssam cop.flags = opflags; 322134911Ssam cop.len = size; 323134911Ssam cop.src = cleartext; 324134911Ssam cop.dst = ciphertext; 325134911Ssam cop.mac = 0; 326134911Ssam cop.iv = iv; 327134911Ssam 328134911Ssam if (ioctl(fd, CIOCCRYPT, &cop) < 0) 329134911Ssam err(1, "ioctl(CIOCCRYPT)"); 330134911Ssam 331134911Ssam if (verify && bcmp(ciphertext, cleartext, size) == 0) { 332134911Ssam printf("cipher text unchanged:"); 333134911Ssam hexdump(ciphertext, size); 334134911Ssam } 335134911Ssam 336134911Ssam memset(cleartext, 'x', MIN(size, CHUNK)); 337134911Ssam cop.ses = sop.ses; 338134911Ssam cop.op = COP_DECRYPT; 339134911Ssam cop.flags = opflags; 340134911Ssam cop.len = size; 341134911Ssam cop.src = ciphertext; 342134911Ssam cop.dst = cleartext; 343134911Ssam cop.mac = 0; 344134911Ssam cop.iv = iv; 345134911Ssam 346134911Ssam if (ioctl(fd, CIOCCRYPT, &cop) < 0) 347134911Ssam err(1, "ioctl(CIOCCRYPT)"); 348134911Ssam 349134911Ssam if (verify && bcmp(cleartext, originaltext, size) != 0) { 350134911Ssam printf("decrypt mismatch:\n"); 351134911Ssam printf("original:"); 352134911Ssam hexdump(originaltext, size); 353134911Ssam printf("cleartext:"); 354134911Ssam hexdump(cleartext, size); 355134911Ssam } 356134911Ssam } 357134911Ssam } else { 358134911Ssam for (i = 0; i < count; i++) { 359134911Ssam cop.ses = sop.ses; 360134911Ssam cop.op = 0; 361134911Ssam cop.flags = opflags; 362134911Ssam cop.len = size; 363134911Ssam cop.src = cleartext; 364134911Ssam cop.dst = 0; 365134911Ssam cop.mac = ciphertext; 366134911Ssam cop.iv = 0; 367134911Ssam 368134911Ssam if (ioctl(fd, CIOCCRYPT, &cop) < 0) 369134911Ssam err(1, "ioctl(CIOCCRYPT)"); 370134911Ssam } 371134911Ssam } 372134911Ssam gettimeofday(&stop, NULL); 373134911Ssam 374134911Ssam if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0) 375134911Ssam perror("ioctl(CIOCFSESSION)"); 376134911Ssam 377134911Ssam if (verbose) { 378134911Ssam printf("cleartext:"); 379134911Ssam hexdump(cleartext, MIN(size, CHUNK)); 380134911Ssam } 381134911Ssam timersub(&stop, &start, tv); 382134911Ssam 383134911Ssam free(originaltext); 384134911Ssam 385134911Ssam close(fd); 386134911Ssam} 387134911Ssam 388134911Ssam#ifdef __FreeBSD__ 389134911Ssamstatic void 390134911Ssamresetstats() 391134911Ssam{ 392134911Ssam struct cryptostats stats; 393134911Ssam size_t slen; 394134911Ssam 395134911Ssam slen = sizeof (stats); 396140407Sphk if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) { 397134911Ssam perror("kern.crypto_stats"); 398134911Ssam return; 399134911Ssam } 400134911Ssam bzero(&stats.cs_invoke, sizeof (stats.cs_invoke)); 401134911Ssam bzero(&stats.cs_done, sizeof (stats.cs_done)); 402134911Ssam bzero(&stats.cs_cb, sizeof (stats.cs_cb)); 403134911Ssam bzero(&stats.cs_finis, sizeof (stats.cs_finis)); 404134911Ssam stats.cs_invoke.min.tv_sec = 10000; 405134911Ssam stats.cs_done.min.tv_sec = 10000; 406134911Ssam stats.cs_cb.min.tv_sec = 10000; 407134911Ssam stats.cs_finis.min.tv_sec = 10000; 408134911Ssam if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0) 409134911Ssam perror("kern.cryptostats"); 410134911Ssam} 411134911Ssam 412134911Ssamstatic void 413134911Ssamprintt(const char* tag, struct cryptotstat *ts) 414134911Ssam{ 415134911Ssam uint64_t avg, min, max; 416134911Ssam 417134911Ssam if (ts->count == 0) 418134911Ssam return; 419134911Ssam avg = (1000000000LL*ts->acc.tv_sec + ts->acc.tv_nsec) / ts->count; 420134911Ssam min = 1000000000LL*ts->min.tv_sec + ts->min.tv_nsec; 421134911Ssam max = 1000000000LL*ts->max.tv_sec + ts->max.tv_nsec; 422134911Ssam printf("%16.16s: avg %6llu ns : min %6llu ns : max %7llu ns [%u samps]\n", 423134911Ssam tag, avg, min, max, ts->count); 424134911Ssam} 425134911Ssam#endif 426134911Ssam 427134911Ssamstatic void 428140407Sphkruntests(struct alg *alg, int count, int size, u_long cmd, int threads, int profile) 429134911Ssam{ 430134911Ssam int i, status; 431134911Ssam double t; 432134911Ssam void *region; 433134911Ssam struct timeval *tvp; 434134911Ssam struct timeval total; 435134911Ssam int otiming; 436134911Ssam 437134911Ssam if (size % alg->blocksize) { 438134911Ssam if (verbose) 439134911Ssam printf("skipping blocksize %u 'cuz not a multiple of " 440134911Ssam "%s blocksize %u\n", 441134911Ssam size, alg->name, alg->blocksize); 442134911Ssam return; 443134911Ssam } 444134911Ssam 445134911Ssam region = mmap(NULL, threads * sizeof (struct timeval), 446134911Ssam PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); 447134911Ssam if (region == MAP_FAILED) { 448134911Ssam perror("mmap"); 449134911Ssam return; 450134911Ssam } 451134911Ssam tvp = (struct timeval *) region; 452134911Ssam#ifdef __FreeBSD__ 453134911Ssam if (profile) { 454134911Ssam size_t tlen = sizeof (otiming); 455134911Ssam int timing = 1; 456134911Ssam 457134911Ssam resetstats(); 458134911Ssam if (sysctlbyname("debug.crypto_timing", &otiming, &tlen, 459134911Ssam &timing, sizeof (timing)) < 0) 460134911Ssam perror("debug.crypto_timing"); 461134911Ssam } 462134911Ssam#endif 463134911Ssam 464134911Ssam if (threads > 1) { 465134911Ssam for (i = 0; i < threads; i++) 466134911Ssam if (fork() == 0) { 467134911Ssam runtest(alg, count, size, cmd, &tvp[i]); 468134911Ssam exit(0); 469134911Ssam } 470134911Ssam while (waitpid(WAIT_MYPGRP, &status, 0) != -1) 471134911Ssam ; 472134911Ssam } else 473134911Ssam runtest(alg, count, size, cmd, tvp); 474134911Ssam 475134911Ssam t = 0; 476134911Ssam for (i = 0; i < threads; i++) 477134911Ssam t += (((double)tvp[i].tv_sec * 1000000 + tvp[i].tv_usec) / 1000000); 478134911Ssam if (t) { 479134911Ssam int nops = alg->ishash ? count : 2*count; 480134911Ssam 481167755Ssam#if 0 482134911Ssam t /= threads; 483134911Ssam printf("%6.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n", 484134911Ssam t, nops, alg->name, size, (double)nops*size / t, 485134911Ssam (double)nops*size / t * 8 / 1024 / 1024); 486167755Ssam#else 487167755Ssam nops *= threads; 488167755Ssam printf("%8.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n", 489167755Ssam t, nops, alg->name, size, (double)nops*size / t, 490167755Ssam (double)nops*size / t * 8 / 1024 / 1024); 491167755Ssam#endif 492134911Ssam } 493134911Ssam#ifdef __FreeBSD__ 494134911Ssam if (profile) { 495134911Ssam struct cryptostats stats; 496134911Ssam size_t slen = sizeof (stats); 497134911Ssam 498134911Ssam if (sysctlbyname("debug.crypto_timing", NULL, NULL, 499134911Ssam &otiming, sizeof (otiming)) < 0) 500134911Ssam perror("debug.crypto_timing"); 501140407Sphk if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) 502134911Ssam perror("kern.cryptostats"); 503134911Ssam if (stats.cs_invoke.count) { 504134911Ssam printt("dispatch->invoke", &stats.cs_invoke); 505134911Ssam printt("invoke->done", &stats.cs_done); 506134911Ssam printt("done->cb", &stats.cs_cb); 507134911Ssam printt("cb->finis", &stats.cs_finis); 508134911Ssam } 509134911Ssam } 510134911Ssam#endif 511134911Ssam fflush(stdout); 512134911Ssam} 513134911Ssam 514134911Ssamint 515134911Ssammain(int argc, char **argv) 516134911Ssam{ 517134911Ssam struct alg *alg = NULL; 518134911Ssam int count = 1; 519134911Ssam int sizes[128], nsizes = 0; 520167755Ssam u_long cmd = CIOCGSESSION2; 521134911Ssam int testall = 0; 522134911Ssam int maxthreads = 1; 523134911Ssam int profile = 0; 524134911Ssam int i, ch; 525134911Ssam 526167755Ssam while ((ch = getopt(argc, argv, "cpzsva:bd:t:")) != -1) { 527134911Ssam switch (ch) { 528134911Ssam#ifdef CIOCGSSESSION 529134911Ssam case 's': 530134911Ssam cmd = CIOCGSSESSION; 531134911Ssam break; 532134911Ssam#endif 533134911Ssam case 'v': 534134911Ssam verbose++; 535134911Ssam break; 536134911Ssam case 'a': 537134911Ssam alg = getalgbyname(optarg); 538134911Ssam if (alg == NULL) { 539134911Ssam if (streq(optarg, "rijndael")) 540134911Ssam alg = getalgbyname("aes"); 541134911Ssam else 542134911Ssam usage(argv[0]); 543134911Ssam } 544134911Ssam break; 545167755Ssam case 'd': 546167755Ssam crid = crlookup(optarg); 547167755Ssam break; 548134911Ssam case 't': 549134911Ssam maxthreads = atoi(optarg); 550134911Ssam break; 551134911Ssam case 'z': 552134911Ssam testall = 1; 553134911Ssam break; 554134911Ssam case 'p': 555134911Ssam profile = 1; 556134911Ssam break; 557134911Ssam case 'b': 558134911Ssam opflags |= COP_F_BATCH; 559134911Ssam break; 560134911Ssam case 'c': 561134911Ssam verify = 1; 562134911Ssam break; 563134911Ssam default: 564134911Ssam usage(argv[0]); 565134911Ssam } 566134911Ssam } 567134911Ssam argc -= optind, argv += optind; 568134911Ssam if (argc > 0) 569134911Ssam count = atoi(argv[0]); 570134911Ssam while (argc > 1) { 571134911Ssam int s = atoi(argv[1]); 572134911Ssam if (nsizes < N(sizes)) { 573134911Ssam sizes[nsizes++] = s; 574134911Ssam } else { 575134911Ssam printf("Too many sizes, ignoring %u\n", s); 576134911Ssam } 577134911Ssam argc--, argv++; 578134911Ssam } 579134911Ssam if (nsizes == 0) { 580134911Ssam if (alg) 581134911Ssam sizes[nsizes++] = alg->blocksize; 582134911Ssam else 583134911Ssam sizes[nsizes++] = 8; 584134911Ssam if (testall) { 585134911Ssam while (sizes[nsizes-1] < 8*1024) { 586134911Ssam sizes[nsizes] = sizes[nsizes-1]<<1; 587134911Ssam nsizes++; 588134911Ssam } 589134911Ssam } 590134911Ssam } 591134911Ssam 592134911Ssam if (testall) { 593134911Ssam for (i = 0; i < N(algorithms); i++) { 594134911Ssam int j; 595134911Ssam alg = &algorithms[i]; 596134911Ssam for (j = 0; j < nsizes; j++) 597134911Ssam runtests(alg, count, sizes[j], cmd, maxthreads, profile); 598134911Ssam } 599134911Ssam } else { 600134911Ssam if (alg == NULL) 601134911Ssam alg = getalgbycode(CRYPTO_3DES_CBC); 602134911Ssam for (i = 0; i < nsizes; i++) 603134911Ssam runtests(alg, count, sizes[i], cmd, maxthreads, profile); 604134911Ssam } 605134911Ssam 606134911Ssam return (0); 607134911Ssam} 608134911Ssam 609134911Ssamvoid 610134911Ssamhexdump(char *p, int n) 611134911Ssam{ 612134911Ssam int i, off; 613134911Ssam 614134911Ssam for (off = 0; n > 0; off += 16, n -= 16) { 615134911Ssam printf("%s%04x:", off == 0 ? "\n" : "", off); 616134911Ssam i = (n >= 16 ? 16 : n); 617134911Ssam do { 618134911Ssam printf(" %02x", *p++ & 0xff); 619134911Ssam } while (--i); 620134911Ssam printf("\n"); 621134911Ssam } 622134911Ssam} 623