X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/ba6e6b64033b1f9de49feccb5c9cd438354481f7..0f00dc4c8eb47e67bc0f148c2dd109f73a451e0a:/perftest.c diff --git a/perftest.c b/perftest.c deleted file mode 100644 index 3c26937..0000000 --- a/perftest.c +++ /dev/null @@ -1,616 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Measure performance of various operations (Unix-specific) - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb 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 Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "rand.h" -#include "mp.h" -#include "mprand.h" -#include "fibrand.h" -#include "rsa.h" -#include "mpmont.h" -#include "mpbarrett.h" -#include "dh.h" -#include "pgen.h" -#include "ec.h" -#include "group.h" - -#include "cc.h" -#include "gcipher.h" -#include "ghash.h" -#include "gmac.h" -#include "ectab.h" -#include "ptab.h" - -/*----- Options -----------------------------------------------------------*/ - -typedef struct opts { - const char *name; /* Pre-configured named thing */ - unsigned fbits; /* Field size bits */ - unsigned gbits; /* Group size bits */ - unsigned n; /* Number of factors */ - unsigned i; /* Number of intervals (or zero) */ - double t; /* Time for each interval (secs) */ - unsigned f; /* Flags */ -#define OF_NOCHECK 1u /* Don't do group checking */ -} opts; - -/*----- Job switch --------------------------------------------------------*/ - -/* --- Barrett exponentiation --- */ - -typedef struct bar_ctx { - size_t n; - mpbarrett b; - mp_expfactor *e; -} bar_ctx; - -static void *bar_init(opts *o) -{ - bar_ctx *c = CREATE(bar_ctx); - gprime_param gp; - qd_parse qd; - size_t i; - - if (o->name) { - qd.p = o->name; - if (dh_parse(&qd, &gp)) - die(1, "bad prime group: %s", qd.e); - } else { - if (!o->fbits) o->fbits = 1024; - dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0); - } - mpbarrett_create(&c->b, gp.p); - if (!o->n) o->n = 1; - c->n = o->n; - c->e = xmalloc(c->n * sizeof(group_expfactor)); - for (i = 0; i < c->n; i++) { - c->e[i].base = mprand_range(MP_NEW, gp.p, &rand_global, 0); - c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0); - } - dh_paramfree(&gp); - return (c); -} - -static void bar_run(void *cc) -{ - bar_ctx *c = cc; - mp *d = mpbarrett_exp(&c->b, MP_NEW, c->e[0].base, c->e[0].exp); - MP_DROP(d); -} - -static void barsim_run(void *cc) -{ - bar_ctx *c = cc; - mp *d = mpbarrett_mexp(&c->b, MP_NEW, c->e, c->n); - MP_DROP(d); -} - -/* --- Montgomery exponentiation --- */ - -typedef struct mont_ctx { - size_t n; - mpmont m; - mp_expfactor *e; -} mont_ctx; - -static void *mont_init(opts *o) -{ - mont_ctx *c = CREATE(mont_ctx); - gprime_param gp; - qd_parse qd; - size_t i; - - if (o->name) { - qd.p = o->name; - if (dh_parse(&qd, &gp)) - die(1, "bad prime group: %s", qd.e); - } else { - if (!o->fbits) o->fbits = 1024; - dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0); - } - mpmont_create(&c->m, gp.p); - if (!o->n) o->n = 1; - c->n = o->n; - c->e = xmalloc(c->n * sizeof(mp_expfactor)); - for (i = 0; i < c->n; i++) { - c->e[i].base = mprand_range(MP_NEW, gp.p, &rand_global, 0); - c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0); - } - dh_paramfree(&gp); - return (c); -} - -static void mont_run(void *cc) -{ - mont_ctx *c = cc; - mp *d = mpmont_expr(&c->m, MP_NEW, c->e[0].base, c->e[0].exp); - MP_DROP(d); -} - -static void montsim_run(void *cc) -{ - mont_ctx *c = cc; - mp *d = mpmont_mexpr(&c->m, MP_NEW, c->e, c->n); - MP_DROP(d); -} - -/* --- Group exponentiation --- */ - -typedef struct gr_ctx { - size_t n; - group *g; - group_expfactor *e; -} gr_ctx; - -static void *grp_init(opts *o) -{ - gr_ctx *c = CREATE(gr_ctx); - const char *e; - gprime_param gp; - qd_parse qd; - size_t i; - - if (o->name) { - qd.p = o->name; - if (dh_parse(&qd, &gp)) - die(1, "bad prime group: %s", qd.e); - } else { - if (!o->fbits) o->fbits = 1024; - dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0); - } - c->g = group_prime(&gp); - if (!(o->f & OF_NOCHECK) && (e = G_CHECK(c->g, &rand_global)) != 0) - die(1, "bad group: %s", e); - if (!o->n) o->n = 1; - c->n = o->n; - c->e = xmalloc(c->n * sizeof(group_expfactor)); - for (i = 0; i < c->n; i++) { - c->e[i].base = G_CREATE(c->g); - G_FROMINT(c->g, c->e[i].base, - mprand_range(MP_NEW, gp.p, &rand_global, 0)); - c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0); - } - dh_paramfree(&gp); - return (c); -} - -static void *grec_init(opts *o) -{ - gr_ctx *c = CREATE(gr_ctx); - const char *e; - ec_info ei; - ec p = EC_INIT; - size_t i; - - if (!o->name) - die(1, "can't generate elliptic curves"); - if ((e = ec_getinfo(&ei, o->name)) != 0) - die(1, "bad curve: %s", e); - c->g = group_ec(&ei); - if (!(o->f & OF_NOCHECK) && (e = G_CHECK(c->g, &rand_global)) != 0) - die(1, "bad group: %s", e); - if (!o->n) o->n = 1; - c->n = o->n; - c->e = xmalloc(c->n * sizeof(group_expfactor)); - for (i = 0; i < c->n; i++) { - c->e[i].base = G_CREATE(c->g); - ec_rand(ei.c, &p, &rand_global); - G_FROMEC(c->g, c->e[i].base, &p); - c->e[i].exp = mprand_range(MP_NEW, ei.r, &rand_global, 0); - } - EC_DESTROY(&p); - return (c); -} - -static void gr_run(void *cc) -{ - gr_ctx *c = cc; - ge *x = G_CREATE(c->g); - G_EXP(c->g, x, c->e[0].base, c->e[0].exp); - G_DESTROY(c->g, x); -} - -static void grsim_run(void *cc) -{ - gr_ctx *c = cc; - ge *x = G_CREATE(c->g); - G_MEXP(c->g, x, c->e, c->n); - G_DESTROY(c->g, x); -} - -/* --- RSA --- */ - -typedef struct rsapriv_ctx { - rsa_priv rp; - rsa_privctx rpc; - mp *m; -} rsapriv_ctx; - -static void *rsapriv_init(opts *o) -{ - rsapriv_ctx *c = CREATE(rsapriv_ctx); - - if (!o->fbits) o->fbits = 1024; - rsa_gen(&c->rp, o->fbits, &rand_global, 0, pgen_evspin, 0); - rsa_privcreate(&c->rpc, &c->rp, 0); - c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0); - return (c); -} - -static void *rsaprivblind_init(opts *o) -{ - rsapriv_ctx *c = CREATE(rsapriv_ctx); - - if (!o->fbits) o->fbits = 1024; - rsa_gen(&c->rp, o->fbits, &rand_global, 0, pgen_evspin, 0); - rsa_privcreate(&c->rpc, &c->rp, fibrand_create(0)); - c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0); - return (c); -} - -static void rsapriv_run(void *cc) -{ - rsapriv_ctx *c = cc; - mp *d = rsa_privop(&c->rpc, MP_NEW, c->m); - MP_DROP(d); -} - -typedef struct rsapub_ctx { - rsa_pub rp; - rsa_pubctx rpc; - mp *m; -} rsapub_ctx; - -static void *rsapub_init(opts *o) -{ - rsapub_ctx *c = CREATE(rsapub_ctx); - rsa_priv rp; - - if (!o->fbits) o->fbits = 1024; - rsa_gen(&rp, o->fbits, &rand_global, 0, pgen_evspin, 0); - c->rp.n = MP_COPY(rp.n); - c->rp.e = MP_COPY(rp.e); - rsa_privfree(&rp); - rsa_pubcreate(&c->rpc, &c->rp); - c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0); - return (c); -} - -static void rsapub_run(void *cc) -{ - rsapub_ctx *c = cc; - mp *d = rsa_pubop(&c->rpc, MP_NEW, c->m); - MP_DROP(d); -} - -/* --- Symmetric encryption --- */ - -typedef struct ksched_ctx { - const gccipher *c; - octet *k; - size_t ksz; -} ksched_ctx; - -static void *ksched_init(opts *o) -{ - ksched_ctx *c = CREATE(ksched_ctx); - if (!o->name) - die(1, "must specify encryption scheme name"); - if ((c->c = gcipher_byname(o->name)) == 0) - die(1, "encryption scheme `%s' not known", o->name); - c->ksz = keysz(o->gbits/8, c->c->keysz); - c->k = xmalloc(c->ksz); - rand_get(RAND_GLOBAL, c->k, c->ksz); - return (c); -} - -static void ksched_run(void *cc) -{ - ksched_ctx *c = cc; - gcipher *gc = GC_INIT(c->c, c->k, c->ksz); - GC_DESTROY(gc); -} - -typedef struct enc_ctx { - gcipher *c; - octet *m; - size_t sz; - size_t n; -} enc_ctx; - -static void *enc_init(opts *o) -{ - enc_ctx *c = CREATE(enc_ctx); - const gccipher *cc; - size_t ksz; - octet *k; - if (!o->name) - die(1, "must specify encryption scheme name"); - if ((cc = gcipher_byname(o->name)) == 0) - die(1, "encryption scheme `%s' not known", o->name); - ksz = keysz(0, cc->keysz); - k = xmalloc(ksz); - rand_get(RAND_GLOBAL, k, ksz); - c->c = GC_INIT(cc, k, ksz); - xfree(k); - c->sz = o->gbits ? o->gbits : 65536; - c->n = o->n ? o->n : 16; - c->m = xmalloc(c->sz); - return (c); -} - -static void enc_run(void *cc) -{ - enc_ctx *c = cc; - size_t i; - for (i = 0; i < c->n; i++) - GC_ENCRYPT(c->c, c->m, c->m, c->sz); -} - -/* --- Hashing --- */ - -typedef struct hash_ctx { - const gchash *h; - octet *m; - size_t sz; - size_t n; -} hash_ctx; - -static void *hash_init(opts *o) -{ - hash_ctx *c = CREATE(hash_ctx); - if (!o->name) - die(1, "must specify hash function name"); - if ((c->h = ghash_byname(o->name)) == 0) - die(1, "hash function `%s' not known", o->name); - c->sz = o->gbits ? o->gbits : 65536; - c->n = o->n ? o->n : 16; - c->m = xmalloc(c->sz); - return (c); -} - -static void hash_run(void *cc) -{ - hash_ctx *c = cc; - size_t i; - ghash *h = GH_INIT(c->h); - for (i = 0; i < c->n; i++) - GH_HASH(h, c->m, c->sz); - GH_DONE(h, 0); - GH_DESTROY(h); -} - -/* --- Job table --- */ - -typedef struct jobops { - const char *name; - void *(*init)(opts *); - void (*run)(void *); -} jobops; - -static const jobops jobtab[] = { - { "g-prime-exp", grp_init, gr_run }, - { "g-ec-mul", grec_init, gr_run }, - { "g-prime-exp-sim", grp_init, grsim_run }, - { "g-ec-mul-sim", grec_init, grsim_run }, - { "barrett-exp", bar_init, bar_run }, - { "barrett-exp-sim", bar_init, barsim_run }, - { "mont-exp", mont_init, mont_run }, - { "mont-exp-sim", mont_init, montsim_run }, - { "rsa-priv", rsapriv_init, rsapriv_run }, - { "rsa-priv-blind", rsaprivblind_init, rsapriv_run }, - { "rsa-pub", rsapub_init, rsapub_run }, - { "ksched", ksched_init, ksched_run }, - { "enc", enc_init, enc_run }, - { "hash", hash_init, hash_run }, - { 0, 0, 0 } -}; - -/*----- Main code ---------------------------------------------------------*/ - -void version(FILE *fp) -{ - pquis(fp, "$, Catacomb " VERSION "\n"); -} - -static void usage(FILE *fp) -{ - pquis(fp, "Usage: $ [-options] job\n"); -} - -static void help(FILE *fp) -{ - version(fp); - putc('\n', fp); - usage(fp); - pquis(fp, "\n\ -Various performance tests.\n\ -\n\ -Options:\n\ -\n\ --h, --help Show this help text.\n\ --v, --version Show program version number.\n\ --u, --usage Show terse usage message.\n\ --l, --list [ITEM...] List all the various names of things.\n\ -\n\ --C, --name=NAME Select curve/DH-group/enc/hash name.\n\ --b, --field-bits Field size for g-prime and rsa.\n\ --q, --no-check Don't check field/group for validity.\n\ --B, --group-bits Group size for g-prime; key size for ksched;\n\ - data size for enc and hash.\n\ --n, --factors=COUNT Number of factors for {exp,mul}-sim.\n\ --i, --intervals=COUNT Number of intervals to run for. [0; forever]\n\ --t, --time=TIME Length of an interval in seconds. [1]\n\ -"); -} - -#define LISTS(LI) \ - LI("Lists", list, \ - listtab[i].name, listtab[i].name) \ - LI("Jobs", job, \ - jobtab[i].name, jobtab[i].name) \ - LI("Elliptic curves", ec, \ - ectab[i].name, ectab[i].name) \ - LI("Diffie-Hellman groups", dh, \ - ptab[i].name, ptab[i].name) \ - LI("Encryption algorithms", cipher, \ - gciphertab[i], gciphertab[i]->name) \ - LI("Hash functions", hash, \ - ghashtab[i], ghashtab[i]->name) - -MAKELISTTAB(listtab, LISTS) - -static unsigned uarg(const char *what, const char *p) -{ - char *q; - unsigned long u; - errno = 0; - u = strtoul(p, &q, 0); - if (*q || u > UINT_MAX || q == p || errno) - die(1, "bad %s `%s'", what, p); - return (u); -} - -static double farg(const char *what, const char *p) -{ - char *q; - double f; - errno = 0; - f = strtod(p, &q); - if (*q || q == p || errno) - die(1, "bad %s `%s'", what, p); - return (f); -} - -int main(int argc, char *argv[]) -{ - int i; - opts o = { 0 }; - const jobops *j; - struct timeval tv_next, tv_now; - double t, ttot; - unsigned n; - unsigned long ii; - clock_t c_start, c_stop; - double itot; - void *p; - - ego(argv[0]); - o.t = 1; - for (;;) { - static const struct option opts[] = { - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'v' }, - { "usage", 0, 0, 'u' }, - { "list", 0, 0, 'l' }, - { "name", OPTF_ARGREQ, 0, 'C' }, - { "field-bits", OPTF_ARGREQ, 0, 'b' }, - { "group-bits", OPTF_ARGREQ, 0, 'B' }, - { "factors", OPTF_ARGREQ, 0, 'n' }, - { "intervals", OPTF_ARGREQ, 0, 'i' }, - { "time", OPTF_ARGREQ, 0, 't' }, - { "no-check", 0, 0, 'q' }, - { 0, 0, 0, 0 } - }; - - i = mdwopt(argc, argv, "hvulC:b:B:n:i:t:q", opts, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'h': help(stdout); exit(0); - case 'v': version(stdout); exit(0); - case 'u': usage(stdout); exit(0); - case 'l': exit(displaylists(listtab, argv + optind)); - case 'C': o.name = optarg; break; - case 'b': o.fbits = uarg("field bits", optarg); break; - case 'B': o.gbits = uarg("subgroup bits", optarg); break; - case 'n': o.n = uarg("factor count", optarg); break; - case 'i': o.i = uarg("interval count", optarg); break; - case 't': o.t = farg("interval length", optarg); break; - case 'q': o.f |= OF_NOCHECK; break; - default: usage(stderr); exit(1); - } - } - if (optind + 1 != argc) { usage(stderr); exit(1); } - - for (j = jobtab; j->name; j++) - if (strcmp(j->name, argv[optind]) == 0) break; - if (!j->name) die(1, "unknown job type `%s'", argv[optind]); - p = j->init(&o); - - n = 0; - ttot = itot = 0; - gettimeofday(&tv_now, 0); - do { - tv_addl(&tv_next, &tv_now, o.t, fmod(o.t * MILLION, MILLION)); - ii = 0; - c_start = clock(); - do { - j->run(p); - ii++; - gettimeofday(&tv_now, 0); - } while (TV_CMP(&tv_now, <, &tv_next)); - c_stop = clock(); - t = (double)(c_stop - c_start)/CLOCKS_PER_SEC; - itot += ii; - ttot += t; - printf("%5u: did = %5lu; /sec = %5f; avg /sec = %5f\n", - n, ii, ii/t, itot/ttot); - fflush(stdout); - n++; - } while (!o.i || n < o.i); - - return (0); -} - -/*----- That's all, folks -------------------------------------------------*/