X-Git-Url: https://git.distorted.org.uk/~mdw/tripe/blobdiff_plain/76e91db906e1e949955fee632b57a6e442046aef..a5c4a56a64e127a1a5e5d436cf52df1e7a96eb33:/server/keyexch.c diff --git a/server/keyexch.c b/server/keyexch.c index 9e66e60d..7d1fa7df 100644 --- a/server/keyexch.c +++ b/server/keyexch.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 ------------------------------------------------------*/ @@ -374,6 +373,66 @@ static void rs_time(retry *rs, struct timeval *tv, const struct timeval *now) static void rs_reset(retry *rs) { rs->t = 0; } +/* --- @notice_message@ --- * + * + * Arguments: @keyexch *kx@ = pointer to key-exchange block + * + * Returns: Zero if OK; @-1@ if the public key is in a bad state. + * + * Use: Updates the key-exchange state following a received message. + * Specifically, if there's no currently active key-exchange in + * progress, and we're not in the cooling-off period, then + * commence a new one; reset the retry timers; and if we're + * corked then pop the cork so that we can reply. + */ + +static int checkpub(keyexch *kx); +static void stop(keyexch *kx); +static void start(keyexch *kx, time_t now); + +static int notice_message(keyexch *kx) +{ + struct timeval now, tv; + + gettimeofday(&now, 0); + rs_reset(&kx->rs); + if (kx->f & KXF_CORK) { + start(kx, now.tv_sec); + rs_time(&kx->rs, &tv, &now); + settimer(kx, &tv); + a_notify("KXSTART", "?PEER", kx->p, A_END); + } + if (checkpub(kx)) return (-1); + if (!VALIDP(kx, now.tv_sec)) { + stop(kx); + start(kx, now.tv_sec); + } + return (0); +} + +/* --- @update_stats_tx@, @update_stats_rx@ --- * + * + * Arguments: @keyexch *kx@ = pointer to key-exchange block + * @int ok@ = nonzero if the message was valid (for @rx@) + * @size_t sz@ = size of sent message + * + * Returns: --- + * + * Use: Records that a key-exchange message was sent to, or received + * from, the peer. + */ + +static void update_stats_tx(keyexch *kx, size_t sz) + { stats *st = p_stats(kx->p); st->n_kxout++; st->sz_kxout += sz; } + +static void update_stats_rx(keyexch *kx, int ok, size_t sz) +{ + stats *st = p_stats(kx->p); + + if (!ok) st->n_reject++; + else { st->n_kxin++; st->sz_kxin += sz; } +} + /*----- Challenge management ----------------------------------------------*/ /* --- Notes on challenge management --- * @@ -528,7 +587,6 @@ static void kxc_timer(struct timeval *tv, void *v) static void kxc_answer(keyexch *kx, kxchal *kxc) { - stats *st = p_stats(kx->p); buf *b = p_txstart(kx->p, MSG_KEYEXCH | KX_REPLY); const dhgrp *g = kx->kpriv->grp; struct timeval tv; @@ -546,8 +604,7 @@ static void kxc_answer(keyexch *kx, kxchal *kxc) /* --- Update the statistics --- */ if (BOK(b)) { - st->n_kxout++; - st->sz_kxout += BLEN(b); + update_stats_tx(kx, BLEN(b)); p_txend(kx->p); } @@ -575,7 +632,6 @@ static void kxc_answer(keyexch *kx, kxchal *kxc) static int doprechallenge(keyexch *kx, buf *b) { - stats *st = p_stats(kx->p); const dhgrp *g = kx->kpriv->grp; dhge *C = 0; ghash *h; @@ -604,8 +660,7 @@ static int doprechallenge(keyexch *kx, buf *b) hashge(h, g, C); sendchallenge(kx, b, C, GH_DONE(h, 0)); GH_DESTROY(h); - st->n_kxout++; - st->sz_kxout += BLEN(b); + update_stats_tx(kx, BLEN(b)); p_txend(kx->p); /* --- Done --- */ @@ -638,8 +693,8 @@ static kxchal *respond(keyexch *kx, unsigned msg, buf *b) dhge *C = 0; dhge *R = 0; dhge *CC = 0; + deriveargs a; const octet *hc, *ck; - size_t x, y, z; dhsc *c = 0; kxchal *kxc; ghash *h = 0; @@ -753,13 +808,13 @@ static kxchal *respond(keyexch *kx, unsigned msg, buf *b) /* --- Create a new symmetric keyset --- */ - buf_init(&bb, buf_o, sizeof(buf_o)); - g->ops->stge(g, &bb, kx->C, DHFMT_HASH); x = BLEN(&bb); - g->ops->stge(g, &bb, kxc->C, DHFMT_HASH); y = BLEN(&bb); - g->ops->stge(g, &bb, R, DHFMT_HASH); z = BLEN(&bb); + buf_init(&bb, buf_o, sizeof(buf_o)); a.k = BBASE(&bb); + g->ops->stge(g, &bb, kx->C, DHFMT_HASH); a.x = BLEN(&bb); + g->ops->stge(g, &bb, kxc->C, DHFMT_HASH); a.y = BLEN(&bb); + g->ops->stge(g, &bb, R, DHFMT_HASH); a.z = BLEN(&bb); assert(BOK(&bb)); - kxc->ks = ks_gen(BBASE(&bb), x, y, z, kx->p); + kxc->ks = ks_gen(&a, kx->p); } if (C) g->ops->freege(g, C); @@ -824,7 +879,6 @@ static void resend(keyexch *kx) { kxchal *kxc; buf bb; - stats *st = p_stats(kx->p); struct timeval tv; const dhgrp *g = kx->kpriv->grp; buf *b; @@ -864,8 +918,7 @@ static void resend(keyexch *kx) } if (BOK(b)) { - st->n_kxout++; - st->sz_kxout += BLEN(b); + update_stats_tx(kx, BLEN(b)); p_txend(kx->p); } @@ -1278,58 +1331,27 @@ void kx_start(keyexch *kx, int forcep) void kx_message(keyexch *kx, unsigned msg, buf *b) { - struct timeval now, tv; - stats *st = p_stats(kx->p); size_t sz = BSZ(b); int rc; - gettimeofday(&now, 0); - rs_reset(&kx->rs); - if (kx->f & KXF_CORK) { - start(kx, now.tv_sec); - rs_time(&kx->rs, &tv, &now); - settimer(kx, &tv); - a_notify("KXSTART", "?PEER", kx->p, A_END); - } - - if (checkpub(kx)) - return; + if (notice_message(kx)) return; - if (!VALIDP(kx, now.tv_sec)) { - stop(kx); - start(kx, now.tv_sec); - } T( trace(T_KEYEXCH, "keyexch: processing %s packet from `%s'", msg < KX_NMSG ? pkname[msg] : "unknown", p_name(kx->p)); ) switch (msg) { - case KX_PRECHAL: - rc = doprechallenge(kx, b); - break; - case KX_CHAL: - rc = dochallenge(kx, b); - break; - case KX_REPLY: - rc = doreply(kx, b); - break; - case KX_SWITCH: - rc = doswitch(kx, b); - break; - case KX_SWITCHOK: - rc = doswitchok(kx, b); - break; + case KX_PRECHAL: rc = doprechallenge(kx, b); break; + case KX_CHAL: rc = dochallenge(kx, b); break; + case KX_REPLY: rc = doreply(kx, b); break; + case KX_SWITCH: rc = doswitch(kx, b); break; + case KX_SWITCHOK: rc = doswitchok(kx, b); break; default: a_warn("KX", "?PEER", kx->p, "unknown-message", "0x%02x", msg, A_END); rc = -1; break; } - if (rc) - st->n_reject++; - else { - st->n_kxin++; - st->sz_kxin += sz; - } + update_stats_rx(kx, !rc, sz); } /* --- @kx_free@ --- * @@ -1473,7 +1495,7 @@ newkeys: } } -/* --- @kx_init@ --- * +/* --- @kx_setup@ --- * * * Arguments: @keyexch *kx@ = pointer to key exchange context * @peer *p@ = pointer to peer context @@ -1487,7 +1509,7 @@ newkeys: * exchange. */ -int kx_init(keyexch *kx, peer *p, keyset **ks, unsigned f) +int kx_setup(keyexch *kx, peer *p, keyset **ks, unsigned f) { if ((kx->kpriv = km_findpriv(p_privtag(p))) == 0) goto fail_0; if ((kx->kpub = km_findpub(p_tag(p))) == 0) goto fail_1;