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 --- *
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;
/* --- Update the statistics --- */
if (BOK(b)) {
- st->n_kxout++;
- st->sz_kxout += BLEN(b);
+ update_stats_tx(kx, BLEN(b));
p_txend(kx->p);
}
static int doprechallenge(keyexch *kx, buf *b)
{
- stats *st = p_stats(kx->p);
const dhgrp *g = kx->kpriv->grp;
dhge *C = 0;
ghash *h;
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 --- */
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;
/* --- 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);
{
kxchal *kxc;
buf bb;
- stats *st = p_stats(kx->p);
struct timeval tv;
const dhgrp *g = kx->kpriv->grp;
buf *b;
}
if (BOK(b)) {
- st->n_kxout++;
- st->sz_kxout += BLEN(b);
+ update_stats_tx(kx, BLEN(b));
p_txend(kx->p);
}
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)); )
break;
}
- if (rc)
- st->n_reject++;
- else {
- st->n_kxin++;
- st->sz_kxin += sz;
- }
+ update_stats_rx(kx, !rc, sz);
}
/* --- @kx_free@ --- *
}
}
-/* --- @kx_init@ --- *
+/* --- @kx_setup@ --- *
*
* Arguments: @keyexch *kx@ = pointer to key exchange context
* @peer *p@ = pointer to peer context
* 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;