Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F36276127
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
73 KB
Subscribers
None
View Options
diff --git a/tests/bench-slope.c b/tests/bench-slope.c
index 62543bc4..5687bf1e 100644
--- a/tests/bench-slope.c
+++ b/tests/bench-slope.c
@@ -1,1172 +1,1177 @@
/* bench-slope.c - for libgcrypt
* Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser general Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <time.h>
#ifdef _GCRYPT_IN_LIBGCRYPT
#include "../src/gcrypt-int.h"
#include "../compat/libcompat.h"
#else
#include <gcrypt.h>
#endif
#define PGM "bench-slope"
static int verbose;
/* CPU Ghz value provided by user, allows constructing cycles/byte and other
results. */
static double cpu_ghz = -1;
/*************************************** Default parameters for measurements. */
/* Start at small buffer size, to get reasonable timer calibration for fast
* implementations (AES-NI etc). Sixteen selected to support the largest block
* size of current set cipher blocks. */
#define BUF_START_SIZE 16
/* From ~0 to ~4kbytes give comparable results with results from academia
* (SUPERCOP). */
#define BUF_END_SIZE (BUF_START_SIZE + 4096)
/* With 128 byte steps, we get (4096)/128 = 32 data points. */
#define BUF_STEP_SIZE 128
/* Number of repeated measurements at each data point. The median of these
* measurements is selected as data point further analysis. */
#define NUM_MEASUREMENT_REPETITIONS 32
/**************************************************** High-resolution timers. */
/* This benchmarking module needs needs high resolution timer. */
#undef NO_GET_NSEC_TIME
#if defined(_WIN32)
struct nsec_time
{
LARGE_INTEGER perf_count;
};
static void
get_nsec_time (struct nsec_time *t)
{
BOOL ok;
ok = QueryPerformanceCounter (&t->perf_count);
assert (ok);
}
static double
get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end)
{
static double nsecs_per_count = 0.0;
double nsecs;
if (nsecs_per_count == 0.0)
{
LARGE_INTEGER perf_freq;
BOOL ok;
/* Get counts per second. */
ok = QueryPerformanceFrequency (&perf_freq);
assert (ok);
nsecs_per_count = 1.0 / perf_freq.QuadPart;
nsecs_per_count *= 1000000.0 * 1000.0; /* sec => nsec */
assert (nsecs_per_count > 0.0);
}
nsecs = end->perf_count.QuadPart - start->perf_count.QuadPart; /* counts */
nsecs *= nsecs_per_count; /* counts * (nsecs / count) => nsecs */
return nsecs;
}
#elif defined(HAVE_CLOCK_GETTIME)
struct nsec_time
{
struct timespec ts;
};
static void
get_nsec_time (struct nsec_time *t)
{
int err;
err = clock_gettime (CLOCK_REALTIME, &t->ts);
assert (err == 0);
}
static double
get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end)
{
double nsecs;
nsecs = end->ts.tv_sec - start->ts.tv_sec;
nsecs *= 1000000.0 * 1000.0; /* sec => nsec */
/* This way we don't have to care if tv_nsec unsigned or signed. */
if (end->ts.tv_nsec >= start->ts.tv_nsec)
nsecs += end->ts.tv_nsec - start->ts.tv_nsec;
else
nsecs -= start->ts.tv_nsec - end->ts.tv_nsec;
return nsecs;
}
#elif defined(HAVE_GETTIMEOFDAY)
struct nsec_time
{
struct timeval tv;
};
static void
get_nsec_time (struct nsec_time *t)
{
int err;
err = gettimeofday (&t->tv, NULL);
assert (err == 0);
}
static double
get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end)
{
double nsecs;
nsecs = end->tv.tv_sec - start->tv.tv_sec;
nsecs *= 1000000; /* sec => µsec */
/* This way we don't have to care if tv_usec unsigned or signed. */
if (end->tv.tv_usec >= start->tv.tv_usec)
nsecs += end->tv.tv_usec - start->tv.tv_usec;
else
nsecs -= start->tv.tv_usec - end->tv.tv_usec;
nsecs *= 1000; /* µsec => nsec */
return nsecs;
}
#else
#define NO_GET_NSEC_TIME 1
#endif
/* If no high resolution timer found, provide dummy bench-slope. */
#ifdef NO_GET_NSEC_TIME
int
main (void)
{
/* No nsec timer => SKIP test. */
return 77;
}
#else /* !NO_GET_NSEC_TIME */
/********************************************** Slope benchmarking framework. */
struct bench_obj
{
const struct bench_ops *ops;
unsigned int num_measure_repetitions;
unsigned int min_bufsize;
unsigned int max_bufsize;
unsigned int step_size;
void *priv;
};
typedef int (*const bench_initialize_t) (struct bench_obj * obj);
typedef void (*const bench_finalize_t) (struct bench_obj * obj);
typedef void (*const bench_do_run_t) (struct bench_obj * obj, void *buffer,
size_t buflen);
struct bench_ops
{
bench_initialize_t initialize;
bench_finalize_t finalize;
bench_do_run_t do_run;
};
double
get_slope (double (*const get_x) (unsigned int idx, void *priv),
void *get_x_priv, double y_points[], unsigned int npoints,
double *overhead)
{
double sumx, sumy, sumx2, sumy2, sumxy;
unsigned int i;
double b, a;
sumx = sumy = sumx2 = sumy2 = sumxy = 0;
for (i = 0; i < npoints; i++)
{
double x, y;
x = get_x (i, get_x_priv); /* bytes */
y = y_points[i]; /* nsecs */
sumx += x;
sumy += y;
sumx2 += x * x;
- //sumy2 += y * y;
+ /*sumy2 += y * y;*/
sumxy += x * y;
}
b = (npoints * sumxy - sumx * sumy) / (npoints * sumx2 - sumx * sumx);
a = (sumy - b * sumx) / npoints;
if (overhead)
*overhead = a; /* nsecs */
return b; /* nsecs per byte */
}
double
get_bench_obj_point_x (unsigned int idx, void *priv)
{
struct bench_obj *obj = priv;
return (double) (obj->min_bufsize + (idx * obj->step_size));
}
unsigned int
get_num_measurements (struct bench_obj *obj)
{
unsigned int buf_range = obj->max_bufsize - obj->min_bufsize;
unsigned int num = buf_range / obj->step_size + 1;
while (obj->min_bufsize + (num * obj->step_size) > obj->max_bufsize)
num--;
return num + 1;
}
static int
-double_cmp (const void *__a, const void *__b)
+double_cmp (const void *_a, const void *_b)
{
const double *a, *b;
- a = __a;
- b = __b;
+ a = _a;
+ b = _b;
if (*a > *b)
return 1;
if (*a < *b)
return -1;
return 0;
}
double
do_bench_obj_measurement (struct bench_obj *obj, void *buffer, size_t buflen,
double *measurement_raw,
unsigned int loop_iterations)
{
const unsigned int num_repetitions = obj->num_measure_repetitions;
const bench_do_run_t do_run = obj->ops->do_run;
struct nsec_time start, end;
unsigned int rep, loop;
double res;
if (num_repetitions < 1 || loop_iterations < 1)
return 0.0;
for (rep = 0; rep < num_repetitions; rep++)
{
get_nsec_time (&start);
for (loop = 0; loop < loop_iterations; loop++)
do_run (obj, buffer, buflen);
get_nsec_time (&end);
measurement_raw[rep] = get_time_nsec_diff (&start, &end);
}
/* Return median of repeated measurements. */
qsort (measurement_raw, num_repetitions, sizeof (measurement_raw[0]),
double_cmp);
if (num_repetitions % 2 == 1)
return measurement_raw[num_repetitions / 2];
res = measurement_raw[num_repetitions / 2]
+ measurement_raw[num_repetitions / 2 - 1];
return res / 2;
}
unsigned int
adjust_loop_iterations_to_timer_accuracy (struct bench_obj *obj, void *buffer,
double *measurement_raw)
{
const double increase_thres = 3.0;
double tmp, nsecs;
unsigned int loop_iterations;
unsigned int test_bufsize;
test_bufsize = obj->min_bufsize;
if (test_bufsize == 0)
test_bufsize += obj->step_size;
loop_iterations = 0;
do
{
/* Increase loop iterations until we get other results than zero. */
nsecs =
do_bench_obj_measurement (obj, buffer, test_bufsize,
measurement_raw, ++loop_iterations);
}
while (nsecs < 1.0 - 0.1);
do
{
/* Increase loop iterations until we get reasonable increase for elapsed time. */
tmp =
do_bench_obj_measurement (obj, buffer, test_bufsize,
measurement_raw, ++loop_iterations);
}
while (tmp < nsecs * (increase_thres - 0.1));
return loop_iterations;
}
/* Benchmark and return linear regression slope in nanoseconds per byte. */
double
do_slope_benchmark (struct bench_obj *obj)
{
unsigned int num_measurements;
double *measurements = NULL;
double *measurement_raw = NULL;
double slope, overhead;
unsigned int loop_iterations, midx, i;
unsigned char *real_buffer = NULL;
unsigned char *buffer;
size_t cur_bufsize;
int err;
err = obj->ops->initialize (obj);
if (err < 0)
return -1;
num_measurements = get_num_measurements (obj);
measurements = calloc (num_measurements, sizeof (*measurements));
if (!measurements)
goto err_free;
measurement_raw =
calloc (obj->num_measure_repetitions, sizeof (*measurement_raw));
if (!measurement_raw)
goto err_free;
if (num_measurements < 1 || obj->num_measure_repetitions < 1 ||
obj->max_bufsize < 1 || obj->min_bufsize > obj->max_bufsize)
goto err_free;
real_buffer = malloc (obj->max_bufsize + 128);
if (!real_buffer)
goto err_free;
/* Get aligned buffer */
buffer = real_buffer;
buffer += 128 - ((real_buffer - (unsigned char *) 0) & (128 - 1));
for (i = 0; i < obj->max_bufsize; i++)
buffer[i] = 0x55 ^ (-i);
/* Adjust number of loop iterations up to timer accuracy. */
loop_iterations = adjust_loop_iterations_to_timer_accuracy (obj, buffer,
measurement_raw);
/* Perform measurements */
for (midx = 0, cur_bufsize = obj->min_bufsize;
cur_bufsize <= obj->max_bufsize; cur_bufsize += obj->step_size, midx++)
{
measurements[midx] =
do_bench_obj_measurement (obj, buffer, cur_bufsize, measurement_raw,
loop_iterations);
measurements[midx] /= loop_iterations;
}
assert (midx == num_measurements);
slope =
get_slope (&get_bench_obj_point_x, obj, measurements, num_measurements,
&overhead);
free (measurement_raw);
free (real_buffer);
obj->ops->finalize (obj);
return slope;
err_free:
if (measurement_raw)
free (measurement_raw);
if (measurements)
free (measurements);
if (real_buffer)
free (real_buffer);
obj->ops->finalize (obj);
return -1;
}
/********************************************************** Printing results. */
static void
double_to_str (char *out, size_t outlen, double value)
{
const char *fmt;
if (value < 1.0)
fmt = "%.3f";
else if (value < 100.0)
fmt = "%.2f";
else
fmt = "%.1f";
snprintf (out, outlen, fmt, value);
}
static void
bench_print_result (double nsecs_per_byte)
{
double cycles_per_byte, mbytes_per_sec;
char nsecpbyte_buf[16];
char mbpsec_buf[16];
char cpbyte_buf[16];
strcpy (cpbyte_buf, "-");
double_to_str (nsecpbyte_buf, sizeof (nsecpbyte_buf), nsecs_per_byte);
/* If user didn't provide CPU speed, we cannot show cycles/byte results. */
if (cpu_ghz > 0.0)
{
cycles_per_byte = nsecs_per_byte * cpu_ghz;
double_to_str (cpbyte_buf, sizeof (cpbyte_buf), cycles_per_byte);
}
mbytes_per_sec =
(1000.0 * 1000.0 * 1000.0) / (nsecs_per_byte * 1024 * 1024);
double_to_str (mbpsec_buf, sizeof (mbpsec_buf), mbytes_per_sec);
strncat (nsecpbyte_buf, " ns/B", sizeof (nsecpbyte_buf) - 1);
strncat (mbpsec_buf, " MiB/s", sizeof (mbpsec_buf) - 1);
strncat (cpbyte_buf, " c/B", sizeof (cpbyte_buf) - 1);
printf ("%14s %15s %13s\n", nsecpbyte_buf, mbpsec_buf, cpbyte_buf);
}
static void
bench_print_header (const char *algo_name)
{
printf (" %-14s | ", algo_name);
printf ("%14s %15s %13s\n", "nanosecs/byte", "mebibytes/sec",
"cycles/byte");
}
static void
bench_print_footer (void)
{
printf (" %-14s =\n", "");
}
/********************************************************* Cipher benchmarks. */
struct bench_cipher_mode
{
int mode;
const char *name;
struct bench_ops *ops;
int algo;
};
static int
bench_encrypt_init (struct bench_obj *obj)
{
struct bench_cipher_mode *mode = obj->priv;
gcry_cipher_hd_t hd;
int err, keylen;
obj->min_bufsize = BUF_START_SIZE;
obj->max_bufsize = BUF_END_SIZE;
obj->step_size = BUF_STEP_SIZE;
obj->num_measure_repetitions = NUM_MEASUREMENT_REPETITIONS;
err = gcry_cipher_open (&hd, mode->algo, mode->mode, 0);
if (err)
{
fprintf (stderr, PGM ": error opening cipher `%s'\n",
gcry_cipher_algo_name (mode->algo));
exit (1);
}
keylen = gcry_cipher_get_algo_keylen (mode->algo);
if (keylen)
{
char key[keylen];
int i;
for (i = 0; i < keylen; i++)
key[i] = 0x33 ^ (11 - i);
err = gcry_cipher_setkey (hd, key, keylen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
else
{
fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n",
gcry_cipher_algo_name (mode->algo));
gcry_cipher_close (hd);
exit (1);
}
obj->priv = hd;
return 0;
}
static void
bench_encrypt_free (struct bench_obj *obj)
{
gcry_cipher_hd_t hd = obj->priv;
gcry_cipher_close (hd);
}
static void
bench_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
{
gcry_cipher_hd_t hd = obj->priv;
int err;
err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static void
bench_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
{
gcry_cipher_hd_t hd = obj->priv;
int err;
err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static struct bench_ops encrypt_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_encrypt_do_bench
};
static struct bench_ops decrypt_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_decrypt_do_bench
};
static void
bench_ccm_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
{
gcry_cipher_hd_t hd = obj->priv;
int err;
char tag[8];
char nonce[11] = { 0x80, 0x01, };
size_t params[3];
gcry_cipher_setiv (hd, nonce, sizeof (nonce));
/* Set CCM lengths */
params[0] = buflen;
params[1] = 0; /*aadlen */
params[2] = sizeof (tag);
err =
gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof (params));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_ctl failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_gettag (hd, tag, sizeof (tag));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static void
bench_ccm_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
{
gcry_cipher_hd_t hd = obj->priv;
int err;
char tag[8] = { 0, };
char nonce[11] = { 0x80, 0x01, };
size_t params[3];
gcry_cipher_setiv (hd, nonce, sizeof (nonce));
/* Set CCM lengths */
params[0] = buflen;
params[1] = 0; /*aadlen */
params[2] = sizeof (tag);
err =
gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof (params));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_ctl failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_checktag (hd, tag, sizeof (tag));
if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
err = gpg_error (GPG_ERR_NO_ERROR);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static void
bench_ccm_authenticate_do_bench (struct bench_obj *obj, void *buf,
size_t buflen)
{
gcry_cipher_hd_t hd = obj->priv;
int err;
char tag[8] = { 0, };
char nonce[11] = { 0x80, 0x01, };
size_t params[3];
char data = 0xff;
gcry_cipher_setiv (hd, nonce, sizeof (nonce));
/* Set CCM lengths */
params[0] = sizeof (data); /*datalen */
params[1] = buflen; /*aadlen */
params[2] = sizeof (tag);
err =
gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof (params));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_ctl failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_authenticate (hd, buf, buflen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_authenticate failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_encrypt (hd, &data, sizeof (data), &data, sizeof (data));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_gettag (hd, tag, sizeof (tag));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static struct bench_ops ccm_encrypt_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_ccm_encrypt_do_bench
};
static struct bench_ops ccm_decrypt_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_ccm_decrypt_do_bench
};
static struct bench_ops ccm_authenticate_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_ccm_authenticate_do_bench
};
static struct bench_cipher_mode cipher_modes[] = {
{GCRY_CIPHER_MODE_ECB, "ECB enc", &encrypt_ops},
{GCRY_CIPHER_MODE_ECB, "ECB dec", &decrypt_ops},
{GCRY_CIPHER_MODE_CBC, "CBC enc", &encrypt_ops},
{GCRY_CIPHER_MODE_CBC, "CBC dec", &decrypt_ops},
{GCRY_CIPHER_MODE_CFB, "CFB enc", &encrypt_ops},
{GCRY_CIPHER_MODE_CFB, "CFB dec", &decrypt_ops},
{GCRY_CIPHER_MODE_OFB, "OFB enc", &encrypt_ops},
{GCRY_CIPHER_MODE_OFB, "OFB dec", &decrypt_ops},
{GCRY_CIPHER_MODE_CTR, "CTR enc", &encrypt_ops},
{GCRY_CIPHER_MODE_CTR, "CTR dec", &decrypt_ops},
{GCRY_CIPHER_MODE_CCM, "CCM enc", &ccm_encrypt_ops},
{GCRY_CIPHER_MODE_CCM, "CCM dec", &ccm_decrypt_ops},
{GCRY_CIPHER_MODE_CCM, "CCM auth", &ccm_authenticate_ops},
{0},
};
static void
cipher_bench_one (int algo, struct bench_cipher_mode *pmode)
{
struct bench_cipher_mode mode = *pmode;
struct bench_obj obj = { 0 };
double result;
unsigned int blklen;
mode.algo = algo;
/* Check if this mode is ok */
blklen = gcry_cipher_get_algo_blklen (algo);
if (!blklen)
return;
/* Stream cipher? Only test with ECB. */
if (blklen == 1 && mode.mode != GCRY_CIPHER_MODE_ECB)
return;
if (blklen == 1 && mode.mode == GCRY_CIPHER_MODE_ECB)
{
mode.mode = GCRY_CIPHER_MODE_STREAM;
mode.name = mode.ops == &encrypt_ops ? "STREAM enc" : "STREAM dec";
}
/* CCM has restrictions for block-size */
if (mode.mode == GCRY_CIPHER_MODE_CCM && blklen != GCRY_CCM_BLOCK_LEN)
return;
printf (" %14s | ", mode.name);
fflush (stdout);
obj.ops = mode.ops;
obj.priv = &mode;
result = do_slope_benchmark (&obj);
bench_print_result (result);
}
static void
-__cipher_bench (int algo)
+_cipher_bench (int algo)
{
const char *algoname;
int i;
algoname = gcry_cipher_algo_name (algo);
bench_print_header (algoname);
for (i = 0; cipher_modes[i].mode; i++)
cipher_bench_one (algo, &cipher_modes[i]);
bench_print_footer ();
}
void
cipher_bench (char **argv, int argc)
{
int i, algo;
printf ("Cipher:\n");
if (argv && argc)
{
for (i = 0; i < argc; i++)
{
algo = gcry_cipher_map_name (argv[i]);
if (algo)
- __cipher_bench (algo);
+ _cipher_bench (algo);
}
}
else
{
for (i = 1; i < 400; i++)
if (!gcry_cipher_test_algo (i))
- __cipher_bench (i);
+ _cipher_bench (i);
}
}
/*********************************************************** Hash benchmarks. */
struct bench_hash_mode
{
const char *name;
struct bench_ops *ops;
int algo;
};
static int
bench_hash_init (struct bench_obj *obj)
{
struct bench_hash_mode *mode = obj->priv;
gcry_md_hd_t hd;
int err;
obj->min_bufsize = BUF_START_SIZE;
obj->max_bufsize = BUF_END_SIZE;
obj->step_size = BUF_STEP_SIZE;
obj->num_measure_repetitions = NUM_MEASUREMENT_REPETITIONS;
err = gcry_md_open (&hd, mode->algo, 0);
if (err)
{
fprintf (stderr, PGM ": error opening hash `%s'\n",
gcry_md_algo_name (mode->algo));
exit (1);
}
obj->priv = hd;
return 0;
}
static void
bench_hash_free (struct bench_obj *obj)
{
gcry_md_hd_t hd = obj->priv;
gcry_md_close (hd);
}
static void
bench_hash_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
{
gcry_md_hd_t hd = obj->priv;
gcry_md_write (hd, buf, buflen);
gcry_md_final (hd);
}
static struct bench_ops hash_ops = {
&bench_hash_init,
&bench_hash_free,
&bench_hash_do_bench
};
static struct bench_hash_mode hash_modes[] = {
{"", &hash_ops},
{0},
};
static void
hash_bench_one (int algo, struct bench_hash_mode *pmode)
{
struct bench_hash_mode mode = *pmode;
struct bench_obj obj = { 0 };
double result;
mode.algo = algo;
if (mode.name[0] == '\0')
printf (" %-14s | ", gcry_md_algo_name (algo));
else
printf (" %14s | ", mode.name);
fflush (stdout);
obj.ops = mode.ops;
obj.priv = &mode;
result = do_slope_benchmark (&obj);
bench_print_result (result);
}
static void
-__hash_bench (int algo)
+_hash_bench (int algo)
{
int i;
for (i = 0; hash_modes[i].name; i++)
hash_bench_one (algo, &hash_modes[i]);
}
void
hash_bench (char **argv, int argc)
{
int i, algo;
printf ("Hash:\n");
bench_print_header ("");
if (argv && argc)
{
for (i = 0; i < argc; i++)
{
algo = gcry_md_map_name (argv[i]);
if (algo)
- __hash_bench (algo);
+ _hash_bench (algo);
}
}
else
{
for (i = 1; i < 400; i++)
if (!gcry_md_test_algo (i))
- __hash_bench (i);
+ _hash_bench (i);
}
bench_print_footer ();
}
/************************************************************** Main program. */
void
print_help (void)
{
static const char *help_lines[] = {
"usage: bench-slope [options] [hash|cipher [algonames]]",
"",
" options:",
" --cpu-mhz <mhz> Set CPU speed for calculating cycles per bytes",
" results.",
" --disable-hwf <features> Disable hardware acceleration feature(s) for",
" benchmarking.",
NULL
};
const char **line;
for (line = help_lines; *line; line++)
fprintf (stdout, "%s\n", *line);
}
/* Warm up CPU. */
static void
warm_up_cpu (void)
{
struct nsec_time start, end;
get_nsec_time (&start);
do
{
get_nsec_time (&end);
}
while (get_time_nsec_diff (&start, &end) < 1000.0 * 1000.0 * 1000.0);
}
int
main (int argc, char **argv)
{
int last_argc = -1;
int debug = 0;
if (argc)
{
argc--;
argv++;
}
+ /* We skip this test if we are running under the test suite (no args
+ and srcdir defined) and GCRYPT_NO_BENCHMARKS is set. */
+ if (!argc && getenv ("srcdir") && getenv ("GCRYPT_NO_BENCHMARKS"))
+ exit (77);
+
while (argc && last_argc != argc)
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--;
argv++;
break;
}
else if (!strcmp (*argv, "--help"))
{
print_help ();
exit (0);
}
else if (!strcmp (*argv, "--verbose"))
{
verbose++;
argc--;
argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose += 2;
debug++;
argc--;
argv++;
}
else if (!strcmp (*argv, "--disable-hwf"))
{
argc--;
argv++;
if (argc)
{
if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL))
fprintf (stderr,
PGM
": unknown hardware feature `%s' - option ignored\n",
*argv);
argc--;
argv++;
}
}
else if (!strcmp (*argv, "--cpu-mhz"))
{
argc--;
argv++;
if (argc)
{
cpu_ghz = atof (*argv);
cpu_ghz /= 1000; /* Mhz => Ghz */
argc--;
argv++;
}
}
}
gcry_control (GCRYCTL_SET_VERBOSITY, (int) verbose);
if (!gcry_check_version (GCRYPT_VERSION))
{
fprintf (stderr, PGM ": version mismatch; pgm=%s, library=%s\n",
GCRYPT_VERSION, gcry_check_version (NULL));
exit (1);
}
if (debug)
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
if (!argc)
{
warm_up_cpu ();
hash_bench (NULL, 0);
cipher_bench (NULL, 0);
}
else if (!strcmp (*argv, "hash"))
{
argc--;
argv++;
warm_up_cpu ();
hash_bench ((argc == 0) ? NULL : argv, argc);
}
else if (!strcmp (*argv, "cipher"))
{
argc--;
argv++;
warm_up_cpu ();
cipher_bench ((argc == 0) ? NULL : argv, argc);
}
else
{
fprintf (stderr, PGM ": unknown argument: %s\n", *argv);
print_help ();
}
return 0;
}
#endif /* !NO_GET_NSEC_TIME */
diff --git a/tests/benchmark.c b/tests/benchmark.c
index d3ef1a23..8326ab22 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
@@ -1,1402 +1,1407 @@
/* benchmark.c - for libgcrypt
* Copyright (C) 2002, 2004, 2005, 2006, 2008 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser general Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#ifdef _GCRYPT_IN_LIBGCRYPT
# include "../src/gcrypt-int.h"
# include "../compat/libcompat.h"
#else
# include <gcrypt.h>
#endif
#include "stopwatch.h"
#define PGM "benchmark"
static int verbose;
/* Do encryption tests with large buffers. */
static int large_buffers;
/* Number of cipher repetitions. */
static int cipher_repetitions;
/* Number of hash repetitions. */
static int hash_repetitions;
/* Alignment of the buffers. */
static int buffer_alignment;
/* Whether to include the keysetup in the cipher timings. */
static int cipher_with_keysetup;
/* Whether fips mode was active at startup. */
static int in_fips_mode;
static const char sample_private_dsa_key_1024[] =
"(private-key\n"
" (dsa\n"
" (p #00A126202D592214C5A8F6016E2C3F4256052ACB1CB17D88E64B1293FAF08F5E4685"
"03E6F68366B326A56284370EB2103E92D8346A163E44A08FDC422AC8E9E44268557A"
"853539A6AF39353A59CE5E78FD98B57D0F3E3A7EBC8A256AC9A775BA59689F3004BF"
"C3035730C4C0C51626C5D7F5852637EC589BB29DAB46C161572E4B#)\n"
" (q #00DEB5A296421887179ECA1762884DE2AF8185AFC5#)\n"
" (g #3958B34AE7747194ECBD312F8FEE8CBE3918E94DF9FD11E2912E56318F33BDC38622"
"B18DDFF393074BCA8BAACF50DF27AEE529F3E8AEECE55C398DAB3A5E04C2EA142312"
"FACA2FE7F0A88884F8DAC3979EE67598F9A383B2A2325F035C796F352A5C3CDF2CB3"
"85AD24EC52A6E55247E1BB37D260F79E617D2A4446415B6AD79A#)\n"
" (y #519E9FE9AB0545A6724E74603B7B04E48DC1437E0284A11EA605A7BA8AB1CF354FD4"
"ECC93880AC293391C69B558AD84E7AAFA88F11D028CF3A378F241D6B056A90C588F6"
"66F68D27262B4DA84657D15057D371BCEC1F6504032507D5B881E45FC93A1B973155"
"D91C57219D090C3ACD75E7C2B9F1176A208AC03D6C12AC28A271#)\n"
" (x #4186F8A58C5DF46C5BCFC7006BEEBF05E93C0CA7#)\n"
"))\n";
static const char sample_public_dsa_key_1024[] =
"(public-key\n"
" (dsa\n"
" (p #00A126202D592214C5A8F6016E2C3F4256052ACB1CB17D88E64B1293FAF08F5E4685"
"03E6F68366B326A56284370EB2103E92D8346A163E44A08FDC422AC8E9E44268557A"
"853539A6AF39353A59CE5E78FD98B57D0F3E3A7EBC8A256AC9A775BA59689F3004BF"
"C3035730C4C0C51626C5D7F5852637EC589BB29DAB46C161572E4B#)\n"
" (q #00DEB5A296421887179ECA1762884DE2AF8185AFC5#)\n"
" (g #3958B34AE7747194ECBD312F8FEE8CBE3918E94DF9FD11E2912E56318F33BDC38622"
"B18DDFF393074BCA8BAACF50DF27AEE529F3E8AEECE55C398DAB3A5E04C2EA142312"
"FACA2FE7F0A88884F8DAC3979EE67598F9A383B2A2325F035C796F352A5C3CDF2CB3"
"85AD24EC52A6E55247E1BB37D260F79E617D2A4446415B6AD79A#)\n"
" (y #519E9FE9AB0545A6724E74603B7B04E48DC1437E0284A11EA605A7BA8AB1CF354FD4"
"ECC93880AC293391C69B558AD84E7AAFA88F11D028CF3A378F241D6B056A90C588F6"
"66F68D27262B4DA84657D15057D371BCEC1F6504032507D5B881E45FC93A1B973155"
"D91C57219D090C3ACD75E7C2B9F1176A208AC03D6C12AC28A271#)\n"
"))\n";
static const char sample_private_dsa_key_2048[] =
"(private-key\n"
" (dsa\n"
" (p #00B54636673962B64F7DC23C71ACEF6E7331796F607560B194DFCC0CA370E858A365"
"A413152FB6EB8C664BD171AC316FE5B381CD084D07377571599880A068EF1382D85C"
"308B4E9DEAC12D66DE5C4A826EBEB5ED94A62E7301E18927E890589A2F230272A150"
"C118BC3DC2965AE0D05BE4F65C6137B2BA7EDABB192C3070D202C10AA3F534574970"
"71454DB8A73DDB6511A5BA98EF1450FD90DE5BAAFC9FD3AC22EBEA612DD075BB7405"
"D56866D125E33982C046808F7CEBA8E5C0B9F19A6FE451461660A1CBA9EF68891179"
"0256A573D3B8F35A5C7A0C6C31F2DB90E25A26845252AD9E485EF2D339E7B5890CD4"
"2F9C9F315ED409171EC35CA04CC06B275577B3#)\n"
" (q #00DA67989167FDAC4AE3DF9247A716859A30C0CF9C5A6DBA01EABA3481#)\n"
" (g #48E35DA584A089D05142AA63603FDB00D131B07A0781E2D5A8F9614D2B33D3E40A78"
"98A9E10CDBB612CF093F95A3E10D09566726F2C12823836B2D9CD974BB695665F3B3"
"5D219A9724B87F380BD5207EDA0AE38C79E8F18122C3F76E4CEB0ABED3250914987F"
"B30D4B9E19C04C28A5D4F45560AF586F6A1B41751EAD90AE7F044F4E2A4A50C1F508"
"4FC202463F478F678B9A19392F0D2961C5391C546EF365368BB46410C9C1CEE96E9F"
"0C953570C2ED06328B11C90E86E57CAA7FA5ABAA278E22A4C8C08E16EE59F484EC44"
"2CF55535BAA2C6BEA8833A555372BEFE1E665D3C7DAEF58061D5136331EF4EB61BC3"
"6EE4425A553AF8885FEA15A88135BE133520#)\n"
" (y #66E0D1A69D663466F8FEF2B7C0878DAC93C36A2FB2C05E0306A53B926021D4B92A1C"
"2FA6860061E88E78CBBBA49B0E12700F07DBF86F72CEB2927EDAC0C7E3969C3A47BB"
"4E0AE93D8BB3313E93CC7A72DFEEE442EFBC81B3B2AEC9D8DCBE21220FB760201D79"
"328C41C773866587A44B6954767D022A88072900E964089D9B17133603056C985C4F"
"8A0B648F297F8D2C3CB43E4371DC6002B5B12CCC085BDB2CFC5074A0587566187EE3"
"E11A2A459BD94726248BB8D6CC62938E11E284C2C183576FBB51749EB238C4360923"
"79C08CE1C8CD77EB57404CE9B4744395ACF721487450BADE3220576F2F816248B0A7"
"14A264330AECCB24DE2A1107847B23490897#)\n"
" (x #477BD14676E22563C5ABA68025CEBA2A48D485F5B2D4AD4C0EBBD6D0#)\n"
"))\n";
static const char sample_public_dsa_key_2048[] =
"(public-key\n"
" (dsa\n"
" (p #00B54636673962B64F7DC23C71ACEF6E7331796F607560B194DFCC0CA370E858A365"
"A413152FB6EB8C664BD171AC316FE5B381CD084D07377571599880A068EF1382D85C"
"308B4E9DEAC12D66DE5C4A826EBEB5ED94A62E7301E18927E890589A2F230272A150"
"C118BC3DC2965AE0D05BE4F65C6137B2BA7EDABB192C3070D202C10AA3F534574970"
"71454DB8A73DDB6511A5BA98EF1450FD90DE5BAAFC9FD3AC22EBEA612DD075BB7405"
"D56866D125E33982C046808F7CEBA8E5C0B9F19A6FE451461660A1CBA9EF68891179"
"0256A573D3B8F35A5C7A0C6C31F2DB90E25A26845252AD9E485EF2D339E7B5890CD4"
"2F9C9F315ED409171EC35CA04CC06B275577B3#)\n"
" (q #00DA67989167FDAC4AE3DF9247A716859A30C0CF9C5A6DBA01EABA3481#)\n"
" (g #48E35DA584A089D05142AA63603FDB00D131B07A0781E2D5A8F9614D2B33D3E40A78"
"98A9E10CDBB612CF093F95A3E10D09566726F2C12823836B2D9CD974BB695665F3B3"
"5D219A9724B87F380BD5207EDA0AE38C79E8F18122C3F76E4CEB0ABED3250914987F"
"B30D4B9E19C04C28A5D4F45560AF586F6A1B41751EAD90AE7F044F4E2A4A50C1F508"
"4FC202463F478F678B9A19392F0D2961C5391C546EF365368BB46410C9C1CEE96E9F"
"0C953570C2ED06328B11C90E86E57CAA7FA5ABAA278E22A4C8C08E16EE59F484EC44"
"2CF55535BAA2C6BEA8833A555372BEFE1E665D3C7DAEF58061D5136331EF4EB61BC3"
"6EE4425A553AF8885FEA15A88135BE133520#)\n"
" (y #66E0D1A69D663466F8FEF2B7C0878DAC93C36A2FB2C05E0306A53B926021D4B92A1C"
"2FA6860061E88E78CBBBA49B0E12700F07DBF86F72CEB2927EDAC0C7E3969C3A47BB"
"4E0AE93D8BB3313E93CC7A72DFEEE442EFBC81B3B2AEC9D8DCBE21220FB760201D79"
"328C41C773866587A44B6954767D022A88072900E964089D9B17133603056C985C4F"
"8A0B648F297F8D2C3CB43E4371DC6002B5B12CCC085BDB2CFC5074A0587566187EE3"
"E11A2A459BD94726248BB8D6CC62938E11E284C2C183576FBB51749EB238C4360923"
"79C08CE1C8CD77EB57404CE9B4744395ACF721487450BADE3220576F2F816248B0A7"
"14A264330AECCB24DE2A1107847B23490897#)\n"
"))\n";
static const char sample_private_dsa_key_3072[] =
"(private-key\n"
" (dsa\n"
" (p #00BA73E148AEA5E8B64878AF5BE712B8302B9671C5F3EEB7722A9D0D9868D048C938"
"877C91C335C7819292E69C7D34264F1578E32EC2DA8408DF75D0EB76E0D3030B84B5"
"62D8EF93AB53BAB6B8A5DE464F5CA87AEA43BDCF0FB0B7815AA3114CFC84FD916A83"
"B3D5FD78390189332232E9D037D215313FD002FF46C048B66703F87FAE092AAA0988"
"AC745336EBE672A01DEDBD52395783579B67CF3AE1D6F1602CCCB12154FA0E00AE46"
"0D9B289CF709194625BCB919B11038DEFC50ADBBA20C3F320078E4E9529B4F6848E2"
"AB5E6278DB961FE226F2EEBD201E071C48C5BEF98B4D9BEE42C1C7102D893EBF8902"
"D7A91266340AFD6CE1D09E52282FFF5B97EAFA3886A3FCF84FF76D1E06538D0D8E60"
"B3332145785E07D29A5965382DE3470D1D888447FA9C00A2373378FC3FA7B9F7D17E"
"95A6A5AE1397BE46D976EF2C96E89913AC4A09351CA661BF6F67E30407DA846946C7"
"62D9BAA6B77825097D3E7B886456BB32E3E74516BF3FD93D71B257AA8F723E01CE33"
"8015353D3778B02B892AF7#)\n"
" (q #00BFF3F3CC18FA018A5B8155A8695E1E4939660D5E4759322C39D50F3B93E5F68B#)\n"
" (g #6CCFD8219F5FCE8EF2BEF3262929787140847E38674B1EF8DB20255E212CB6330EC4"
"DFE8A26AB7ECC5760DEB9BBF59A2B2821D510F1868172222867558B8D204E889C474"
"7CA30FBF9D8CF41AE5D5BD845174641101593849FF333E6C93A6550931B2B9D56B98"
"9CAB01729D9D736FA6D24A74D2DDE1E9E648D141473E443DD6BBF0B3CAB64F9FE4FC"
"134B2EB57437789F75C744DF1FA67FA8A64603E5441BC7ECE29E00BDF262BDC81E8C"
"7330A18A412DE38E7546D342B89A0AF675A89E6BEF00540EB107A2FE74EA402B0D89"
"F5C02918DEEEAF8B8737AC866B09B50810AB8D8668834A1B9E1E53866E2B0A926FAB"
"120A0CDE5B3715FFFE6ACD1AB73588DCC1EC4CE9392FE57F8D1D35811200CB07A0E6"
"374E2C4B0AEB7E3D077B8545C0E438DCC0F1AE81E186930E99EBC5B91B77E92803E0"
"21602887851A4FFDB3A7896AC655A0901218C121C5CBB0931E7D5EAC243F37711B5F"
"D5A62B1B38A83F03D8F6703D8B98DF367FC8A76990335F62173A5391836F0F2413EC"
"4997AF9EB55C6660B01A#)\n"
" (y #2320B22434C5DB832B4EC267CC52E78DD5CCFA911E8F0804E7E7F32B186B2D4167AE"
"4AA6869822E76400492D6A193B0535322C72B0B7AA4A87E33044FDC84BE24C64A053"
"A37655EE9EABDCDC1FDF63F3F1C677CEB41595DF7DEFE9178D85A3D621B4E4775492"
"8C0A58D2458D06F9562E4DE2FE6129A64063A99E88E54485B97484A28188C4D33F15"
"DDC903B6CEA0135E3E3D27B4EA39319696305CE93D7BA7BE00367DBE3AAF43491E71"
"CBF254744A5567F5D70090D6139E0C990239627B3A1C5B20B6F9F6374B8D8D8A8997"
"437265BE1E3B4810D4B09254400DE287A0DFFBAEF339E48D422B1D41A37E642BC026"
"73314701C8FA9792845C129351A87A945A03E6C895860E51D6FB8B7340A94D1A8A7B"
"FA85AC83B4B14E73AB86CB96C236C8BFB0978B61B2367A7FE4F7891070F56C78D5DD"
"F5576BFE5BE4F333A4E2664E79528B3294907AADD63F4F2E7AA8147B928D8CD69765"
"3DB98C4297CB678046ED55C0DBE60BF7142C594603E4D705DC3D17270F9F086EC561"
"2703D518D8D49FF0EBE6#)\n"
" (x #00A9FFFC88E67D6F7B810E291C050BAFEA7FC4A75E8D2F16CFED3416FD77607232#)\n"
"))\n";
static const char sample_public_dsa_key_3072[] =
"(public-key\n"
" (dsa\n"
" (p #00BA73E148AEA5E8B64878AF5BE712B8302B9671C5F3EEB7722A9D0D9868D048C938"
"877C91C335C7819292E69C7D34264F1578E32EC2DA8408DF75D0EB76E0D3030B84B5"
"62D8EF93AB53BAB6B8A5DE464F5CA87AEA43BDCF0FB0B7815AA3114CFC84FD916A83"
"B3D5FD78390189332232E9D037D215313FD002FF46C048B66703F87FAE092AAA0988"
"AC745336EBE672A01DEDBD52395783579B67CF3AE1D6F1602CCCB12154FA0E00AE46"
"0D9B289CF709194625BCB919B11038DEFC50ADBBA20C3F320078E4E9529B4F6848E2"
"AB5E6278DB961FE226F2EEBD201E071C48C5BEF98B4D9BEE42C1C7102D893EBF8902"
"D7A91266340AFD6CE1D09E52282FFF5B97EAFA3886A3FCF84FF76D1E06538D0D8E60"
"B3332145785E07D29A5965382DE3470D1D888447FA9C00A2373378FC3FA7B9F7D17E"
"95A6A5AE1397BE46D976EF2C96E89913AC4A09351CA661BF6F67E30407DA846946C7"
"62D9BAA6B77825097D3E7B886456BB32E3E74516BF3FD93D71B257AA8F723E01CE33"
"8015353D3778B02B892AF7#)\n"
" (q #00BFF3F3CC18FA018A5B8155A8695E1E4939660D5E4759322C39D50F3B93E5F68B#)\n"
" (g #6CCFD8219F5FCE8EF2BEF3262929787140847E38674B1EF8DB20255E212CB6330EC4"
"DFE8A26AB7ECC5760DEB9BBF59A2B2821D510F1868172222867558B8D204E889C474"
"7CA30FBF9D8CF41AE5D5BD845174641101593849FF333E6C93A6550931B2B9D56B98"
"9CAB01729D9D736FA6D24A74D2DDE1E9E648D141473E443DD6BBF0B3CAB64F9FE4FC"
"134B2EB57437789F75C744DF1FA67FA8A64603E5441BC7ECE29E00BDF262BDC81E8C"
"7330A18A412DE38E7546D342B89A0AF675A89E6BEF00540EB107A2FE74EA402B0D89"
"F5C02918DEEEAF8B8737AC866B09B50810AB8D8668834A1B9E1E53866E2B0A926FAB"
"120A0CDE5B3715FFFE6ACD1AB73588DCC1EC4CE9392FE57F8D1D35811200CB07A0E6"
"374E2C4B0AEB7E3D077B8545C0E438DCC0F1AE81E186930E99EBC5B91B77E92803E0"
"21602887851A4FFDB3A7896AC655A0901218C121C5CBB0931E7D5EAC243F37711B5F"
"D5A62B1B38A83F03D8F6703D8B98DF367FC8A76990335F62173A5391836F0F2413EC"
"4997AF9EB55C6660B01A#)\n"
" (y #2320B22434C5DB832B4EC267CC52E78DD5CCFA911E8F0804E7E7F32B186B2D4167AE"
"4AA6869822E76400492D6A193B0535322C72B0B7AA4A87E33044FDC84BE24C64A053"
"A37655EE9EABDCDC1FDF63F3F1C677CEB41595DF7DEFE9178D85A3D621B4E4775492"
"8C0A58D2458D06F9562E4DE2FE6129A64063A99E88E54485B97484A28188C4D33F15"
"DDC903B6CEA0135E3E3D27B4EA39319696305CE93D7BA7BE00367DBE3AAF43491E71"
"CBF254744A5567F5D70090D6139E0C990239627B3A1C5B20B6F9F6374B8D8D8A8997"
"437265BE1E3B4810D4B09254400DE287A0DFFBAEF339E48D422B1D41A37E642BC026"
"73314701C8FA9792845C129351A87A945A03E6C895860E51D6FB8B7340A94D1A8A7B"
"FA85AC83B4B14E73AB86CB96C236C8BFB0978B61B2367A7FE4F7891070F56C78D5DD"
"F5576BFE5BE4F333A4E2664E79528B3294907AADD63F4F2E7AA8147B928D8CD69765"
"3DB98C4297CB678046ED55C0DBE60BF7142C594603E4D705DC3D17270F9F086EC561"
"2703D518D8D49FF0EBE6#)\n"
"))\n";
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
#define DIMof(type,member) DIM(((type *)0)->member)
#define BUG() do {fprintf ( stderr, "Ooops at %s:%d\n", __FILE__ , __LINE__ );\
exit(2);} while(0)
static void
die (const char *format, ...)
{
va_list arg_ptr ;
va_start( arg_ptr, format ) ;
putchar ('\n');
fputs ( PGM ": ", stderr);
vfprintf (stderr, format, arg_ptr );
va_end(arg_ptr);
exit (1);
}
static void
show_sexp (const char *prefix, gcry_sexp_t a)
{
char *buf;
size_t size;
fputs (prefix, stderr);
size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
buf = malloc (size);
if (!buf)
die ("out of core\n");
gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
fprintf (stderr, "%.*s", (int)size, buf);
}
static void
progress_cb (void *cb_data, const char *what, int printchar,
int current, int total)
{
(void)cb_data;
fprintf (stderr, PGM ": progress (%s %c %d %d)\n",
what, printchar, current, total);
fflush (stderr);
}
static void
random_bench (int very_strong)
{
char buf[128];
int i;
printf ("%-10s", "random");
if (!very_strong)
{
start_timer ();
for (i=0; i < 100; i++)
gcry_randomize (buf, sizeof buf, GCRY_STRONG_RANDOM);
stop_timer ();
printf (" %s", elapsed_time ());
}
start_timer ();
for (i=0; i < 100; i++)
gcry_randomize (buf, 8,
very_strong? GCRY_VERY_STRONG_RANDOM:GCRY_STRONG_RANDOM);
stop_timer ();
printf (" %s", elapsed_time ());
putchar ('\n');
if (verbose)
gcry_control (GCRYCTL_DUMP_RANDOM_STATS);
}
static void
md_bench ( const char *algoname )
{
int algo;
gcry_md_hd_t hd;
int i, j, repcount;
char buf_base[1000+15];
size_t bufsize = 1000;
char *buf;
char *largebuf_base;
char *largebuf;
char digest[512/8];
gcry_error_t err = GPG_ERR_NO_ERROR;
if (!algoname)
{
for (i=1; i < 400; i++)
if (in_fips_mode && i == GCRY_MD_MD5)
; /* Don't use MD5 in fips mode. */
else if ( !gcry_md_test_algo (i) )
md_bench (gcry_md_algo_name (i));
return;
}
buf = buf_base + ((16 - ((size_t)buf_base & 0x0f)) % buffer_alignment);
algo = gcry_md_map_name (algoname);
if (!algo)
{
fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname);
exit (1);
}
err = gcry_md_open (&hd, algo, 0);
if (err)
{
fprintf (stderr, PGM ": error opening hash algorithm `%s'\n", algoname);
exit (1);
}
for (i=0; i < bufsize; i++)
buf[i] = i;
printf ("%-12s", gcry_md_algo_name (algo));
start_timer ();
for (repcount=0; repcount < hash_repetitions; repcount++)
for (i=0; i < 1000; i++)
gcry_md_write (hd, buf, bufsize);
gcry_md_final (hd);
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
gcry_md_reset (hd);
start_timer ();
for (repcount=0; repcount < hash_repetitions; repcount++)
for (i=0; i < 10000; i++)
gcry_md_write (hd, buf, bufsize/10);
gcry_md_final (hd);
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
gcry_md_reset (hd);
start_timer ();
for (repcount=0; repcount < hash_repetitions; repcount++)
for (i=0; i < 1000000; i++)
gcry_md_write (hd, buf, 1);
gcry_md_final (hd);
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
start_timer ();
for (repcount=0; repcount < hash_repetitions; repcount++)
for (i=0; i < 1000; i++)
for (j=0; j < bufsize; j++)
gcry_md_putc (hd, buf[j]);
gcry_md_final (hd);
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
gcry_md_close (hd);
/* Now 100 hash operations on 10000 bytes using the fast function.
We initialize the buffer so that all memory pages are committed
and we have repeatable values. */
if (gcry_md_get_algo_dlen (algo) > sizeof digest)
die ("digest buffer too short\n");
largebuf_base = malloc (10000+15);
if (!largebuf_base)
die ("out of core\n");
largebuf = (largebuf_base
+ ((16 - ((size_t)largebuf_base & 0x0f)) % buffer_alignment));
for (i=0; i < 10000; i++)
largebuf[i] = i;
start_timer ();
for (repcount=0; repcount < hash_repetitions; repcount++)
for (i=0; i < 100; i++)
gcry_md_hash_buffer (algo, digest, largebuf, 10000);
stop_timer ();
printf (" %s", elapsed_time ());
free (largebuf_base);
putchar ('\n');
fflush (stdout);
}
static void ccm_aead_init(gcry_cipher_hd_t hd, size_t buflen, int authlen)
{
const int _L = 4;
const int noncelen = 15 - _L;
char nonce[noncelen];
size_t params[3];
gcry_error_t err = GPG_ERR_NO_ERROR;
memset (nonce, 0x33, noncelen);
err = gcry_cipher_setiv (hd, nonce, noncelen);
if (err)
{
fprintf (stderr, "gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
params[0] = buflen; /* encryptedlen */
params[1] = 0; /* aadlen */
params[2] = authlen; /* authtaglen */
err = gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof(params));
if (err)
{
fprintf (stderr, "gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static void
cipher_bench ( const char *algoname )
{
static int header_printed;
int algo;
gcry_cipher_hd_t hd;
int i;
int keylen, blklen;
char key[128];
char *outbuf, *buf;
char *raw_outbuf, *raw_buf;
size_t allocated_buflen, buflen;
int repetitions;
static const struct {
int mode;
const char *name;
int blocked;
void (* const aead_init)(gcry_cipher_hd_t hd, size_t buflen, int authlen);
int req_blocksize;
int authlen;
} modes[] = {
{ GCRY_CIPHER_MODE_ECB, " ECB/Stream", 1 },
{ GCRY_CIPHER_MODE_CBC, " CBC", 1 },
{ GCRY_CIPHER_MODE_CFB, " CFB", 0 },
{ GCRY_CIPHER_MODE_OFB, " OFB", 0 },
{ GCRY_CIPHER_MODE_CTR, " CTR", 0 },
{ GCRY_CIPHER_MODE_CCM, " CCM", 0,
ccm_aead_init, GCRY_CCM_BLOCK_LEN, 8 },
{ GCRY_CIPHER_MODE_STREAM, "", 0 },
{0}
};
int modeidx;
gcry_error_t err = GPG_ERR_NO_ERROR;
if (!algoname)
{
for (i=1; i < 400; i++)
if ( !gcry_cipher_test_algo (i) )
cipher_bench (gcry_cipher_algo_name (i));
return;
}
if (large_buffers)
{
allocated_buflen = 1024 * 100;
repetitions = 10;
}
else
{
allocated_buflen = 1024;
repetitions = 1000;
}
repetitions *= cipher_repetitions;
raw_buf = gcry_xmalloc (allocated_buflen+15);
buf = (raw_buf
+ ((16 - ((size_t)raw_buf & 0x0f)) % buffer_alignment));
outbuf = raw_outbuf = gcry_xmalloc (allocated_buflen+15);
outbuf = (raw_outbuf
+ ((16 - ((size_t)raw_outbuf & 0x0f)) % buffer_alignment));
if (!header_printed)
{
if (cipher_repetitions != 1)
printf ("Running each test %d times.\n", cipher_repetitions);
printf ("%-12s", "");
for (modeidx=0; modes[modeidx].mode; modeidx++)
if (*modes[modeidx].name)
printf (" %-15s", modes[modeidx].name );
putchar ('\n');
printf ("%-12s", "");
for (modeidx=0; modes[modeidx].mode; modeidx++)
if (*modes[modeidx].name)
printf (" ---------------" );
putchar ('\n');
header_printed = 1;
}
algo = gcry_cipher_map_name (algoname);
if (!algo)
{
fprintf (stderr, PGM ": invalid cipher algorithm `%s'\n", algoname);
exit (1);
}
keylen = gcry_cipher_get_algo_keylen (algo);
if (!keylen)
{
fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n",
algoname);
exit (1);
}
if ( keylen > sizeof key )
{
fprintf (stderr, PGM ": algo %d, keylength problem (%d)\n",
algo, keylen );
exit (1);
}
for (i=0; i < keylen; i++)
key[i] = i + (clock () & 0xff);
blklen = gcry_cipher_get_algo_blklen (algo);
if (!blklen)
{
fprintf (stderr, PGM ": failed to get block length for algorithm `%s'\n",
algoname);
exit (1);
}
printf ("%-12s", gcry_cipher_algo_name (algo));
fflush (stdout);
for (modeidx=0; modes[modeidx].mode; modeidx++)
{
if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM)
|| (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM))
continue;
if (modes[modeidx].req_blocksize > 0
&& blklen != modes[modeidx].req_blocksize)
{
printf (" %7s %7s", "-", "-" );
continue;
}
for (i=0; i < sizeof buf; i++)
buf[i] = i;
err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0);
if (err)
{
fprintf (stderr, PGM ": error opening cipher `%s'\n", algoname);
exit (1);
}
if (!cipher_with_keysetup)
{
err = gcry_cipher_setkey (hd, key, keylen);
if (err)
{
fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
buflen = allocated_buflen;
if (modes[modeidx].blocked)
buflen = (buflen / blklen) * blklen;
start_timer ();
for (i=err=0; !err && i < repetitions; i++)
{
if (cipher_with_keysetup)
{
err = gcry_cipher_setkey (hd, key, keylen);
if (err)
{
fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
if (modes[modeidx].aead_init)
{
(*modes[modeidx].aead_init) (hd, buflen, modes[modeidx].authlen);
err = gcry_cipher_encrypt (hd, outbuf, buflen, buf, buflen);
if (err)
break;
err = gcry_cipher_gettag (hd, outbuf, modes[modeidx].authlen);
}
else
{
err = gcry_cipher_encrypt (hd, outbuf, buflen, buf, buflen);
}
}
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
gcry_cipher_close (hd);
if (err)
{
fprintf (stderr, "gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err) );
exit (1);
}
err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0);
if (err)
{
fprintf (stderr, PGM ": error opening cipher `%s'/n", algoname);
exit (1);
}
if (!cipher_with_keysetup)
{
err = gcry_cipher_setkey (hd, key, keylen);
if (err)
{
fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
start_timer ();
for (i=err=0; !err && i < repetitions; i++)
{
if (cipher_with_keysetup)
{
err = gcry_cipher_setkey (hd, key, keylen);
if (err)
{
fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
if (modes[modeidx].aead_init)
{
(*modes[modeidx].aead_init) (hd, buflen, modes[modeidx].authlen);
err = gcry_cipher_decrypt (hd, outbuf, buflen, buf, buflen);
if (err)
break;
err = gcry_cipher_checktag (hd, outbuf, modes[modeidx].authlen);
if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
err = gpg_error (GPG_ERR_NO_ERROR);
}
else
err = gcry_cipher_decrypt (hd, outbuf, buflen, buf, buflen);
}
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
gcry_cipher_close (hd);
if (err)
{
fprintf (stderr, "gcry_cipher_decrypt failed: %s\n",
gpg_strerror (err) );
exit (1);
}
}
putchar ('\n');
gcry_free (raw_buf);
gcry_free (raw_outbuf);
}
static void
rsa_bench (int iterations, int print_header, int no_blinding)
{
gpg_error_t err;
int p_sizes[] = { 1024, 2048, 3072, 4096 };
int testno;
if (print_header)
printf ("Algorithm generate %4d*sign %4d*verify\n"
"------------------------------------------------\n",
iterations, iterations );
for (testno=0; testno < DIM (p_sizes); testno++)
{
gcry_sexp_t key_spec, key_pair, pub_key, sec_key;
gcry_mpi_t x;
gcry_sexp_t data;
gcry_sexp_t sig = NULL;
int count;
printf ("RSA %3d bit ", p_sizes[testno]);
fflush (stdout);
err = gcry_sexp_build (&key_spec, NULL,
gcry_fips_mode_active ()
? "(genkey (RSA (nbits %d)))"
: "(genkey (RSA (nbits %d)(transient-key)))",
p_sizes[testno]);
if (err)
die ("creating S-expression failed: %s\n", gcry_strerror (err));
start_timer ();
err = gcry_pk_genkey (&key_pair, key_spec);
if (err)
die ("creating %d bit RSA key failed: %s\n",
p_sizes[testno], gcry_strerror (err));
pub_key = gcry_sexp_find_token (key_pair, "public-key", 0);
if (! pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key_pair, "private-key", 0);
if (! sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key_pair);
gcry_sexp_release (key_spec);
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
x = gcry_mpi_new (p_sizes[testno]);
gcry_mpi_randomize (x, p_sizes[testno]-8, GCRY_WEAK_RANDOM);
err = gcry_sexp_build (&data, NULL,
"(data (flags raw) (value %m))", x);
gcry_mpi_release (x);
if (err)
die ("converting data failed: %s\n", gcry_strerror (err));
start_timer ();
for (count=0; count < iterations; count++)
{
gcry_sexp_release (sig);
err = gcry_pk_sign (&sig, data, sec_key);
if (err)
die ("signing failed (%d): %s\n", count, gpg_strerror (err));
}
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
start_timer ();
for (count=0; count < iterations; count++)
{
err = gcry_pk_verify (sig, data, pub_key);
if (err)
{
putchar ('\n');
show_sexp ("seckey:\n", sec_key);
show_sexp ("data:\n", data);
show_sexp ("sig:\n", sig);
die ("verify failed (%d): %s\n", count, gpg_strerror (err));
}
}
stop_timer ();
printf (" %s", elapsed_time ());
if (no_blinding)
{
fflush (stdout);
x = gcry_mpi_new (p_sizes[testno]);
gcry_mpi_randomize (x, p_sizes[testno]-8, GCRY_WEAK_RANDOM);
err = gcry_sexp_build (&data, NULL,
"(data (flags no-blinding) (value %m))", x);
gcry_mpi_release (x);
if (err)
die ("converting data failed: %s\n", gcry_strerror (err));
start_timer ();
for (count=0; count < iterations; count++)
{
gcry_sexp_release (sig);
err = gcry_pk_sign (&sig, data, sec_key);
if (err)
die ("signing failed (%d): %s\n", count, gpg_strerror (err));
}
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
}
putchar ('\n');
fflush (stdout);
gcry_sexp_release (sig);
gcry_sexp_release (data);
gcry_sexp_release (sec_key);
gcry_sexp_release (pub_key);
}
}
static void
dsa_bench (int iterations, int print_header)
{
gpg_error_t err;
gcry_sexp_t pub_key[3], sec_key[3];
int p_sizes[3] = { 1024, 2048, 3072 };
int q_sizes[3] = { 160, 224, 256 };
gcry_sexp_t data;
gcry_sexp_t sig = NULL;
int i, j;
err = gcry_sexp_sscan (pub_key+0, NULL, sample_public_dsa_key_1024,
strlen (sample_public_dsa_key_1024));
if (!err)
err = gcry_sexp_sscan (sec_key+0, NULL, sample_private_dsa_key_1024,
strlen (sample_private_dsa_key_1024));
if (!err)
err = gcry_sexp_sscan (pub_key+1, NULL, sample_public_dsa_key_2048,
strlen (sample_public_dsa_key_2048));
if (!err)
err = gcry_sexp_sscan (sec_key+1, NULL, sample_private_dsa_key_2048,
strlen (sample_private_dsa_key_2048));
if (!err)
err = gcry_sexp_sscan (pub_key+2, NULL, sample_public_dsa_key_3072,
strlen (sample_public_dsa_key_3072));
if (!err)
err = gcry_sexp_sscan (sec_key+2, NULL, sample_private_dsa_key_3072,
strlen (sample_private_dsa_key_3072));
if (err)
{
fprintf (stderr, PGM ": converting sample keys failed: %s\n",
gcry_strerror (err));
exit (1);
}
if (print_header)
printf ("Algorithm generate %4d*sign %4d*verify\n"
"------------------------------------------------\n",
iterations, iterations );
for (i=0; i < DIM (q_sizes); i++)
{
gcry_mpi_t x;
x = gcry_mpi_new (q_sizes[i]);
gcry_mpi_randomize (x, q_sizes[i], GCRY_WEAK_RANDOM);
err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x);
gcry_mpi_release (x);
if (err)
{
fprintf (stderr, PGM ": converting data failed: %s\n",
gcry_strerror (err));
exit (1);
}
printf ("DSA %d/%d -", p_sizes[i], q_sizes[i]);
fflush (stdout);
start_timer ();
for (j=0; j < iterations; j++)
{
gcry_sexp_release (sig);
err = gcry_pk_sign (&sig, data, sec_key[i]);
if (err)
{
putchar ('\n');
fprintf (stderr, PGM ": signing failed: %s\n",
gpg_strerror (err));
exit (1);
}
}
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
start_timer ();
for (j=0; j < iterations; j++)
{
err = gcry_pk_verify (sig, data, pub_key[i]);
if (err)
{
putchar ('\n');
fprintf (stderr, PGM ": verify failed: %s\n",
gpg_strerror (err));
exit (1);
}
}
stop_timer ();
printf (" %s\n", elapsed_time ());
fflush (stdout);
gcry_sexp_release (sig);
gcry_sexp_release (data);
sig = NULL;
}
for (i=0; i < DIM (q_sizes); i++)
{
gcry_sexp_release (sec_key[i]);
gcry_sexp_release (pub_key[i]);
}
}
static void
ecc_bench (int iterations, int print_header)
{
#if USE_ECC
gpg_error_t err;
const char *p_sizes[] = { "192", "224", "256", "384", "521", "Ed25519",
"gost256", "gost512" };
int testno;
if (print_header)
printf ("Algorithm generate %4d*sign %4d*verify\n"
"------------------------------------------------\n",
iterations, iterations );
for (testno=0; testno < DIM (p_sizes); testno++)
{
gcry_sexp_t key_spec, key_pair, pub_key, sec_key;
gcry_mpi_t x;
gcry_sexp_t data;
gcry_sexp_t sig = NULL;
int count;
int p_size;
int is_ed25519;
int is_gost;
is_ed25519 = !strcmp (p_sizes[testno], "Ed25519");
is_gost = !strncmp (p_sizes[testno], "gost", 4);
if (is_ed25519)
{
p_size = 256;
printf ("EdDSA Ed25519 ");
fflush (stdout);
}
else if (is_gost)
{
p_size = atoi (p_sizes[testno] + 4);
printf ("GOST %3d bit ", p_size);
fflush (stdout);
}
else
{
p_size = atoi (p_sizes[testno]);
printf ("ECDSA %3d bit ", p_size);
}
fflush (stdout);
if (is_ed25519)
err = gcry_sexp_build (&key_spec, NULL,
"(genkey (ecdsa (curve \"Ed25519\")))");
else if (is_gost)
err = gcry_sexp_build (&key_spec, NULL,
"(genkey (ecdsa (curve %s)))",
p_size == 256 ? "GOST2001-test" : "GOST2012-test");
else
err = gcry_sexp_build (&key_spec, NULL,
"(genkey (ECDSA (nbits %d)))", p_size);
if (err)
die ("creating S-expression failed: %s\n", gcry_strerror (err));
start_timer ();
err = gcry_pk_genkey (&key_pair, key_spec);
if (err)
die ("creating %d bit ECC key failed: %s\n",
p_size, gcry_strerror (err));
if (verbose > 2)
show_sexp ("ECC key:\n", key_pair);
pub_key = gcry_sexp_find_token (key_pair, "public-key", 0);
if (! pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key_pair, "private-key", 0);
if (! sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key_pair);
gcry_sexp_release (key_spec);
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
x = gcry_mpi_new (p_size);
gcry_mpi_randomize (x, p_size, GCRY_WEAK_RANDOM);
if (is_ed25519)
err = gcry_sexp_build (&data, NULL,
"(data (flags eddsa)(hash-algo sha512)"
" (value %m))", x);
else if (is_gost)
err = gcry_sexp_build (&data, NULL, "(data (flags gost) (value %m))", x);
else
err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x);
gcry_mpi_release (x);
if (err)
die ("converting data failed: %s\n", gcry_strerror (err));
start_timer ();
for (count=0; count < iterations; count++)
{
gcry_sexp_release (sig);
err = gcry_pk_sign (&sig, data, sec_key);
if (err)
{
if (verbose)
{
putc ('\n', stderr);
show_sexp ("signing key:\n", sec_key);
show_sexp ("signed data:\n", data);
}
die ("signing failed: %s\n", gpg_strerror (err));
}
}
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
start_timer ();
for (count=0; count < iterations; count++)
{
err = gcry_pk_verify (sig, data, pub_key);
if (err)
{
putchar ('\n');
show_sexp ("seckey:\n", sec_key);
show_sexp ("data:\n", data);
show_sexp ("sig:\n", sig);
die ("verify failed: %s\n", gpg_strerror (err));
}
}
stop_timer ();
printf (" %s\n", elapsed_time ());
fflush (stdout);
gcry_sexp_release (sig);
gcry_sexp_release (data);
gcry_sexp_release (sec_key);
gcry_sexp_release (pub_key);
}
#endif /*USE_ECC*/
}
static void
do_powm ( const char *n_str, const char *e_str, const char *m_str)
{
gcry_mpi_t e, n, msg, cip;
gcry_error_t err;
int i;
err = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX, n_str, 0, 0);
if (err) BUG ();
err = gcry_mpi_scan (&e, GCRYMPI_FMT_HEX, e_str, 0, 0);
if (err) BUG ();
err = gcry_mpi_scan (&msg, GCRYMPI_FMT_HEX, m_str, 0, 0);
if (err) BUG ();
cip = gcry_mpi_new (0);
start_timer ();
for (i=0; i < 1000; i++)
gcry_mpi_powm (cip, msg, e, n);
stop_timer ();
printf (" %s", elapsed_time ()); fflush (stdout);
/* { */
/* char *buf; */
/* if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void**)&buf, NULL, cip)) */
/* BUG (); */
/* printf ("result: %s\n", buf); */
/* gcry_free (buf); */
/* } */
gcry_mpi_release (cip);
gcry_mpi_release (msg);
gcry_mpi_release (n);
gcry_mpi_release (e);
}
static void
mpi_bench (void)
{
printf ("%-10s", "powm"); fflush (stdout);
do_powm (
"20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E4",
"29",
"B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8"
);
do_powm (
"20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA40716",
"29",
"B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847"
);
do_powm (
"20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA4071620A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA40716",
"29",
"B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847"
);
putchar ('\n');
}
int
main( int argc, char **argv )
{
int last_argc = -1;
int no_blinding = 0;
int use_random_daemon = 0;
int with_progress = 0;
int debug = 0;
int pk_count = 100;
buffer_alignment = 1;
if (argc)
{ argc--; argv++; }
+ /* We skip this test if we are running under the test suite (no args
+ and srcdir defined) and GCRYPT_NO_BENCHMARKS is set. */
+ if (!argc && getenv ("srcdir") && getenv ("GCRYPT_NO_BENCHMARKS"))
+ exit (77);
+
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--help"))
{
fputs ("usage: benchmark "
"[md|cipher|random|mpi|rsa|dsa|ecc [algonames]]\n",
stdout);
exit (0);
}
else if (!strcmp (*argv, "--verbose"))
{
verbose++;
argc--; argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose += 2;
debug++;
argc--; argv++;
}
else if (!strcmp (*argv, "--use-random-daemon"))
{
use_random_daemon = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--prefer-standard-rng"))
{
/* This is anyway the default, but we may want to use it for
debugging. */
gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_STANDARD);
argc--; argv++;
}
else if (!strcmp (*argv, "--prefer-fips-rng"))
{
gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS);
argc--; argv++;
}
else if (!strcmp (*argv, "--prefer-system-rng"))
{
gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM);
argc--; argv++;
}
else if (!strcmp (*argv, "--no-blinding"))
{
no_blinding = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--large-buffers"))
{
large_buffers = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--cipher-repetitions"))
{
argc--; argv++;
if (argc)
{
cipher_repetitions = atoi(*argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--cipher-with-keysetup"))
{
cipher_with_keysetup = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--hash-repetitions"))
{
argc--; argv++;
if (argc)
{
hash_repetitions = atoi(*argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--pk-count"))
{
argc--; argv++;
if (argc)
{
pk_count = atoi(*argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--alignment"))
{
argc--; argv++;
if (argc)
{
buffer_alignment = atoi(*argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--disable-hwf"))
{
argc--; argv++;
if (argc)
{
if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL))
fprintf (stderr, PGM ": unknown hardware feature `%s'"
" - option ignored\n", *argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--fips"))
{
argc--; argv++;
/* This command needs to be called before gcry_check_version. */
gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
}
else if (!strcmp (*argv, "--progress"))
{
argc--; argv++;
with_progress = 1;
}
}
if (buffer_alignment < 1 || buffer_alignment > 16)
die ("value for --alignment must be in the range 1 to 16\n");
gcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
if (!gcry_check_version (GCRYPT_VERSION))
{
fprintf (stderr, PGM ": version mismatch; pgm=%s, library=%s\n",
GCRYPT_VERSION, gcry_check_version (NULL));
exit (1);
}
if (debug)
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
if (gcry_fips_mode_active ())
in_fips_mode = 1;
else
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
if (use_random_daemon)
gcry_control (GCRYCTL_USE_RANDOM_DAEMON, 1);
if (with_progress)
gcry_set_progress_handler (progress_cb, NULL);
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
if (cipher_repetitions < 1)
cipher_repetitions = 1;
if (hash_repetitions < 1)
hash_repetitions = 1;
if ( !argc )
{
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
md_bench (NULL);
putchar ('\n');
cipher_bench (NULL);
putchar ('\n');
rsa_bench (pk_count, 1, no_blinding);
dsa_bench (pk_count, 0);
ecc_bench (pk_count, 0);
putchar ('\n');
mpi_bench ();
putchar ('\n');
random_bench (0);
}
else if ( !strcmp (*argv, "random") || !strcmp (*argv, "strongrandom"))
{
if (argc == 1)
random_bench ((**argv == 's'));
else if (argc == 2)
{
gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, argv[1]);
random_bench ((**argv == 's'));
gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
}
else
fputs ("usage: benchmark [strong]random [seedfile]\n", stdout);
}
else if ( !strcmp (*argv, "md"))
{
if (argc == 1)
md_bench (NULL);
else
for (argc--, argv++; argc; argc--, argv++)
md_bench ( *argv );
}
else if ( !strcmp (*argv, "cipher"))
{
if (argc == 1)
cipher_bench (NULL);
else
for (argc--, argv++; argc; argc--, argv++)
cipher_bench ( *argv );
}
else if ( !strcmp (*argv, "mpi"))
{
mpi_bench ();
}
else if ( !strcmp (*argv, "rsa"))
{
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
rsa_bench (pk_count, 1, no_blinding);
}
else if ( !strcmp (*argv, "dsa"))
{
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
dsa_bench (pk_count, 1);
}
else if ( !strcmp (*argv, "ecc"))
{
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
ecc_bench (pk_count, 1);
}
else
{
fprintf (stderr, PGM ": bad arguments\n");
return 1;
}
if (in_fips_mode && !gcry_fips_mode_active ())
fprintf (stderr, PGM ": FIPS mode is not anymore active\n");
return 0;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Feb 22, 6:39 PM (4 h, 35 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
93/83/fe817c0525eedd71a414800787c0
Attached To
rC libgcrypt
Event Timeline
Log In to Comment