From d9d419b020ab2b6fc1b7bdfc8db24735c7f7b6fb Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Thu, 26 May 2016 09:26:09 +0100 Subject: [PATCH] progs/cc-kem.c: Add `naclbox' crypto transform. Organization: Straylight/Edgeware From: Mark Wooding This uses Salsa20/r (or ChaChar) and Poly1305 in the same way as NaCl `secretbox'. Difference: NaCl uses XSalsa20 for the extended nonce size, but we have no need of that here. --- progs/catcrypt.1 | 22 +++++++++ progs/cc-kem.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) diff --git a/progs/catcrypt.1 b/progs/catcrypt.1 index af5e6b3a..a3ebff8a 100644 --- a/progs/catcrypt.1 +++ b/progs/catcrypt.1 @@ -226,6 +226,28 @@ and .B mac attributes. This is the default transform. +.TP +.B naclbox +Use Salsa20 or ChaCha and Poly1305 to secure the bulk data. +This is nearly the same as the NaCl +.B crypto_secretbox +construction, +except that +.B catcrypt +uses Salsa20 or ChaCha rather than XSalsa20, +because it doesn't need the latter's extended nonce. +The +.B cipher +attribute may be set to one of +.BR salsa20 , +.BR salsa20/12 , +.BR salsa20/8 , +.BR chacha20 , +.BR chacha12 , +or +.BR chacha8 ; +the default is +.BR salsa20 . .PP As well as the KEM itself, a number of supporting algorithms are used. These are taken from appropriately named attributes on the key or, diff --git a/progs/cc-kem.c b/progs/cc-kem.c index 6c4d7f30..4a2cf192 100644 --- a/progs/cc-kem.c +++ b/progs/cc-kem.c @@ -46,11 +46,123 @@ #include "rmd160.h" #include "blowfish-cbc.h" +#include "poly1305.h" +#include "salsa20.h" +#include "chacha.h" #include "cc.h" /*----- Bulk crypto -------------------------------------------------------*/ +/* --- NaCl `secretbox' --- */ + +typedef struct naclbox_encctx { + bulk b; + const gccipher *cc; + gcipher *c; +} naclbox_encctx; + +static bulk *naclbox_init(key *k, const char *calg, const char *halg) +{ + naclbox_encctx *ctx = CREATE(naclbox_encctx); + dstr t = DSTR_INIT; + const char *q; + + key_fulltag(k, &t); + + if ((q = key_getattr(0, k, "cipher")) != 0) calg = q; + if (!calg || strcmp(calg, "salsa20") == 0) ctx->cc = &salsa20; + else if (strcmp(calg, "salsa20/12") == 0) ctx->cc = &salsa2012; + else if (strcmp(calg, "salsa20/8") == 0) ctx->cc = &salsa208; + else if (strcmp(calg, "chacha20") == 0) ctx->cc = &chacha20; + else if (strcmp(calg, "chacha12") == 0) ctx->cc = &chacha12; + else if (strcmp(calg, "chacha8") == 0) ctx->cc = &chacha8; + else { + die(EXIT_FAILURE, + "unknown or inappropriate encryption scheme `%s' in key `%s'", + calg, t.buf); + } + + dstr_destroy(&t); + return (&ctx->b); +} + +static int naclbox_setup(bulk *b, gcipher *cx) +{ + naclbox_encctx *ctx = (naclbox_encctx *)b; + octet k[SALSA20_KEYSZ]; + + GC_ENCRYPT(cx, 0, k, sizeof(k)); + ctx->c = GC_INIT(ctx->cc, k, sizeof(k)); + return (0); +} + +static size_t naclbox_overhead(bulk *b) { return (POLY1305_TAGSZ); } + +static void naclbox_destroy(bulk *b) +{ + naclbox_encctx *ctx = (naclbox_encctx *)b; + + GC_DESTROY(ctx->c); + DESTROY(ctx); +} + +static const char *naclbox_encdoit(bulk *b, uint32 seq, buf *bb, + const void *p, size_t sz) +{ + naclbox_encctx *ctx = (naclbox_encctx *)b; + octet t[32]; + poly1305_key ak; + poly1305_ctx a; + octet *tag, *ct; + + STORE32(t, seq); STORE32(t + 4, 0); GC_SETIV(ctx->c, t); + GC_ENCRYPT(ctx->c, 0, t, POLY1305_KEYSZ + POLY1305_MASKSZ); + poly1305_keyinit(&ak, t, POLY1305_KEYSZ); + poly1305_macinit(&a, &ak, t + POLY1305_KEYSZ); + + tag = buf_get(bb, POLY1305_TAGSZ); assert(tag); + ct = buf_get(bb, sz); assert(ct); + GC_ENCRYPT(ctx->c, p, ct, sz); + poly1305_hash(&a, ct, sz); + poly1305_done(&a, tag); + return (0); +} + +static const char *naclbox_decdoit(bulk *b, uint32 seq, buf *bb, + const void *p, size_t sz) +{ + naclbox_encctx *ctx = (naclbox_encctx *)b; + buf bin; + octet t[32]; + poly1305_key ak; + poly1305_ctx a; + octet *tag, *ct, *pt; + + STORE32(t, seq); STORE32(t + 4, 0); GC_SETIV(ctx->c, t); + GC_ENCRYPT(ctx->c, 0, t, POLY1305_KEYSZ + POLY1305_MASKSZ); + poly1305_keyinit(&ak, t, POLY1305_KEYSZ); + poly1305_macinit(&a, &ak, t + POLY1305_KEYSZ); + + buf_init(&bin, (/*unconst*/ void *)p, sz); + if ((tag = buf_get(&bin, POLY1305_TAGSZ)) == 0) return ("no tag"); + ct = BCUR(&bin); sz = BLEFT(&bin); + poly1305_hash(&a, ct, sz); + poly1305_done(&a, t); + if (!ct_memeq(t, tag, POLY1305_TAGSZ)) return ("authentication failure"); + pt = buf_get(bb, sz); assert(pt); + GC_DECRYPT(ctx->c, ct, pt, sz); + return (0); +} + +static const bulkops naclbox_encops = { + naclbox_init, naclbox_setup, naclbox_overhead, + naclbox_encdoit, naclbox_destroy +}, naclbox_decops = { + naclbox_init, naclbox_setup, naclbox_overhead, + naclbox_decdoit, naclbox_destroy +}; + /* --- Generic composition --- */ typedef struct gencomp_encctx { @@ -185,6 +297,7 @@ static const bulkops gencomp_encops = { const struct bulktab bulktab[] = { { "gencomp", &gencomp_encops, &gencomp_decops }, + { "naclbox", &naclbox_encops, &naclbox_decops }, { 0, 0, 0 } }; -- [mdw]