From 593f7bd3b9a9c80fdde181d79ba87d57cae1f1ed Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Thu, 11 May 2017 10:42:15 +0100 Subject: [PATCH] progs/: Generate XDH and EdDSA operations using macros. There are already two very similar XDH implementations, and EdDSA is likely to have more. Let's not write more code than we need to. --- progs/cc-kem.c | 208 +++++++++++++++++++++------------------------------------ progs/cc-sig.c | 116 ++++++++++++++++++-------------- progs/key.c | 116 +++++++++++++++++--------------- 3 files changed, 205 insertions(+), 235 deletions(-) diff --git a/progs/cc-kem.c b/progs/cc-kem.c index 5b0cbf79..cf53eaf1 100644 --- a/progs/cc-kem.c +++ b/progs/cc-kem.c @@ -604,135 +604,79 @@ static const kemops ec_decops = { ec_decinit, dh_decdoit, dh_enccheck, dh_encdestroy }; -/* --- X25519 --- */ - -static kem *x25519_encinit(key *k, void *kd) { return (CREATE(kem)); } -static void x25519_encdestroy(kem *k) { DESTROY(k); } - -static const char *x25519_enccheck(kem *k) -{ - x25519_pub *kd = k->kd; - - if (kd->pub.sz != X25519_PUBSZ) - return ("incorrect X25519 public key length"); - return (0); -} - -static int x25519_encdoit(kem *k, dstr *d, ghash *h) -{ - octet t[X25519_KEYSZ], z[X25519_OUTSZ]; - x25519_pub *kd = k->kd; - - rand_get(RAND_GLOBAL, t, sizeof(t)); - dstr_ensure(d, X25519_PUBSZ); - x25519((octet *)d->buf, t, x25519_base); - x25519(z, t, kd->pub.k); - d->len += X25519_PUBSZ; - GH_HASH(h, d->buf, X25519_PUBSZ); - GH_HASH(h, z, X25519_OUTSZ); - return (0); -} - -static const char *x25519_deccheck(kem *k) -{ - x25519_priv *kd = k->kd; - - if (kd->priv.sz != X25519_KEYSZ) - return ("incorrect X25519 private key length"); - if (kd->pub.sz != X25519_PUBSZ) - return ("incorrect X25519 public key length"); - return (0); -} - -static int x25519_decdoit(kem *k, dstr *d, ghash *h) -{ - octet z[X25519_OUTSZ]; - x25519_priv *kd = k->kd; - int rc = -1; - - if (d->len != X25519_PUBSZ) goto done; - x25519(z, kd->priv.k, (const octet *)d->buf); - GH_HASH(h, d->buf, X25519_PUBSZ); - GH_HASH(h, z, X25519_OUTSZ); - rc = 0; -done: - return (rc); -} - -static const kemops x25519_encops = { - x25519_pubfetch, sizeof(x25519_pub), - x25519_encinit, x25519_encdoit, x25519_enccheck, x25519_encdestroy -}; - -static const kemops x25519_decops = { - x25519_privfetch, sizeof(x25519_priv), - x25519_encinit, x25519_decdoit, x25519_deccheck, x25519_encdestroy -}; - -/* --- X448 --- */ - -static kem *x448_encinit(key *k, void *kd) { return (CREATE(kem)); } -static void x448_encdestroy(kem *k) { DESTROY(k); } - -static const char *x448_enccheck(kem *k) -{ - x448_pub *kd = k->kd; - - if (kd->pub.sz != X448_PUBSZ) - return ("incorrect X448 public key length"); - return (0); -} - -static int x448_encdoit(kem *k, dstr *d, ghash *h) -{ - octet t[X448_KEYSZ], z[X448_OUTSZ]; - x448_pub *kd = k->kd; - - rand_get(RAND_GLOBAL, t, sizeof(t)); - dstr_ensure(d, X448_PUBSZ); - x448((octet *)d->buf, t, x448_base); - x448(z, t, kd->pub.k); - d->len += X448_PUBSZ; - GH_HASH(h, d->buf, X448_PUBSZ); - GH_HASH(h, z, X448_OUTSZ); - return (0); -} - -static const char *x448_deccheck(kem *k) -{ - x448_priv *kd = k->kd; - - if (kd->priv.sz != X448_KEYSZ) - return ("incorrect X448 private key length"); - if (kd->pub.sz != X448_PUBSZ) - return ("incorrect X448 public key length"); - return (0); -} - -static int x448_decdoit(kem *k, dstr *d, ghash *h) -{ - octet z[X448_OUTSZ]; - x448_priv *kd = k->kd; - int rc = -1; - - if (d->len != X448_PUBSZ) goto done; - x448(z, kd->priv.k, (const octet *)d->buf); - GH_HASH(h, d->buf, X448_PUBSZ); - GH_HASH(h, z, X448_OUTSZ); - rc = 0; -done: - return (rc); -} - -static const kemops x448_encops = { - x448_pubfetch, sizeof(x448_pub), - x448_encinit, x448_encdoit, x448_enccheck, x448_encdestroy -}; - -static const kemops x448_decops = { - x448_privfetch, sizeof(x448_priv), - x448_encinit, x448_decdoit, x448_deccheck, x448_encdestroy -}; +/* --- X25519 and similar schemes --- */ + +#define XDHS(_) \ + _(x25519, X25519) \ + _(x448, X448) + +#define XDHDEF(xdh, XDH) \ + \ + static kem *xdh##_encinit(key *k, void *kd) { return (CREATE(kem)); } \ + static void xdh##_encdestroy(kem *k) { DESTROY(k); } \ + \ + static const char *xdh##_enccheck(kem *k) \ + { \ + xdh##_pub *kd = k->kd; \ + \ + if (kd->pub.sz != XDH##_PUBSZ) \ + return ("incorrect " #XDH "public key length"); \ + return (0); \ + } \ + \ + static int xdh##_encdoit(kem *k, dstr *d, ghash *h) \ + { \ + octet t[XDH##_KEYSZ], z[XDH##_OUTSZ]; \ + xdh##_pub *kd = k->kd; \ + \ + rand_get(RAND_GLOBAL, t, sizeof(t)); \ + dstr_ensure(d, XDH##_PUBSZ); \ + xdh((octet *)d->buf, t, xdh##_base); \ + xdh(z, t, kd->pub.k); \ + d->len += XDH##_PUBSZ; \ + GH_HASH(h, d->buf, XDH##_PUBSZ); \ + GH_HASH(h, z, XDH##_OUTSZ); \ + return (0); \ + } \ + \ + static const char *xdh##_deccheck(kem *k) \ + { \ + xdh##_priv *kd = k->kd; \ + \ + if (kd->priv.sz != XDH##_KEYSZ) \ + return ("incorrect " #XDH " private key length"); \ + if (kd->pub.sz != XDH##_PUBSZ) \ + return ("incorrect " #XDH " public key length"); \ + return (0); \ + } \ + \ + static int xdh##_decdoit(kem *k, dstr *d, ghash *h) \ + { \ + octet z[XDH##_OUTSZ]; \ + xdh##_priv *kd = k->kd; \ + int rc = -1; \ + \ + if (d->len != XDH##_PUBSZ) goto done; \ + xdh(z, kd->priv.k, (const octet *)d->buf); \ + GH_HASH(h, d->buf, XDH##_PUBSZ); \ + GH_HASH(h, z, XDH##_OUTSZ); \ + rc = 0; \ + done: \ + return (rc); \ + } \ + \ + static const kemops xdh##_encops = { \ + xdh##_pubfetch, sizeof(xdh##_pub), \ + xdh##_encinit, xdh##_encdoit, xdh##_enccheck, xdh##_encdestroy \ + }; \ + \ + static const kemops xdh##_decops = { \ + xdh##_privfetch, sizeof(xdh##_priv), \ + xdh##_encinit, xdh##_decdoit, xdh##_deccheck, xdh##_encdestroy \ + }; + +XDHS(XDHDEF) +#undef XDHDEF /* --- Symmetric --- */ @@ -802,8 +746,10 @@ const struct kemtab kemtab[] = { { "dh", &dh_encops, &dh_decops }, { "bindh", &bindh_encops, &bindh_decops }, { "ec", &ec_encops, &ec_decops }, - { "x25519", &x25519_encops, &x25519_decops }, - { "x448", &x448_encops, &x448_decops }, +#define XDHTAB(xdh, XDH) \ + { #xdh, &xdh##_encops, &xdh##_decops }, + XDHS(XDHTAB) +#undef XDHTAB { "symm", &symm_encops, &symm_decops }, { 0, 0, 0 } }; diff --git a/progs/cc-sig.c b/progs/cc-sig.c index f14b4b8e..7303c563 100644 --- a/progs/cc-sig.c +++ b/progs/cc-sig.c @@ -574,60 +574,73 @@ static const sigops eckcdsa_vrf = { eckcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy }; -/* --- Ed25519 --- */ +/* --- EdDSA --- */ -static sig *ed25519_siginit(key *k, void *kd, const gchash *hc) - { sig *s = CREATE(sig); s->h = 0; return (s); } +#define EDDSAS(_) \ + _(ed25519, ED25519, "Ed25519", sha512) -static int ed25519_sigdoit(sig *s, dstr *d) +static sig *eddsa_siginit(key *k, void *kd, const gchash *hc) { - ed25519_priv *k = s->kd; - - dstr_ensure(d, ED25519_SIGSZ); - ed25519_sign((octet *)d->buf, k->priv.k, k->priv.sz, k->pub.k, - GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz); - d->len += ED25519_SIGSZ; - return (0); -} - -static const char *ed25519_sigcheck(sig *s) -{ - ed25519_priv *k = s->kd; - - if (k->pub.sz != ED25519_PUBSZ) - return ("incorrect Ed25519 public key length"); - return (0); -} - -static void ed25519_sigdestroy(sig *s) { DESTROY(s); } - -static const sigops ed25519_sig = { - ed25519_privfetch, sizeof(ed25519_priv), - ed25519_siginit, ed25519_sigdoit, ed25519_sigcheck, ed25519_sigdestroy -}; - -static int ed25519_vrfdoit(sig *s, dstr *d) -{ - ed25519_pub *k = s->kd; - - if (d->len != ED25519_SIGSZ) return (-1); - return (ed25519_verify(k->pub.k, GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz, - (const octet *)d->buf)); -} - -static const char *ed25519_vrfcheck(sig *s) -{ - ed25519_pub *k = s->kd; - - if (k->pub.sz != ED25519_PUBSZ) - return ("incorrect Ed25519 public key length"); - return (0); + sig *s = CREATE(sig); + s->h = 0; + return (s); } -static const sigops ed25519_vrf = { - ed25519_pubfetch, sizeof(ed25519_pub), - ed25519_siginit, ed25519_vrfdoit, ed25519_vrfcheck, ed25519_sigdestroy -}; +static void eddsa_sigdestroy(sig *s) { DESTROY(s); } + +#define EDDSADEF(ed, ED, name, hash) \ + \ + static int ed##_sigdoit(sig *s, dstr *d) \ + { \ + ed##_priv *k = s->kd; \ + \ + dstr_ensure(d, ED##_SIGSZ); \ + ed##_sign((octet *)d->buf, k->priv.k, k->priv.sz, k->pub.k, \ + GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz); \ + d->len += ED##_SIGSZ; \ + return (0); \ + } \ + \ + static const char *ed##_sigcheck(sig *s) \ + { \ + ed##_priv *k = s->kd; \ + \ + if (k->pub.sz != ED##_PUBSZ) \ + return ("incorrect " #name " public key length"); \ + return (0); \ + } \ + \ + static const sigops ed##_sig = { \ + ed##_privfetch, sizeof(ed##_priv), \ + eddsa_siginit, ed##_sigdoit, ed##_sigcheck, eddsa_sigdestroy \ + }; \ + \ + static int ed##_vrfdoit(sig *s, dstr *d) \ + { \ + ed##_pub *k = s->kd; \ + \ + if (d->len != ED##_SIGSZ) return (-1); \ + return (ed##_verify(k->pub.k, \ + GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz, \ + (const octet *)d->buf)); \ + } \ + \ + static const char *ed##_vrfcheck(sig *s) \ + { \ + ed##_pub *k = s->kd; \ + \ + if (k->pub.sz != ED##_PUBSZ) \ + return ("incorrect " #name " public key length"); \ + return (0); \ + } \ + \ + static const sigops ed##_vrf = { \ + ed##_pubfetch, sizeof(ed##_pub), \ + eddsa_siginit, ed##_vrfdoit, ed##_vrfcheck, eddsa_sigdestroy \ + }; + +EDDSAS(EDDSADEF) +#undef EDDSADEF /* --- Symmetric message authentication --- */ @@ -727,7 +740,10 @@ const struct sigtab sigtab[] = { { "kcdsa", &kcdsa_sig, &kcdsa_vrf, &has160 }, { "binkcdsa", &binkcdsa_sig, &binkcdsa_vrf, &has160 }, { "eckcdsa", &eckcdsa_sig, &eckcdsa_vrf, &has160 }, - { "ed25519", &ed25519_sig, &ed25519_vrf, &sha512 }, +#define EDDSATAB(ed, ED, name, hash) \ + { #ed, &ed##_sig, &ed##_vrf, &hash }, + EDDSAS(EDDSATAB) +#undef EDDSATAB { "mac", &mac_sig, &mac_vrf, &rmd160 }, { 0, 0, 0 } }; diff --git a/progs/key.c b/progs/key.c index e85107ae..74060cd1 100644 --- a/progs/key.c +++ b/progs/key.c @@ -945,59 +945,62 @@ static void alg_ec(keyopts *k) mp_drop(x); } -static void alg_x25519(keyopts *k) -{ - key_data *kd, *kkd; - octet priv[X25519_KEYSZ], pub[X25519_PUBSZ]; - - copyparam(k, 0); - k->r->ops->fill(k->r, priv, sizeof(priv)); - x25519(pub, priv, x25519_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); -} - -static void alg_x448(keyopts *k) -{ - key_data *kd, *kkd; - octet priv[X448_KEYSZ], pub[X448_PUBSZ]; - - copyparam(k, 0); - k->r->ops->fill(k->r, priv, sizeof(priv)); - x448(pub, priv, x448_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); -} - -static void alg_ed25519(keyopts *k) -{ - key_data *kd, *kkd; - octet priv[ED25519_KEYSZ], pub[ED25519_PUBSZ]; +#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); \ + } - copyparam(k, 0); - k->r->ops->fill(k->r, priv, sizeof(priv)); - ed25519_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))); +XDHS(XDHALG) +#undef XDHALG + +#define EDDSAS(_) \ + _(ed25519, ED25519, "Ed25519") + +#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); \ + } - key_setkeydata(k->kf, k->k, kd); -} +EDDSAS(EDDSAALG) +#undef EDDSAALG /* --- The algorithm tables --- */ @@ -1020,9 +1023,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" }, - { "x25519", alg_x25519, "X25519 key exchange" }, - { "x448", alg_x448, "X448 key exchange" }, - { "ed25519", alg_ed25519, "Ed25519 digital signatures" }, +#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 } }; -- 2.11.0