diff options
Diffstat (limited to 'plugins/MirOTR/libgcrypt-1.4.6/tests/pkbench.c')
-rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/tests/pkbench.c | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/plugins/MirOTR/libgcrypt-1.4.6/tests/pkbench.c b/plugins/MirOTR/libgcrypt-1.4.6/tests/pkbench.c new file mode 100644 index 0000000000..67b94dc9a6 --- /dev/null +++ b/plugins/MirOTR/libgcrypt-1.4.6/tests/pkbench.c @@ -0,0 +1,514 @@ +/* pkbench.c - Pubkey menchmarking + * Copyright (C) 2004, 2005, 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 <gcrypt.h> +#include <assert.h> +#include <stdlib.h> +#include <ctype.h> +#include <sys/stat.h> +#ifndef HAVE_W32_SYSTEM +# include <sys/times.h> +#endif /*HAVE_W32_SYSTEM*/ +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <errno.h> + +#define PGM "pkbench" + + +static int verbose; +static int debug; +static int error_count; + + +typedef struct context +{ + gcry_sexp_t key_secret; + gcry_sexp_t key_public; + gcry_sexp_t data; + gcry_sexp_t data_encrypted; + gcry_sexp_t data_signed; +} *context_t; + +typedef int (*work_t) (context_t context, unsigned int final); + + +static void +fail (const char *format, ...) +{ + va_list arg_ptr; + + fputs ( PGM ": ", stderr); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + error_count++; +} + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + putchar ('\n'); + fputs ( PGM ": ", stderr); + va_start (arg_ptr, format); + 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 = gcry_xmalloc (size); + + gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); + fprintf (stderr, "%.*s", (int)size, buf); + gcry_free (buf); +} + + +static void * +read_file (const char *fname, size_t *r_length) +{ + FILE *fp; + struct stat st; + char *buf; + size_t buflen; + + fp = fopen (fname, "rb"); + if (!fp) + { + fail ("can't open `%s': %s\n", fname, strerror (errno)); + return NULL; + } + + if (fstat (fileno(fp), &st)) + { + fail ("can't stat `%s': %s\n", fname, strerror (errno)); + fclose (fp); + return NULL; + } + + buflen = st.st_size; + buf = gcry_xmalloc (buflen+1); + if (fread (buf, buflen, 1, fp) != 1) + { + fail ("error reading `%s': %s\n", fname, strerror (errno)); + fclose (fp); + gcry_free (buf); + return NULL; + } + fclose (fp); + + if (r_length) + *r_length = buflen; + return buf; +} + + + +static void +benchmark (work_t worker, context_t context) +{ + clock_t timer_start, timer_stop; + unsigned int loop = 10; + unsigned int i = 0; + struct tms timer; + int ret = 0; + +#ifdef HAVE_W32_SYSTEM + timer_start = clock (); +#else + times (&timer); + timer_start = timer.tms_utime; +#endif + for (i = 0; i < loop; i++) + { + ret = (*worker) (context, (i + 1) == loop); + if (! ret) + break; + } +#ifdef HAVE_W32_SYSTEM + timer_stop = clock (); +#else + times (&timer); + timer_stop = timer.tms_utime; +#endif + + if (ret) + printf ("%.0f ms\n", + (((double) ((timer_stop - timer_start) / loop)) / CLOCKS_PER_SEC) + * 10000000); + else + printf ("[skipped]\n"); +} + +static int +work_encrypt (context_t context, unsigned int final) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + gcry_sexp_t data_encrypted = NULL; + int ret = 1; + + err = gcry_pk_encrypt (&data_encrypted, + context->data, context->key_public); + if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED) + { + err = GPG_ERR_NO_ERROR; + ret = 0; + } + else + { + assert (! err); + + if (final) + context->data_encrypted = data_encrypted; + else + gcry_sexp_release (data_encrypted); + } + + return ret; +} + +static int +work_decrypt (context_t context, unsigned int final) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + int ret = 1; + + if (! context->data_encrypted) + ret = 0; + else + { + gcry_sexp_t data_decrypted = NULL; + + err = gcry_pk_decrypt (&data_decrypted, + context->data_encrypted, + context->key_secret); + assert (! err); + if (final) + { + gcry_sexp_release (context->data_encrypted); + context->data_encrypted = NULL; + } + gcry_sexp_release (data_decrypted); + } + + return ret; +} + +static int +work_sign (context_t context, unsigned int final) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + gcry_sexp_t data_signed = NULL; + int ret = 1; + + err = gcry_pk_sign (&data_signed, + context->data, context->key_secret); + if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED) + { + err = GPG_ERR_NO_ERROR; + ret = 0; + } + else if (err) + { + fail ("pk_sign failed: %s\n", gpg_strerror (err)); + ret = 0; + } + else + { + if (final) + context->data_signed = data_signed; + else + gcry_sexp_release (data_signed); + } + + return ret; +} + +static int +work_verify (context_t context, unsigned int final) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + int ret = 1; + + if (!context->data_signed) + return 0; + + err = gcry_pk_verify (context->data_signed, + context->data, + context->key_public); + if (err) + { + show_sexp ("data_signed:\n", context->data_signed); + show_sexp ("data:\n", context->data); + fail ("pk_verify failed: %s\n", gpg_strerror (err)); + ret = 0; + } + else if (final) + { + gcry_sexp_release (context->data_signed); + context->data_signed = NULL; + } + + return ret; +} + +static void +process_key_pair (context_t context) +{ + struct + { + work_t worker; + const char *identifier; + } worker_functions[] = { { work_encrypt, "encrypt" }, + { work_decrypt, "decrypt" }, + { work_sign, "sign" }, + { work_verify, "verify" } }; + unsigned int i = 0; + + for (i = 0; i < (sizeof (worker_functions) / sizeof (*worker_functions)); i++) + { + printf ("%s: ", worker_functions[i].identifier); + benchmark (worker_functions[i].worker, context); + } +} + +static void +context_init (context_t context, gcry_sexp_t key_secret, gcry_sexp_t key_public) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + unsigned int key_size = 0; + gcry_mpi_t data = NULL; + gcry_sexp_t data_sexp = NULL; + + key_size = gcry_pk_get_nbits (key_secret); + assert (key_size); + + data = gcry_mpi_new (key_size); + assert (data); + + gcry_mpi_randomize (data, key_size, GCRY_STRONG_RANDOM); + gcry_mpi_clear_bit (data, key_size - 1); + err = gcry_sexp_build (&data_sexp, NULL, + "(data (flags raw) (value %m))", + data); + assert (! err); + gcry_mpi_release (data); + + context->key_secret = key_secret; + context->key_public = key_public; + context->data = data_sexp; + context->data_encrypted = NULL; + context->data_signed = NULL; +} + +static void +context_destroy (context_t context) +{ + gcry_sexp_release (context->key_secret); + gcry_sexp_release (context->key_public); + gcry_sexp_release (context->data); +} + +static void +process_key_pair_file (const char *key_pair_file) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + void *key_pair_buffer = NULL; + gcry_sexp_t key_pair_sexp = NULL; + gcry_sexp_t key_secret_sexp = NULL; + gcry_sexp_t key_public_sexp = NULL; + struct context context = { NULL }; + size_t file_length; + + key_pair_buffer = read_file (key_pair_file, &file_length); + if (!key_pair_buffer) + die ("failed to open `%s'\n", key_pair_file); + + err = gcry_sexp_sscan (&key_pair_sexp, NULL, + key_pair_buffer, file_length); + if (err) + die ("gcry_sexp_sscan failed\n"); + + key_secret_sexp = gcry_sexp_find_token (key_pair_sexp, "private-key", 0); + assert (key_secret_sexp); + key_public_sexp = gcry_sexp_find_token (key_pair_sexp, "public-key", 0); + assert (key_public_sexp); + + gcry_sexp_release (key_pair_sexp); + + context_init (&context, key_secret_sexp, key_public_sexp); + + printf ("Key file: %s\n", key_pair_file); + process_key_pair (&context); + printf ("\n"); + + context_destroy (&context); + gcry_free (key_pair_buffer); +} + + +static void +generate_key (const char *algorithm, const char *key_size) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + size_t key_pair_buffer_size = 0; + char *key_pair_buffer = NULL; + gcry_sexp_t key_spec = NULL; + gcry_sexp_t key_pair = NULL; + + if (isdigit ((unsigned int)*key_size)) + err = gcry_sexp_build (&key_spec, NULL, + "(genkey (%s (nbits %s)))", + algorithm, key_size); + else + err = gcry_sexp_build (&key_spec, NULL, + "(genkey (%s (curve %s)))", + algorithm, key_size); + if (err) + die ("sexp_build failed: %s\n", gpg_strerror (err)); + + err = gcry_pk_genkey (&key_pair, key_spec); + if (err) + { + show_sexp ("request:\n", key_spec); + die ("pk_genkey failed: %s\n", gpg_strerror (err)); + } + + key_pair_buffer_size = gcry_sexp_sprint (key_pair, GCRYSEXP_FMT_ADVANCED, + NULL, 0); + key_pair_buffer = gcry_xmalloc (key_pair_buffer_size); + + gcry_sexp_sprint (key_pair, GCRYSEXP_FMT_ADVANCED, + key_pair_buffer, key_pair_buffer_size); + + printf ("%.*s", (int)key_pair_buffer_size, key_pair_buffer); + gcry_free (key_pair_buffer); +} + + + +int +main (int argc, char **argv) +{ + int last_argc = -1; + int genkey_mode = 0; + int fips_mode = 0; + + if (argc) + { argc--; argv++; } + + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--help")) + { + puts ("Usage: " PGM " [OPTIONS] [FILES]\n" + "Various public key tests:\n\n" + " Default is to process all given key files\n\n" + " --genkey ALGONAME SIZE Generate a public key\n" + "\n" + " --verbose enable extra informational output\n" + " --debug enable additional debug output\n" + " --help display this help and exit\n\n"); + exit (0); + } + else if (!strcmp (*argv, "--verbose")) + { + verbose++; + argc--; argv++; + } + else if (!strcmp (*argv, "--debug")) + { + verbose = debug = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--genkey")) + { + genkey_mode = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--fips")) + { + fips_mode = 1; + argc--; argv++; + } + } + + gcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose); + + if (fips_mode) + gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0); + + gcry_control (GCRYCTL_DISABLE_SECMEM); + if (!gcry_check_version (GCRYPT_VERSION)) + { + fprintf (stderr, PGM ": version mismatch\n"); + exit (1); + } + + if (genkey_mode) + { + /* No valuable keys are create, so we can speed up our RNG. */ + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + } + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + + + if (genkey_mode && argc == 2) + { + generate_key (argv[0], argv[1]); + } + else if (!genkey_mode && argc) + { + int i; + + for (i = 0; i < argc; i++) + process_key_pair_file (argv[i]); + } + else + { + fprintf (stderr, "usage: " PGM + " [OPTIONS] [FILES] (try --help for more information)\n"); + exit (1); + } + + return error_count ? 1 : 0; +} |