Generate, store and retreive elliptic curve keys.
authormdw <mdw>
Sun, 28 Mar 2004 01:58:47 +0000 (01:58 +0000)
committermdw <mdw>
Sun, 28 Mar 2004 01:58:47 +0000 (01:58 +0000)
Makefile.m4
ec-fetch.c [new file with mode: 0644]
ec-keys.h [new file with mode: 0644]
key-binary.c
key-data.c
key-data.h
key-flags.c
key-pack.c
key-text.c
keyutil.c

index 15bf6bb..c6885f1 100644 (file)
@@ -1,6 +1,6 @@
 ## -*-m4-*-
 ##
-## $Id: Makefile.m4,v 1.73 2004/03/27 18:38:00 mdw Exp $
+## $Id: Makefile.m4,v 1.74 2004/03/28 01:58:47 mdw Exp $
 ##
 ## Makefile for Catacomb
 ##
@@ -29,6 +29,9 @@
 ##----- Revision history ----------------------------------------------------
 ##
 ## $Log: Makefile.m4,v $
+## Revision 1.74  2004/03/28 01:58:47  mdw
+## Generate, store and retreive elliptic curve keys.
+##
 ## Revision 1.73  2004/03/27 18:38:00  mdw
 ## Fix distribution.
 ##
@@ -371,7 +374,7 @@ pkginclude_HEADERS = \
        oaep.h pkcs1.h pss.h tlsprf.h sslprf.h \
        gfshare.h share.h \
        rho.h \
-       field.h ec.h ec-exp.h ec-test.h \
+       field.h ec.h ec-exp.h ec-test.h ectab.h ec-keys.h \
        allwithsuffix(`ciphers', `cipher_modes', `.h') \
        allwithsuffix(`hashes', `hash_modes', `.h') \
        addsuffix(`cipher_modes', `-def.h') \
@@ -396,7 +399,8 @@ define(`GF_SOURCES',
 
 define(`EC_SOURCES',
        `field.c field-parse.c f-prime.c f-niceprime.c f-binpoly.c \
-       ec.c ec-prime.c ec-bin.c ec-test.c ec-info.c ectab.c ectab.h')
+       ec.c ec-prime.c ec-bin.c ec-test.c ec-info.c ectab.c \
+       ec-fetch.c')
 
 define(`PGEN_SOURCES',
        `pfilt.c rabin.c \
diff --git a/ec-fetch.c b/ec-fetch.c
new file mode 100644 (file)
index 0000000..ed7faa7
--- /dev/null
@@ -0,0 +1,99 @@
+/* -*-c-*-
+ *
+ * $Id: ec-fetch.c,v 1.1 2004/03/28 01:58:47 mdw Exp $
+ *
+ * Key fetching for elliptic curve public and private keys
+ *
+ * (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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: ec-fetch.c,v $
+ * Revision 1.1  2004/03/28 01:58:47  mdw
+ * Generate, store and retreive elliptic curve keys.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "ec-keys.h"
+#include "key.h"
+
+/*----- Key fetching ------------------------------------------------------*/
+
+const key_fetchdef ec_paramfetch[] = {
+  { "curve",   offsetof(ec_pub, cstr),         KENC_STRING,    0 },
+  { 0,         0,                              0,              0 }
+};
+
+const key_fetchdef ec_pubfetch[] = {
+  { "curve",   offsetof(ec_pub, cstr),         KENC_STRING,    0 },
+  { "p",       offsetof(ec_pub, p),            KENC_EC,        0 },
+  { 0,         0,                              0,              0 }
+};
+
+static const key_fetchdef priv[] = {
+  { "x",       offsetof(ec_priv, x),           KENC_MP,        0 },
+  { 0,         0,                              0,              0 }
+};
+
+const key_fetchdef ec_privfetch[] = {
+  { "curve",   offsetof(ec_pub, cstr),         KENC_STRING,    0 },
+  { "p",       offsetof(ec_pub, p),            KENC_EC,        0 },
+  { "private", 0,                              KENC_STRUCT,    priv },
+  { 0,         0,                              0,              0 }  
+};
+
+/* --- @ec_paramfree@, @ec_pubfree@, @ec_privfree@ --- *
+ *
+ * Arguments:  @ec_param *ep@, @ec_pub *ep@, @ec_priv *ep@ = pointer to
+ *                     key block to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees an elliptic curve key block
+ */
+
+void ec_paramfree(ec_param *ep)
+{
+  if (ep->ei.c) ec_freeinfo(&ep->ei);
+  xfree(ep->cstr);
+}
+
+void ec_pubfree(ec_pub *ep)
+{
+  if (ep->ei.c) ec_freeinfo(&ep->ei);
+  xfree(ep->cstr);
+  EC_DESTROY(&ep->p);
+}
+
+void ec_privfree(ec_priv *ep)
+{
+  if (ep->ei.c) ec_freeinfo(&ep->ei);
+  xfree(ep->cstr);
+  EC_DESTROY(&ep->p);
+  mp_drop(ep->x);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/ec-keys.h b/ec-keys.h
new file mode 100644 (file)
index 0000000..847bc6a
--- /dev/null
+++ b/ec-keys.h
@@ -0,0 +1,83 @@
+/* -*-c-*-
+ *
+ * $Id: ec-keys.h,v 1.1 2004/03/28 01:58:47 mdw Exp $
+ *
+ * Elliptic curve key-fetching
+ *
+ * (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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: ec-keys.h,v $
+ * Revision 1.1  2004/03/28 01:58:47  mdw
+ * Generate, store and retreive elliptic curve keys.
+ *
+ */
+
+#ifndef CATACOMB_EC_KEYS_H
+#define CATACOMB_EC_KEYS_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_EC_H
+#  include "ec.h"
+#endif
+
+#ifndef CATACOMB_KEY_H
+#  include "key.h"
+#endif
+
+/*----- Key structures ----------------------------------------------------*/
+
+typedef struct ec_param {
+  ec_info ei;                          /* Curve information */
+  char *cstr;                          /* Curve definition string */
+} ec_param;
+
+typedef struct ec_pub {
+  ec_info ei;                          /* Curve information */
+  char *cstr;                          /* Curve definition string */
+  ec p;                                        /* Public point */
+} ec_pub;
+
+typedef struct ec_priv {
+  ec_info ei;                          /* Curve information */
+  char *cstr;                          /* Curve definition string */
+  ec p;                                        /* Public point */
+  mp *x;                               /* Secret exponent */
+} ec_priv;
+
+extern const key_fetchdef ec_paramfetch[], ec_pubfetch[], ec_privfetch[];
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
index 79712e1..c05adee 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: key-binary.c,v 1.3 2001/02/03 11:57:00 mdw Exp $
+ * $Id: key-binary.c,v 1.4 2004/03/28 01:58:47 mdw Exp $
  *
  * Key binary encoding
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: key-binary.c,v $
+ * Revision 1.4  2004/03/28 01:58:47  mdw
+ * Generate, store and retreive elliptic curve keys.
+ *
  * Revision 1.3  2001/02/03 11:57:00  mdw
  * Track mLib change: symbols no longer need to include a terminating
  * null.
@@ -107,6 +110,28 @@ int key_decode(const void *p, size_t sz, key_data *k)
       k->u.m = mp_loadb(k->e & KF_BURN ? MP_NEWSEC : MP_NEW, q + 4, psz);
       break;
 
+    /* --- String data --- */
+
+    case KENC_STRING:
+      k->u.p = xmalloc(sz + 1);
+      memcpy(k->u.p, q + 4, sz);
+      k->u.p[sz] = 0;
+      break;
+
+    /* --- Elliptic curve point data --- */
+
+    case KENC_EC: {
+      size_t xsz, ysz;
+      if (sz < 2) return (-1);
+      xsz = LOAD16(q + 4);
+      if (sz < xsz + 4) return (-1);
+      ysz = LOAD16(q + 6 + xsz);
+      if (sz < xsz + ysz + 4) return (-1);
+      EC_CREATE(&k->u.e);
+      k->u.e.x = mp_loadb(MP_NEW, q + 6, xsz);
+      k->u.e.y = mp_loadb(MP_NEW, q + 6 + xsz, ysz);
+    } break;
+
     /* --- Structured key data --- */
 
     case KENC_STRUCT: {
@@ -216,6 +241,36 @@ int key_encode(key_data *k, dstr *d, const key_filter *kf)
       rc = 1;
     } break;
 
+    case KENC_STRING: {
+      char *p;
+      size_t sz = strlen(k->u.p);
+
+      DENSURE(d, (sz + 7) & ~3);
+      p = d->buf + d->len;
+      STORE16(p, k->e);
+      STORE16(p + 2, sz);
+      memcpy(p + 4, k->u.p, sz);
+      d->len += sz + 4;
+      rc = 1;
+    } break;
+
+    case KENC_EC: {
+      char *p;
+      size_t xsz = mp_octets(k->u.e.x), ysz = mp_octets(k->u.e.y);
+      size_t sz = xsz + ysz + 4;
+
+      DENSURE(d, (sz + 7) & ~3);
+      p = d->buf + d->len;
+      STORE16(p, k->e);
+      STORE16(p + 2, sz);
+      STORE16(p + 4, xsz);
+      mp_storeb(k->u.e.x, p + 6, xsz);
+      STORE16(p + 6 + xsz, ysz);
+      mp_storeb(k->u.e.y, p + 8 + xsz, ysz);
+      d->len += sz + 4;
+      rc = 1;
+    } break;
+
     case KENC_STRUCT: {
       size_t n;
       char *p;
index 2a57cf2..494e9c8 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: key-data.c,v 1.4 2000/07/16 19:51:58 mdw Exp $
+ * $Id: key-data.c,v 1.5 2004/03/28 01:58:47 mdw Exp $
  *
  * Encoding and decoding of key data
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: key-data.c,v $
+ * Revision 1.5  2004/03/28 01:58:47  mdw
+ * Generate, store and retreive elliptic curve keys.
+ *
  * Revision 1.4  2000/07/16 19:51:58  mdw
  * Shut stupid compiler up.
  *
@@ -117,6 +120,39 @@ void key_mp(key_data *k, mp *m)
   k->u.m = MP_COPY(m);
 }
 
+/* --- @key_string@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const char *p@ = pointer to the value to set
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets a plain string in a key block.
+ */
+
+void key_string(key_data *k, const char *p)
+{
+  k->e = (k->e & ~KF_ENCMASK) | KENC_STRING;
+  k->u.p = xstrdup(p);
+}
+
+/* --- @key_ec@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const ec *e@ = pointer to the value to set
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets an elliptic curve point in a key block.
+ */
+
+void key_ec(key_data *k, const ec *e)
+{
+  k->e = (k->e & ~KF_ENCMASK) | KENC_EC;
+  EC_CREATE(&k->u.e);
+  EC_COPY(&k->u.e, e);
+}
+
 /* --- @key_structure@ --- *
  *
  * Arguments:  @key_data *k@ = pointer to key data block
@@ -199,6 +235,12 @@ void key_destroy(key_data *k)
     case KENC_MP:
       mp_drop(k->u.m);
       break;
+    case KENC_STRING:
+      xfree(k->u.p);
+      break;
+    case KENC_EC:
+      EC_DESTROY(&k->u.e);
+      break;
     case KENC_STRUCT: {
       sym_iter i;
       key_struct *ks;
@@ -287,6 +329,19 @@ int key_copy(key_data *kd, key_data *k, const key_filter *kf)
       kd->u.m = MP_COPY(k->u.m);
       break;
 
+    /* --- Strings --- */
+
+    case KENC_STRING:
+      kd->u.p = xstrdup(k->u.p);
+      break;
+
+    /* --- Elliptic curve points --- */
+
+    case KENC_EC:
+      EC_CREATE(&kd->u.e);
+      EC_COPY(&kd->u.e, &k->u.e);
+      break;
+
     /* --- Structured key data --- */
 
     case KENC_STRUCT: {
index 4ee99aa..4eb8845 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: key-data.h,v 1.2 2000/06/17 11:26:18 mdw Exp $
+ * $Id: key-data.h,v 1.3 2004/03/28 01:58:47 mdw Exp $
  *
  * Manipulating key data
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: key-data.h,v $
+ * Revision 1.3  2004/03/28 01:58:47  mdw
+ * Generate, store and retreive elliptic curve keys.
+ *
  * Revision 1.2  2000/06/17 11:26:18  mdw
  * Add the key packing interface.
  *
 #  include "mp.h"
 #endif
 
+#ifndef CATACOMB_EC_H
+#  include "ec.h"
+#endif
+
 /*----- Data structures ---------------------------------------------------*/
 
 /* --- Key binary data --- */
@@ -74,6 +81,8 @@ typedef struct key_data {
     key_bin k;                         /* Binary key data */
     mp *m;                             /* Multiprecision integer */
     sym_table s;                       /* Structured key data */
+    char *p;                           /* String pointer */
+    ec e;                              /* Elliptic curve point */
   } u;
 } key_data;
 
@@ -118,11 +127,13 @@ enum {
 
   /* --- Bottom two bits are the encoding type --- */
 
-  KF_ENCMASK   = 0x03,                 /* Encoding mask */
+  KF_ENCMASK   = 0x83,                 /* Encoding mask */
   KENC_BINARY  = 0x00,                 /* Plain binary key (@k@) */
   KENC_MP      = 0x01,                 /* Multiprecision integer (@i@) */
   KENC_STRUCT  = 0x02,                 /* Structured key data (@s@) */
   KENC_ENCRYPT = 0x03,                 /* Encrypted key type (@k@) */
+  KENC_STRING  = 0x80,                 /* ASCII string (@p@) */
+  KENC_EC      = 0x81,                 /* Elliptic curve point (@e@) */
 
   /* --- Key category bits --- */
 
@@ -239,6 +250,30 @@ extern void key_encrypted(key_data */*k*/, const void */*p*/, size_t /*sz*/);
 
 extern void key_mp(key_data */*k*/, mp */*m*/);
 
+/* --- @key_string@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const char *p@ = pointer to the value to set
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets a plain string in a key block.
+ */
+
+extern void key_string(key_data */*k*/, const char */*p*/);
+
+/* --- @key_ec@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const ec *e@ = pointer to the value to set
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets an elliptic curve point in a key block.
+ */
+
+extern void key_ec(key_data */*k*/, const ec */*e*/);
+
 /* --- @key_structure@ --- *
  *
  * Arguments:  @key_data *k@ = pointer to key data block
index 7840462..b225ba1 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: key-flags.c,v 1.2 2000/02/12 18:21:02 mdw Exp $
+ * $Id: key-flags.c,v 1.3 2004/03/28 01:58:47 mdw Exp $
  *
  * Reading and writing key flag strings
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: key-flags.c,v $
+ * Revision 1.3  2004/03/28 01:58:47  mdw
+ * Generate, store and retreive elliptic curve keys.
+ *
  * Revision 1.2  2000/02/12 18:21:02  mdw
  * Overhaul of key management (again).
  *
@@ -71,6 +74,8 @@ static flagent flagtab[] = {
   { "integer",         KENC_MP,        KF_ENCMASK },
   { "struct",          KENC_STRUCT,    KF_ENCMASK },
   { "encrypt",         KENC_ENCRYPT,   KF_ENCMASK },
+  { "string",          KENC_STRING,    KF_ENCMASK },
+  { "ec",              KENC_EC,        KF_ENCMASK },
 
   /* --- Classes of keys --- */
 
index e6f2825..575fd93 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: key-pack.c,v 1.1 2000/06/17 10:42:41 mdw Exp $
+ * $Id: key-pack.c,v 1.2 2004/03/28 01:58:47 mdw Exp $
  *
  * Packing and unpacking key data
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: key-pack.c,v $
+ * Revision 1.2  2004/03/28 01:58:47  mdw
+ * Generate, store and retreive elliptic curve keys.
+ *
  * Revision 1.1  2000/06/17 10:42:41  mdw
  * Packing and unpacking structured keys.
  *
@@ -67,6 +70,12 @@ int key_pack(key_packdef *kp, key_data *kd, dstr *d)
     case KENC_MP:
       kd->u.m = *(mp **)kp->p;
       return (0);
+    case KENC_STRING:
+      kd->u.p = *(char **)kp->p;
+      return (0);
+    case KENC_EC:
+      kd->u.e = *(ec *)kp->p;
+      return (0);
 
     /* --- Encrypted keys are a little tricky --- *
      *
@@ -161,6 +170,12 @@ int key_unpack(key_packdef *kp, key_data *kd, dstr *d)
     case KENC_MP:
       *(mp **)kp->p = kd->u.m;
       break;
+    case KENC_STRING:
+      *(char **)kp->p = kd->u.p;
+      break;
+    case KENC_EC:
+      *(ec *)kp->p = kd->u.e;
+      break;
 
     /* --- Structured keys take a little care --- */
 
index 238c571..60a1822 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: key-text.c,v 1.3 2001/02/03 11:57:00 mdw Exp $
+ * $Id: key-text.c,v 1.4 2004/03/28 01:58:47 mdw Exp $
  *
  * Key textual encoding
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: key-text.c,v $
+ * Revision 1.4  2004/03/28 01:58:47  mdw
+ * Generate, store and retreive elliptic curve keys.
+ *
  * Revision 1.3  2001/02/03 11:57:00  mdw
  * Track mLib change: symbols no longer need to include a terminating
  * null.
@@ -52,6 +55,7 @@
 #include <mLib/dstr.h>
 #include <mLib/sub.h>
 #include <mLib/sym.h>
+#include <mLib/url.h>
 
 #include "key-data.h"
 #include "mp.h"
@@ -131,6 +135,51 @@ int key_read(const char *p, key_data *k, char **pp)
       p = q;
     } break;
 
+    /* --- String encoding --- *
+     *
+     * We use form-urlencoding to ensure that evil characters don't get out.
+     */
+
+    case KENC_STRING: {
+      dstr d = DSTR_INIT;
+      size_t sz = strcspn(p, ",]");
+      const char *l = p + sz;
+      unsigned int ch;
+      int x, n;
+
+      while (p < l) {
+       switch (*p) {
+         case '+':
+           DPUTC(&d, ' '); break;
+         case '%':
+           x = sscanf(p + 1, "%2x%n", &ch, &n);
+           if (x == 1) { DPUTC(&d, ch); p += n; break; }
+         default:
+           DPUTC(&d, *p); break;
+       }
+       p++;
+      }
+      DPUTZ(&d);
+      k->u.p = xstrdup(d.buf);
+      dstr_destroy(&d);
+    } break;
+
+    /* --- Elliptic curve encoding --- *
+     *
+     * Again, we have a convenient function.  Assume for now that points
+     * aren't secret.  (Reasonably safe.)
+     */
+
+    case KENC_EC: {
+      qd_parse qd;
+      qd.p = p;
+      qd.e = 0;
+      EC_CREATE(&k->u.e);
+      if (!ec_ptparse(&qd, &k->u.e))
+       return (-1);
+      p = qd.p;
+    } break;
+
     /* --- Structured information encoding --- *
      *
      * The format for structured key data is `[NAME=KEY,...]', where the
@@ -276,6 +325,24 @@ int key_write(key_data *k, dstr *d, const key_filter *kf)
       mp_writedstr(k->u.m, d, 10);
       rc = 1;
       break;
+    case KENC_STRING: {
+      const char *p = k->u.p;
+      key_writeflags(k->e, d);
+      DPUTC(d, ':');
+      while (*p) {
+       if (*p == ' ') DPUTC(d, '+');
+       else if (!isalnum((unsigned char)*p)) dstr_putf(d, "%%%02x", *p);
+       else DPUTC(d, *p);
+       p++;
+      }
+      rc = 1;
+    } break;
+    case KENC_EC:
+      key_writeflags(k->e, d);
+      DPUTS(d, ":0x"); mp_writedstr(k->u.e.x, d, 16);
+      DPUTS(d, ",0x"); mp_writedstr(k->u.e.y, d, 16);
+      rc = 1;
+      break;
     case KENC_STRUCT: {
       sym_iter i;
       key_struct *ks;
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\