X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/1ba83484ee5bb486da9aa958576de4bc29ef0c1d..59919ae4b1721ca271c3d3e5955c09d322573821:/keyutil.c diff --git a/keyutil.c b/keyutil.c index 0911021..025c8f2 100644 --- a/keyutil.c +++ b/keyutil.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: keyutil.c,v 1.17 2004/03/28 01:58:47 mdw Exp $ + * $Id: keyutil.c,v 1.22 2004/04/03 15:45:06 mdw Exp $ * * Simple key manager program * @@ -30,6 +30,25 @@ /*----- Revision history --------------------------------------------------* * * $Log: keyutil.c,v $ + * Revision 1.22 2004/04/03 15:45:06 mdw + * Oops. Fix formatting. :-S + * + * Revision 1.21 2004/04/03 15:15:19 mdw + * Fix stupid error in previous rashly-committed version. + * + * Revision 1.20 2004/04/03 15:14:28 mdw + * Handle points at infinity properly in listings. + * + * Revision 1.19 2004/04/03 03:31:01 mdw + * Allow explicit group parameters for DH groups. + * + * Revision 1.18 2004/04/01 12:50:09 mdw + * Add cyclic group abstraction, with test code. Separate off exponentation + * functions for better static linking. Fix a buttload of bugs on the way. + * Generally ensure that negative exponents do inversion correctly. Add + * table of standard prime-field subgroups. (Binary field subgroups are + * currently unimplemented but easy to add if anyone ever finds a good one.) + * * Revision 1.17 2004/03/28 01:58:47 mdw * Generate, store and retreive elliptic curve keys. * @@ -111,6 +130,7 @@ #include "bbs.h" #include "dh.h" #include "dsa.h" +#include "dsarand.h" #include "ec.h" #include "ec-keys.h" #include "ectab.h" @@ -122,8 +142,22 @@ #include "mprand.h" #include "mptext.h" #include "pgen.h" +#include "ptab.h" #include "rsa.h" +#include "sha-mgf.h" +#include "sha256-mgf.h" +#include "sha224-mgf.h" +#include "sha384-mgf.h" +#include "sha512-mgf.h" +#include "tiger-mgf.h" +#include "rmd128-mgf.h" +#include "rmd160-mgf.h" +#include "rmd256-mgf.h" +#include "rmd320-mgf.h" +#include "md5-mgf.h" +#include "dsarand.h" + /*----- Handy global state ------------------------------------------------*/ static const char *keyfile = "keyring"; @@ -199,6 +233,26 @@ static void setattr(key_file *f, key *k, char *v[]) } } +/*----- Seeding -----------------------------------------------------------*/ + +const struct seedalg { const char *p; grand *(*gen)(const void *, size_t); } +seedtab[] = { + { "dsarand", dsarand_create }, + { "rmd128-mgf", rmd128_mgfrand }, + { "rmd160-mgf", rmd160_mgfrand }, + { "rmd256-mgf", rmd256_mgfrand }, + { "rmd320-mgf", rmd320_mgfrand }, + { "sha-mgf", sha_mgfrand }, + { "sha224-mgf", sha224_mgfrand }, + { "sha256-mgf", sha256_mgfrand }, + { "sha384-mgf", sha384_mgfrand }, + { "sha512-mgf", sha512_mgfrand }, + { "tiger-mgf", tiger_mgfrand }, + { 0, 0 } +}; + +#define SEEDALG_DEFAULT (seedtab + 2) + /*----- Key generation ----------------------------------------------------*/ /* --- Key generation parameters --- */ @@ -210,6 +264,7 @@ typedef struct keyopts { unsigned f; /* Flags for the new key */ unsigned bits, qbits; /* Bit length for the new key */ const char *curve; /* Elliptic curve name/info */ + grand *r; /* Random number source */ key *p; /* Parameters key-data */ } keyopts; @@ -388,7 +443,7 @@ static void alg_binary(keyopts *k) sz = (k->bits + 7) >> 3; p = sub_alloc(sz); m = (1 << (((k->bits - 1) & 7) + 1)) - 1; - rand_get(RAND_GLOBAL, p, sz); + k->r->ops->fill(k->r, p, sz); *p &= m; key_binary(&k->k->k, p, sz); k->k->k.e |= KCAT_SYMM | KF_BURN; @@ -412,7 +467,7 @@ static void alg_des(keyopts *k) sz = k->bits / 7; p = sub_alloc(sz); - rand_get(RAND_GLOBAL, p, sz); /* Too much work done here! */ + k->r->ops->fill(k->r, p, sz); for (i = 0; i < sz; i++) { octet x = p[i] | 0x01; x = x ^ (x >> 4); @@ -441,14 +496,14 @@ static void alg_rsa(keyopts *k) /* --- Generate the RSA parameters --- */ - if (rsa_gen(&rp, k->bits, &rand_global, 0, + if (rsa_gen(&rp, k->bits, k->r, 0, (k->f & f_quiet) ? 0 : pgen_ev, 0)) die(EXIT_FAILURE, "RSA key generation failed"); /* --- Run a test encryption --- */ { - grand *g = fibrand_create(rand_global.ops->word(&rand_global)); + grand *g = fibrand_create(k->r->ops->word(k->r)); rsa_pub rpp; mp *m = mprand_range(MP_NEW, rp.n, g, 0); mp *c; @@ -508,7 +563,7 @@ static void alg_dsaparam(keyopts *k) sz = (k->qbits + 7) >> 3; p = sub_alloc(sz); - rand_get(RAND_GLOBAL, p, sz); + k->r->ops->fill(k->r, p, sz); /* --- Allocate the parameters --- */ @@ -559,7 +614,7 @@ static void alg_dsa(keyopts *k) /* --- Choose a private key --- */ - x = mprand_range(MP_NEWSEC, q, &rand_global, 0); + x = mprand_range(MP_NEWSEC, q, k->r, 0); mpmont_create(&mm, p); y = mpmont_exp(&mm, MP_NEW, g, x); @@ -578,11 +633,27 @@ static void alg_dsa(keyopts *k) static void alg_dhparam(keyopts *k) { static const char *pl[] = { "p", "q", "g", 0 }; + key_data *kd = &k->k->k; if (!copyparam(k, pl)) { dh_param dp; - key_data *kd = &k->k->k; int rc; + if (k->curve) { + qd_parse qd; + + if (strcmp(k->curve, "list") == 0) { + const pentry *pe; + printf("Built-in prime groups:\n"); + for (pe = ptab; pe->name; pe++) + printf(" %s\n", pe->name); + exit(0); + } + qd.p = k->curve; + if (dh_parse(&qd, &dp)) + die(EXIT_FAILURE, "error in group spec: %s", qd.e); + goto done; + } + if (!k->bits) k->bits = 1024; @@ -595,7 +666,7 @@ static void alg_dhparam(keyopts *k) k->qbits = 256; rc = dh_limlee(&dp, k->qbits, k->bits, (k->f & f_subgroup) ? DH_SUBGROUP : 0, - 0, &rand_global, (k->f & f_quiet) ? 0 : pgen_ev, 0, + 0, k->r, (k->f & f_quiet) ? 0 : pgen_ev, 0, (k->f & f_quiet) ? 0 : pgen_evspin, 0, &nf, &f); if (!rc) { dstr d = DSTR_INIT; @@ -610,12 +681,13 @@ static void alg_dhparam(keyopts *k) dstr_destroy(&d); } } else - rc = dh_gen(&dp, k->qbits, k->bits, 0, &rand_global, + rc = dh_gen(&dp, k->qbits, k->bits, 0, k->r, (k->f & f_quiet) ? 0 : pgen_ev, 0); if (rc) die(EXIT_FAILURE, "Diffie-Hellman parameter generation failed"); + done: key_structure(kd); mpkey(kd, "p", dp.p, KCAT_SHARE); mpkey(kd, "q", dp.q, KCAT_SHARE); @@ -623,7 +695,7 @@ static void alg_dhparam(keyopts *k) mp_drop(dp.q); mp_drop(dp.p); mp_drop(dp.g); - } + } } static void alg_dh(keyopts *k) @@ -645,7 +717,7 @@ static void alg_dh(keyopts *k) * Since %$g$% has order %$q$%, choose %$x < q$%. */ - x = mprand_range(MP_NEWSEC, q, &rand_global, 0); + x = mprand_range(MP_NEWSEC, q, k->r, 0); /* --- Compute the public key %$y = g^x \bmod p$% --- */ @@ -679,7 +751,7 @@ static void alg_bbs(keyopts *k) /* --- Generate the BBS parameters --- */ - if (bbs_gen(&bp, k->bits, &rand_global, 0, + if (bbs_gen(&bp, k->bits, k->r, 0, (k->f & f_quiet) ? 0 : pgen_ev, 0)) die(EXIT_FAILURE, "Blum-Blum-Shub key generation failed"); @@ -709,6 +781,13 @@ static void alg_ecparam(keyopts *k) /* --- Decide on a curve --- */ if (!k->bits) k->bits = 256; + if (k->curve && strcmp(k->curve, "list") == 0) { + const ecentry *ee; + printf("Built-in elliptic curves:\n"); + for (ee = ectab; ee->name; ee++) + printf(" %s\n", ee->name); + exit(0); + } if (!k->curve) { if (k->bits <= 56) k->curve = "secp112r1"; else if (k->bits <= 64) k->curve = "secp128r1"; @@ -727,7 +806,7 @@ static void alg_ecparam(keyopts *k) 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) + if (!(k->f & f_quiet) && (e = ec_checkinfo(&ei, k->r)) != 0) moan("WARNING! curve check failed: %s", e); ec_freeinfo(&ei); @@ -761,7 +840,7 @@ static void alg_ec(keyopts *k) /* --- Invent a private exponent and compute the public key --- */ - x = mprand_range(MP_NEWSEC, ei.r, &rand_global, 0); + x = mprand_range(MP_NEWSEC, ei.r, k->r, 0); ec_mul(ei.c, &p, &ei.g, x); /* --- Store everything away --- */ @@ -811,7 +890,10 @@ static int cmd_add(int argc, char *argv[]) const char *c = 0; keyalg *alg = algtab; const char *rtag = 0; - keyopts k = { 0, 0, DSTR_INIT, 0, 0, 0, 0 }; + const struct seedalg *sa = SEEDALG_DEFAULT; + keyopts k = { 0, 0, DSTR_INIT, 0, 0, 0, 0, 0 }; + const char *seed = 0; + k.r = &rand_global; /* --- Parse options for the subcommand --- */ @@ -826,13 +908,17 @@ static int cmd_add(int argc, char *argv[]) { "tag", OPTF_ARGREQ, 0, 't' }, { "rand-id", OPTF_ARGREQ, 0, 'R' }, { "curve", OPTF_ARGREQ, 0, 'C' }, + { "seedalg", OPTF_ARGREQ, 0, 'A' }, + { "seed", OPTF_ARGREQ, 0, 's' }, + { "newseed", OPTF_ARGREQ, 0, 'n' }, { "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:C:lqrLS", opt, 0, 0, 0); + int i = mdwopt(argc, argv, "+a:b:B:p:e:c:t:R:C:A:s:n:lqrLS", + opt, 0, 0, 0); if (i < 0) break; @@ -913,13 +999,6 @@ static int cmd_add(int argc, char *argv[]) /* --- 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; @@ -934,6 +1013,56 @@ static int cmd_add(int argc, char *argv[]) k.f |= f_retag; break; + /* --- Seeding --- */ + + case 'A': { + const struct seedalg *ss; + if (strcmp(optarg, "list") == 0) { + printf("Seed algorithms:\n"); + for (ss = seedtab; ss->p; ss++) + printf(" %s\n", ss->p); + exit(0); + } + if (seed) die(EXIT_FAILURE, "seed already set -- put -A first"); + sa = 0; + for (ss = seedtab; ss->p; ss++) { + if (strcmp(optarg, ss->p) == 0) + sa = ss; + } + if (!sa) + die(EXIT_FAILURE, "seed algorithm `%s' not known", optarg); + } break; + + case 's': { + base64_ctx b; + dstr d = DSTR_INIT; + if (seed) die(EXIT_FAILURE, "seed already set"); + base64_init(&b); + base64_decode(&b, optarg, strlen(optarg), &d); + base64_decode(&b, 0, 0, &d); + k.r = sa->gen(d.buf, d.len); + seed = optarg; + dstr_destroy(&d); + } break; + + case 'n': { + base64_ctx b; + dstr d = DSTR_INIT; + char *p; + unsigned n = strtoul(optarg, &p, 0); + if (n == 0 || *p != 0 || n % 8 != 0) + die(EXIT_FAILURE, "bad seed length `%s'", optarg); + if (seed) die(EXIT_FAILURE, "seed already set"); + n /= 8; + p = xmalloc(n); + rand_get(RAND_GLOBAL, p, n); + base64_init(&b); + base64_encode(&b, p, n, &d); + base64_encode(&b, 0, 0, &d); + seed = d.buf; + k.r = sa->gen(p, n); + } break; + /* --- Other flags --- */ case 'R': @@ -1016,6 +1145,10 @@ static int cmd_add(int argc, char *argv[]) } setattr(&f, k.k, argv + optind + 1); + if (seed) { + key_putattr(&f, k.k, "genseed", seed); + key_putattr(&f, k.k, "seedalg", sa->p); + } key_fulltag(k.k, &k.tag); @@ -1148,9 +1281,13 @@ static void showkeydata(key_data *k, int ind, listopts *o, dstr *d) /* --- 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'); + if (EC_ATINF(&k->u.e)) + fputs(" inf\n", stdout); + else { + 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 --- *