X-Git-Url: https://git.distorted.org.uk/~mdw/tripe/blobdiff_plain/a93aacce200e0d68b614d8bfb05d9cbeba850b12..e8ea4061c8cda115466e3520fa897caa559438ac:/server/keyset.c diff --git a/server/keyset.c b/server/keyset.c index 6da6cc0f..9429fa4a 100644 --- a/server/keyset.c +++ b/server/keyset.c @@ -9,19 +9,18 @@ * * This file is part of Trivial IP Encryption (TrIPE). * - * TrIPE is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * TrIPE is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your + * option) any later version. * - * TrIPE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * TrIPE is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. * * You should have received a copy of the GNU General Public License - * along with TrIPE; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with TrIPE. If not, see . */ /*----- Header files ------------------------------------------------------*/ @@ -83,15 +82,16 @@ static int doencrypt(keyset *ks, unsigned ty, buf *b, buf *bb) IF_TRACING(T_KEYSET, { trace(T_KEYSET, - "keyset: encrypting packet %lu (type %u) using keyset %u", + "keyset: encrypting packet %lu (type 0x%02x) using keyset %u", (unsigned long)ks->oseq, ty, ks->seq); trace_block(T_CRYPTO, "crypto: plaintext packet", BCUR(b), sz); }) /* --- Apply the bulk-crypto transformation --- */ - rc = ks->bulk->encrypt(ks, ty, b, bb); + rc = ks->bulk->ops->encrypt(ks->bulk, ty, b, bb, ks->oseq); if (rc || !BOK(bb)) return (rc); + ks->oseq++; /* --- Do the necessary accounting for data volume --- */ @@ -134,12 +134,12 @@ static int dodecrypt(keyset *ks, unsigned ty, buf *b, buf *bb, uint32 *seq) IF_TRACING(T_KEYSET, { trace(T_KEYSET, - "keyset: try decrypting packet (type %u) using keyset %u", + "keyset: try decrypting packet (type 0x%02x) using keyset %u", ty, ks->seq); trace_block(T_CRYPTO, "crypto: ciphertext packet", BCUR(b), BLEFT(b)); }) - rc = ks->bulk->decrypt(ks, ty, b, bb, seq); + rc = ks->bulk->ops->decrypt(ks->bulk, ty, b, bb, seq); if (rc) return (rc); IF_TRACING(T_KEYSET, { @@ -164,22 +164,64 @@ static int dodecrypt(keyset *ks, unsigned ty, buf *b, buf *bb, uint32 *seq) void ks_drop(keyset *ks) { - if (--ks->ref) - return; - -#define DROP(dir, a, drop) do { if (ks->dir.a) drop(ks->dir.a); } while (0) -#define DROP_DIR(dir) do { \ - DROP(dir, c, GC_DESTROY); \ - DROP(dir, m, GM_DESTROY); \ -} while (0) + if (--ks->ref) return; + ks->bulk->ops->freectx(ks->bulk); + DESTROY(ks); +} - DROP_DIR(in); - DROP_DIR(out); +/* --- @ks_derivekey@ --- * + * + * Arguments: @octet *k@ = pointer to an output buffer of at least + * @MAXHASHSZ@ bytes + * @size_t ksz@ = actual size wanted (for tracing) + * @const struct rawkey *rk@ = a raw key, as passed into + * @genkeys@ + * @int dir@ = direction for the key (@DIR_IN@ or @DIR_OUT@) + * @const char *what@ = label for the key (input to derivation) + * + * Returns: --- + * + * Use: Derives a session key, for use on incoming or outgoing data. + * This function is part of a private protocol between @ks_gen@ + * and the bulk crypto transform @genkeys@ operation. + */ -#undef DROP -#undef DROP_DIR +struct rawkey { + const gchash *hc; + const octet *k; + size_t x, y, z; +}; - DESTROY(ks); +void ks_derivekey(octet *k, size_t ksz, const struct rawkey *rk, + int dir, const char *what) +{ + const gchash *hc = rk->hc; + ghash *h; + + assert(ksz <= hc->hashsz); + assert(hc->hashsz <= MAXHASHSZ); + h = GH_INIT(hc); + GH_HASH(h, "tripe-", 6); GH_HASH(h, what, strlen(what) + 1); + switch (dir) { + case DIR_IN: + GH_HASH(h, rk->k, rk->x); + GH_HASH(h, rk->k + rk->x, rk->y - rk->x); + break; + case DIR_OUT: + GH_HASH(h, rk->k + rk->x, rk->y - rk->x); + GH_HASH(h, rk->k, rk->x); + break; + default: + abort(); + } + GH_HASH(h, rk->k + rk->y, rk->z - rk->y); + GH_DONE(h, k); + GH_DESTROY(h); + IF_TRACING(T_KEYSET, { IF_TRACING(T_CRYPTO, { + char _buf[32]; + sprintf(_buf, "crypto: %s key %s", dir ? "outgoing" : "incoming", what); + trace_block(T_CRYPTO, _buf, k, ksz); + }) }) } /* --- @ks_gen@ --- * @@ -196,75 +238,38 @@ void ks_drop(keyset *ks) * the key material; between @k + x@ and @k + y@ is `your' * contribution; and between @k + y@ and @k + z@ is a shared * value we made together. These are used to construct two - * pairs of symmetric keys. Each pair consists of an encryption - * key and a message authentication key. One pair is used for - * outgoing messages, the other for incoming messages. + * collections of symmetric keys: one for outgoing messages, the + * other for incoming messages. * * The new key is marked so that it won't be selected for output * by @ksl_encrypt@. You can still encrypt data with it by * calling @ks_encrypt@ directly. */ -static void gen_dir(const algswitch *algs, struct ksdir *ksd, - const char *whichdir, - const octet *from, size_t fromsz, - const octet *to, size_t tosz, - const octet *both, size_t bothsz) -{ -#define SETKEY(what, a, init) do { \ - ghash *_h; \ - octet *_hh; \ - \ - if (!algs->a) \ - ksd->a = 0; \ - else { \ - _h = GH_INIT(algs->h); \ - HASH_STRING(_h, "tripe-" what); \ - GH_HASH(_h, from, fromsz); \ - GH_HASH(_h, to, tosz); \ - GH_HASH(_h, both, bothsz); \ - _hh = GH_DONE(_h, 0); \ - IF_TRACING(T_KEYSET, { IF_TRACING(T_CRYPTO, { \ - char _buf[32]; \ - sprintf(_buf, "crypto: %s key " what, whichdir); \ - trace_block(T_CRYPTO, _buf, _hh, algs->a##ksz); \ - }) }) \ - ksd->a = init(algs->a, _hh, algs->a##ksz); \ - GH_DESTROY(_h); \ - } \ -} while (0) - - SETKEY("encryption", c, GC_INIT); - SETKEY("integrity", m, GM_KEY); - -#undef SETKEY -} - keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p) { keyset *ks = CREATE(keyset); time_t now = time(0); - const octet *pp = k; const algswitch *algs = &p->kx.kpriv->algs; + struct rawkey rk; T( static unsigned seq = 0; ) T( trace(T_KEYSET, "keyset: adding new keyset %u", seq); ) - gen_dir(algs, &ks->in, "incoming", pp, x, pp + x, y - x, pp + y, z - y); - gen_dir(algs, &ks->out, "outgoing", pp + x, y - x, pp, x, pp + y, z - y); + rk.hc = algs->h; rk.k = k; rk.x = x; rk.y = y; rk.z = z; + ks->bulk = algs->bulk->ops->genkeys(algs->bulk, &rk); + ks->bulk->ops = algs->bulk->ops; T( ks->seq = seq++; ) - ks->bulk = algs->bulk; ks->ref = 1; ks->t_exp = now + T_EXP; - ks->sz_exp = algs->expsz; - ks->sz_regen = algs->expsz/2; + ks->sz_exp = algs->bulk->ops->expsz(algs->bulk); + ks->sz_regen = ks->sz_exp/2; ks->oseq = 0; seq_reset(&ks->iseq); ks->next = 0; ks->p = p; ks->f = KSF_LISTEN; - ks->tagsz = algs->tagsz; return (ks); }