cryptotest.c revision 175979
150397Sobrien/*- 2117395Skan * Copyright (c) 2004 Sam Leffler, Errno Consulting 3117395Skan * All rights reserved. 450397Sobrien * 550397Sobrien * Redistribution and use in source and binary forms, with or without 690075Sobrien * modification, are permitted provided that the following conditions 750397Sobrien * are met: 890075Sobrien * 1. Redistributions of source code must retain the above copyright 990075Sobrien * notice, this list of conditions and the following disclaimer, 1090075Sobrien * without modification. 1190075Sobrien * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1250397Sobrien * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 1390075Sobrien * redistribution must be conditioned upon including a substantially 1490075Sobrien * similar Disclaimer requirement for further binary redistribution. 1590075Sobrien * 3. Neither the names of the above-listed copyright holders nor the names 1690075Sobrien * of any contributors may be used to endorse or promote products derived 1750397Sobrien * from this software without specific prior written permission. 1850397Sobrien * 1990075Sobrien * NO WARRANTY 2090075Sobrien * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2190075Sobrien * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2250397Sobrien * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 2350397Sobrien * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 2450397Sobrien * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 2550397Sobrien * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2690075Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2790075Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 2890075Sobrien * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2950397Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3050397Sobrien * THE POSSIBILITY OF SUCH DAMAGES. 3150397Sobrien * 3290075Sobrien * $FreeBSD: head/tools/tools/crypto/cryptotest.c 175979 2008-02-05 08:07:19Z matteo $ 3350397Sobrien */ 3452284Sobrien 3550397Sobrien/* 3690075Sobrien * Simple tool for testing hardware/system crypto support. 3752284Sobrien * 3890075Sobrien * cryptotest [-czsbv] [-a algorithm] [count] [size ...] 3990075Sobrien * 40117395Skan * Run count iterations of a crypt+decrypt or mac operation on a buffer of 4150397Sobrien * size bytes. A random key and iv are used. Options: 4252284Sobrien * -c check the results 4352284Sobrien * -d dev pin work on device dev 4490075Sobrien * -z run all available algorithms on a variety of buffer sizes 4590075Sobrien * -v be verbose 4652284Sobrien * -b mark operations for batching 4752284Sobrien * -p profile kernel crypto operations (must be root) 4852284Sobrien * -t n fork n threads and run tests concurrently 4952284Sobrien * Known algorithms are: 5052284Sobrien * null null cbc 5152284Sobrien * des des cbc 5252284Sobrien * 3des 3des cbc 5352284Sobrien * blf blowfish cbc 5452284Sobrien * cast cast cbc 5552284Sobrien * skj skipjack cbc 5652284Sobrien * aes rijndael/aes 128-bit cbc 5752284Sobrien * aes192 rijndael/aes 192-bit cbc 5852284Sobrien * aes256 rijndael/aes 256-bit cbc 5990075Sobrien * md5 md5 hmac 6090075Sobrien * sha1 sha1 hmac 6190075Sobrien * sha256 256-bit sha2 hmac 6252284Sobrien * sha384 384-bit sha2 hmac 6390075Sobrien * sha512 512--bit sha2 hmac 6490075Sobrien * 6590075Sobrien * For a test of how fast a crypto card is, use something like: 6690075Sobrien * cryptotest -z 1024 6790075Sobrien * This will run a series of tests using the available crypto/cipher 6852284Sobrien * algorithms over a variety of buffer sizes. The 1024 says to do 1024 6952284Sobrien * iterations. Extra arguments can be used to specify one or more buffer 7052284Sobrien * sizes to use in doing tests. 7152284Sobrien * 7290075Sobrien * To fork multiple processes all doing the same work, specify -t X on the 7390075Sobrien * command line to get X "threads" running simultaneously. No effort is made 7452284Sobrien * to synchronize the threads or otherwise maximize load. 7590075Sobrien * 7652284Sobrien * If the kernel crypto code is built with CRYPTO_TIMING and you run as root, 7752284Sobrien * then you can specify the -p option to get a "profile" of the time spent 7890075Sobrien * processing crypto operations. At present this data is only meaningful for 7952284Sobrien * symmetric operations. To get meaningful numbers you must run on an idle 80117395Skan * machine. 8152284Sobrien * 8252284Sobrien * Expect ~400 Mb/s for a Broadcom 582x for 8K buffers on a reasonable CPU 8352284Sobrien * (64-bit PCI helps). Hifn 7811 parts top out at ~110 Mb/s. 8452284Sobrien */ 8552284Sobrien#include <sys/types.h> 8690075Sobrien#include <sys/param.h> 8790075Sobrien#include <sys/time.h> 8890075Sobrien#include <sys/ioctl.h> 8990075Sobrien#include <stdio.h> 9050397Sobrien#include <fcntl.h> 9190075Sobrien#include <unistd.h> 9290075Sobrien#include <sys/wait.h> 9390075Sobrien#include <sys/mman.h> 9490075Sobrien#include <paths.h> 9590075Sobrien#include <stdlib.h> 9690075Sobrien#include <string.h> 9790075Sobrien 9890075Sobrien#include <sys/sysctl.h> 9990075Sobrien#include <sys/time.h> 10090075Sobrien#include <crypto/cryptodev.h> 10190075Sobrien 10290075Sobrien#define CHUNK 64 /* how much to display */ 10390075Sobrien#define N(a) (sizeof (a) / sizeof (a[0])) 10490075Sobrien#define streq(a,b) (strcasecmp(a,b) == 0) 10590075Sobrien 10690075Sobrienvoid hexdump(char *, int); 10790075Sobrien 10890075Sobrienint verbose = 0; 10990075Sobrienint opflags = 0; 11090075Sobrienint verify = 0; 11190075Sobrienint crid = CRYPTO_FLAG_HARDWARE; 11290075Sobrien 113117395Skanstruct alg { 114117395Skan const char* name; 11590075Sobrien int ishash; 116117395Skan int blocksize; 117117395Skan int minkeylen; 118117395Skan int maxkeylen; 119117395Skan int code; 12090075Sobrien} algorithms[] = { 12150397Sobrien#ifdef CRYPTO_NULL_CBC 12250397Sobrien { "null", 0, 8, 1, 256, CRYPTO_NULL_CBC }, 12390075Sobrien#endif 12450397Sobrien { "des", 0, 8, 8, 8, CRYPTO_DES_CBC }, 12550397Sobrien { "3des", 0, 8, 24, 24, CRYPTO_3DES_CBC }, 12650397Sobrien { "blf", 0, 8, 5, 56, CRYPTO_BLF_CBC }, 12752284Sobrien { "cast", 0, 8, 5, 16, CRYPTO_CAST_CBC }, 12852284Sobrien { "skj", 0, 8, 10, 10, CRYPTO_SKIPJACK_CBC }, 12952284Sobrien { "aes", 0, 16, 16, 16, CRYPTO_RIJNDAEL128_CBC}, 13052284Sobrien { "aes192", 0, 16, 24, 24, CRYPTO_RIJNDAEL128_CBC}, 13152284Sobrien { "aes256", 0, 16, 32, 32, CRYPTO_RIJNDAEL128_CBC}, 13250397Sobrien#ifdef notdef 13350397Sobrien { "arc4", 0, 8, 1, 32, CRYPTO_ARC4 }, 13490075Sobrien#endif 13550397Sobrien { "md5", 1, 8, 16, 16, CRYPTO_MD5_HMAC }, 136117395Skan { "sha1", 1, 8, 20, 20, CRYPTO_SHA1_HMAC }, 13750397Sobrien { "sha256", 1, 8, 32, 32, CRYPTO_SHA2_256_HMAC }, 13850397Sobrien { "sha384", 1, 8, 48, 48, CRYPTO_SHA2_384_HMAC }, 13950397Sobrien { "sha512", 1, 8, 64, 64, CRYPTO_SHA2_512_HMAC }, 14050397Sobrien}; 14150397Sobrien 14250397Sobrienstatic void 14350397Sobrienusage(const char* cmd) 14450397Sobrien{ 145117395Skan printf("usage: %s [-czsbv] [-d dev] [-a algorithm] [count] [size ...]\n", 14650397Sobrien cmd); 14790075Sobrien printf("where algorithm is one of:\n"); 14890075Sobrien printf(" des 3des (default) blowfish cast skipjack\n"); 14990075Sobrien printf(" aes (aka rijndael) aes192 aes256 arc4\n"); 15090075Sobrien printf("count is the number of encrypt/decrypt ops to do\n"); 15190075Sobrien printf("size is the number of bytes of text to encrypt+decrypt\n"); 15290075Sobrien printf("\n"); 15390075Sobrien printf("-c check the results (slows timing)\n"); 15490075Sobrien printf("-d use specific device\n"); 15590075Sobrien printf("-z run all available algorithms on a variety of sizes\n"); 156117395Skan printf("-v be verbose\n"); 15790075Sobrien printf("-b mark operations for batching\n"); 15890075Sobrien printf("-p profile kernel crypto operation (must be root)\n"); 15990075Sobrien exit(-1); 160117395Skan} 161117395Skan 162117395Skanstatic struct alg* 163117395Skangetalgbycode(int cipher) 16450397Sobrien{ 16590075Sobrien int i; 16690075Sobrien 16750397Sobrien for (i = 0; i < N(algorithms); i++) 16850397Sobrien if (cipher == algorithms[i].code) 16950397Sobrien return &algorithms[i]; 17050397Sobrien return NULL; 17150397Sobrien} 17250397Sobrien 17350397Sobrienstatic struct alg* 17450397Sobriengetalgbyname(const char* name) 17550397Sobrien{ 17650397Sobrien int i; 17750397Sobrien 17890075Sobrien for (i = 0; i < N(algorithms); i++) 17990075Sobrien if (streq(name, algorithms[i].name)) 18090075Sobrien return &algorithms[i]; 18190075Sobrien return NULL; 18250397Sobrien} 18350397Sobrien 18450397Sobrienstatic int 18590075Sobriendevcrypto(void) 18650397Sobrien{ 18750397Sobrien static int fd = -1; 18850397Sobrien 18950397Sobrien if (fd < 0) { 19090075Sobrien fd = open(_PATH_DEV "crypto", O_RDWR, 0); 19190075Sobrien if (fd < 0) 19290075Sobrien err(1, _PATH_DEV "crypto"); 19390075Sobrien if (fcntl(fd, F_SETFD, 1) == -1) 19490075Sobrien err(1, "fcntl(F_SETFD) (devcrypto)"); 19590075Sobrien } 19690075Sobrien return fd; 19790075Sobrien} 19890075Sobrien 19950397Sobrienstatic int 20050397Sobriencrlookup(const char *devname) 20150397Sobrien{ 20250397Sobrien struct crypt_find_op find; 203117395Skan 20450397Sobrien find.crid = -1; 20552284Sobrien strlcpy(find.name, devname, sizeof(find.name)); 20652284Sobrien if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) 20790075Sobrien err(1, "ioctl(CIOCFINDDEV)"); 20852284Sobrien return find.crid; 20952284Sobrien} 21052284Sobrien 21152284Sobrienstatic const char * 21252284Sobriencrfind(int crid) 21390075Sobrien{ 21452284Sobrien static struct crypt_find_op find; 21590075Sobrien 21690075Sobrien bzero(&find, sizeof(find)); 21752284Sobrien find.crid = crid; 21890075Sobrien if (ioctl(devcrypto(), CRIOFINDDEV, &find) == -1) 21952284Sobrien err(1, "ioctl(CIOCFINDDEV): crid %d", crid); 22052284Sobrien return find.name; 22190075Sobrien} 22290075Sobrien 22352284Sobrienstatic int 224117395Skancrget(void) 22552284Sobrien{ 22652284Sobrien int fd; 22752284Sobrien 22852284Sobrien if (ioctl(devcrypto(), CRIOGET, &fd) == -1) 229117395Skan err(1, "ioctl(CRIOGET)"); 23052284Sobrien if (fcntl(fd, F_SETFD, 1) == -1) 23152284Sobrien err(1, "fcntl(F_SETFD) (crget)"); 23252284Sobrien return fd; 23352284Sobrien} 23452284Sobrien 23552284Sobrienstatic char 23652284Sobrienrdigit(void) 23790075Sobrien{ 23890075Sobrien const char a[] = { 23952284Sobrien 0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41, 24052284Sobrien 0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01 24152284Sobrien }; 24290075Sobrien return 0x20+a[random()%N(a)]; 24390075Sobrien} 24490075Sobrien 24590075Sobrienstatic void 24690075Sobrienruntest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) 24790075Sobrien{ 24890075Sobrien int i, fd = crget(); 24990075Sobrien struct timeval start, stop, dt; 25090075Sobrien char *cleartext, *ciphertext, *originaltext; 25190075Sobrien struct session2_op sop; 25290075Sobrien struct crypt_op cop; 25390075Sobrien char iv[8]; 25490075Sobrien 25590075Sobrien bzero(&sop, sizeof(sop)); 25690075Sobrien if (!alg->ishash) { 25790075Sobrien sop.keylen = (alg->minkeylen + alg->maxkeylen)/2; 25890075Sobrien sop.key = (char *) malloc(sop.keylen); 25990075Sobrien if (sop.key == NULL) 26090075Sobrien err(1, "malloc (key)"); 26190075Sobrien for (i = 0; i < sop.keylen; i++) 26290075Sobrien sop.key[i] = rdigit(); 26390075Sobrien sop.cipher = alg->code; 26490075Sobrien } else { 26590075Sobrien sop.mackeylen = (alg->minkeylen + alg->maxkeylen)/2; 26690075Sobrien sop.mackey = (char *) malloc(sop.mackeylen); 26790075Sobrien if (sop.mackey == NULL) 26890075Sobrien err(1, "malloc (mac)"); 26990075Sobrien for (i = 0; i < sop.mackeylen; i++) 27090075Sobrien sop.mackey[i] = rdigit(); 27190075Sobrien sop.mac = alg->code; 27290075Sobrien } 27390075Sobrien sop.crid = crid; 27490075Sobrien if (ioctl(fd, cmd, &sop) < 0) { 27590075Sobrien if (cmd == CIOCGSESSION || cmd == CIOCGSESSION2) { 27690075Sobrien close(fd); 27790075Sobrien if (verbose) { 27890075Sobrien printf("cipher %s", alg->name); 27990075Sobrien if (alg->ishash) 28090075Sobrien printf(" mackeylen %u\n", sop.mackeylen); 28190075Sobrien else 28290075Sobrien printf(" keylen %u\n", sop.keylen); 28390075Sobrien perror("CIOCGSESSION"); 28490075Sobrien } 28590075Sobrien /* hardware doesn't support algorithm; skip it */ 28690075Sobrien return; 28790075Sobrien } 28890075Sobrien printf("cipher %s keylen %u mackeylen %u\n", 28990075Sobrien alg->name, sop.keylen, sop.mackeylen); 29090075Sobrien err(1, "CIOCGSESSION"); 29190075Sobrien } 29290075Sobrien 29390075Sobrien originaltext = malloc(3*size); 29490075Sobrien if (originaltext == NULL) 29590075Sobrien err(1, "malloc (text)"); 29690075Sobrien cleartext = originaltext+size; 29790075Sobrien ciphertext = cleartext+size; 29890075Sobrien for (i = 0; i < size; i++) 29990075Sobrien cleartext[i] = rdigit(); 30090075Sobrien memcpy(originaltext, cleartext, size); 30190075Sobrien for (i = 0; i < N(iv); i++) 30290075Sobrien iv[i] = rdigit(); 30390075Sobrien 30490075Sobrien if (verbose) { 30590075Sobrien printf("session = 0x%x\n", sop.ses); 30652284Sobrien printf("device = %s\n", crfind(sop.crid)); 30752284Sobrien printf("count = %d, size = %d\n", count, size); 30890075Sobrien if (!alg->ishash) { 30990075Sobrien printf("iv:"); 31090075Sobrien hexdump(iv, sizeof iv); 31190075Sobrien } 31290075Sobrien printf("cleartext:"); 31390075Sobrien hexdump(cleartext, MIN(size, CHUNK)); 31490075Sobrien } 31590075Sobrien 31690075Sobrien gettimeofday(&start, NULL); 31790075Sobrien if (!alg->ishash) { 31890075Sobrien for (i = 0; i < count; i++) { 31990075Sobrien cop.ses = sop.ses; 32090075Sobrien cop.op = COP_ENCRYPT; 32190075Sobrien cop.flags = opflags; 32290075Sobrien cop.len = size; 32390075Sobrien cop.src = cleartext; 32490075Sobrien cop.dst = ciphertext; 32590075Sobrien cop.mac = 0; 326117395Skan cop.iv = iv; 327117395Skan 32890075Sobrien if (ioctl(fd, CIOCCRYPT, &cop) < 0) 32990075Sobrien err(1, "ioctl(CIOCCRYPT)"); 33090075Sobrien 33190075Sobrien if (verify && bcmp(ciphertext, cleartext, size) == 0) { 33252284Sobrien printf("cipher text unchanged:"); 33352284Sobrien hexdump(ciphertext, size); 33490075Sobrien } 33590075Sobrien 33690075Sobrien memset(cleartext, 'x', MIN(size, CHUNK)); 33790075Sobrien cop.ses = sop.ses; 338107590Sobrien cop.op = COP_DECRYPT; 339107590Sobrien cop.flags = opflags; 34052284Sobrien cop.len = size; 34152284Sobrien cop.src = ciphertext; 34290075Sobrien cop.dst = cleartext; 34390075Sobrien cop.mac = 0; 34490075Sobrien cop.iv = iv; 34590075Sobrien 34690075Sobrien if (ioctl(fd, CIOCCRYPT, &cop) < 0) 34752284Sobrien err(1, "ioctl(CIOCCRYPT)"); 348117395Skan 349117395Skan if (verify && bcmp(cleartext, originaltext, size) != 0) { 35052284Sobrien printf("decrypt mismatch:\n"); 351117395Skan printf("original:"); 352117395Skan hexdump(originaltext, size); 353117395Skan printf("cleartext:"); 354117395Skan hexdump(cleartext, size); 355117395Skan } 356117395Skan } 35752284Sobrien } else { 35890075Sobrien for (i = 0; i < count; i++) { 35990075Sobrien cop.ses = sop.ses; 36090075Sobrien cop.op = 0; 36190075Sobrien cop.flags = opflags; 36290075Sobrien cop.len = size; 36352284Sobrien cop.src = cleartext; 36490075Sobrien cop.dst = 0; 36590075Sobrien cop.mac = ciphertext; 36690075Sobrien cop.iv = 0; 36790075Sobrien 36890075Sobrien if (ioctl(fd, CIOCCRYPT, &cop) < 0) 36952284Sobrien err(1, "ioctl(CIOCCRYPT)"); 37090075Sobrien } 37190075Sobrien } 37290075Sobrien gettimeofday(&stop, NULL); 37390075Sobrien 37490075Sobrien if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0) 37590075Sobrien perror("ioctl(CIOCFSESSION)"); 37690075Sobrien 37790075Sobrien if (verbose) { 37890075Sobrien printf("cleartext:"); 37990075Sobrien hexdump(cleartext, MIN(size, CHUNK)); 38090075Sobrien } 38190075Sobrien timersub(&stop, &start, tv); 38290075Sobrien 38390075Sobrien free(originaltext); 38490075Sobrien 38590075Sobrien close(fd); 38690075Sobrien} 38790075Sobrien 38890075Sobrien#ifdef __FreeBSD__ 38990075Sobrienstatic void 39090075Sobrienresetstats() 39190075Sobrien{ 39290075Sobrien struct cryptostats stats; 39390075Sobrien size_t slen; 39490075Sobrien 39590075Sobrien slen = sizeof (stats); 39690075Sobrien if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) { 39790075Sobrien perror("kern.crypto_stats"); 39890075Sobrien return; 39990075Sobrien } 40090075Sobrien bzero(&stats.cs_invoke, sizeof (stats.cs_invoke)); 40190075Sobrien bzero(&stats.cs_done, sizeof (stats.cs_done)); 40290075Sobrien bzero(&stats.cs_cb, sizeof (stats.cs_cb)); 40390075Sobrien bzero(&stats.cs_finis, sizeof (stats.cs_finis)); 40490075Sobrien stats.cs_invoke.min.tv_sec = 10000; 40590075Sobrien stats.cs_done.min.tv_sec = 10000; 40690075Sobrien stats.cs_cb.min.tv_sec = 10000; 40790075Sobrien stats.cs_finis.min.tv_sec = 10000; 40890075Sobrien if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0) 40990075Sobrien perror("kern.cryptostats"); 41090075Sobrien} 41190075Sobrien 41290075Sobrienstatic void 41390075Sobrienprintt(const char* tag, struct cryptotstat *ts) 41490075Sobrien{ 41590075Sobrien uint64_t avg, min, max; 41690075Sobrien 41790075Sobrien if (ts->count == 0) 41890075Sobrien return; 41990075Sobrien avg = (1000000000LL*ts->acc.tv_sec + ts->acc.tv_nsec) / ts->count; 42090075Sobrien min = 1000000000LL*ts->min.tv_sec + ts->min.tv_nsec; 42190075Sobrien max = 1000000000LL*ts->max.tv_sec + ts->max.tv_nsec; 42290075Sobrien printf("%16.16s: avg %6llu ns : min %6llu ns : max %7llu ns [%u samps]\n", 42390075Sobrien tag, avg, min, max, ts->count); 42452284Sobrien} 42590075Sobrien#endif 42690075Sobrien 42790075Sobrienstatic void 42852284Sobrienruntests(struct alg *alg, int count, int size, u_long cmd, int threads, int profile) 42990075Sobrien{ 43090075Sobrien int i, status; 43190075Sobrien double t; 43290075Sobrien void *region; 43390075Sobrien struct timeval *tvp; 43490075Sobrien struct timeval total; 43590075Sobrien int otiming; 43690075Sobrien 43790075Sobrien if (size % alg->blocksize) { 43890075Sobrien if (verbose) 43990075Sobrien printf("skipping blocksize %u 'cuz not a multiple of " 44090075Sobrien "%s blocksize %u\n", 44190075Sobrien size, alg->name, alg->blocksize); 44290075Sobrien return; 44390075Sobrien } 44490075Sobrien 44590075Sobrien region = mmap(NULL, threads * sizeof (struct timeval), 44690075Sobrien PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); 44790075Sobrien if (region == MAP_FAILED) { 44852284Sobrien perror("mmap"); 44952284Sobrien return; 45052284Sobrien } 45190075Sobrien tvp = (struct timeval *) region; 45290075Sobrien#ifdef __FreeBSD__ 45390075Sobrien if (profile) { 45490075Sobrien size_t tlen = sizeof (otiming); 45590075Sobrien int timing = 1; 45690075Sobrien 45790075Sobrien resetstats(); 45890075Sobrien if (sysctlbyname("debug.crypto_timing", &otiming, &tlen, 45990075Sobrien &timing, sizeof (timing)) < 0) 46090075Sobrien perror("debug.crypto_timing"); 46190075Sobrien } 46290075Sobrien#endif 46390075Sobrien 46490075Sobrien if (threads > 1) { 46590075Sobrien for (i = 0; i < threads; i++) 46690075Sobrien if (fork() == 0) { 46790075Sobrien runtest(alg, count, size, cmd, &tvp[i]); 46890075Sobrien exit(0); 46990075Sobrien } 47090075Sobrien while (waitpid(WAIT_MYPGRP, &status, 0) != -1) 47190075Sobrien ; 47290075Sobrien } else 47390075Sobrien runtest(alg, count, size, cmd, tvp); 47490075Sobrien 47590075Sobrien t = 0; 47690075Sobrien for (i = 0; i < threads; i++) 47790075Sobrien t += (((double)tvp[i].tv_sec * 1000000 + tvp[i].tv_usec) / 1000000); 47890075Sobrien if (t) { 47990075Sobrien int nops = alg->ishash ? count : 2*count; 48090075Sobrien 48190075Sobrien#if 0 48290075Sobrien t /= threads; 48390075Sobrien printf("%6.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n", 48490075Sobrien t, nops, alg->name, size, (double)nops*size / t, 48590075Sobrien (double)nops*size / t * 8 / 1024 / 1024); 48690075Sobrien#else 48790075Sobrien nops *= threads; 48890075Sobrien printf("%8.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n", 48990075Sobrien t, nops, alg->name, size, (double)nops*size / t, 49090075Sobrien (double)nops*size / t * 8 / 1024 / 1024); 49190075Sobrien#endif 49290075Sobrien } 49390075Sobrien#ifdef __FreeBSD__ 49490075Sobrien if (profile) { 49590075Sobrien struct cryptostats stats; 49690075Sobrien size_t slen = sizeof (stats); 49790075Sobrien 49890075Sobrien if (sysctlbyname("debug.crypto_timing", NULL, NULL, 49990075Sobrien &otiming, sizeof (otiming)) < 0) 50090075Sobrien perror("debug.crypto_timing"); 50190075Sobrien if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) 50290075Sobrien perror("kern.cryptostats"); 50390075Sobrien if (stats.cs_invoke.count) { 50490075Sobrien printt("dispatch->invoke", &stats.cs_invoke); 50590075Sobrien printt("invoke->done", &stats.cs_done); 50690075Sobrien printt("done->cb", &stats.cs_cb); 50790075Sobrien printt("cb->finis", &stats.cs_finis); 50890075Sobrien } 50990075Sobrien } 51090075Sobrien#endif 51190075Sobrien fflush(stdout); 51290075Sobrien} 51390075Sobrien 51490075Sobrienint 51590075Sobrienmain(int argc, char **argv) 51690075Sobrien{ 51790075Sobrien struct alg *alg = NULL; 51890075Sobrien int count = 1; 51990075Sobrien int sizes[128], nsizes = 0; 52090075Sobrien u_long cmd = CIOCGSESSION2; 52190075Sobrien int testall = 0; 52290075Sobrien int maxthreads = 1; 52390075Sobrien int profile = 0; 52490075Sobrien int i, ch; 525117395Skan 526117395Skan while ((ch = getopt(argc, argv, "cpzsva:bd:t:")) != -1) { 52790075Sobrien switch (ch) { 52890075Sobrien#ifdef CIOCGSSESSION 52990075Sobrien case 's': 53090075Sobrien cmd = CIOCGSSESSION; 53190075Sobrien break; 53290075Sobrien#endif 53390075Sobrien case 'v': 53490075Sobrien verbose++; 53590075Sobrien break; 53690075Sobrien case 'a': 53790075Sobrien alg = getalgbyname(optarg); 53890075Sobrien if (alg == NULL) { 53990075Sobrien if (streq(optarg, "rijndael")) 54090075Sobrien alg = getalgbyname("aes"); 54190075Sobrien else 54290075Sobrien usage(argv[0]); 54390075Sobrien } 54490075Sobrien break; 54590075Sobrien case 'd': 54690075Sobrien crid = crlookup(optarg); 54790075Sobrien break; 54890075Sobrien case 't': 54990075Sobrien maxthreads = atoi(optarg); 55090075Sobrien break; 55190075Sobrien case 'z': 55290075Sobrien testall = 1; 55390075Sobrien break; 55490075Sobrien case 'p': 55590075Sobrien profile = 1; 55690075Sobrien break; 55790075Sobrien case 'b': 55890075Sobrien opflags |= COP_F_BATCH; 55990075Sobrien break; 56090075Sobrien case 'c': 56190075Sobrien verify = 1; 56290075Sobrien break; 56390075Sobrien default: 56490075Sobrien usage(argv[0]); 56590075Sobrien } 56690075Sobrien } 56790075Sobrien argc -= optind, argv += optind; 56890075Sobrien if (argc > 0) 56990075Sobrien count = atoi(argv[0]); 57090075Sobrien while (argc > 1) { 57190075Sobrien int s = atoi(argv[1]); 57290075Sobrien if (nsizes < N(sizes)) { 57390075Sobrien sizes[nsizes++] = s; 57490075Sobrien } else { 57590075Sobrien printf("Too many sizes, ignoring %u\n", s); 57690075Sobrien } 57790075Sobrien argc--, argv++; 57890075Sobrien } 57990075Sobrien if (nsizes == 0) { 58090075Sobrien if (alg) 581102780Skan sizes[nsizes++] = alg->blocksize; 582102780Skan else 583102780Skan sizes[nsizes++] = 8; 584102780Skan if (testall) { 585102780Skan while (sizes[nsizes-1] < 8*1024) { 586102780Skan sizes[nsizes] = sizes[nsizes-1]<<1; 587102780Skan nsizes++; 588102780Skan } 58990075Sobrien } 59090075Sobrien } 59190075Sobrien 59290075Sobrien if (testall) { 59390075Sobrien for (i = 0; i < N(algorithms); i++) { 59490075Sobrien int j; 59590075Sobrien alg = &algorithms[i]; 59690075Sobrien for (j = 0; j < nsizes; j++) 59790075Sobrien runtests(alg, count, sizes[j], cmd, maxthreads, profile); 59890075Sobrien } 59990075Sobrien } else { 60090075Sobrien if (alg == NULL) 60190075Sobrien alg = getalgbycode(CRYPTO_3DES_CBC); 60290075Sobrien for (i = 0; i < nsizes; i++) 60390075Sobrien runtests(alg, count, sizes[i], cmd, maxthreads, profile); 60490075Sobrien } 60590075Sobrien 60690075Sobrien return (0); 60790075Sobrien} 60890075Sobrien 60990075Sobrienvoid 61090075Sobrienhexdump(char *p, int n) 61190075Sobrien{ 61290075Sobrien int i, off; 61390075Sobrien 61490075Sobrien for (off = 0; n > 0; off += 16, n -= 16) { 61590075Sobrien printf("%s%04x:", off == 0 ? "\n" : "", off); 61652284Sobrien i = (n >= 16 ? 16 : n); 61752284Sobrien do { 61852284Sobrien printf(" %02x", *p++ & 0xff); 61952284Sobrien } while (--i); 620117395Skan printf("\n"); 62152284Sobrien } 62252284Sobrien} 62352284Sobrien