From 1ba83484ee5bb486da9aa958576de4bc29ef0c1d Mon Sep 17 00:00:00 2001 From: mdw Date: Sun, 28 Mar 2004 01:58:47 +0000 Subject: [PATCH] Generate, store and retreive elliptic curve keys. --- Makefile.m4 | 10 +++-- ec-fetch.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++ ec-keys.h | 83 +++++++++++++++++++++++++++++++++++++++ key-binary.c | 57 ++++++++++++++++++++++++++- key-data.c | 57 ++++++++++++++++++++++++++- key-data.h | 39 ++++++++++++++++++- key-flags.c | 7 +++- key-pack.c | 17 +++++++- key-text.c | 69 ++++++++++++++++++++++++++++++++- keyutil.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 10 files changed, 550 insertions(+), 13 deletions(-) create mode 100644 ec-fetch.c create mode 100644 ec-keys.h diff --git a/Makefile.m4 b/Makefile.m4 index 15bf6bb..c6885f1 100644 --- a/Makefile.m4 +++ b/Makefile.m4 @@ -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 index 0000000..ed7faa7 --- /dev/null +++ b/ec-fetch.c @@ -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 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 diff --git a/key-binary.c b/key-binary.c index 79712e1..c05adee 100644 --- a/key-binary.c +++ b/key-binary.c @@ -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; diff --git a/key-data.c b/key-data.c index 2a57cf2..494e9c8 100644 --- a/key-data.c +++ b/key-data.c @@ -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: { diff --git a/key-data.h b/key-data.h index 4ee99aa..4eb8845 100644 --- a/key-data.h +++ b/key-data.h @@ -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. * @@ -57,6 +60,10 @@ # 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 diff --git a/key-flags.c b/key-flags.c index 7840462..b225ba1 100644 --- a/key-flags.c +++ b/key-flags.c @@ -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 --- */ diff --git a/key-pack.c b/key-pack.c index e6f2825..575fd93 100644 --- a/key-pack.c +++ b/key-pack.c @@ -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 --- */ diff --git a/key-text.c b/key-text.c index 238c571..60a1822 100644 --- a/key-text.c +++ b/key-text.c @@ -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 #include #include +#include #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; diff --git a/keyutil.c b/keyutil.c index 1871c1a..0911021 100644 --- 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. * @@ -108,6 +111,9 @@ #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\ -- 2.11.0