X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/b2a72eca5851cfbd4146dd7e65867cd939b8f623..4155aec42e2aa48af1ebe8f1197f58e2f5830ccf:/server/keymgmt.c?ds=sidebyside diff --git a/server/keymgmt.c b/server/keymgmt.c index 0ef633c0..d80b81e8 100644 --- a/server/keymgmt.c +++ b/server/keymgmt.c @@ -42,135 +42,124 @@ typedef struct kgops { int (*loadpub)(key_data *, kdata *, dstr *, dstr *); } kgops; -/* --- Diffie-Hellman --- */ - -static int kgdh_priv(key_data *d, kdata *kd, dstr *t, dstr *e) -{ - key_packstruct kps[DH_PRIVFETCHSZ]; - key_packdef *kp; - dh_priv dp; - int rc; - - kp = key_fetchinit(dh_privfetch, kps, &dp); - if ((rc = key_unpack(kp, d, t)) != 0) { - a_format(e, "unpack-failed", "%s", key_strerror(rc), A_END); - goto fail_0; - } - kd->g = group_prime(&dp.dp); - kd->kpriv = MP_COPY(dp.x); - rc = 0; - goto done; -fail_0: - rc = -1; -done: - key_fetchdone(kp); - return (rc); -} - -static int kgdh_pub(key_data *d, kdata *kd, dstr *t, dstr *e) -{ - key_packstruct kps[DH_PUBFETCHSZ]; - key_packdef *kp; - dh_pub dp; - int rc; - - kp = key_fetchinit(dh_pubfetch, kps, &dp); - if ((rc = key_unpack(kp, d, t)) != 0) { - a_format(e, "unpack-failed", "%s", key_strerror(rc), A_END); - goto fail_0; - } - kd->g = group_prime(&dp.dp); - kd->kpub = G_CREATE(kd->g); - if (G_FROMINT(kd->g, kd->kpub, dp.y)) { - a_format(e, "bad-public-vector", A_END); - goto fail_1; - } - rc = 0; - goto done; -fail_1: - G_DESTROY(kd->g, kd->kpub); - G_DESTROYGROUP(kd->g); -fail_0: - rc = -1; -done: - key_fetchdone(kp); - return (rc); -} - -static const kgops kgdh_ops = { "dh", kgdh_priv, kgdh_pub }; - -/* --- Elliptic curve --- */ - -static int kgec_priv(key_data *d, kdata *kd, dstr *t, dstr *e) -{ - key_packstruct kps[EC_PRIVFETCHSZ]; - key_packdef *kp; - ec_priv ep; - ec_info ei; - const char *err; - int rc; +/* --- @KLOAD@ --- * + * + * Arguments: @ty@, @TY@ = key type name (lower- and upper-case) + * @which@, @WHICH@ = `pub' or `priv' (and upper-case) + * @setgroup@ = code to initialize @kd->g@ + * @setpriv@ = code to initialize @kd->kpriv@ + * @setpub@ = code to initialize @kd->kpub@ + * + * Use: Generates the body of one of the (rather tedious) key loading + * functions. See the description of @KEYTYPES@ below for the + * details. + */ - kp = key_fetchinit(ec_privfetch, kps, &ep); - if ((rc = key_unpack(kp, d, t)) != 0) { - a_format(e, "unpack-failed", "%s", key_strerror(rc), A_END); - goto fail_0; - } - if ((err = ec_getinfo(&ei, ep.cstr)) != 0) { - a_format(e, "decode-failed", "%s", err, A_END); - goto fail_0; - } - kd->g = group_ec(&ei); - kd->kpriv = MP_COPY(ep.x); - rc = 0; - goto done; -fail_0: - rc = -1; -done: - key_fetchdone(kp); - return (rc); +#define KLOAD(ty, TY, which, WHICH, setgroup, setpriv, setpub) \ +static int kg##ty##_##which(key_data *d, kdata *kd, dstr *t, dstr *e) \ +{ \ + key_packstruct kps[TY##_##WHICH##FETCHSZ]; \ + key_packdef *kp; \ + ty##_##which p; \ + int rc; \ + \ + /* --- Initialize things we've not set up yet --- */ \ + \ + kd->g = 0; kd->kpub = 0; \ + \ + /* --- Unpack the key --- */ \ + \ + kp = key_fetchinit(ty##_##which##fetch, kps, &p); \ + if ((rc = key_unpack(kp, d, t)) != 0) { \ + a_format(e, "unpack-failed", "%s", key_strerror(rc), A_END); \ + goto fail; \ + } \ + \ + /* --- Extract the pieces of the key --- */ \ + \ + setgroup; \ + setpriv; \ + kd->kpub = G_CREATE(kd->g); \ + setpub; \ + \ + /* --- We win --- */ \ + \ + rc = 0; \ + goto done; \ + \ +fail: \ + if (kd->kpub) G_DESTROY(kd->g, kd->kpub); \ + if (kd->g) G_DESTROYGROUP(kd->g); \ + rc = -1; \ + \ +done: \ + key_fetchdone(kp); \ + return (rc); \ } -static int kgec_pub(key_data *d, kdata *kd, dstr *t, dstr *e) -{ - key_packstruct kps[EC_PUBFETCHSZ]; - key_packdef *kp; - ec_pub ep; - ec_info ei; - const char *err; - int rc; +/* --- @KEYTYPES@ --- * + * + * A list of the various key types, and how to unpack them. Each entry in + * the list has the form + * + * _(ty, TY, setgroup, setpriv, setpub) + * + * The @ty@ and @TY@ are lower- and upper-case versions of the key type name, + * and there should be @key_fetchdef@s called @ty_{priv,pub}fetch@. + * + * The @setgroup@, @setpriv@ and @setpub@ items are code fragments which are + * passed to @KLOAD@ to build appropriate key-loading methods. By the time + * these code fragments are run, the key has been unpacked from the incoming + * key data using @ty_whichfetch@ into a @ty_which@ structure named @p@. + * They can report errors by writing an appropriate token sequence to @e@ and + * jumping to @fail@. + */ - kp = key_fetchinit(ec_pubfetch, kps, &ep); - if ((rc = key_unpack(kp, d, t)) != 0) { - a_format(e, "unpack-failed", "%s", key_strerror(rc), A_END); - goto fail_0; - } - if ((err = ec_getinfo(&ei, ep.cstr)) != 0) { - a_format(e, "decode-failed", "%s", err, A_END); - goto fail_0; - } - kd->g = group_ec(&ei); - kd->kpub = G_CREATE(kd->g); - if (G_FROMEC(kd->g, kd->kpub, &ep.p)) { - a_format(e, "bad-public-vector", A_END); - goto fail_1; - } - rc = 0; - goto done; -fail_1: - G_DESTROY(kd->g, kd->kpub); - G_DESTROYGROUP(kd->g); -fail_0: - rc = -1; -done: - key_fetchdone(kp); - return (rc); -} +#define KEYTYPES(_) \ + \ + /* --- Diffie-Hellman --- */ \ + \ + _(dh, DH, \ + { kd->g = group_prime(&p.dp); }, \ + { kd->kpriv = MP_COPY(p.x); }, \ + { if (G_FROMINT(kd->g, kd->kpub, p.y)) { \ + a_format(e, "bad-public-vector", A_END); \ + goto fail; \ + } \ + }) \ + \ + /* --- Elliptic curves --- */ \ + \ + _(ec, EC, \ + { ec_info ei; const char *err; \ + if ((err = ec_getinfo(&ei, p.cstr)) != 0) { \ + a_format(e, "decode-failed", "%s", err, A_END); \ + goto fail; \ + } \ + kd->g = group_ec(&ei); \ + }, \ + { kd->kpriv = MP_COPY(p.x); }, \ + { if (G_FROMEC(kd->g, kd->kpub, &p.p)) { \ + a_format(e, "bad-public-vector", A_END); \ + goto fail; \ + } \ + }) -static const kgops kgec_ops = { "ec", kgec_priv, kgec_pub }; +#define KEYTYPE_DEF(ty, TY, setgroup, setpriv, setpub) \ + KLOAD(ty, TY, priv, PRIV, setgroup, setpriv, \ + { G_EXP(kd->g, kd->kpub, kd->g->g, kd->kpriv); }) \ + KLOAD(ty, TY, pub, PUB, setgroup, { }, setpub) \ + static const kgops kg##ty##_ops = { #ty, kg##ty##_priv, kg##ty##_pub }; +KEYTYPES(KEYTYPE_DEF) /* --- Table of supported key types --- */ -static const kgops *kgtab[] = { &kgdh_ops, &kgec_ops, 0 }; +static const kgops *kgtab[] = { +#define KEYTYPE_ENTRY(ty, TY, setgroup, setpriv, setpub) &kg##ty##_ops, + KEYTYPES(KEYTYPE_ENTRY) +#undef KEYTYPE_ENTRY + 0 +}; /*----- Algswitch stuff ---------------------------------------------------*/ @@ -404,12 +393,11 @@ static int kh_loadpriv(const kgops *ko, key_data *d, kdata *kd, a_format(e, "bad-group", "%s", err, A_END); goto fail_1; } - kd->kpub = G_CREATE(kd->g); - G_EXP(kd->g, kd->kpub, kd->g->g, kd->kpriv); return (0); fail_1: mp_drop(kd->kpriv); + G_DESTROY(kd->g, kd->kpub); G_DESTROYGROUP(kd->g); fail_0: return (-1);