Changeset View
Changeset View
Standalone View
Standalone View
tools/tools/crypto/cryptotest.c
Show First 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | |||||||||
#include <sysexits.h> | #include <sysexits.h> | ||||||||
#include <unistd.h> | #include <unistd.h> | ||||||||
#include <crypto/cryptodev.h> | #include <crypto/cryptodev.h> | ||||||||
#define CHUNK 64 /* how much to display */ | #define CHUNK 64 /* how much to display */ | ||||||||
#define streq(a,b) (strcasecmp(a,b) == 0) | #define streq(a,b) (strcasecmp(a,b) == 0) | ||||||||
void hexdump(char *, int); | static int verbose = 0; | ||||||||
static int opflags = 0; | |||||||||
static int verify = 0; | |||||||||
static int crid = CRYPTO_FLAG_HARDWARE; | |||||||||
int verbose = 0; | static struct alg { | ||||||||
int opflags = 0; | |||||||||
int verify = 0; | |||||||||
int crid = CRYPTO_FLAG_HARDWARE; | |||||||||
struct alg { | |||||||||
const char* name; | const char* name; | ||||||||
int ishash; | int ishash; | ||||||||
int blocksize; | int blocksize; | ||||||||
int minkeylen; | int minkeylen; | ||||||||
int maxkeylen; | int maxkeylen; | ||||||||
int code; | int code; | ||||||||
} algorithms[] = { | } algorithms[] = { | ||||||||
#ifdef CRYPTO_NULL_CBC | #ifdef CRYPTO_NULL_CBC | ||||||||
Show All 13 Lines | #endif | ||||||||
{ "blake2s", 1, 64, 32, 32, CRYPTO_BLAKE2S }, | { "blake2s", 1, 64, 32, 32, CRYPTO_BLAKE2S }, | ||||||||
{ "md5", 1, 8, 16, 16, CRYPTO_MD5_HMAC }, | { "md5", 1, 8, 16, 16, CRYPTO_MD5_HMAC }, | ||||||||
{ "sha1", 1, 8, 20, 20, CRYPTO_SHA1_HMAC }, | { "sha1", 1, 8, 20, 20, CRYPTO_SHA1_HMAC }, | ||||||||
{ "sha256", 1, 8, 32, 32, CRYPTO_SHA2_256_HMAC }, | { "sha256", 1, 8, 32, 32, CRYPTO_SHA2_256_HMAC }, | ||||||||
{ "sha384", 1, 8, 48, 48, CRYPTO_SHA2_384_HMAC }, | { "sha384", 1, 8, 48, 48, CRYPTO_SHA2_384_HMAC }, | ||||||||
{ "sha512", 1, 8, 64, 64, CRYPTO_SHA2_512_HMAC }, | { "sha512", 1, 8, 64, 64, CRYPTO_SHA2_512_HMAC }, | ||||||||
}; | }; | ||||||||
struct alg* getalgbycode(int); | |||||||||
static void usage(const char*); | |||||||||
static struct alg* getalgbyname(const char*); | |||||||||
static int devcrypto(void); | |||||||||
static int crlookup(const char *); | |||||||||
static const char * crfind(int); | |||||||||
static char rdigit(void); | |||||||||
static void runtest(struct alg *, struct alg *, int, int, u_long, struct timeval *); | |||||||||
static void printt(const char *, struct cryptotstat *); | |||||||||
static void runtests(struct alg *, struct alg *, int, int, u_long, int, int); | |||||||||
static void resetstats(void); | |||||||||
static void hexdump(char *, int); | |||||||||
void | void | ||||||||
usage(const char* cmd) | usage(const char* cmd) | ||||||||
{ | { | ||||||||
printf("usage: %s [-czsbv] [-d dev] [-a algorithm] [count] [size ...]\n", | printf("usage: %s [-czsbv] [-d dev] [-a algorithm] [count] [size ...]\n", | ||||||||
cmd); | cmd); | ||||||||
printf("where algorithm is one of:\n"); | printf("where algorithm is one of:\n"); | ||||||||
printf(" null des 3des (default) blowfish cast skipjack rij\n"); | printf(" null des 3des (default) blowfish cast skipjack rij\n"); | ||||||||
printf(" aes aes192 aes256 chacha20 md5 sha1 sha256 sha384 sha512\n"); | printf(" aes aes192 aes256 chacha20 md5 sha1 sha256 sha384 sha512\n"); | ||||||||
Show All 12 Lines | usage(const char* cmd) | ||||||||
printf("-p profile kernel crypto operation (must be root)\n"); | printf("-p profile kernel crypto operation (must be root)\n"); | ||||||||
printf("-t n for n threads and run tests concurrently\n"); | printf("-t n for n threads and run tests concurrently\n"); | ||||||||
exit(-1); | exit(-1); | ||||||||
} | } | ||||||||
struct alg* | struct alg* | ||||||||
getalgbycode(int cipher) | getalgbycode(int cipher) | ||||||||
{ | { | ||||||||
int i; | uint64_t i; | ||||||||
markj: This should probably be `size_t` instead. | |||||||||
for (i = 0; i < nitems(algorithms); i++) | for (i = 0; i < nitems(algorithms); i++) | ||||||||
if (cipher == algorithms[i].code) | if (cipher == algorithms[i].code) | ||||||||
return &algorithms[i]; | return &algorithms[i]; | ||||||||
return NULL; | return NULL; | ||||||||
} | } | ||||||||
struct alg* | struct alg* | ||||||||
getalgbyname(const char* name) | getalgbyname(const char* name) | ||||||||
{ | { | ||||||||
int i; | uint64_t i; | ||||||||
Not Done Inline ActionsDitto. markj: Ditto. | |||||||||
for (i = 0; i < nitems(algorithms); i++) | for (i = 0; i < nitems(algorithms); i++) | ||||||||
if (streq(name, algorithms[i].name)) | if (streq(name, algorithms[i].name)) | ||||||||
return &algorithms[i]; | return &algorithms[i]; | ||||||||
return NULL; | return NULL; | ||||||||
} | } | ||||||||
int | int | ||||||||
Show All 22 Lines | crlookup(const char *devname) | ||||||||
find.crid = -1; | find.crid = -1; | ||||||||
strlcpy(find.name, devname, sizeof(find.name)); | strlcpy(find.name, devname, sizeof(find.name)); | ||||||||
if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) | if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) | ||||||||
err(1, "ioctl(CIOCFINDDEV)"); | err(1, "ioctl(CIOCFINDDEV)"); | ||||||||
return find.crid; | return find.crid; | ||||||||
} | } | ||||||||
const char * | const char * | ||||||||
crfind(int crid) | crfind(int id) | ||||||||
{ | { | ||||||||
static struct crypt_find_op find; | static struct crypt_find_op find; | ||||||||
bzero(&find, sizeof(find)); | bzero(&find, sizeof(find)); | ||||||||
find.crid = crid; | find.crid = id; | ||||||||
if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) | if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) | ||||||||
err(1, "ioctl(CIOCFINDDEV): crid %d", crid); | err(1, "ioctl(CIOCFINDDEV): crid %d", crid); | ||||||||
return find.name; | return find.name; | ||||||||
} | } | ||||||||
char | char | ||||||||
rdigit(void) | rdigit(void) | ||||||||
{ | { | ||||||||
const char a[] = { | const char a[] = { | ||||||||
0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41, | 0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41, | ||||||||
0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01 | 0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01 | ||||||||
}; | }; | ||||||||
return 0x20+a[random()%nitems(a)]; | return 0x20+a[random()%nitems(a)]; | ||||||||
} | } | ||||||||
void | void | ||||||||
runtest(struct alg *ealg, struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) | runtest(struct alg *ealg, struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) | ||||||||
{ | { | ||||||||
uint32_t j; | |||||||||
uint64_t k; | |||||||||
Not Done Inline ActionsThese can be declared in the for-loop headers where they are used. markj: These can be declared in the for-loop headers where they are used. | |||||||||
int i, fd = devcrypto(); | int i, fd = devcrypto(); | ||||||||
struct timeval start, stop, dt; | struct timeval start, stop; | ||||||||
char *cleartext, *ciphertext, *originaltext, *key; | char *cleartext, *ciphertext, *originaltext, *key; | ||||||||
struct session2_op sop; | struct session2_op sop; | ||||||||
struct crypt_op cop; | struct crypt_op cop; | ||||||||
char iv[EALG_MAX_BLOCK_LEN]; | char iv[EALG_MAX_BLOCK_LEN]; | ||||||||
char digest[512/8]; | char digest[512/8]; | ||||||||
/* Canonicalize 'ealg' to crypt alg and 'alg' to authentication alg. */ | /* Canonicalize 'ealg' to crypt alg and 'alg' to authentication alg. */ | ||||||||
if (ealg == NULL && !alg->ishash) { | if (ealg == NULL && !alg->ishash) { | ||||||||
ealg = alg; | ealg = alg; | ||||||||
alg = NULL; | alg = NULL; | ||||||||
} | } | ||||||||
bzero(&sop, sizeof(sop)); | bzero(&sop, sizeof(sop)); | ||||||||
if (ealg != NULL) { | if (ealg != NULL) { | ||||||||
sop.keylen = (ealg->minkeylen + ealg->maxkeylen)/2; | sop.keylen = (ealg->minkeylen + ealg->maxkeylen)/2; | ||||||||
key = (char *) malloc(sop.keylen); | key = (char *) malloc(sop.keylen); | ||||||||
if (key == NULL) | if (key == NULL) | ||||||||
err(1, "malloc (key)"); | err(1, "malloc (key)"); | ||||||||
for (i = 0; i < sop.keylen; i++) | for (j = 0; j < sop.keylen; j++) | ||||||||
key[i] = rdigit(); | key[j] = rdigit(); | ||||||||
sop.key = key; | sop.key = key; | ||||||||
sop.cipher = ealg->code; | sop.cipher = ealg->code; | ||||||||
} | } | ||||||||
if (alg != NULL) { | if (alg != NULL) { | ||||||||
sop.mackeylen = (alg->minkeylen + alg->maxkeylen)/2; | sop.mackeylen = (alg->minkeylen + alg->maxkeylen)/2; | ||||||||
key = (char *) malloc(sop.mackeylen); | key = (char *) malloc(sop.mackeylen); | ||||||||
if (key == NULL) | if (key == NULL) | ||||||||
err(1, "malloc (mac)"); | err(1, "malloc (mac)"); | ||||||||
Show All 30 Lines | runtest(struct alg *ealg, struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) | ||||||||
originaltext = malloc(3*size); | originaltext = malloc(3*size); | ||||||||
if (originaltext == NULL) | if (originaltext == NULL) | ||||||||
err(1, "malloc (text)"); | err(1, "malloc (text)"); | ||||||||
cleartext = originaltext+size; | cleartext = originaltext+size; | ||||||||
ciphertext = cleartext+size; | ciphertext = cleartext+size; | ||||||||
for (i = 0; i < size; i++) | for (i = 0; i < size; i++) | ||||||||
cleartext[i] = rdigit(); | cleartext[i] = rdigit(); | ||||||||
memcpy(originaltext, cleartext, size); | memcpy(originaltext, cleartext, size); | ||||||||
for (i = 0; i < nitems(iv); i++) | for (k = 0; k < nitems(iv); k++) | ||||||||
iv[i] = rdigit(); | iv[k] = rdigit(); | ||||||||
if (verbose) { | if (verbose) { | ||||||||
printf("session = 0x%x\n", sop.ses); | printf("session = 0x%x\n", sop.ses); | ||||||||
printf("device = %s\n", crfind(sop.crid)); | printf("device = %s\n", crfind(sop.crid)); | ||||||||
printf("count = %d, size = %d\n", count, size); | printf("count = %d, size = %d\n", count, size); | ||||||||
if (ealg) { | if (ealg) { | ||||||||
printf("iv:"); | printf("iv:"); | ||||||||
hexdump(iv, sizeof iv); | hexdump(iv, sizeof iv); | ||||||||
▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | runtest(struct alg *ealg, struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) | ||||||||
free(originaltext); | free(originaltext); | ||||||||
close(fd); | close(fd); | ||||||||
} | } | ||||||||
#ifdef __FreeBSD__ | #ifdef __FreeBSD__ | ||||||||
void | void | ||||||||
resetstats() | resetstats(void) | ||||||||
{ | { | ||||||||
struct cryptostats stats; | struct cryptostats stats; | ||||||||
size_t slen; | size_t slen; | ||||||||
slen = sizeof (stats); | slen = sizeof (stats); | ||||||||
if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) { | if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) { | ||||||||
perror("kern.crypto_stats"); | perror("kern.crypto_stats"); | ||||||||
return; | return; | ||||||||
} | } | ||||||||
bzero(&stats.cs_invoke, sizeof (stats.cs_invoke)); | bzero(&stats.cs_invoke, sizeof (stats.cs_invoke)); | ||||||||
bzero(&stats.cs_done, sizeof (stats.cs_done)); | bzero(&stats.cs_done, sizeof (stats.cs_done)); | ||||||||
bzero(&stats.cs_cb, sizeof (stats.cs_cb)); | bzero(&stats.cs_cb, sizeof (stats.cs_cb)); | ||||||||
bzero(&stats.cs_finis, sizeof (stats.cs_finis)); | bzero(&stats.cs_finis, sizeof (stats.cs_finis)); | ||||||||
stats.cs_invoke.min.tv_sec = 10000; | stats.cs_invoke.min.tv_sec = 10000; | ||||||||
stats.cs_done.min.tv_sec = 10000; | stats.cs_done.min.tv_sec = 10000; | ||||||||
stats.cs_cb.min.tv_sec = 10000; | stats.cs_cb.min.tv_sec = 10000; | ||||||||
stats.cs_finis.min.tv_sec = 10000; | stats.cs_finis.min.tv_sec = 10000; | ||||||||
if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0) | if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0) | ||||||||
perror("kern.cryptostats"); | perror("kern.cryptostats"); | ||||||||
} | } | ||||||||
void | void | ||||||||
printt(const char* tag, struct cryptotstat *ts) | printt(const char* tag, struct cryptotstat *ts) | ||||||||
{ | { | ||||||||
uint64_t avg, min, max; | unsigned long long avg, min, max; | ||||||||
if (ts->count == 0) | if (ts->count == 0) | ||||||||
return; | return; | ||||||||
avg = (1000000000LL*ts->acc.tv_sec + ts->acc.tv_nsec) / ts->count; | avg = (1000000000LL*ts->acc.tv_sec + ts->acc.tv_nsec) / ts->count; | ||||||||
min = 1000000000LL*ts->min.tv_sec + ts->min.tv_nsec; | min = 1000000000LL*ts->min.tv_sec + ts->min.tv_nsec; | ||||||||
max = 1000000000LL*ts->max.tv_sec + ts->max.tv_nsec; | max = 1000000000LL*ts->max.tv_sec + ts->max.tv_nsec; | ||||||||
printf("%16.16s: avg %6llu ns : min %6llu ns : max %7llu ns [%u samps]\n", | printf("%16.16s: avg %6llu ns : min %6llu ns : max %7llu ns [%u samps]\n", | ||||||||
tag, avg, min, max, ts->count); | tag, avg, min, max, ts->count); | ||||||||
} | } | ||||||||
#endif | #endif | ||||||||
void | void | ||||||||
runtests(struct alg *ealg, struct alg *alg, int count, int size, u_long cmd, int threads, int profile) | runtests(struct alg *ealg, struct alg *alg, int count, int size, u_long cmd, int threads, int profile) | ||||||||
{ | { | ||||||||
int i, status; | int i, status; | ||||||||
double t; | double t; | ||||||||
void *region; | void *region; | ||||||||
struct timeval *tvp; | struct timeval *tvp; | ||||||||
struct timeval total; | |||||||||
int otiming; | int otiming; | ||||||||
if (size % alg->blocksize || (ealg && size % ealg->blocksize)) { | if (size % alg->blocksize || (ealg && size % ealg->blocksize)) { | ||||||||
if (verbose) | if (verbose) | ||||||||
printf("skipping blocksize %u 'cuz not a multiple of " | printf("skipping blocksize %u 'cuz not a multiple of " | ||||||||
"%s blocksize %u (or %s blocksize %u)\n", | "%s blocksize %u (or %s blocksize %u)\n", | ||||||||
size, alg->name, alg->blocksize, | size, alg->name, alg->blocksize, | ||||||||
ealg ? ealg->name : "n/a", | ealg ? ealg->name : "n/a", | ||||||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | |||||||||
} | } | ||||||||
int | int | ||||||||
main(int argc, char **argv) | main(int argc, char **argv) | ||||||||
{ | { | ||||||||
struct alg *alg = NULL, *ealg = NULL; | struct alg *alg = NULL, *ealg = NULL; | ||||||||
char *tmp; | char *tmp; | ||||||||
int count = 1; | int count = 1; | ||||||||
int sizes[128], nsizes = 0; | int sizes[128]; | ||||||||
uint64_t nsizes = 0; | |||||||||
u_long cmd = CIOCGSESSION2; | u_long cmd = CIOCGSESSION2; | ||||||||
int testall = 0; | int testall = 0; | ||||||||
int maxthreads = 1; | int maxthreads = 1; | ||||||||
int profile = 0; | int profile = 0; | ||||||||
int i, ch; | int ch; | ||||||||
uint64_t i; | |||||||||
while ((ch = getopt(argc, argv, "cpzsva:bd:t:")) != -1) { | while ((ch = getopt(argc, argv, "cpzsva:bd:t:")) != -1) { | ||||||||
switch (ch) { | switch (ch) { | ||||||||
#ifdef CIOCGSSESSION | #ifdef CIOCGSSESSION | ||||||||
case 's': | case 's': | ||||||||
cmd = CIOCGSSESSION; | cmd = CIOCGSSESSION; | ||||||||
break; | break; | ||||||||
#endif | #endif | ||||||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | if (testall) { | ||||||||
sizes[nsizes] = sizes[nsizes-1]<<1; | sizes[nsizes] = sizes[nsizes-1]<<1; | ||||||||
nsizes++; | nsizes++; | ||||||||
} | } | ||||||||
} | } | ||||||||
} | } | ||||||||
if (testall) { | if (testall) { | ||||||||
for (i = 0; i < nitems(algorithms); i++) { | for (i = 0; i < nitems(algorithms); i++) { | ||||||||
int j; | uint64_t j; | ||||||||
alg = &algorithms[i]; | alg = &algorithms[i]; | ||||||||
for (j = 0; j < nsizes; j++) | for (j = 0; j < nsizes; j++) | ||||||||
Not Done Inline Actions
markj: | |||||||||
runtests(ealg, alg, count, sizes[j], cmd, maxthreads, profile); | runtests(ealg, alg, count, sizes[j], cmd, maxthreads, profile); | ||||||||
} | } | ||||||||
} else { | } else { | ||||||||
if (alg == NULL) | if (alg == NULL) | ||||||||
alg = getalgbycode(CRYPTO_3DES_CBC); | alg = getalgbycode(CRYPTO_3DES_CBC); | ||||||||
for (i = 0; i < nsizes; i++) | for (i = 0; i < nsizes; i++) | ||||||||
runtests(ealg, alg, count, sizes[i], cmd, maxthreads, profile); | runtests(ealg, alg, count, sizes[i], cmd, maxthreads, profile); | ||||||||
} | } | ||||||||
Show All 18 Lines |
This should probably be size_t instead.