X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/e4a509b8174c8b2cfc0a084b78c9c7b7d08b624b..ef13e9a46baaa347014ac236f36a2536f055b108:/keyutil.c diff --git a/keyutil.c b/keyutil.c index 3be95b3..1d4bbca 100644 --- a/keyutil.c +++ b/keyutil.c @@ -201,7 +201,7 @@ typedef struct keyopts { /* --- @dolock@ --- * * * Arguments: @keyopts *k@ = key generation options - * @key_data *kd@ = pointer to key data to lock + * @key_data **kd@ = pointer to key data to lock * @const char *t@ = tag suffix or null * * Returns: --- @@ -209,35 +209,16 @@ typedef struct keyopts { * Use: Does passphrase locking on new keys. */ -static void dolock(keyopts *k, key_data *kd, const char *t) +static void dolock(keyopts *k, key_data **kd, const char *t) { if (!(k->f & f_lock)) return; if (t) dstr_putf(&k->tag, ".%s", t); - if (key_plock(k->tag.buf, kd, kd)) + if (key_plock(kd, 0, k->tag.buf)) die(EXIT_FAILURE, "couldn't lock key"); } -/* --- @mpkey@ --- * - * - * Arguments: @key_data *kd@ = pointer to parent key block - * @const char *tag@ = pointer to tag string - * @mp *m@ = integer to store - * @unsigned f@ = flags to set - * - * Returns: --- - * - * Use: Sets a multiprecision integer subkey. - */ - -static void mpkey(key_data *kd, const char *tag, mp *m, unsigned f) -{ - key_data *kkd = key_structcreate(kd, tag); - key_mp(kkd, m); - kkd->e |= f; -} - /* --- @copyparam@ --- * * * Arguments: @keyopts *k@ = pointer to key options @@ -263,7 +244,7 @@ static int copyparam(keyopts *k, const char **pp) /* --- Run through the checklist --- */ while (*pp) { - key_data *kd = key_structfind(&k->p->k, *pp); + key_data *kd = key_structfind(k->p->k, *pp); if (!kd) die(EXIT_FAILURE, "bad parameter key: parameter `%s' not found", *pp); if ((kd->e & KF_CATMASK) != KCAT_SHARE) @@ -275,8 +256,7 @@ static int copyparam(keyopts *k, const char **pp) kf.f = KCAT_SHARE; kf.m = KF_CATMASK; - if (!key_copy(&k->k->k, &k->p->k, &kf)) - die(EXIT_FAILURE, "unexpected failure while copying parameters"); + key_setkeydata(k->kf, k->k, k->p->k); /* --- Copy over attributes --- */ @@ -331,7 +311,8 @@ static void keyrand(key_file *kf, const char *id) k = key_bytype(kf, "catacomb-rand"); if (k) { - key_data *kd = &k->k, kkd; + key_data *kd = k->k, *kkd; + key_incref(kd); again: switch (kd->e & KF_ENCMASK) { @@ -340,10 +321,11 @@ static void keyrand(key_file *kf, const char *id) case KENC_ENCRYPT: { dstr d = DSTR_INIT; key_fulltag(k, &d); - if (key_punlock(d.buf, kd, &kkd)) + if (key_punlock(&kkd, kd, d.buf)) die(EXIT_FAILURE, "error unlocking key `%s'", d.buf); dstr_destroy(&d); - kd = &kkd; + key_drop(kd); + kd = kkd; } goto again; default: { dstr d = DSTR_INIT; @@ -355,8 +337,7 @@ static void keyrand(key_file *kf, const char *id) /* --- Key the generator --- */ rand_key(RAND_GLOBAL, kd->u.k.k, kd->u.k.sz); - if (kd == &kkd) - key_destroy(&kkd); + key_drop(kd); } } @@ -366,6 +347,7 @@ static void alg_binary(keyopts *k) { unsigned sz; unsigned m; + key_data *kd; octet *p; if (!k->bits) @@ -378,17 +360,19 @@ static void alg_binary(keyopts *k) m = (1 << (((k->bits - 1) & 7) + 1)) - 1; 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; + kd = key_newbinary(KCAT_SYMM | KF_BURN, p, sz); memset(p, 0, sz); + dolock(k, &kd, 0); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); sub_free(p, sz); - dolock(k, &k->k->k, 0); } static void alg_des(keyopts *k) { unsigned sz; octet *p; + key_data *kd; int i; if (!k->bits) @@ -408,17 +392,18 @@ static void alg_des(keyopts *k) x = x ^ (x >> 1); p[i] = (p[i] & 0xfe) | (x & 0x01); } - key_binary(&k->k->k, p, sz); - k->k->k.e |= KCAT_SYMM | KF_BURN; + kd = key_newbinary(KCAT_SYMM | KF_BURN, p, sz); memset(p, 0, sz); + dolock(k, &kd, 0); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); sub_free(p, sz); - dolock(k, &k->k->k, 0); } static void alg_rsa(keyopts *k) { rsa_priv rp; - key_data *kd; + key_data *kd, *kkd; /* --- Sanity checking --- */ @@ -455,21 +440,21 @@ static void alg_rsa(keyopts *k) /* --- Allrighty then --- */ - kd = &k->k->k; - key_structure(kd); - mpkey(kd, "n", rp.n, KCAT_PUB); - mpkey(kd, "e", rp.e, KCAT_PUB); - - kd = key_structcreate(kd, "private"); - key_structure(kd); - mpkey(kd, "d", rp.d, KCAT_PRIV | KF_BURN); - mpkey(kd, "p", rp.p, KCAT_PRIV | KF_BURN); - mpkey(kd, "q", rp.q, KCAT_PRIV | KF_BURN); - mpkey(kd, "q-inv", rp.q_inv, KCAT_PRIV | KF_BURN); - mpkey(kd, "d-mod-p", rp.dp, KCAT_PRIV | KF_BURN); - mpkey(kd, "d-mod-q", rp.dq, KCAT_PRIV | KF_BURN); - dolock(k, kd, "private"); - + kd = key_newstruct(); + key_structsteal(kd, "n", key_newmp(KCAT_PUB, rp.n)); + key_structsteal(kd, "e", key_newmp(KCAT_PUB, rp.e)); + + kkd = key_newstruct(); + key_structsteal(kkd, "d", key_newmp(KCAT_PRIV | KF_BURN, rp.d)); + key_structsteal(kkd, "p", key_newmp(KCAT_PRIV | KF_BURN, rp.p)); + key_structsteal(kkd, "q", key_newmp(KCAT_PRIV | KF_BURN, rp.q)); + key_structsteal(kkd, "q-inv", key_newmp(KCAT_PRIV | KF_BURN, rp.q_inv)); + key_structsteal(kkd, "d-mod-p", key_newmp(KCAT_PRIV | KF_BURN, rp.dp)); + key_structsteal(kkd, "d-mod-q", key_newmp(KCAT_PRIV | KF_BURN, rp.dq)); + dolock(k, &kkd, "private"); + key_structsteal(kd, "private", kkd); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); rsa_privfree(&rp); } @@ -482,7 +467,7 @@ static void alg_dsaparam(keyopts *k) size_t sz; dstr d = DSTR_INIT; base64_ctx c; - key_data *kd = &k->k->k; + key_data *kd; dsa_seed ds; /* --- Choose appropriate bit lengths if necessary --- */ @@ -490,7 +475,7 @@ static void alg_dsaparam(keyopts *k) if (!k->qbits) k->qbits = 160; if (!k->bits) - k->bits = 768; + k->bits = 1024; /* --- Allocate a seed block --- */ @@ -506,13 +491,15 @@ static void alg_dsaparam(keyopts *k) /* --- Store the parameters --- */ - key_structure(kd); - mpkey(kd, "q", dp.q, KCAT_SHARE); - mpkey(kd, "p", dp.p, KCAT_SHARE); - mpkey(kd, "g", dp.g, KCAT_SHARE); + kd = key_newstruct(); + key_structsteal(kd, "q", key_newmp(KCAT_SHARE, dp.q)); + key_structsteal(kd, "p", key_newmp(KCAT_SHARE, dp.p)); + key_structsteal(kd, "g", key_newmp(KCAT_SHARE, dp.g)); mp_drop(dp.q); mp_drop(dp.p); mp_drop(dp.g); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); /* --- Store the seed for future verification --- */ @@ -521,6 +508,7 @@ static void alg_dsaparam(keyopts *k) c.indent = ""; base64_encode(&c, ds.p, ds.sz, &d); base64_encode(&c, 0, 0, &d); + DPUTZ(&d); key_putattr(k->kf, k->k, "seed", d.buf); DRESET(&d); dstr_putf(&d, "%u", ds.count); @@ -536,11 +524,12 @@ static void alg_dsa(keyopts *k) mp *q, *p, *g; mp *x, *y; mpmont mm; - key_data *kd = &k->k->k; + key_data *kd, *kkd; /* --- Get the shared parameters --- */ alg_dsaparam(k); + key_split(&k->k->k); kd = k->k->k; q = getmp(kd, "q"); p = getmp(kd, "p"); g = getmp(kd, "g"); @@ -553,12 +542,12 @@ static void alg_dsa(keyopts *k) /* --- Store everything away --- */ - mpkey(kd, "y", y, KCAT_PUB); + key_structsteal(kd, "y", key_newmp(KCAT_PUB, y)); - kd = key_structcreate(kd, "private"); - key_structure(kd); - mpkey(kd, "x", x, KCAT_PRIV | KF_BURN); - dolock(k, kd, "private"); + kkd = key_newstruct(); + key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x)); + dolock(k, &kkd, "private"); + key_structsteal(kd, "private", kkd); mp_drop(x); mp_drop(y); } @@ -566,7 +555,7 @@ 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; + key_data *kd; if (!copyparam(k, pl)) { dh_param dp; int rc; @@ -628,13 +617,15 @@ static void alg_dhparam(keyopts *k) 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); - mpkey(kd, "g", dp.g, KCAT_SHARE); + kd = key_newstruct(); + key_structsteal(kd, "p", key_newmp(KCAT_SHARE, dp.p)); + key_structsteal(kd, "q", key_newmp(KCAT_SHARE, dp.q)); + key_structsteal(kd, "g", key_newmp(KCAT_SHARE, dp.g)); mp_drop(dp.q); mp_drop(dp.p); mp_drop(dp.g); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); } } @@ -643,11 +634,12 @@ static void alg_dh(keyopts *k) mp *x, *y; mp *p, *q, *g; mpmont mm; - key_data *kd = &k->k->k; + key_data *kd, *kkd; /* --- Get the shared parameters --- */ alg_dhparam(k); + key_split(&k->k->k); kd = k->k->k; p = getmp(kd, "p"); q = getmp(kd, "q"); g = getmp(kd, "g"); @@ -667,12 +659,12 @@ static void alg_dh(keyopts *k) /* --- Store everything away --- */ - mpkey(kd, "y", y, KCAT_PUB); + key_structsteal(kd, "y", key_newmp(KCAT_PUB, y)); - kd = key_structcreate(kd, "private"); - key_structure(kd); - mpkey(kd, "x", x, KCAT_PRIV | KF_BURN); - dolock(k, kd, "private"); + kkd = key_newstruct(); + key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x)); + dolock(k, &kkd, "private"); + key_structsteal(kd, "private", kkd); mp_drop(x); mp_drop(y); } @@ -680,7 +672,7 @@ static void alg_dh(keyopts *k) static void alg_bbs(keyopts *k) { bbs_priv bp; - key_data *kd; + key_data *kd, *kkd; /* --- Sanity checking --- */ @@ -697,15 +689,16 @@ static void alg_bbs(keyopts *k) /* --- Allrighty then --- */ - kd = &k->k->k; - key_structure(kd); - mpkey(kd, "n", bp.n, KCAT_PUB); + kd = key_newstruct(); + key_structsteal(kd, "n", key_newmp(KCAT_PUB, bp.n)); - kd = key_structcreate(kd, "private"); - key_structure(kd); - mpkey(kd, "p", bp.p, KCAT_PRIV | KF_BURN); - mpkey(kd, "q", bp.q, KCAT_PRIV | KF_BURN); - dolock(k, kd, "private"); + kkd = key_newstruct(); + key_structsteal(kkd, "p", key_newmp(KCAT_PRIV | KF_BURN, bp.p)); + key_structsteal(kkd, "q", key_newmp(KCAT_PRIV | KF_BURN, bp.q)); + dolock(k, &kkd, "private"); + key_structsteal(kd, "private", kkd); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); bbs_privfree(&bp); } @@ -718,7 +711,7 @@ static void alg_binparam(keyopts *k) qd_parse qd; group *g; const char *e; - key_data *kd = &k->k->k; + key_data *kd; /* --- Decide on a field --- */ @@ -759,13 +752,15 @@ static void alg_binparam(keyopts *k) /* --- Write out the answer --- */ - key_structure(kd); - mpkey(kd, "p", gb.p, KCAT_SHARE); - mpkey(kd, "q", gb.q, KCAT_SHARE); - mpkey(kd, "g", gb.g, KCAT_SHARE); + kd = key_newstruct(); + key_structsteal(kd, "p", key_newmp(KCAT_SHARE, gb.p)); + key_structsteal(kd, "q", key_newmp(KCAT_SHARE, gb.q)); + key_structsteal(kd, "g", key_newmp(KCAT_SHARE, gb.g)); mp_drop(gb.q); mp_drop(gb.p); mp_drop(gb.g); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); } } @@ -774,11 +769,12 @@ static void alg_bin(keyopts *k) mp *x, *y; mp *p, *q, *g; gfreduce r; - key_data *kd = &k->k->k; + key_data *kd, *kkd; /* --- Get the shared parameters --- */ alg_binparam(k); + key_split(&k->k->k); kd = k->k->k; p = getmp(kd, "p"); q = getmp(kd, "q"); g = getmp(kd, "g"); @@ -798,12 +794,12 @@ static void alg_bin(keyopts *k) /* --- Store everything away --- */ - mpkey(kd, "y", y, KCAT_PUB); + key_structsteal(kd, "y", key_newmp(KCAT_PUB, y)); - kd = key_structcreate(kd, "private"); - key_structure(kd); - mpkey(kd, "x", x, KCAT_PRIV | KF_BURN); - dolock(k, kd, "private"); + kkd = key_newstruct(); + key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x)); + dolock(k, &kkd, "private"); + key_structsteal(kd, "private", kkd); mp_drop(x); mp_drop(y); } @@ -814,7 +810,7 @@ static void alg_ecparam(keyopts *k) if (!copyparam(k, pl)) { ec_info ei; const char *e; - key_data *kd = &k->k->k; + key_data *kd; /* --- Decide on a curve --- */ @@ -849,16 +845,16 @@ static void alg_ecparam(keyopts *k) /* --- Write out the answer --- */ - key_structure(kd); - kd = key_structcreate(kd, "curve"); - key_string(kd, k->curve); - kd->e |= KCAT_SHARE; + kd = key_newstruct(); + key_structsteal(kd, "curve", key_newstring(KCAT_SHARE, k->curve)); + key_setkeydata(k->kf, k->k, kd); + key_drop(kd); } } static void alg_ec(keyopts *k) { - key_data *kd = &k->k->k; + key_data *kd; key_data *kkd; mp *x = MP_NEW; ec p = EC_INIT; @@ -868,6 +864,7 @@ static void alg_ec(keyopts *k) /* --- Get the curve --- */ alg_ecparam(k); + key_split(&k->k->k); kd = k->k->k; if ((kkd = key_structfind(kd, "curve")) == 0) die(EXIT_FAILURE, "unexpected failure looking up subkey `curve')"); if ((kkd->e & KF_ENCMASK) != KENC_STRING) @@ -882,13 +879,12 @@ static void alg_ec(keyopts *k) /* --- 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); - dolock(k, kkd, "private"); + key_structsteal(kd, "p", key_newec(KCAT_PUB, &p)); + + kkd = key_newstruct(); + key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x)); + dolock(k, &kkd, "private"); + key_structsteal(kd, "private", kkd); /* --- Done --- */ @@ -1158,10 +1154,9 @@ static int cmd_add(int argc, char *argv[]) for (;;) { uint32 id = rand_global.ops->word(&rand_global); int err; - k.k = key_new(&f, id, argv[optind], exp, &err); - if (k.k) + if ((err = key_new(&f, id, argv[optind], exp, &k.k)) == 0) break; - if (err != KERR_DUPID) + else if (err != KERR_DUPID) die(EXIT_FAILURE, "error adding new key: %s", key_strerror(err)); } @@ -1197,7 +1192,7 @@ static int cmd_add(int argc, char *argv[]) if (ptag) { if ((k.p = key_bytag(&f, ptag)) == 0) die(EXIT_FAILURE, "parameter key `%s' not found", ptag); - if ((k.p->k.e & KF_ENCMASK) != KENC_STRUCT) + if ((k.p->k->e & KF_ENCMASK) != KENC_STRUCT) die(EXIT_FAILURE, "parameter key `%s' is not structured", ptag); } @@ -1207,6 +1202,7 @@ static int cmd_add(int argc, char *argv[]) /* --- Done --- */ + dstr_destroy(&k.tag); doclose(&f); return (0); } @@ -1289,13 +1285,13 @@ static void showkeydata(key_data *k, int ind, listopts *o, dstr *d) if (o->v <= 3) fputs(" encrypted\n", stdout); else { - key_data kd; - if (key_punlock(d->buf, k, &kd)) + key_data *kd; + if (key_punlock(&kd, k, d->buf)) printf(" \n", d->buf); else { fputs(" encrypted", stdout); - showkeydata(&kd, ind, o, d); - key_destroy(&kd); + showkeydata(kd, ind, o, d); + key_drop(kd); } } break; @@ -1336,19 +1332,19 @@ static void showkeydata(key_data *k, int ind, listopts *o, dstr *d) */ case KENC_STRUCT: { - sym_iter i; - key_struct *ks; + key_subkeyiter i; + const char *tag; size_t n = d->len; fputs(" {\n", stdout); - for (sym_mkiter(&i, &k->u.s); (ks = sym_next(&i)) != 0; ) { - if (!key_match(&ks->k, &o->kf)) + for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) { + if (!key_match(k, &o->kf)) continue; INDENT(ind + 2); - printf("%s =", SYM_NAME(ks)); + printf("%s =", tag); d->len = n; - dstr_putf(d, ".%s", SYM_NAME(ks)); - showkeydata(&ks->k, ind + 2, o, d); + dstr_putf(d, ".%s", tag); + showkeydata(k, ind + 2, o, d); } INDENT(ind); fputs("}\n", stdout); @@ -1375,7 +1371,7 @@ static void showkey(key *k, listopts *o) /* --- Skip the key if the filter doesn't match --- */ - if (!key_match(&k->k, &o->kf)) + if (!key_match(k->k, &o->kf)) return; /* --- Sort out the expiry and deletion times --- */ @@ -1447,7 +1443,7 @@ static void showkey(key *k, listopts *o) dstr d = DSTR_INIT; fputs("key:", stdout); key_fulltag(k, &d); - showkeydata(&k->k, 0, o, &d); + showkeydata(k->k, 0, o, &d); dstr_destroy(&d); } @@ -1860,7 +1856,7 @@ static int cmd_lock(int argc, char *argv[]) { key_file f; key *k; - key_data *kd; + key_data **kd; dstr d = DSTR_INIT; if (argc != 2) @@ -1868,9 +1864,9 @@ static int cmd_lock(int argc, char *argv[]) doopen(&f, KOPEN_WRITE); if (key_qtag(&f, argv[1], &d, &k, &kd)) die(EXIT_FAILURE, "key `%s' not found", argv[1]); - if (kd->e == KENC_ENCRYPT && key_punlock(d.buf, kd, kd)) + if ((*kd)->e == KENC_ENCRYPT && key_punlock(kd, 0, d.buf)) die(EXIT_FAILURE, "couldn't unlock key `%s'", d.buf); - if (key_plock(d.buf, kd, kd)) + if (key_plock(kd, 0, d.buf)) die(EXIT_FAILURE, "failed to lock key `%s'", d.buf); f.f |= KF_MODIFIED; doclose(&f); @@ -1883,7 +1879,7 @@ static int cmd_unlock(int argc, char *argv[]) { key_file f; key *k; - key_data *kd; + key_data **kd; dstr d = DSTR_INIT; if (argc != 2) @@ -1891,9 +1887,9 @@ static int cmd_unlock(int argc, char *argv[]) doopen(&f, KOPEN_WRITE); if (key_qtag(&f, argv[1], &d, &k, &kd)) die(EXIT_FAILURE, "key `%s' not found", argv[1]); - if (kd->e != KENC_ENCRYPT) + if ((*kd)->e != KENC_ENCRYPT) die(EXIT_FAILURE, "key `%s' is not encrypted", d.buf); - if (kd->e == KENC_ENCRYPT && key_punlock(d.buf, kd, kd)) + if (key_punlock(kd, 0, d.buf)) die(EXIT_FAILURE, "couldn't unlock key `%s'", d.buf); f.f |= KF_MODIFIED; doclose(&f);