X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/1ba83484ee5bb486da9aa958576de4bc29ef0c1d..34e4f738bcba58e6d8c4cabbb0b3232a65b42a9d:/keyutil.c diff --git a/keyutil.c b/keyutil.c index 0911021..1619707 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.18 2004/04/01 12:50:09 mdw Exp $ * * Simple key manager program * @@ -30,6 +30,13 @@ /*----- Revision history --------------------------------------------------* * * $Log: keyutil.c,v $ + * 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 +118,7 @@ #include "bbs.h" #include "dh.h" #include "dsa.h" +#include "dsarand.h" #include "ec.h" #include "ec-keys.h" #include "ectab.h" @@ -124,6 +132,19 @@ #include "pgen.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 +220,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 +251,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 +430,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 +454,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 +483,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 +550,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 +601,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,9 +620,9 @@ 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->bits) @@ -595,7 +637,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,7 +652,7 @@ 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) @@ -623,7 +665,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 +687,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 +721,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"); @@ -727,7 +769,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 +803,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 +853,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 +871,16 @@ 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; @@ -934,6 +982,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 +1114,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);