summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2003-01-06 22:11:56 +0000
committersam <sam@FreeBSD.org>2003-01-06 22:11:56 +0000
commitf0f8069fbc66b75d41b6f8ff349d866f03c23fce (patch)
tree63a1e0eac96d0d272b2dded0cb071ff6dd4bbffb /tools
parentd110043285c7f70ed63981b7aac6fbea8c664982 (diff)
downloadFreeBSD-src-f0f8069fbc66b75d41b6f8ff349d866f03c23fce.zip
FreeBSD-src-f0f8069fbc66b75d41b6f8ff349d866f03c23fce.tar.gz
more crypto test stuff:
o cryptotest can now run multiple threads with -t option o cryptotest can now "profile" time spent doing symmetric ops with -p o cryptostats dumps the crypto statistics block o cryptokeystat is an openbsd app that tests public key ops
Diffstat (limited to 'tools')
-rw-r--r--tools/tools/crypto/Makefile8
-rw-r--r--tools/tools/crypto/cryptokeytest.c224
-rw-r--r--tools/tools/crypto/cryptostats.c77
-rw-r--r--tools/tools/crypto/cryptotest.c163
4 files changed, 450 insertions, 22 deletions
diff --git a/tools/tools/crypto/Makefile b/tools/tools/crypto/Makefile
index e592761..8dda355 100644
--- a/tools/tools/crypto/Makefile
+++ b/tools/tools/crypto/Makefile
@@ -1,11 +1,17 @@
# $FreeBSD$
-ALL= cryptotest
+ALL= cryptotest cryptokeytest cryptostats
all: ${ALL}
cryptotest: cryptotest.c
${CC} -o cryptotest cryptotest.c
+cryptokeytest: cryptokeytest.c
+ ${CC} -o cryptokeytest cryptokeytest.c -lcrypto
+
+cryptostats: cryptostats.c
+ ${CC} -o cryptostats cryptostats.c
+
clean:
rm -f ${ALL} core a.out
diff --git a/tools/tools/crypto/cryptokeytest.c b/tools/tools/crypto/cryptokeytest.c
new file mode 100644
index 0000000..a031faf
--- /dev/null
+++ b/tools/tools/crypto/cryptokeytest.c
@@ -0,0 +1,224 @@
+/* $FreeBSD$ */
+/*
+ * The big num stuff is a bit broken at the moment and I've not yet fixed it.
+ * The symtom is that odd size big nums will fail. Test code below (it only
+ * uses modexp currently).
+ *
+ * --Jason L. Wright
+ */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <machine/endian.h>
+#include <sys/time.h>
+#include <crypto/cryptodev.h>
+#include <openssl/bn.h>
+#include <fcntl.h>
+#include <err.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+static int crypto_fd = -1;
+
+/*
+ * Convert a little endian byte string in 'p' that
+ * is 'plen' bytes long to a BIGNUM. If 'dst' is NULL,
+ * a new BIGNUM is allocated. Returns NULL on failure.
+ *
+ * XXX there has got to be a more efficient way to do
+ * this, but I haven't figured out enough of the OpenSSL
+ * magic.
+ */
+BIGNUM *
+le_to_bignum(BIGNUM *dst, u_int8_t *p, int plen)
+{
+ u_int8_t *pd;
+ int i;
+
+ if (plen == 0)
+ return (NULL);
+
+ if ((pd = (u_int8_t *)malloc(plen)) == NULL)
+ return (NULL);
+
+ for (i = 0; i < plen; i++)
+ pd[i] = p[plen - i - 1];
+
+ dst = BN_bin2bn(pd, plen, dst);
+ free(pd);
+ return (dst);
+}
+
+/*
+ * Convert a BIGNUM to a little endian byte string.
+ * If 'rd' is NULL, allocate space for it, otherwise
+ * 'rd' is assumed to have room for BN_num_bytes(n)
+ * bytes. Returns NULL on failure.
+ */
+u_int8_t *
+bignum_to_le(BIGNUM *n, u_int8_t *rd)
+{
+ int i, j, k;
+ int blen = BN_num_bytes(n);
+
+ if (blen == 0)
+ return (NULL);
+ if (rd == NULL)
+ rd = (u_int8_t *)malloc(blen);
+ if (rd == NULL)
+ return (NULL);
+
+ for (i = 0, j = 0; i < n->top; i++) {
+ for (k = 0; k < BN_BITS2 / 8; k++) {
+ if ((j + k) >= blen)
+ goto out;
+ rd[j + k] = n->d[i] >> (k * 8);
+ }
+ j += BN_BITS2 / 8;
+ }
+out:
+ return (rd);
+}
+
+int
+UB_mod_exp(BIGNUM *res, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx)
+{
+ struct crypt_kop kop;
+ u_int8_t *ale, *ble, *cle;
+
+ if (crypto_fd == -1) {
+ int fd, fdc = open("/dev/crypto", O_RDONLY);
+
+ if (fdc == -1)
+ err(1, "/dev/crypto");
+ if (ioctl(fdc, CRIOGET, &fd) == -1)
+ err(1, "CRIOGET");
+ close(fdc);
+ crypto_fd = fd;
+ }
+
+ if ((ale = bignum_to_le(a, NULL)) == NULL)
+ err(1, "bignum_to_le, a");
+ if ((ble = bignum_to_le(b, NULL)) == NULL)
+ err(1, "bignum_to_le, b");
+ if ((cle = bignum_to_le(c, NULL)) == NULL)
+ err(1, "bignum_to_le, c");
+
+ bzero(&kop, sizeof(kop));
+ kop.crk_op = CRK_MOD_EXP;
+ kop.crk_iparams = 3;
+ kop.crk_oparams = 1;
+ kop.crk_param[0].crp_p = ale;
+ kop.crk_param[0].crp_nbits = BN_num_bytes(a) * 8;
+ kop.crk_param[1].crp_p = ble;
+ kop.crk_param[1].crp_nbits = BN_num_bytes(b) * 8;
+ kop.crk_param[2].crp_p = cle;
+ kop.crk_param[2].crp_nbits = BN_num_bytes(c) * 8;
+ kop.crk_param[3].crp_p = cle;
+ kop.crk_param[3].crp_nbits = BN_num_bytes(c) * 8;
+
+ if (ioctl(crypto_fd, CIOCKEY, &kop) == -1)
+ err(1, "CIOCKEY");
+
+ bzero(ale, BN_num_bytes(a));
+ free(ale);
+ bzero(ble, BN_num_bytes(b));
+ free(ble);
+
+ if (kop.crk_status != 0) {
+ printf("error %d\n", kop.crk_status);
+ bzero(cle, BN_num_bytes(c));
+ free(cle);
+ return (-1);
+ } else {
+ res = le_to_bignum(res, cle, BN_num_bytes(c));
+ bzero(cle, BN_num_bytes(c));
+ free(cle);
+ if (res == NULL)
+ err(1, "le_to_bignum");
+ return (0);
+ }
+ return (0);
+}
+
+void
+show_result(a, b, c, sw, hw)
+BIGNUM *a, *b, *c, *sw, *hw;
+{
+ printf("\n");
+
+ printf("A = ");
+ BN_print_fp(stdout, a);
+ printf("\n");
+
+ printf("B = ");
+ BN_print_fp(stdout, b);
+ printf("\n");
+
+ printf("C = ");
+ BN_print_fp(stdout, c);
+ printf("\n");
+
+ printf("sw= ");
+ BN_print_fp(stdout, sw);
+ printf("\n");
+
+ printf("hw= ");
+ BN_print_fp(stdout, hw);
+ printf("\n");
+
+ printf("\n");
+}
+
+void
+testit(void)
+{
+ BIGNUM *a, *b, *c, *r1, *r2;
+ BN_CTX *ctx;
+
+ ctx = BN_CTX_new();
+
+ a = BN_new();
+ b = BN_new();
+ c = BN_new();
+ r1 = BN_new();
+ r2 = BN_new();
+
+ BN_pseudo_rand(a, 1023, 0, 0);
+ BN_pseudo_rand(b, 1023, 0, 0);
+ BN_pseudo_rand(c, 1024, 0, 0);
+
+ if (BN_cmp(a, c) > 0) {
+ BIGNUM *rem = BN_new();
+
+ BN_mod(rem, a, c, ctx);
+ UB_mod_exp(r2, rem, b, c, ctx);
+ BN_free(rem);
+ } else {
+ UB_mod_exp(r2, a, b, c, ctx);
+ }
+ BN_mod_exp(r1, a, b, c, ctx);
+
+ if (BN_cmp(r1, r2) != 0) {
+ show_result(a, b, c, r1, r2);
+ }
+
+ BN_free(r2);
+ BN_free(r1);
+ BN_free(c);
+ BN_free(b);
+ BN_free(a);
+ BN_CTX_free(ctx);
+}
+
+int
+main()
+{
+ int i;
+
+ for (i = 0; i < 1000; i++) {
+ fprintf(stderr, "test %d\n", i);
+ testit();
+ }
+ return (0);
+}
diff --git a/tools/tools/crypto/cryptostats.c b/tools/tools/crypto/cryptostats.c
new file mode 100644
index 0000000..3e0c5c1
--- /dev/null
+++ b/tools/tools/crypto/cryptostats.c
@@ -0,0 +1,77 @@
+/* $FreeBSD$ */
+
+/*
+ * Little program to dump the crypto statistics block and, optionally,
+ * zero all the stats or just the timing stuff.
+ */
+#include <stdio.h>
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <crypto/cryptodev.h>
+
+static void
+printt(const char* tag, struct cryptotstat *ts)
+{
+ uint64_t avg, min, max;
+
+ if (ts->count == 0)
+ return;
+ avg = (1000000000LL*ts->acc.tv_sec + ts->acc.tv_nsec) / ts->count;
+ min = 1000000000LL*ts->min.tv_sec + ts->min.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",
+ tag, avg, min, max, ts->count);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct cryptostats stats;
+ size_t slen;
+
+ slen = sizeof (stats);
+ if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, NULL) < 0)
+ err(1, "kern.cryptostats");
+
+ if (argc > 1 && strcmp(argv[1], "-z") == 0) {
+ bzero(&stats.cs_invoke, sizeof (stats.cs_invoke));
+ bzero(&stats.cs_done, sizeof (stats.cs_done));
+ bzero(&stats.cs_cb, sizeof (stats.cs_cb));
+ bzero(&stats.cs_finis, sizeof (stats.cs_finis));
+ stats.cs_invoke.min.tv_sec = 10000;
+ stats.cs_done.min.tv_sec = 10000;
+ stats.cs_cb.min.tv_sec = 10000;
+ stats.cs_finis.min.tv_sec = 10000;
+ if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0)
+ err(1, "kern.cryptostats");
+ exit(0);
+ }
+ if (argc > 1 && strcmp(argv[1], "-Z") == 0) {
+ bzero(&stats, sizeof (stats));
+ stats.cs_invoke.min.tv_sec = 10000;
+ stats.cs_done.min.tv_sec = 10000;
+ stats.cs_cb.min.tv_sec = 10000;
+ stats.cs_finis.min.tv_sec = 10000;
+ if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0)
+ err(1, "kern.cryptostats");
+ exit(0);
+ }
+
+
+ printf("%u symmetric crypto ops (%u errors, %u times driver blocked)\n"
+ , stats.cs_ops, stats.cs_errs, stats.cs_blocks);
+ printf("%u key ops (%u errors, %u times driver blocked)\n"
+ , stats.cs_kops, stats.cs_kerrs, stats.cs_kblocks);
+ printf("%u crypto dispatch thread activations\n", stats.cs_intrs);
+ printf("%u crypto return thread activations\n", stats.cs_rets);
+ if (stats.cs_invoke.count) {
+ printf("\n");
+ printt("dispatch->invoke", &stats.cs_invoke);
+ printt("invoke->done", &stats.cs_done);
+ printt("done->cb", &stats.cs_cb);
+ printt("cb->finis", &stats.cs_finis);
+ }
+ return 0;
+}
diff --git a/tools/tools/crypto/cryptotest.c b/tools/tools/crypto/cryptotest.c
index 70008b2..c4b1df5 100644
--- a/tools/tools/crypto/cryptotest.c
+++ b/tools/tools/crypto/cryptotest.c
@@ -12,20 +12,34 @@
* iterations. Extra arguments can be used to specify one or more buffer
* sizes to use in doing tests.
*
+ * To fork multiple processes all doing the same work, specify -t X on the
+ * command line to get X "threads" running simultaneously. No effort is made
+ * synchronize the threads or otherwise maximize load.
+ *
+ * If the kernel crypto code is built with CRYPTO_TIMING and you run as root,
+ * then you can specify the -p option to get a "profile" of the time spent
+ * processing crypto operations. At present this data is only meaningful for
+ * symmetric operations. To get meaningful numbers you must run on an idle
+ * machine.
+ *
* Expect ~400 Mb/s for a Broadcom 582x for 16K buffers on a reasonable CPU.
* Hifn 7811 parts top out at ~110 Mb/s.
*
* This code originally came from openbsd; give them all the credit.
*/
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
-#include <crypto/cryptodev.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <crypto/cryptodev.h>
#define CHUNK 64 /* how much to display */
#define N(a) (sizeof (a) / sizeof (a[0]))
@@ -47,7 +61,9 @@ struct alg {
int maxkeylen;
int code;
} algorithms[] = {
+#ifdef CRYPTO_NULL_CBC
{ "null", 8, 1, 256, CRYPTO_NULL_CBC },
+#endif
{ "des", 8, 8, 8, CRYPTO_DES_CBC },
{ "3des", 8, 24, 24, CRYPTO_3DES_CBC },
{ "blf", 8, 5, 56, CRYPTO_BLF_CBC },
@@ -95,20 +111,11 @@ getalgbyname(const char* name)
}
static void
-runtest(struct alg *alg, int count, int size, int cmd)
+runtest(struct alg *alg, int count, int size, int cmd, struct timeval *tv)
{
int i;
struct timeval start, stop, dt;
char *cleartext, *ciphertext;
- double t;
-
- if (size % alg->blocksize) {
- if (verbose)
- printf("skipping blocksize %u 'cuz not a multiple of "
- "%s blocksize %u\n",
- size, alg->name, alg->blocksize);
- return;
- }
if (ioctl(cryptodev_fd,CRIOGET,&fd) == -1)
err(1, "CRIOGET failed");
@@ -182,11 +189,7 @@ runtest(struct alg *alg, int count, int size, int cmd)
printf("cleartext:");
hexdump(cleartext, MIN(size, CHUNK));
}
- timersub(&stop, &start, &dt);
- t = (((double)dt.tv_sec * 1000000 + dt.tv_usec) / 1000000);
- printf("%6.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n",
- t, 2*count, alg->name, size, (double)2*count*size / t,
- (double)2*count*size / t * 8 / 1024 / 1024);
+ timersub(&stop, &start, tv);
free(ciphertext);
free(cleartext);
@@ -194,6 +197,116 @@ runtest(struct alg *alg, int count, int size, int cmd)
close(fd);
}
+static void
+resetstats()
+{
+ struct cryptostats stats;
+ size_t slen;
+
+ slen = sizeof (stats);
+ if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, NULL) < 0) {
+ perror("kern.crypto_stats");
+ return;
+ }
+ bzero(&stats.cs_invoke, sizeof (stats.cs_invoke));
+ bzero(&stats.cs_done, sizeof (stats.cs_done));
+ bzero(&stats.cs_cb, sizeof (stats.cs_cb));
+ bzero(&stats.cs_finis, sizeof (stats.cs_finis));
+ stats.cs_invoke.min.tv_sec = 10000;
+ stats.cs_done.min.tv_sec = 10000;
+ stats.cs_cb.min.tv_sec = 10000;
+ stats.cs_finis.min.tv_sec = 10000;
+ if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0)
+ perror("kern.cryptostats");
+}
+
+static void
+printt(const char* tag, struct cryptotstat *ts)
+{
+ uint64_t avg, min, max;
+
+ if (ts->count == 0)
+ return;
+ avg = (1000000000LL*ts->acc.tv_sec + ts->acc.tv_nsec) / ts->count;
+ min = 1000000000LL*ts->min.tv_sec + ts->min.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",
+ tag, avg, min, max, ts->count);
+}
+
+static void
+runtests(struct alg *alg, int count, int size, int cmd, int threads, int profile)
+{
+ int i, status;
+ double t;
+ void *region;
+ struct timeval *tvp;
+ struct timeval total;
+ int otiming;
+
+ if (size % alg->blocksize) {
+ if (verbose)
+ printf("skipping blocksize %u 'cuz not a multiple of "
+ "%s blocksize %u\n",
+ size, alg->name, alg->blocksize);
+ return;
+ }
+
+ region = mmap(NULL, threads * sizeof (struct timeval),
+ PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
+ if (region == MAP_FAILED) {
+ perror("mmap");
+ return;
+ }
+ tvp = (struct timeval *) region;
+ if (profile) {
+ size_t tlen = sizeof (otiming);
+ int timing = 1;
+
+ resetstats();
+ if (sysctlbyname("debug.crypto_timing", &otiming, &tlen,
+ &timing, sizeof (timing)) < 0)
+ perror("debug.crypto_timing");
+ }
+
+ if (threads > 1) {
+ for (i = 0; i < threads; i++)
+ if (fork() == 0) {
+ runtest(alg, count, size, cmd, &tvp[i]);
+ exit(0);
+ }
+ while (waitpid(WAIT_MYPGRP, &status, 0) != -1)
+ ;
+ } else
+ runtest(alg, count, size, cmd, tvp);
+
+ t = 0;
+ for (i = 0; i < threads; i++)
+ t += (((double)tvp[i].tv_sec * 1000000 + tvp[i].tv_usec) / 1000000);
+ if (t) {
+ printf("%6.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n",
+ t/threads, 2*count*threads, alg->name, size, (double)2*count*size*threads / t,
+ (double)2*count*size*threads / t * 8 / 1024 / 1024);
+ }
+ if (profile) {
+ struct cryptostats stats;
+ size_t slen = sizeof (stats);
+
+ if (sysctlbyname("debug.crypto_timing", NULL, NULL,
+ &otiming, sizeof (otiming)) < 0)
+ perror("debug.crypto_timing");
+ if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, NULL) < 0)
+ perror("kern.cryptostats");
+ if (stats.cs_invoke.count) {
+ printt("dispatch->invoke", &stats.cs_invoke);
+ printt("invoke->done", &stats.cs_done);
+ printt("done->cb", &stats.cs_cb);
+ printt("cb->finis", &stats.cs_finis);
+ }
+ }
+ fflush(stdout);
+}
+
int
main(int argc, char **argv)
{
@@ -202,9 +315,11 @@ main(int argc, char **argv)
int sizes[128], nsizes = 0;
int cmd = CIOCGSESSION;
int testall = 0;
+ int maxthreads = 1;
+ int profile = 0;
int i, ch;
- while ((ch = getopt(argc, argv, "zsva:")) != -1) {
+ while ((ch = getopt(argc, argv, "pzsva:t:")) != -1) {
switch (ch) {
#ifdef CIOCGSSESSION
case 's':
@@ -223,9 +338,15 @@ main(int argc, char **argv)
usage(argv[0]);
}
break;
+ case 't':
+ maxthreads = atoi(optarg);
+ break;
case 'z':
testall = 1;
break;
+ case 'p':
+ profile = 1;
+ break;
default:
usage(argv[0]);
}
@@ -245,7 +366,7 @@ main(int argc, char **argv)
if (nsizes == 0) {
sizes[nsizes++] = 8;
if (testall) {
- while (sizes[nsizes-1] < 32768) {
+ while (sizes[nsizes-1] < 8*1024) {
sizes[nsizes] = sizes[nsizes-1]<<1;
nsizes++;
}
@@ -260,13 +381,13 @@ main(int argc, char **argv)
int j;
alg = &algorithms[i];
for (j = 0; j < nsizes; j++)
- runtest(alg, count, sizes[j], cmd);
+ runtests(alg, count, sizes[j], cmd, maxthreads, profile);
}
} else {
if (alg == NULL)
alg = getalgbycode(CRYPTO_3DES_CBC);
for (i = 0; i < nsizes; i++)
- runtest(alg, count, sizes[i], cmd);
+ runtests(alg, count, sizes[i], cmd, maxthreads, profile);
}
return (0);
OpenPOWER on IntegriCloud