Generate, store and retreive elliptic curve keys.
[u/mdw/catacomb] / keyutil.c
index 1871c1a..0911021 100644 (file)
--- a/keyutil.c
+++ b/keyutil.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: keyutil.c,v 1.16 2003/10/15 09:31:45 mdw Exp $
+ * $Id: keyutil.c,v 1.17 2004/03/28 01:58:47 mdw Exp $
  *
  * Simple key manager program
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: keyutil.c,v $
+ * Revision 1.17  2004/03/28 01:58:47  mdw
+ * Generate, store and retreive elliptic curve keys.
+ *
  * Revision 1.16  2003/10/15 09:31:45  mdw
  * Fix help message.
  *
 #include "bbs.h"
 #include "dh.h"
 #include "dsa.h"
+#include "ec.h"
+#include "ec-keys.h"
+#include "ectab.h"
 #include "fibrand.h"
 #include "getdate.h"
 #include "key.h"
@@ -203,6 +209,7 @@ typedef struct keyopts {
   dstr tag;                            /* Full tag name for the key */
   unsigned f;                          /* Flags for the new key */
   unsigned bits, qbits;                        /* Bit length for the new key */
+  const char *curve;                   /* Elliptic curve name/info */
   key *p;                              /* Parameters key-data */
 } keyopts;
 
@@ -397,7 +404,7 @@ static void alg_des(keyopts *k)
   int i;
 
   if (!k->bits)
-    k->bits = 112;
+    k->bits = 168;
   if (k->p)
     die(EXIT_FAILURE, "no shared parameters for DES keys");
   if (k->bits % 56 || k->bits > 168)
@@ -691,6 +698,87 @@ static void alg_bbs(keyopts *k)
   bbs_privfree(&bp);
 }
 
+static void alg_ecparam(keyopts *k)
+{
+  static const char *pl[] = { "curve", 0 };
+  if (!copyparam(k, pl)) {
+    ec_info ei;
+    const char *e;
+    key_data *kd = &k->k->k;
+
+    /* --- Decide on a curve --- */
+
+    if (!k->bits) k->bits = 256;
+    if (!k->curve) {
+      if (k->bits <= 56) k->curve = "secp112r1";
+      else if (k->bits <= 64) k->curve = "secp128r1";
+      else if (k->bits <= 80) k->curve = "secp160r1";
+      else if (k->bits <= 96) k->curve = "secp192r1";
+      else if (k->bits <= 112) k->curve = "secp224r1";
+      else if (k->bits <= 128) k->curve = "secp256r1";
+      else if (k->bits <= 192) k->curve = "secp384r1";
+      else if (k->bits <= 256) k->curve = "secp521r1";
+      else
+       die(EXIT_FAILURE, "no built-in curves provide %u-bit security",
+           k->bits);
+    }
+
+    /* --- Check it --- */
+
+    if ((e = ec_getinfo(&ei, k->curve)) != 0)
+      die(EXIT_FAILURE, "error in curve spec: %s", e);
+    if (!(k->f & f_quiet) && (e = ec_checkinfo(&ei, &rand_global)) != 0)
+      moan("WARNING!  curve check failed: %s", e);
+    ec_freeinfo(&ei);
+
+    /* --- Write out the answer --- */
+
+    key_structure(kd);
+    kd = key_structcreate(kd, "curve");
+    key_string(kd, k->curve);
+    kd->e |= KCAT_SHARE;
+  }
+}
+
+static void alg_ec(keyopts *k)
+{
+  key_data *kd = &k->k->k;
+  key_data *kkd;
+  mp *x = MP_NEW;
+  ec p = EC_INIT;
+  const char *e;
+  ec_info ei;
+
+  /* --- Get the curve --- */
+
+  alg_ecparam(k);
+  if ((kkd = key_structfind(kd, "curve")) == 0)
+    die(EXIT_FAILURE, "unexpected failure looking up subkey `curve')");
+  if ((kkd->e & KF_ENCMASK) != KENC_STRING)
+    die(EXIT_FAILURE, "subkey `curve' is not a string");
+  if ((e = ec_getinfo(&ei, kkd->u.p)) != 0)
+    die(EXIT_FAILURE, "error in curve spec: %s", e);
+
+  /* --- Invent a private exponent and compute the public key --- */
+
+  x = mprand_range(MP_NEWSEC, ei.r, &rand_global, 0);
+  ec_mul(ei.c, &p, &ei.g, x);
+
+  /* --- Store everything away --- */
+
+  kkd = key_structcreate(kd, "p");
+  key_ec(kkd, &p);
+  kkd->e |= KCAT_PUB;
+  kkd = key_structcreate(kd, "private");
+  key_structure(kkd);
+  mpkey(kkd, "x", x, KCAT_PRIV | KF_BURN);
+
+  /* --- Done --- */
+
+  ec_freeinfo(&ei);
+  mp_drop(x);
+}
+
 /* --- The algorithm tables --- */
 
 typedef struct keyalg {
@@ -708,6 +796,8 @@ static keyalg algtab[] = {
   { "dh",              alg_dh,         "Diffie-Hellman key exchange" },
   { "dh-param",                alg_dhparam,    "Diffie-Hellman parameters" },
   { "bbs",             alg_bbs,        "Blum-Blum-Shub generator" },
+  { "ec-param",                alg_ecparam,    "Elliptic curve parameters" },
+  { "ec",              alg_ec,         "Elliptic curve crypto" },
   { 0,                 0 }
 };
 
@@ -735,13 +825,14 @@ static int cmd_add(int argc, char *argv[])
       { "comment",     OPTF_ARGREQ,    0,      'c' },
       { "tag",         OPTF_ARGREQ,    0,      't' },
       { "rand-id",     OPTF_ARGREQ,    0,      'R' },
+      { "curve",       OPTF_ARGREQ,    0,      'C' },
       { "lock",                0,              0,      'l' },
       { "quiet",       0,              0,      'q' },
       { "lim-lee",     0,              0,      'L' },
       { "subgroup",    0,              0,      'S' },
       { 0,             0,              0,      0 }
     };
-    int i = mdwopt(argc, argv, "+a:b:B:p:e:c:t:R:lqrLS", opt, 0, 0, 0);
+    int i = mdwopt(argc, argv, "+a:b:B:p:e:c:t:R:C:lqrLS", opt, 0, 0, 0);
     if (i < 0)
       break;
 
@@ -819,6 +910,19 @@ static int cmd_add(int argc, char *argv[])
        c = optarg;
        break;
 
+      /* --- Elliptic curve parameters --- */
+
+      case 'C':
+       if (strcmp(optarg, "list") == 0) {
+         const ecentry *ee;
+         printf("Built-in elliptic curves:\n");
+         for (ee = ectab; ee->name; ee++)
+           printf("  %s\n", ee->name);
+         exit(0);
+       }
+       k.curve = optarg;
+       break;
+
       /* --- Store tags --- */
 
       case 't':
@@ -1035,6 +1139,20 @@ static void showkeydata(key_data *k, int ind, listopts *o, dstr *d)
       putchar('\n');
       break;
 
+    /* --- Strings --- */
+
+    case KENC_STRING:
+      printf(" `%s'\n", k->u.p);
+      break;
+
+    /* --- Elliptic curve points --- */
+
+    case KENC_EC:
+      fputs(" 0x", stdout); mp_writefile(k->u.e.x, stdout, 16);
+      fputs(", 0x", stdout); mp_writefile(k->u.e.y, stdout, 16);
+      putchar('\n');
+      break;      
+
     /* --- Structured keys --- *
      *
      * Just iterate over the subkeys.
@@ -1623,6 +1741,7 @@ Options:\n\
 -b, --bits=N           Generate an N-bit key.\n\
 -B, --qbits=N          Use an N-bit subgroup or factors.\n\
 -p, --parameters=TAG   Get group parameters from TAG.\n\
+-C, --curve=CURVE      Use elliptic curve CURVE.\n\
 -e, --expire=TIME      Make the key expire after TIME.\n\
 -c, --comment=STRING   Attach the command STRING to the key.\n\
 -t, --tag=TAG          Tag the key with the name TAG.\n\