From: Mark Wooding Date: Thu, 5 Sep 2019 12:06:10 +0000 (+0100) Subject: server/bulkcrypto.c: Implement a bulk transform based on AEAD schemes. X-Git-Tag: 1.5.0~4 X-Git-Url: https://git.distorted.org.uk/~mdw/tripe/commitdiff_plain/e53273effe4843c10e8ac6b6490b6a32ff856f0f server/bulkcrypto.c: Implement a bulk transform based on AEAD schemes. Reimplement `naclbox' mostly in terms of this. It doesn't quite fit, because `naclbox' can't be used directly for challenges. --- diff --git a/configure.ac b/configure.ac index e2e763ee..b61659f7 100644 --- a/configure.ac +++ b/configure.ac @@ -87,7 +87,7 @@ case $want_adns,$have_adns in esac PKG_CHECK_MODULES([mLib], [mLib >= 2.2.1]) -PKG_CHECK_MODULES([catacomb], [catacomb >= 2.2.2-38]) +PKG_CHECK_MODULES([catacomb], [catacomb >= 2.4.2-70]) AM_CFLAGS="$AM_CFLAGS $mLib_CFLAGS $catacomb_CFLAGS" diff --git a/debian/control b/debian/control index b03aefd0..0bf822c9 100644 --- a/debian/control +++ b/debian/control @@ -6,7 +6,7 @@ XS-Python-Version: >= 2.4 Build-Depends: debhelper (>= 9), pkg-config, curl, rsync, python (>= 2.6.6-3~), mlib-dev (>= 2.2.2), - catacomb-dev (>= 2.4.0), catacomb-bin (>= 2.1.4) + catacomb-dev (>= 2.4.2+70), catacomb-bin (>= 2.1.4) Build-Depends-Indep: python-cdb, python-gtk2, python-mlib (>= 1.0.2), python-catacomb (>= 1.2.0), tshark, wireshark-dev (>= 1.12.1) diff --git a/server/bulkcrypto.c b/server/bulkcrypto.c index d0e654cc..6b175ddd 100644 --- a/server/bulkcrypto.c +++ b/server/bulkcrypto.c @@ -46,7 +46,7 @@ #define TRACE_MACERR(pmac, tagsz) do { IF_TRACING(T_KEYSET, { \ trace(T_KEYSET, "keyset: incorrect MAC: decryption failed"); \ - trace_block(T_CRYPTO, "crypto: expected MAC", (pmac), (tagsz)); \ + trace_block(T_CRYPTO, "crypto: provided MAC", (pmac), (tagsz)); \ }) } while (0) /* --- @derivekey@ --- * @@ -814,6 +814,332 @@ static int iiv_decrypt(bulkctx *bbc, unsigned ty, return (0); } +/*----- The AEAD transform ------------------------------------------------* + * + * This transform uses a general authenticated encryption scheme (the + * additional data isn't necessary). Good options include + * `chacha20-poly1305' or `rijndael-ocb3'. + * + * To be acceptable, the scheme must accept at least a 64-bit nonce. (All of + * Catacomb's current AEAD schemes are suitable.) The low 32 bits are the + * sequence number, and the high 32 bits are the type, both big-endian. + * + * +------+------+ + * | seq | type | + * +------+------+ + * 32 32 + * + * The ciphertext is formatted as + * + * +---...---+------+------...------+ + * | tag | seq | ciphertext | + * +---...---+------+------...------+ + * tagsz 32 sz + * + */ + +#define AEAD_NONCEMAX 64 + +typedef struct aead_algs { + bulkalgs _b; + const gcaead *c; + size_t ksz, nsz, tsz; +} aead_algs; + +typedef struct aead_ctx { + bulkctx _b; + struct { gaead_key *k; } d[NDIR]; + size_t nsz, tsz; +} aead_ctx; + +static bulkalgs *aead_getalgs(const algswitch *asw, dstr *e, + key_file *kf, key *k) +{ + aead_algs *a = CREATE(aead_algs); + const char *p; + char *qq; + gaead_key *kk = 0; + size_t ksz; + size_t csz = 0; + unsigned long n; + + /* --- Collect the selected cipher and check that it's supported --- */ + + p = key_getattr(kf, k, "cipher"); if (!p) p = "rijndael-ocb3"; + a->c = gaead_byname(p); + if (!a->c) { a_format(e, "unknown-cipher", "%s", p, A_END); goto fail; } + if (a->c->f&AEADF_NOAAD) { + a_format(e, "unsuitable-aead-cipher", "%s", p, "no-aad", A_END); + goto fail; + } + a->nsz = keysz_pad(8, a->c->noncesz); + if (!a->nsz) { + a_format(e, "unsuitable-aead-cipher", "%s", p, "nonce-too-small", A_END); + goto fail; + } else if (a->nsz > AEAD_NONCEMAX) { + a_format(e, "unsuitable-aead-cipher", "%s", p, "nonce-too-large", A_END); + goto fail; + } + + /* --- Collect the selected MAC, and check the tag length --- * + * + * Of course, there isn't a separate MAC, so only accept `aead'. + */ + + p = key_getattr(kf, k, "tagsz"); + if (!p) { + p = key_getattr(kf, k, "mac"); + if (strncmp(p, "aead", 4) != 0 || (p[4] && p[4] != '/')) { + a_format(e, "unknown-mac", "%s", p, A_END); + goto fail; + } + if (p[4] == '/') p += 5; + else p = 0; + } + if (!p) + a->tsz = keysz(0, a->c->tagsz); + else { + n = strtoul(p, &qq, 0); + if (*qq) { + a_format(e, "bad-tag-length-string", "%s", p, A_END); + goto fail; + } + if (n%8 || (a->tsz = keysz(n/8, a->c->tagsz)) == 0) + { a_format(e, "bad-tag-length", "%lu", n, A_END); goto fail; } + } + + /* --- Check that an empty message gives an empty ciphertext --- * + * + * This is necessary for producing challenges. If the overhead is zero + * then we're fine; otherwise, we have to check the hard way. + */ + + if (a->c->ohd) { + ksz = keysz(0, a->c->keysz); + memset(buf_t, 0, ksz > a->nsz ? ksz : a->nsz); + kk = GAEAD_KEY(a->c, buf_t, ksz); + if (gaead_encrypt(kk, buf_t, a->nsz, + buf_t, ksz, + 0, 0, + buf_t, &csz, + buf_t, a->tsz)) { + a_format(e, "unsuitable-aead-cipher", "%s", a->c->name, + "nonempty-ciphertext-for-empty-message", A_END); + goto fail; + } + GAEAD_DESTROY(kk); kk = 0; + } + + return (&a->_b); +fail: + if (kk) GAEAD_DESTROY(kk); + DESTROY(a); + return (0); +} + +#ifndef NTRACE +static void aead_tracealgs(const bulkalgs *aa) +{ + const aead_algs *a = (const aead_algs *)aa; + + trace(T_CRYPTO, "crypto: cipher = %s", a->c->name); + trace(T_CRYPTO, "crypto: noncesz = %lu", (unsigned long)a->nsz); + trace(T_CRYPTO, "crypto: tagsz = %lu", (unsigned long)a->tsz); +} +#endif + +static int aead_checkalgs(bulkalgs *aa, const algswitch *asw, dstr *e) +{ + aead_algs *a = (aead_algs *)aa; + + if ((a->ksz = keysz(asw->hashsz, a->c->keysz)) == 0) { + a_format(e, "cipher", "%s", a->c->name, + "no-key-size", "%lu", (unsigned long)asw->hashsz, + A_END); + return (-1); + } + return (0); +} + +static int aead_samealgsp(const bulkalgs *aa, const bulkalgs *bb) +{ + const aead_algs *a = (const aead_algs *)aa, + *b = (const aead_algs *)bb; + return (a->c == b->c && a->tsz == b->tsz); +} + +static void aead_alginfo(const bulkalgs *aa, admin *adm) +{ + const aead_algs *a = (const aead_algs *)aa; + a_info(adm, "cipher=%s", a->c->name, + "cipher-keysz=%lu", (unsigned long)a->ksz, + A_END); + a_info(adm, "mac=aead", "mac-tagsz=%lu", (unsigned long)a->tsz, A_END); +} + +static size_t aead_overhead(const bulkalgs *aa) +{ + const aead_algs *a = (const aead_algs *)aa; + return (a->tsz + SEQSZ + a->c->ohd); +} + +static size_t aead_expsz(const bulkalgs *aa) +{ + const aead_algs *a = (const aead_algs *)aa; + return (a->c->blksz < 16 ? MEG(64) : MEG(2048)); +} + +static bulkctx *aead_genkeys(const bulkalgs *aa, const deriveargs *da) +{ + const aead_algs *a = (const aead_algs *)aa; + aead_ctx *bc = CREATE(aead_ctx); + octet k[MAXHASHSZ]; + int i; + + for (i = 0; i < NDIR; i++) { + if (!(da->f&(1 << i))) { bc->d[i].k = 0; continue; } + derivekey(k, a->ksz, da, i, "encryption"); + bc->d[i].k = GAEAD_KEY(a->c, k, a->ksz); + } + bc->nsz = a->nsz; bc->tsz = a->tsz; + return (&bc->_b); +} + +typedef struct aead_chal { + bulkchal _b; + gaead_key *k; +} aead_chal; + +static bulkchal *aead_genchal(const bulkalgs *aa) +{ + const aead_algs *a = (const aead_algs *)aa; + aead_chal *c = CREATE(aead_chal); + rand_get(RAND_GLOBAL, buf_t, a->ksz); + c->k = GAEAD_KEY(a->c, buf_t, a->ksz); + IF_TRACING(T_CHAL, { + trace(T_CHAL, "chal: generated new challenge key"); + trace_block(T_CRYPTO, "chal: new key", buf_t, a->ksz); + }) + c->_b.tagsz = a->tsz; + return (&c->_b); +} + +static int aead_chaltag(bulkchal *bc, const void *m, size_t msz, + uint32 seq, void *t) +{ + aead_chal *c = (aead_chal *)bc; + octet b[AEAD_NONCEMAX]; + size_t nsz = keysz_pad(4, c->k->ops->c->noncesz); + size_t csz = 0; + int rc; + + assert(nsz); assert(nsz <= sizeof(b)); + memset(b, 0, nsz - 4); STORE32(b + nsz - 4, seq); + rc = gaead_encrypt(c->k, b, nsz, m, msz, 0, 0, + buf_t, &csz, t, c->_b.tagsz); + assert(!rc); + return (0); +} + +static int aead_chalvrf(bulkchal *bc, const void *m, size_t msz, + uint32 seq, const void *t) +{ + aead_chal *c = (aead_chal *)bc; + octet b[AEAD_NONCEMAX]; + size_t nsz = keysz(4, c->k->ops->c->noncesz); + size_t psz = 0; + int rc; + + assert(nsz); assert(nsz <= sizeof(b)); + memset(b, 0, nsz - 4); STORE32(b + nsz - 4, seq); + rc = gaead_decrypt(c->k, b, nsz, m, msz, 0, 0, + buf_t, &psz, t, c->_b.tagsz); + assert(rc >= 0); + return (rc == 1 ? 0 : -1); +} + +static void aead_freechal(bulkchal *bc) + { aead_chal *c = (aead_chal *)bc; GAEAD_DESTROY(c->k); DESTROY(c); } + +static void aead_freealgs(bulkalgs *aa) + { aead_algs *a = (aead_algs *)aa; DESTROY(a); } + +static void aead_freectx(bulkctx *bbc) +{ + aead_ctx *bc = (aead_ctx *)bbc; + int i; + + for (i = 0; i < NDIR; i++) { if (bc->d[i].k) GAEAD_DESTROY(bc->d[i].k); } + DESTROY(bc); +} + +static int aead_encrypt(bulkctx *bbc, unsigned ty, + buf *b, buf *bb, uint32 seq) +{ + aead_ctx *bc = (aead_ctx *)bbc; + const octet *p = BCUR(b); + gaead_key *k = bc->d[DIR_OUT].k; + size_t sz = BLEFT(b); + size_t csz = sz + k->ops->c->ohd; + octet *qmac, *qseq, *qpk; + octet n[AEAD_NONCEMAX]; + int rc; + + assert(k); + + if (buf_ensure(bb, bc->tsz + SEQSZ + csz)) return (0); + qmac = BCUR(bb); qseq = qmac + bc->tsz; qpk = qseq + SEQSZ; + STORE32(qseq, seq); + + assert(bc->nsz <= sizeof(n)); + memcpy(n, qseq, SEQSZ); STORE32(n + SEQSZ, ty); + if (bc->nsz > 8) memset(n + 8, 0, bc->nsz - 8); + TRACE_IV(n, bc->nsz); + + rc = gaead_encrypt(k, n, bc->nsz, 0, 0, p, sz, qpk, &csz, qmac, bc->tsz); + assert(!rc); + BSTEP(bb, bc->tsz + SEQSZ + csz); + TRACE_CT(qpk, csz); + TRACE_MAC(qmac, bc->tsz); + + return (0); +} + +static int aead_decrypt(bulkctx *bbc, unsigned ty, + buf *b, buf *bb, uint32 *seq) +{ + aead_ctx *bc = (aead_ctx *)bbc; + gaead_key *k = bc->d[DIR_IN].k; + const octet *pmac, *pseq, *ppk; + size_t psz = BLEFT(b); + size_t sz; + octet *q = BCUR(bb); + octet n[AEAD_NONCEMAX]; + int rc; + + assert(k); + + if (psz < bc->tsz + SEQSZ) { + T( trace(T_KEYSET, "keyset: block too small for keyset"); ) + return (KSERR_MALFORMED); + } + sz = psz - bc->tsz - SEQSZ; + pmac = BCUR(b); pseq = pmac + bc->tsz; ppk = pseq + SEQSZ; + + assert(bc->nsz <= sizeof(n)); + memcpy(n, pseq, SEQSZ); STORE32(n + SEQSZ, ty); + if (bc->nsz > 8) memset(n + 8, 0, bc->nsz - 8); + TRACE_IV(n, bc->nsz); + + rc = gaead_decrypt(k, n, bc->nsz, 0, 0, ppk, sz, q, &sz, pmac, bc->tsz); + assert(rc >= 0); + if (!rc) { TRACE_MACERR(pmac, bc->tsz); return (KSERR_DECRYPT); } + + *seq = LOAD32(pseq); + BSTEP(bb, sz); + return (0); +} + /*----- The NaCl box transform --------------------------------------------* * * This transform is very similar to the NaCl `crypto_secretbox' transform @@ -857,16 +1183,10 @@ static int iiv_decrypt(bulkctx *bbc, unsigned ty, */ typedef struct naclbox_algs { - bulkalgs _b; - const gccipher *c; size_t cksz; + aead_algs _b; + const gccipher *c; } naclbox_algs; -typedef struct naclbox_ctx { - bulkctx _b; - struct { gcipher *c; } d[NDIR]; -} naclbox_ctx; - - static bulkalgs *naclbox_getalgs(const algswitch *asw, dstr *e, key_file *kf, key *k) { @@ -878,16 +1198,23 @@ static bulkalgs *naclbox_getalgs(const algswitch *asw, dstr *e, /* --- Collect the selected cipher and check that it's supported --- */ p = key_getattr(kf, k, "cipher"); - if (!p || strcmp(p, "salsa20") == 0) a->c = &salsa20; - else if (strcmp(p, "salsa20/12") == 0) a->c = &salsa2012; - else if (strcmp(p, "salsa20/8") == 0) a->c = &salsa208; - else if (strcmp(p, "chacha20") == 0) a->c = &chacha20; - else if (strcmp(p, "chacha12") == 0) a->c = &chacha12; - else if (strcmp(p, "chacha8") == 0) a->c = &chacha8; + if (!p || strcmp(p, "salsa20") == 0) + { a->_b.c = &salsa20_naclbox; a->c = &salsa20; } + else if (strcmp(p, "salsa20/12") == 0) + { a->_b.c = &salsa2012_naclbox; a->c = &salsa2012; } + else if (strcmp(p, "salsa20/8") == 0) + { a->_b.c = &salsa208_naclbox; a->c = &salsa208; } + else if (strcmp(p, "chacha20") == 0) + { a->_b.c = &chacha20_naclbox; a->c = &chacha20; } + else if (strcmp(p, "chacha12") == 0) + { a->_b.c = &chacha12_naclbox; a->c = &chacha12; } + else if (strcmp(p, "chacha8") == 0) + { a->_b.c = &chacha8_naclbox; a->c = &chacha8; } else { a_format(e, "unknown-cipher", "%s", p, A_END); goto fail; } + a->_b.nsz = 8; /* --- Collect the selected MAC, and check the tag length --- */ @@ -908,8 +1235,9 @@ static bulkalgs *naclbox_getalgs(const algswitch *asw, dstr *e, goto fail; } } + a->_b.tsz = 16; - return (&a->_b); + return (&a->_b._b); fail: DESTROY(a); return (0); @@ -925,25 +1253,8 @@ static void naclbox_tracealgs(const bulkalgs *aa) } #endif -static int naclbox_checkalgs(bulkalgs *aa, const algswitch *asw, dstr *e) -{ - naclbox_algs *a = (naclbox_algs *)aa; - - if ((a->cksz = keysz(asw->hashsz, a->c->keysz)) == 0) { - a_format(e, "cipher", "%s", a->c->name, - "no-key-size", "%lu", (unsigned long)asw->hashsz, - A_END); - return (-1); - } - return (0); -} - -static int naclbox_samealgsp(const bulkalgs *aa, const bulkalgs *bb) -{ - const naclbox_algs *a = (const naclbox_algs *)aa, - *b = (const naclbox_algs *)bb; - return (a->c == b->c); -} +#define naclbox_checkalgs aead_checkalgs +#define naclbox_samealgsp aead_samealgsp static void naclbox_alginfo(const bulkalgs *aa, admin *adm) { @@ -952,26 +1263,9 @@ static void naclbox_alginfo(const bulkalgs *aa, admin *adm) a_info(adm, "mac=poly1305", "mac-tagsz=16", A_END); } -static size_t naclbox_overhead(const bulkalgs *aa) - { return (POLY1305_TAGSZ + SEQSZ); } - -static size_t naclbox_expsz(const bulkalgs *aa) - { return (MEG(2048)); } - -static bulkctx *naclbox_genkeys(const bulkalgs *aa, const deriveargs *da) -{ - const naclbox_algs *a = (const naclbox_algs *)aa; - naclbox_ctx *bc = CREATE(naclbox_ctx); - octet k[MAXHASHSZ]; - int i; - - for (i = 0; i < NDIR; i++) { - if (!(da->f&(1 << i))) { bc->d[i].c = 0; continue; } - derivekey(k, a->cksz, da, i, "encryption"); - bc->d[i].c = GC_INIT(a->c, k, a->cksz); - } - return (&bc->_b); -} +#define naclbox_overhead aead_overhead +#define naclbox_expsz aead_expsz +#define naclbox_genkeys aead_genkeys typedef struct naclbox_chal { bulkchal _b; @@ -982,11 +1276,11 @@ static bulkchal *naclbox_genchal(const bulkalgs *aa) { const naclbox_algs *a = (const naclbox_algs *)aa; naclbox_chal *c = CREATE(naclbox_chal); - rand_get(RAND_GLOBAL, buf_t, a->cksz); - c->c = GC_INIT(a->c, buf_t, a->cksz); + rand_get(RAND_GLOBAL, buf_t, a->_b.ksz); + c->c = GC_INIT(a->c, buf_t, a->_b.ksz); IF_TRACING(T_CHAL, { trace(T_CHAL, "chal: generated new challenge key"); - trace_block(T_CRYPTO, "chal: new key", buf_t, a->cksz); + trace_block(T_CRYPTO, "chal: new key", buf_t, a->_b.ksz); }) c->_b.tagsz = POLY1305_TAGSZ; return (&c->_b); @@ -1034,118 +1328,9 @@ static void naclbox_freechal(bulkchal *bc) static void naclbox_freealgs(bulkalgs *aa) { naclbox_algs *a = (naclbox_algs *)aa; DESTROY(a); } -static void naclbox_freectx(bulkctx *bbc) -{ - naclbox_ctx *bc = (naclbox_ctx *)bbc; - int i; - - for (i = 0; i < NDIR; i++) { if (bc->d[i].c) GC_DESTROY(bc->d[i].c); } - DESTROY(bc); -} - -static int naclbox_encrypt(bulkctx *bbc, unsigned ty, - buf *b, buf *bb, uint32 seq) -{ - naclbox_ctx *bc = (naclbox_ctx *)bbc; - gcipher *c = bc->d[DIR_OUT].c; - poly1305_key polyk; - poly1305_ctx poly; - const octet *p = BCUR(b); - size_t sz = BLEFT(b); - octet *qmac, *qseq, *qpk; - - assert(c); - - /* --- Determine the ciphertext layout --- */ - - if (buf_ensure(bb, POLY1305_TAGSZ + SEQSZ + sz)) return (0); - qmac = BCUR(bb); qseq = qmac + POLY1305_TAGSZ; qpk = qseq + SEQSZ; - BSTEP(bb, POLY1305_TAGSZ + SEQSZ + sz); - - /* --- Construct and set the nonce --- */ - - STORE32(qseq, seq); - memcpy(buf_u, qseq, SEQSZ); STORE32(buf_u + SEQSZ, ty); - GC_SETIV(c, buf_u); - TRACE_IV(buf_u, SALSA20_NONCESZ); - - /* --- Determine the MAC key --- */ - - GC_ENCRYPT(c, 0, buf_u, POLY1305_KEYSZ + POLY1305_MASKSZ); - poly1305_keyinit(&polyk, buf_u, POLY1305_KEYSZ); - poly1305_macinit(&poly, &polyk, buf_u + POLY1305_KEYSZ); - - /* --- Encrypt the message --- */ - - GC_ENCRYPT(c, p, qpk, sz); - TRACE_CT(qpk, sz); - - /* --- Compute the MAC --- */ - - poly1305_hash(&poly, qpk, sz); - poly1305_done(&poly, qmac); - TRACE_MAC(qmac, POLY1305_TAGSZ); - - /* --- We're done --- */ - - return (0); -} - -static int naclbox_decrypt(bulkctx *bbc, unsigned ty, - buf *b, buf *bb, uint32 *seq) -{ - naclbox_ctx *bc = (naclbox_ctx *)bbc; - gcipher *c = bc->d[DIR_IN].c; - poly1305_key polyk; - poly1305_ctx poly; - const octet *pmac, *pseq, *ppk; - size_t psz = BLEFT(b); - size_t sz; - octet *q = BCUR(bb); - - assert(c); - - /* --- Break up the packet into its components --- */ - - if (psz < SEQSZ + POLY1305_TAGSZ) { - T( trace(T_KEYSET, "keyset: block too small for keyset"); ) - return (KSERR_MALFORMED); - } - sz = psz - SEQSZ - POLY1305_TAGSZ; - pmac = BCUR(b); pseq = pmac + POLY1305_TAGSZ; ppk = pseq + SEQSZ; - - /* --- Construct and set the nonce --- */ - - memcpy(buf_u, pseq, SEQSZ); STORE32(buf_u + SEQSZ, ty); - GC_SETIV(c, buf_u); - TRACE_IV(buf_u, SALSA20_NONCESZ); - - /* --- Determine the MAC key --- */ - - GC_ENCRYPT(c, 0, buf_u, POLY1305_KEYSZ + POLY1305_MASKSZ); - poly1305_keyinit(&polyk, buf_u, POLY1305_KEYSZ); - poly1305_macinit(&poly, &polyk, buf_u + POLY1305_KEYSZ); - - /* --- Verify the MAC on the packet --- */ - - poly1305_hash(&poly, ppk, sz); - poly1305_done(&poly, buf_u); - TRACE_MAC(buf_u, POLY1305_TAGSZ); - if (!ct_memeq(buf_u, pmac, POLY1305_TAGSZ)) { - TRACE_MACERR(pmac, POLY1305_TAGSZ); - return (KSERR_DECRYPT); - } - - /* --- Decrypt the packet --- */ - - GC_DECRYPT(c, ppk, q, sz); - - /* --- Finished --- */ - - *seq = LOAD32(pseq); - BSTEP(bb, sz); - return (0); -} +#define naclbox_freectx aead_freectx +#define naclbox_encrypt aead_encrypt +#define naclbox_decrypt aead_decrypt /*----- Bulk crypto transform table ---------------------------------------*/ @@ -1163,6 +1348,7 @@ const bulkops bulktab[] = { BULK("v0", v0), BULK("iiv", iiv), + BULK("aead", aead), BULK("naclbox", naclbox), #undef BULK diff --git a/server/tripe.8.in b/server/tripe.8.in index 4ec21bee..96d8896b 100644 --- a/server/tripe.8.in +++ b/server/tripe.8.in @@ -500,6 +500,36 @@ doesn't need the (possibly slow) random number generator, and (b) it closes a kleptographic channel, over which a compromised implementation could leak secret information to a third party. .TP +.B aead +A transform based on an all-in-one `authenticated encryption with +additional data' scheme. The scheme is named in the +.B cipher +attribute; the default is +.BR rijndael-ocb3 . +If the +.B mac +attribute is given, it must be either +.B aead +or +.BR aead/ \c +.IR tagsz , +where +.I tagsz +is the desired tag length in bits; alternatively, the tag length can be +set in the +.B tagsz +attribute. The chosen AEAD scheme must accept at least a 64-bit nonce +(this rules out OCB3 and CCM with 64-bit blockciphers); it mustn't +require an absurdly large nonce size (none of the schemes implemented in +Catacomb present a problem here, but it bears mentioning); it must +actually support additional header data (which rules out the +.B naclbox +schemes, but see the +.B naclbox +transform below); and it must produce an empty ciphertext when +encrypting an empty message (again, all of Catacomb's schemes meet this +requirement). +.TP .B naclbox A transform based on the NaCl .B crypto_secretbox diff --git a/server/tripe.h b/server/tripe.h index 0e336f39..ea980c6b 100644 --- a/server/tripe.h +++ b/server/tripe.h @@ -99,9 +99,11 @@ #include #include +#include #include #include #include +#include #include #include #include diff --git a/wireshark/tripe.lua b/wireshark/tripe.lua index 5c6d7ba9..a3544e9d 100644 --- a/wireshark/tripe.lua +++ b/wireshark/tripe.lua @@ -57,7 +57,7 @@ local CONFIG = { -- order. { var = "bulk", name = "Bulk transform", - type = "enum", allowed = { "v0", "iiv", "naclbox" }, + type = "enum", allowed = { "v0", "iiv", "naclbox", "aead" }, descr = "Bulk cryptographic transform", default = "v0" }, { var = "hashsz", name = "Hash length", type = "int", min = 0, descr = "Hash length (bytes)", default = 20 }, @@ -184,6 +184,11 @@ end -- Dissect a ciphertext of some particular kind. local dissect_ct = { } +function dissect_ct.aead(buf, tree, pos, sz) + tree:add(PF["tripe.ciphertext.tag"], buf(pos, C.tagsz)); pos = pos + C.tagsz + tree:add(PF["tripe.ciphertext.seq"], buf(pos, 4)); pos = pos + 4 + tree:add(PF["tripe.ciphertext.body"], buf(pos, sz - pos)) +end function dissect_ct.naclbox(buf, tree, pos, sz) tree:add(PF["tripe.ciphertext.tag"], buf(pos, 16)); pos = pos + 16 tree:add(PF["tripe.ciphertext.seq"], buf(pos, 4)); pos = pos + 4