X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/7532e25e9f8a4347274d62f8fdeffe227afe849e..c81b29e0a7b1c0ee0b3299a39dafe480f16159ef:/progs/key.c diff --git a/progs/key.c b/progs/key.c index 29cc1b7a..9c9466b8 100644 --- a/progs/key.c +++ b/progs/key.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -63,12 +64,17 @@ #include "gfreduce.h" #include "key.h" #include "mp.h" +#include "mpint.h" #include "mpmont.h" #include "mprand.h" #include "mptext.h" #include "pgen.h" #include "ptab.h" #include "rsa.h" +#include "x25519.h" +#include "x448.h" +#include "ed25519.h" +#include "ed448.h" #include "cc.h" #include "sha-mgf.h" @@ -193,6 +199,7 @@ typedef struct keyopts { unsigned bits, qbits; /* Bit length for the new key */ const char *curve; /* Elliptic curve name/info */ grand *r; /* Random number source */ + mp *e; /* Public exponent */ key *p; /* Parameters key-data */ } keyopts; @@ -440,11 +447,15 @@ static void alg_rsa(keyopts *k) copyparam(k, 0); if (!k->bits) k->bits = 1024; + if (k->bits < 64) + die(EXIT_FAILURE, "RSA key too tiny"); + if (!k->e) + k->e = mp_fromulong(MP_NEW, 65537); /* --- Generate the RSA parameters --- */ - if (rsa_gen(&rp, k->bits, k->r, 0, - (k->f & f_quiet) ? 0 : pgen_ev, 0)) + if (rsa_gen_e(&rp, k->bits, k->e, k->r, 0, + (k->f & f_quiet) ? 0 : pgen_ev, 0)) die(EXIT_FAILURE, "RSA key generation failed"); /* --- Run a test encryption --- */ @@ -592,7 +603,7 @@ static void alg_dhparam(keyopts *k) group *g; const char *e; - if (strcmp(k->curve, "list") == 0) { + if (STRCMP(k->curve, ==, "list")) { unsigned i, w; LIST("Built-in prime fields", stdout, ptab[i].name, ptab[i].name); exit(0); @@ -760,7 +771,7 @@ static void alg_binparam(keyopts *k) /* --- Decide on a field --- */ if (!k->bits) k->bits = 128; - if (k->curve && strcmp(k->curve, "list") == 0) { + if (k->curve && STRCMP(k->curve, ==, "list")) { unsigned i, w; LIST("Built-in binary fields", stdout, bintab[i].name, bintab[i].name); @@ -859,7 +870,7 @@ static void alg_ecparam(keyopts *k) /* --- Decide on a curve --- */ if (!k->bits) k->bits = 256; - if (k->curve && strcmp(k->curve, "list") == 0) { + if (k->curve && STRCMP(k->curve, ==, "list")) { unsigned i, w; LIST("Built-in elliptic curves", stdout, ectab[i].name, ectab[i].name); @@ -936,6 +947,64 @@ static void alg_ec(keyopts *k) mp_drop(x); } +#define XDHS(_) \ + _(x25519, X25519, "X25519") \ + _(x448, X448, "X448") + +#define XDHALG(xdh, XDH, name) \ + \ + static void alg_##xdh(keyopts *k) \ + { \ + key_data *kd, *kkd; \ + octet priv[XDH##_KEYSZ], pub[XDH##_PUBSZ]; \ + \ + copyparam(k, 0); \ + k->r->ops->fill(k->r, priv, sizeof(priv)); \ + xdh(pub, priv, xdh##_base); \ + kkd = key_newstruct(); \ + key_structsteal(kkd, "priv", \ + key_newbinary(KCAT_PRIV | KF_BURN, \ + priv, sizeof(priv))); \ + kd = key_newstruct(); \ + key_structsteal(kd, "private", kkd); \ + key_structsteal(kd, "pub", \ + key_newbinary(KCAT_PUB, pub, sizeof(pub))); \ + \ + key_setkeydata(k->kf, k->k, kd); \ + } + +XDHS(XDHALG) +#undef XDHALG + +#define EDDSAS(_) \ + _(ed25519, ED25519, "Ed25519") \ + _(ed448, ED448, "Ed448") + +#define EDDSAALG(ed, ED, name) \ + \ + static void alg_##ed(keyopts *k) \ + { \ + key_data *kd, *kkd; \ + octet priv[ED##_KEYSZ], pub[ED##_PUBSZ]; \ + \ + copyparam(k, 0); \ + k->r->ops->fill(k->r, priv, sizeof(priv)); \ + ed##_pubkey(pub, priv, sizeof(priv)); \ + kkd = key_newstruct(); \ + key_structsteal(kkd, "priv", \ + key_newbinary(KCAT_PRIV | KF_BURN, \ + priv, sizeof(priv))); \ + kd = key_newstruct(); \ + key_structsteal(kd, "private", kkd); \ + key_structsteal(kd, "pub", \ + key_newbinary(KCAT_PUB, pub, sizeof(pub))); \ + \ + key_setkeydata(k->kf, k->k, kd); \ + } + +EDDSAS(EDDSAALG) +#undef EDDSAALG + /* --- The algorithm tables --- */ typedef struct keyalg { @@ -957,6 +1026,14 @@ static keyalg algtab[] = { { "bindh-param", alg_binparam, "Binary-field DH parameters" }, { "ec-param", alg_ecparam, "Elliptic curve parameters" }, { "ec", alg_ec, "Elliptic curve crypto" }, +#define XDHTAB(xdh, XDH, name) \ + { #xdh, alg_##xdh, "" name " key exchange" }, + XDHS(XDHTAB) +#undef XDHTAB +#define EDDSATAB(ed, ED, name) \ + { #ed, alg_##ed, "" name " digital signatures" }, + EDDSAS(EDDSATAB) +#undef EDDSATAB { "empty", alg_empty, "Empty parametrs-only key" }, { 0, 0 } }; @@ -973,7 +1050,7 @@ static int cmd_add(int argc, char *argv[]) keyalg *alg = algtab; const char *rtag = 0; const struct seedalg *sa = SEEDALG_DEFAULT; - keyopts k = { 0, 0, DSTR_INIT, 0, 0, 0, 0, 0 }; + keyopts k = { 0, 0, DSTR_INIT, 0, 0, 0, 0, 0, 0 }; const char *seed = 0; k.r = &rand_global; @@ -994,6 +1071,7 @@ static int cmd_add(int argc, char *argv[]) { "seedalg", OPTF_ARGREQ, 0, 'A' }, { "seed", OPTF_ARGREQ, 0, 's' }, { "newseed", OPTF_ARGREQ, 0, 'n' }, + { "public-exponent", OPTF_ARGREQ, 0, 'E' }, { "lock", 0, 0, 'l' }, { "quiet", 0, 0, 'q' }, { "lim-lee", 0, 0, 'L' }, @@ -1001,7 +1079,7 @@ static int cmd_add(int argc, char *argv[]) { "kcdsa", 0, 0, 'K' }, { 0, 0, 0, 0 } }; - int i = mdwopt(argc, argv, "+a:b:B:p:e:c:t:R:I:C:A:s:n:lqrLKS", + int i = mdwopt(argc, argv, "+a:b:B:p:e:c:t:R:I:C:A:s:n:E:lqrLKS", opt, 0, 0, 0); if (i < 0) break; @@ -1016,7 +1094,7 @@ static int cmd_add(int argc, char *argv[]) keyalg *a; size_t sz = strlen(optarg); - if (strcmp(optarg, "list") == 0) { + if (STRCMP(optarg, ==, "list")) { for (a = algtab; a->name; a++) printf("%-10s %s\n", a->name, a->help); return (0); @@ -1024,7 +1102,7 @@ static int cmd_add(int argc, char *argv[]) alg = 0; for (a = algtab; a->name; a++) { - if (strncmp(optarg, a->name, sz) == 0) { + if (STRNCMP(optarg, ==, a->name, sz)) { if (a->name[sz] == 0) { alg = a; break; @@ -1063,7 +1141,7 @@ static int cmd_add(int argc, char *argv[]) /* --- Expiry dates get passed to @get_date@ for parsing --- */ case 'e': - if (strcmp(optarg, "forever") == 0) + if (STRCMP(optarg, ==, "forever")) exp = KEXP_FOREVER; else { exp = get_date(optarg, 0); @@ -1101,7 +1179,7 @@ static int cmd_add(int argc, char *argv[]) case 'A': { const struct seedalg *ss; - if (strcmp(optarg, "list") == 0) { + if (STRCMP(optarg, ==, "list")) { printf("Seed algorithms:\n"); for (ss = seedtab; ss->p; ss++) printf(" %s\n", ss->p); @@ -1110,7 +1188,7 @@ static int cmd_add(int argc, char *argv[]) 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) + if (STRCMP(optarg, ==, ss->p)) sa = ss; } if (!sa) @@ -1163,6 +1241,15 @@ static int cmd_add(int argc, char *argv[]) kid = id; } break; + /* --- Public exponent --- */ + + case 'E': { + char *p; + k.e = mp_readstring(k.e, optarg, &p, 0); + if (!k.e || *p || MP_CMP(k.e, <, MP_THREE) || MP_EVENP(k.e)) + die(EXIT_FAILURE, "bad exponent `%s'", optarg); + } break; + /* --- Other flags --- */ case 'R': @@ -1234,7 +1321,7 @@ static int cmd_add(int argc, char *argv[]) if (k.f & f_retag) { if ((kk = key_bytag(&f, tag)) != 0 && kk->tag && - strcmp(kk->tag, tag) == 0) + STRCMP(kk->tag, ==, tag)) key_settag(&f, kk, 0); } if ((err = key_settag(&f, k.k, tag)) != 0) @@ -1739,7 +1826,7 @@ static const struct fpres *lookup_fpres(const char *name) { const struct fpres *fpres; for (fpres = fprestab; fpres->name; fpres++) - if (strcmp(fpres->name, name) == 0) return (fpres); + if (STRCMP(fpres->name, ==, name)) return (fpres); die(EXIT_FAILURE, "unknown presentation syle `%s'", name); } @@ -1784,7 +1871,7 @@ static int cmd_finger(int argc, char *argv[]) argv += optind; argc -= optind; if (rc) { die(EXIT_FAILURE, - "Usage: fingerprint [-a HASHALG] [-p STYLE] [-f FILTER] [TAG...]"); + "Usage: fingerprint [-a HASH] [-p STYLE] [-f FILTER] [TAG...]"); } doopen(&f, KOPEN_READ); @@ -1858,7 +1945,7 @@ static int cmd_verify(int argc, char *argv[]) argv += optind; argc -= optind; if (rc || argc != 2) { die(EXIT_FAILURE, - "Usage: verify [-a HASHALG] [-p STYLE] [-f FILTER] TAG FINGERPRINT"); + "Usage: verify [-a HASH] [-p STYLE] [-f FILTER] TAG FINGERPRINT"); } doopen(&f, KOPEN_READ); @@ -1883,7 +1970,7 @@ static int cmd_verify(int argc, char *argv[]) if (!key_fingerprint(k, h, &kf)) die(EXIT_FAILURE, "key has no fingerprintable components (as filtered)"); fpr = GH_DONE(h, 0); - if (memcmp(fpr, d.buf, ch->hashsz) != 0) + if (MEMCMP(fpr, !=, d.buf, ch->hashsz)) die(EXIT_FAILURE, "key fingerprint mismatch"); dstr_destroy(&d); dstr_destroy(&dd); doclose(&f); @@ -1942,7 +2029,7 @@ static int cmd_tag(int argc, char *argv[]) die(EXIT_FAILURE, "Usage: tag [-r] TAG [NEW-TAG]"); doopen(&f, KOPEN_WRITE); if (flags & f_retag) { - if ((k = key_bytag(&f, argv[1])) != 0 && strcmp(k->tag, argv[1]) == 0) + if ((k = key_bytag(&f, argv[1])) != 0 && STRCMP(k->tag, ==, argv[1])) key_settag(&f, k, 0); } if ((k = key_bytag(&f, argv[0])) == 0) @@ -2036,7 +2123,7 @@ static int cmd_extract(int argc, char *argv[]) argv += optind; argc -= optind; if (rc || argc < 1) die(EXIT_FAILURE, "Usage: extract [-f FILTER] FILE [TAG...]"); - if (strcmp(*argv, "-") == 0) + if (STRCMP(*argv, ==, "-")) fp = stdout; else { outfile = *argv; @@ -2092,7 +2179,7 @@ static int cmd_merge(int argc, char *argv[]) if (argc != 2) die(EXIT_FAILURE, "Usage: merge FILE"); - if (strcmp(argv[1], "-") == 0) + if (STRCMP(argv[1], ==, "-")) fp = stdin; else if (!(fp = fopen(argv[1], "r"))) { die(EXIT_FAILURE, "couldn't open `%s' for reading: %s", @@ -2147,7 +2234,7 @@ Options:\n\ -v, --verbose Show more information.\n\ " }, { "fingerprint", cmd_finger, - "fingerprint [-a HASHALG] [-p STYLE] [-f FILTER] [TAG...]", "\ + "fingerprint [-a HASH] [-p STYLE] [-f FILTER] [TAG...]", "\ Options:\n\ \n\ -f, --filter=FILT Only hash key components matching FILT.\n\