progs/perftest.c: Fix key-size handling.
[catacomb] / progs / perftest.c
index e6f7ddf..5fa6b7f 100644 (file)
 #include "mprand.h"
 #include "fibrand.h"
 #include "rsa.h"
+#include "mpint.h"
+#include "mptext.h"
 #include "mpmont.h"
 #include "mpbarrett.h"
 #include "dh.h"
 #include "pgen.h"
 #include "ec.h"
 #include "group.h"
+#include "x25519.h"
+#include "x448.h"
+#include "ed25519.h"
+#include "ed448.h"
 
 #include "cc.h"
 #include "gcipher.h"
@@ -80,7 +86,9 @@ typedef struct opts {
   unsigned gbits;                      /* Group size bits */
   unsigned n;                          /* Number of factors */
   unsigned i;                          /* Number of intervals (or zero) */
+  unsigned k;                          /* Main loop batch size */
   double t;                            /* Time for each interval (secs) */
+  mp *e;                               /* Public exponent */
   unsigned f;                          /* Flags */
 #define OF_NOCHECK 1u                  /*   Don't do group checking */
 } opts;
@@ -269,6 +277,142 @@ static void grsim_run(void *cc)
   G_DESTROY(c->g, x);
 }
 
+/* --- x25519 --- */
+
+typedef struct x25519_jobctx {
+  octet k[X25519_KEYSZ];
+  octet p[X25519_PUBSZ];
+} x25519_jobctx;
+
+static void *x25519_jobinit(opts *o)
+{
+  x25519_jobctx *c = CREATE(x25519_jobctx);
+  rand_get(RAND_GLOBAL, c->k, sizeof(c->k));
+  rand_get(RAND_GLOBAL, c->p, sizeof(c->p));
+  return (c);
+}
+
+static void x25519_jobrun(void *cc)
+  { x25519_jobctx *c = cc; octet z[X25519_OUTSZ]; x25519(z, c->k, c->p); }
+
+/* --- x448 --- */
+
+typedef struct x448_jobctx {
+  octet k[X448_KEYSZ];
+  octet p[X448_PUBSZ];
+} x448_jobctx;
+
+static void *x448_jobinit(opts *o)
+{
+  x448_jobctx *c = CREATE(x448_jobctx);
+  rand_get(RAND_GLOBAL, c->k, sizeof(c->k));
+  rand_get(RAND_GLOBAL, c->p, sizeof(c->p));
+  return (c);
+}
+
+static void x448_jobrun(void *cc)
+  { x448_jobctx *c = cc; octet z[X448_OUTSZ]; x448(z, c->k, c->p); }
+
+/* --- Ed25519 --- */
+
+typedef struct ed25519_signctx {
+  octet k[ED25519_KEYSZ];
+  octet K[ED25519_PUBSZ];
+  octet m[64];
+} ed25519_signctx;
+
+typedef struct ed25519_vrfctx {
+  octet K[ED25519_PUBSZ];
+  octet m[64];
+  octet sig[ED25519_SIGSZ];
+} ed25519_vrfctx;
+
+static void *ed25519_signinit(opts *o)
+{
+  ed25519_signctx *c = CREATE(ed25519_signctx);
+
+  rand_get(RAND_GLOBAL, c->k, sizeof(c->k));
+  rand_get(RAND_GLOBAL, c->m, sizeof(c->m));
+  ed25519_pubkey(c->K, c->k, sizeof(c->k));
+  return (c);
+}
+
+static void ed25519_signrun(void *cc)
+{
+  ed25519_signctx *c = cc;
+  octet sig[ED25519_SIGSZ];
+
+  ed25519_sign(sig, c->k, sizeof(c->k), c->K, c->m, sizeof(c->m));
+}
+
+static void *ed25519_vrfinit(opts *o)
+{
+  octet k[ED25519_KEYSZ];
+  ed25519_vrfctx *c = CREATE(ed25519_vrfctx);
+
+  rand_get(RAND_GLOBAL, k, sizeof(k));
+  rand_get(RAND_GLOBAL, c->m, sizeof(c->m));
+  ed25519_pubkey(c->K, k, sizeof(k));
+  ed25519_sign(c->sig, k, sizeof(k), c->K, c->m, sizeof(c->m));
+  return (c);
+}
+
+static void ed25519_vrfrun(void *cc)
+{
+  ed25519_vrfctx *c = cc;
+  ed25519_verify(c->K, c->m, sizeof(c->m), c->sig);
+}
+
+/* --- Ed448 --- */
+
+typedef struct ed448_signctx {
+  octet k[ED448_KEYSZ];
+  octet K[ED448_PUBSZ];
+  octet m[64];
+} ed448_signctx;
+
+typedef struct ed448_vrfctx {
+  octet K[ED448_PUBSZ];
+  octet m[64];
+  octet sig[ED448_SIGSZ];
+} ed448_vrfctx;
+
+static void *ed448_signinit(opts *o)
+{
+  ed448_signctx *c = CREATE(ed448_signctx);
+
+  rand_get(RAND_GLOBAL, c->k, sizeof(c->k));
+  rand_get(RAND_GLOBAL, c->m, sizeof(c->m));
+  ed448_pubkey(c->K, c->k, sizeof(c->k));
+  return (c);
+}
+
+static void ed448_signrun(void *cc)
+{
+  ed448_signctx *c = cc;
+  octet sig[ED448_SIGSZ];
+
+  ed448_sign(sig, c->k, sizeof(c->k), c->K, 0, 0, 0, c->m, sizeof(c->m));
+}
+
+static void *ed448_vrfinit(opts *o)
+{
+  octet k[ED448_KEYSZ];
+  ed448_vrfctx *c = CREATE(ed448_vrfctx);
+
+  rand_get(RAND_GLOBAL, k, sizeof(k));
+  rand_get(RAND_GLOBAL, c->m, sizeof(c->m));
+  ed448_pubkey(c->K, k, sizeof(k));
+  ed448_sign(c->sig, k, sizeof(k), c->K, 0, 0, 0, c->m, sizeof(c->m));
+  return (c);
+}
+
+static void ed448_vrfrun(void *cc)
+{
+  ed448_vrfctx *c = cc;
+  ed448_verify(c->K, 0, 0, 0, c->m, sizeof(c->m), c->sig);
+}
+
 /* --- RSA --- */
 
 typedef struct rsapriv_ctx {
@@ -282,7 +426,8 @@ 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);
+  if (!o->e) o->e = mp_fromulong(MP_NEW, 65537);
+  rsa_gen_e(&c->rp, o->fbits, o->e, &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);
@@ -293,7 +438,8 @@ 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);
+  if (!o->e) o->e = mp_fromulong(MP_NEW, 65537);
+  rsa_gen_e(&c->rp, o->fbits, o->e, &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);
@@ -318,7 +464,8 @@ static void *rsapub_init(opts *o)
   rsa_priv rp;
 
   if (!o->fbits) o->fbits = 1024;
-  rsa_gen(&rp, o->fbits, &rand_global, 0, pgen_evspin, 0);
+  if (!o->e) o->e = mp_fromulong(MP_NEW, 65537);
+  rsa_gen_e(&rp, o->fbits, o->e, &rand_global, 0, pgen_evspin, 0);
   c->rp.n = MP_COPY(rp.n);
   c->rp.e = MP_COPY(rp.e);
   rsa_privfree(&rp);
@@ -349,7 +496,9 @@ static void *ksched_init(opts *o)
     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->ksz = keysz(o->fbits/8, c->c->keysz);
+  if (o->fbits%8 || (o->fbits && c->ksz != o->fbits/8))
+    die(1, "bad key size %u for %s", o->fbits, o->name);
   c->k = xmalloc(c->ksz);
   rand_get(RAND_GLOBAL, c->k, c->ksz);
   return (c);
@@ -379,7 +528,9 @@ static void *enc_init(opts *o)
     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);
+  ksz = keysz(o->fbits/8, cc->keysz);
+  if (o->fbits%8 || (o->fbits && ksz != o->fbits/8))
+    die(1, "bad key size %u for %s", o->fbits, o->name);
   k = xmalloc(ksz);
   rand_get(RAND_GLOBAL, k, ksz);
   c->c = GC_INIT(cc, k, ksz);
@@ -485,6 +636,12 @@ static const jobops jobtab[] = {
   { "rsa-priv",                        rsapriv_init,           rsapriv_run },
   { "rsa-priv-blind",          rsaprivblind_init,      rsapriv_run },
   { "rsa-pub",                 rsapub_init,            rsapub_run },
+  { "x25519",                  x25519_jobinit,         x25519_jobrun },
+  { "x448",                    x448_jobinit,           x448_jobrun },
+  { "ed25519-sign",            ed25519_signinit,       ed25519_signrun },
+  { "ed25519-vrf",             ed25519_vrfinit,        ed25519_vrfrun },
+  { "ed448-sign",              ed448_signinit,         ed448_signrun },
+  { "ed448-vrf",               ed448_vrfinit,          ed448_vrfrun },
   { "ksched",                  ksched_init,            ksched_run },
   { "enc",                     enc_init,               enc_run },
   { "hash",                    hash_init,              hash_run },
@@ -520,12 +677,14 @@ Options:\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\
+-b, --field-bits       Field size for g-prime and rsa;\n\
+                         key bits for ksched and enc.\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\
+-B, --group-bits       Group size for g-prime; data size for enc and hash.\n\
+-n, --factors=COUNT    Number of factors for {exp,mul}-sim;\n\
+                         inner iterations for enc and hash.\n\
 -i, --intervals=COUNT  Number of intervals to run for.  [0; forever]\n\
+-k, --batch=COUNT      Number of operations to batch between timer checks.\n\
 -t, --time=TIME                Length of an interval in seconds.  [1]\n\
 ");
 }
@@ -557,6 +716,14 @@ static unsigned uarg(const char *what, const char *p)
   return (u);
 }
 
+static mp *mparg(const char *what, const char *p)
+{
+  char *q;
+  mp *x = mp_readstring(MP_NEW, p, &q, 0);
+  if (!x || *q) die(1, "bad %s `%s'", what, p);
+  return (x);
+}
+
 static double farg(const char *what, const char *p)
 {
   char *q;
@@ -575,9 +742,9 @@ int main(int argc, char *argv[])
   const jobops *j;
   struct timeval tv_next, tv_now;
   double t, ttot;
-  unsigned n;
+  unsigned n, k;
   unsigned long ii;
-  clock_t c_start, c_stop;
+  clock_t c0, c1;
   double itot;
   void *p;
 
@@ -594,12 +761,14 @@ int main(int argc, char *argv[])
       { "group-bits",  OPTF_ARGREQ,    0,      'B' },
       { "factors",     OPTF_ARGREQ,    0,      'n' },
       { "intervals",   OPTF_ARGREQ,    0,      'i' },
+      { "batch",       OPTF_ARGREQ,    0,      'k' },
+      { "public-exponent", OPTF_ARGREQ, 0,     'e' },
       { "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);
+    i = mdwopt(argc, argv, "hvulC:b:B:n:i:k:e:t:q", opts, 0, 0, 0);
     if (i < 0) break;
     switch (i) {
       case 'h': help(stdout); exit(0);
@@ -610,8 +779,14 @@ int main(int argc, char *argv[])
       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 'e':
+       mp_drop(o.e); o.e = mparg("public exponent", optarg);
+       if (MP_CMP(o.e, <, MP_THREE) || MP_EVENP(o.e))
+         die(1, "invalid public exponent");
+       break;
       case 'i': o.i = uarg("interval count", optarg); break;
       case 't': o.t = farg("interval length", optarg); break;
+      case 'k': o.k = uarg("batch size", optarg); break;
       case 'q': o.f |= OF_NOCHECK; break;
       default: usage(stderr); exit(1);
     }
@@ -629,17 +804,16 @@ int main(int argc, char *argv[])
   do {
     tv_addl(&tv_next, &tv_now, o.t, fmod(o.t * MILLION, MILLION));
     ii = 0;
-    c_start = clock();
+    c0 = clock();
     do {
-      j->run(p);
-      ii++;
+      for (k = 0; k < o.k; k++) { j->run(p); }
+      ii += k;
       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;
+    c1 = clock();
     printf("%5u: did = %5lu; /sec = %5f; avg /sec = %5f\n",
+    t = (double)(c1 - c0)/CLOCKS_PER_SEC;
+    itot += ii; ttot += t;
           n, ii, ii/t, itot/ttot);
     fflush(stdout);
     n++;