From 11ee758ad0d59eed47d478a5efe93fa84002f319 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Fri, 9 Nov 2018 18:45:51 +0000 Subject: [PATCH] progs/catcrypt.c: Support the use of AEAD schemes. --- progs/catcrypt.1 | 9 ++++ progs/catcrypt.c | 3 ++ progs/cc-kem.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) diff --git a/progs/catcrypt.1 b/progs/catcrypt.1 index d55b7bfe..97367a52 100644 --- a/progs/catcrypt.1 +++ b/progs/catcrypt.1 @@ -256,6 +256,15 @@ is .BR blowfish-cbc . This is the default transform. .TP +.B aead +Use an `authenticated encryption with additional data' (AEAD) scheme. +The specific scheme is named by the +.B cipher +attribute. Run +.B catcrypt show aead +for a list of supported AEAD schemes; the default is +.BR chacha20-poly1305 . +.TP .B naclbox Use Salsa20 or ChaCha and Poly1305 to secure the bulk data. This is nearly the same as the NaCl diff --git a/progs/catcrypt.c b/progs/catcrypt.c index 72c77807..c31a3d93 100644 --- a/progs/catcrypt.c +++ b/progs/catcrypt.c @@ -51,6 +51,7 @@ #include "key.h" #include "cc.h" +#include "gaead.h" #include "ectab.h" #include "ptab.h" @@ -572,6 +573,8 @@ static int decrypt(int argc, char *argv[]) enctab[i].name, enctab[i].name) \ LI("Symmetric encryption algorithms", cipher, \ gciphertab[i], gciphertab[i]->name) \ + LI("Authenticated encryption schemes", aead, \ + gaeadtab[i], gaeadtab[i]->name) \ LI("Hash functions", hash, \ ghashtab[i], ghashtab[i]->name) \ LI("Message authentication codes", mac, \ diff --git a/progs/cc-kem.c b/progs/cc-kem.c index 1e99e05d..0974f4fa 100644 --- a/progs/cc-kem.c +++ b/progs/cc-kem.c @@ -36,6 +36,7 @@ #include #include +#include "gaead.h" #include "mprand.h" #include "rand.h" @@ -48,6 +49,7 @@ #include "rmd160.h" #include "blowfish-cbc.h" +#include "chacha20-poly1305.h" #include "poly1305.h" #include "salsa20.h" #include "chacha.h" @@ -165,6 +167,139 @@ static const bulkops naclbox_encops = { naclbox_decdoit, naclbox_destroy }; +/* --- Authenticated encryption schemes --- */ + +typedef struct aead_encctx { + bulk b; + const gcaead *aec; + gaead_key *key; + union { gaead_enc *enc; gaead_dec *dec; } ed; + octet *t; + size_t nsz, tsz; +} aead_encctx; + +static bulk *aead_init(key *k, const char *calg, const char *halg) +{ + aead_encctx *ctx = CREATE(aead_encctx); + const char *q; + dstr t = DSTR_INIT; + + key_fulltag(k, &t); + + if ((q = key_getattr(0, k, "cipher")) != 0) calg = q; + if (!calg) ctx->aec = &chacha20_poly1305; + else if ((ctx->aec = gaead_byname(calg)) == 0) + die(EXIT_FAILURE, "AEAD scheme `%s' not found in key `%s'", + calg, t.buf); + + ctx->key = 0; + if ((ctx->nsz = keysz_pad(4, ctx->aec->noncesz)) == 0) + die(EXIT_FAILURE, "no suitable nonce size for `%s'", calg); + ctx->tsz = keysz(0, ctx->aec->tagsz); + + dstr_destroy(&t); + return (&ctx->b); +} + +static int aead_commonsetup(aead_encctx *ctx, gcipher *cx) +{ + size_t ksz, n; + + n = ksz = keysz(0, ctx->aec->keysz); + if (n < ctx->nsz) n = ctx->nsz; + if (n < ctx->tsz) n = ctx->tsz; + ctx->t = xmalloc(n); + + GC_ENCRYPT(cx, 0, ctx->t, ksz); + ctx->key = GAEAD_KEY(ctx->aec, ctx->t, ksz); + return (0); +} + +static size_t aead_overhead(bulk *b) + { aead_encctx *ctx = (aead_encctx *)b; return (ctx->aec->ohd + ctx->tsz); } + +static void aead_commondestroy(aead_encctx *ctx) +{ + if (ctx->key) GAEAD_DESTROY(ctx->key); + xfree(ctx->t); + DESTROY(ctx); +} + +static int aead_encsetup(bulk *b, gcipher *cx) +{ + aead_encctx *ctx = (aead_encctx *)b; + ctx->ed.enc = 0; return (aead_commonsetup(ctx, cx)); +} + +static const char *aead_encdoit(bulk *b, uint32 seq, buf *bb, + const void *p, size_t sz) +{ + aead_encctx *ctx = (aead_encctx *)b; + octet *t; + int rc; + + memset(ctx->t + 4, 0, ctx->nsz - 4); STORE32_B(ctx->t, seq); + if (!ctx->ed.enc) + ctx->ed.enc = GAEAD_ENC(ctx->key, ctx->t, ctx->nsz, 0, sz, ctx->tsz); + else + GAEAD_REINIT(ctx->ed.enc, ctx->t, ctx->nsz, 0, sz, ctx->tsz); + t = buf_get(bb, ctx->tsz); assert(t); + rc = GAEAD_ENCRYPT(ctx->ed.enc, p, sz, bb); assert(rc >= 0); + rc = GAEAD_DONE(ctx->ed.enc, 0, bb, t, ctx->tsz); assert(rc >= 0); + return (0); +} + +static void aead_encdestroy(bulk *b) +{ + aead_encctx *ctx = (aead_encctx *)b; + if (ctx->ed.enc) GAEAD_DESTROY(ctx->ed.enc); + aead_commondestroy(ctx); +} + +static int aead_decsetup(bulk *b, gcipher *cx) +{ + aead_encctx *ctx = (aead_encctx *)b; + ctx->ed.dec = 0; return (aead_commonsetup(ctx, cx)); +} + +static const char *aead_decdoit(bulk *b, uint32 seq, buf *bb, + const void *p, size_t sz) +{ + aead_encctx *ctx = (aead_encctx *)b; + buf bin; + const octet *t; + int rc; + + memset(ctx->t + 4, 0, ctx->nsz - 4); STORE32_B(ctx->t, seq); + if (!ctx->ed.dec) + ctx->ed.dec = GAEAD_DEC(ctx->key, ctx->t, ctx->nsz, 0, sz, ctx->tsz); + else + GAEAD_REINIT(ctx->ed.enc, ctx->t, ctx->nsz, 0, sz, ctx->tsz); + + buf_init(&bin, (/*unconst*/ void *)p, sz); + t = buf_get(&bin, ctx->tsz); if (!t) return ("no tag"); + rc = GAEAD_DECRYPT(ctx->ed.dec, BCUR(&bin), BLEFT(&bin), bb); + assert(rc >= 0); + rc = GAEAD_DONE(ctx->ed.dec, 0, bb, t, ctx->tsz); assert(rc >= 0); + if (!rc) return ("authentication failure"); + return (0); +} + +static void aead_decdestroy(bulk *b) +{ + aead_encctx *ctx = (aead_encctx *)b; + if (ctx->ed.dec) GAEAD_DESTROY(ctx->ed.dec); + aead_commondestroy(ctx); +} + +static const struct bulkops aead_encops = { + aead_init, aead_encsetup, aead_overhead, + aead_encdoit, aead_encdestroy +}, aead_decops = { + aead_init, aead_decsetup, aead_overhead, + aead_decdoit, aead_decdestroy +}; + /* --- Generic composition --- */ typedef struct gencomp_encctx { @@ -300,6 +435,7 @@ static const bulkops gencomp_encops = { const struct bulktab bulktab[] = { { "gencomp", &gencomp_encops, &gencomp_decops }, { "naclbox", &naclbox_encops, &naclbox_decops }, + { "aead", &aead_encops, &aead_decops }, { 0, 0, 0 } }; -- 2.11.0