/* pkbench.c - Pubkey menchmarking
- * Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <gcrypt.h>
#include <assert.h>
#include <stdlib.h>
-#include <sys/mman.h>
+#include <ctype.h>
#include <sys/stat.h>
-#include <sys/times.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
{
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)
{
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",
else
{
gcry_sexp_t data_decrypted = NULL;
-
+
err = gcry_pk_decrypt (&data_decrypted,
context->data_encrypted,
context->key_secret);
err = GPG_ERR_NO_ERROR;
ret = 0;
}
+ else if (err)
+ {
+ fail ("pk_sign failed: %s\n", gpg_strerror (err));
+ ret = 0;
+ }
else
{
- assert (! err);
-
if (final)
context->data_signed = data_signed;
else
gcry_error_t err = GPG_ERR_NO_ERROR;
int ret = 1;
- if (! context->data_signed)
- ret = 0;
- else
+ if (!context->data_signed)
+ return 0;
+
+ err = gcry_pk_verify (context->data_signed,
+ context->data,
+ context->key_public);
+ if (err)
{
- err = gcry_pk_verify (context->data_signed,
- context->data,
- context->key_public);
- assert (! err);
- if (final)
- {
- gcry_sexp_release (context->data_signed);
- context->data_signed = NULL;
- }
+ 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;
gcry_sexp_t key_secret_sexp = NULL;
gcry_sexp_t key_public_sexp = NULL;
struct context context = { NULL };
- struct stat statbuf;
- int key_pair_fd = -1;
- int ret = 0;
-
- ret = stat (key_pair_file, &statbuf);
- assert (! ret);
-
- key_pair_fd = open (key_pair_file, O_RDONLY);
- assert (key_pair_fd != -1);
+ size_t file_length;
- key_pair_buffer = mmap (NULL, statbuf.st_size, PROT_READ,
- MAP_PRIVATE, key_pair_fd, 0);
- assert (key_pair_buffer != MAP_FAILED);
+ 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, statbuf.st_size);
- assert (! err);
+ 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);
assert (key_public_sexp);
gcry_sexp_release (key_pair_sexp);
- ret = munmap (key_pair_buffer, statbuf.st_size);
- assert (! ret);
- ret = close (key_pair_fd);
- assert (! ret);
context_init (&context, key_secret_sexp, key_public_sexp);
printf ("\n");
context_destroy (&context);
+ gcry_free (key_pair_buffer);
}
-static const char *program_name = NULL;
-
-static void
-print_usage (int err)
-{
- fprintf (err ? stderr : stdout,
- "Usage: %s [--help ] [ --genkey <algorithm>,<size> ] <key files ...>\n\n",
- program_name);
- exit (err);
-}
static void
generate_key (const char *algorithm, const char *key_size)
gcry_sexp_t key_spec = NULL;
gcry_sexp_t key_pair = NULL;
- err = gcry_sexp_build (&key_spec, NULL,
- "(genkey (%s (nbits %s)))",
- algorithm, key_size);
- assert (! err);
+ 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);
- assert (! err);
+ 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 = malloc (key_pair_buffer_size);
- assert (key_pair_buffer);
+ 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", key_pair_buffer_size, key_pair_buffer);
+ printf ("%.*s", (int)key_pair_buffer_size, key_pair_buffer);
+ gcry_free (key_pair_buffer);
}
+
+
int
main (int argc, char **argv)
{
- program_name = argc ? argv[0] : "";
+ 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 (argv[1] && ((! strcmp (argv[1], "--help"))
- || (! strcmp (argv[1], "-h"))))
- print_usage (0);
- else if (argv[1] && ((! strcmp (argv[1], "--genkey"))
- || (! strcmp (argv[1], "-g"))))
+ if (!gcry_check_version (GCRYPT_VERSION))
{
- char *algorithm = NULL;
- char *key_size = NULL;
+ 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 (argv[2])
- {
- algorithm = argv[2];
- key_size = strchr (algorithm, ',');
- if (key_size)
- {
- *key_size = 0;
- key_size++;
- }
- }
- if (algorithm && key_size)
- generate_key (algorithm, key_size);
- else
- print_usage (EXIT_FAILURE);
+ if (genkey_mode && argc == 2)
+ {
+ generate_key (argv[0], argv[1]);
}
- else
+ else if (!genkey_mode && argc)
{
- unsigned int i = 0;
+ int i;
- for (i = 1; (i < argc); 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 EXIT_SUCCESS;
+ return error_count ? 1 : 0;
}