/* -*-c-*-
*
- * $Id: keyexch.c,v 1.12 2004/04/08 01:36:17 mdw Exp $
+ * $Id: keyexch.c,v 1.13 2004/04/18 18:08:11 mdw Exp $
*
* Key exchange protocol
*
/* --- @hashge@ --- *
*
- * Arguments: @HASH_CTX *r@ = pointer to hash context
+ * Arguments: @ghash *h@ = pointer to hash context
* @ge *x@ = pointer to group element
*
* Returns: ---
* @buf_t@.
*/
-static void hashge(HASH_CTX *r, ge *x)
+static void hashge(ghash *h, ge *x)
{
buf b;
buf_init(&b, buf_t, sizeof(buf_t));
G_TOBUF(gg, &b, x);
assert(BOK(&b));
- HASH(r, BBASE(&b), BLEN(&b));
+ GH_HASH(h, BBASE(&b), BLEN(&b));
}
-/* --- @mpcrypt@ --- *
+/* --- @mpencrypt@, @mpdecrypt@ --- *
*
* Arguments: @mp *d@ = the destination integer
* @mp *x@ = the plaintext/ciphertext integer
* @size_t sz@ = the expected size of the plaintext
* @const octet *k@ = pointer to key material
- * @size_t ksz@ = size of the key
*
* Returns: The encrypted/decrypted integer.
*
* encryption thing.
*/
-static mp *mpcrypt(mp *d, mp *x, size_t sz, const octet *k, size_t ksz)
+static mp *mpencrypt(mp *d, mp *x, size_t sz, const octet *k)
{
- MGF_CTX m;
+ gcipher *mgf;
- MGF_INIT(&m, k, ksz, 0);
+ mgf = GC_INIT(algs.mgf, k, algs.hashsz);
mp_storeb(x, buf_t, sz);
- MGF_CRYPT(&m, buf_t, buf_t, sz);
+ GC_ENCRYPT(mgf, buf_t, buf_t, sz);
+ GC_DESTROY(mgf);
+ return (mp_loadb(d, buf_t, sz));
+}
+
+static mp *mpdecrypt(mp *d, mp *x, size_t sz, const octet *k)
+{
+ gcipher *mgf;
+
+ mgf = GC_INIT(algs.mgf, k, algs.hashsz);
+ mp_storeb(x, buf_t, sz);
+ GC_DECRYPT(mgf, buf_t, buf_t, sz);
+ GC_DESTROY(mgf);
return (mp_loadb(d, buf_t, sz));
}
unsigned i;
for (i = 0; i < kx->nr; i++) {
- if (memcmp(hc, kx->r[i]->hc, HASHSZ) == 0)
+ if (memcmp(hc, kx->r[i]->hc, algs.hashsz) == 0)
return (kx->r[i]);
}
return (0);
if (!kxc->r)
G_TOBUF(gg, b, kx->c);
else
- buf_put(b, kx->hc, HASHSZ);
- buf_put(b, kxc->hc, HASHSZ);
+ buf_put(b, kx->hc, algs.hashsz);
+ buf_put(b, kxc->hc, algs.hashsz);
buf_putmp(b, kxc->ck);
/* --- Maybe send an actual reply, if we have one --- */
ge *r = G_CREATE(gg);
ge *y = G_CREATE(gg);
mp *a = MP_NEW;
- HASH_CTX h;
- octet buf[HASHSZ];
+ ghash *h;
+ const octet *hh;
int ok;
G_EXP(gg, r, c, kpriv);
- HASH_INIT(&h);
- HASH_STRING(&h, "tripe-expected-reply");
- hashge(&h, c);
- hashge(&h, kx->c);
- hashge(&h, r);
- HASH_DONE(&h, buf);
-
- a = mpcrypt(MP_NEW, ck, mp_octets(gg->r), buf, sizeof(buf));
+ h = GH_INIT(algs.h);
+ HASH_STRING(h, "tripe-expected-reply");
+ hashge(h, c);
+ hashge(h, kx->c);
+ hashge(h, r);
+ hh = GH_DONE(h, 0);
+
+ a = mpdecrypt(MP_NEW, ck, mp_octets(gg->r), hh);
IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
trace(T_CRYPTO, "crypto: computed reply = %s", gestr(gg, r));
- trace_block(T_CRYPTO, "crypto: computed reply hash", buf, HASHSZ);
+ trace_block(T_CRYPTO, "crypto: computed reply hash", hh, algs.hashsz);
trace(T_CRYPTO, "crypto: recovered log = %s", mpstr(a));
}))
+ GH_DESTROY(h);
G_EXP(gg, y, gg->g, a);
ok = G_EQ(gg, y, c);
if (!ok) {
mp *ck = MP_NEW;
const octet *hc = 0;
kxchal *kxc;
- HASH_CTX h;
- octet buf[HASHSZ];
+ ghash *h;
/* --- Ensure that we're in a sensible state --- */
/* --- Unpack the packet --- */
if (G_FROMBUF(gg, b, c) ||
- (msg >= KX_COOKIE && (hc = buf_get(b, HASHSZ)) == 0) ||
+ (msg >= KX_COOKIE && (hc = buf_get(b, algs.hashsz)) == 0) ||
(msg >= KX_CHAL && (ck = buf_getmp(b)) == 0) ||
BLEFT(b)) {
a_warn("malformed packet from `%s'", p_name(kx->p));
IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
trace(T_CRYPTO, "crypto: challenge = %s", gestr(gg, c));
- if (hc) trace_block(T_CRYPTO, "crypto: cookie", hc, HASHSZ);
+ if (hc) trace_block(T_CRYPTO, "crypto: cookie", hc, algs.hashsz);
if (ck) trace(T_CRYPTO, "crypto: check value = %s", mpstr(ck));
}))
T( trace(T_KEYEXCH, "keyexch: too many challenges -- sending cookie"); )
b = p_txstart(kx->p, MSG_KEYEXCH | KX_COOKIE);
G_TOBUF(gg, b, kx->c);
- HASH_INIT(&h);
- HASH_STRING(&h, "tripe-cookie");
- hashge(&h, c);
- HASH_DONE(&h, buf_get(b, HASHSZ));
+ h = GH_INIT(algs.h);
+ HASH_STRING(h, "tripe-cookie");
+ hashge(h, c);
+ GH_DONE(h, buf_get(b, algs.hashsz));
+ GH_DESTROY(h);
p_txend(kx->p);
goto tidy;
}
/* --- Discard a packet with an invalid cookie --- */
- if (hc && memcmp(hc, kx->hc, HASHSZ) != 0) {
+ if (hc && memcmp(hc, kx->hc, algs.hashsz) != 0) {
a_warn("incorrect cookie from `%s'", p_name(kx->p));
goto bad;
}
/* --- Work out the cookie for this challenge --- */
- HASH_INIT(&h);
- HASH_STRING(&h, "tripe-cookie");
- hashge(&h, kxc->c);
- HASH_DONE(&h, kxc->hc);
+ h = GH_INIT(algs.h);
+ HASH_STRING(h, "tripe-cookie");
+ hashge(h, kxc->c);
+ GH_DONE(h, kxc->hc);
+ GH_DESTROY(h);
+
+ IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
+ trace_block(T_CRYPTO, "crypto: computed cookie", kxc->hc, algs.hashsz);
+ }))
/* --- Compute the expected-reply hash --- */
- HASH_INIT(&h);
- HASH_STRING(&h, "tripe-expected-reply");
- hashge(&h, kx->c);
- hashge(&h, kxc->c);
- hashge(&h, kx->rx);
- HASH_DONE(&h, buf);
- kxc->ck = mpcrypt(MP_NEW, kx->alpha, mp_octets(gg->r),
- buf, sizeof(buf));
+ h = GH_INIT(algs.h);
+ HASH_STRING(h, "tripe-expected-reply");
+ hashge(h, kx->c);
+ hashge(h, kxc->c);
+ hashge(h, kx->rx);
+ hc = GH_DONE(h, 0);
+ kxc->ck = mpencrypt(MP_NEW, kx->alpha, mp_octets(gg->r), hc);
+ IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
+ trace_block(T_CRYPTO, "crypto: expected-reply hash", hc, algs.hashsz);
+ trace(T_CRYPTO, "crypto: my reply check = %s", mpstr(kxc->ck));
+ }))
+ GH_DESTROY(h);
/* --- Work out the shared key --- */
r = G_CREATE(gg);
G_EXP(gg, r, c, kx->alpha);
+ IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
+ trace(T_CRYPTO, "crypto: shared secret = %s", gestr(gg, r));
+ }))
/* --- Compute the switch messages --- */
- HASH_INIT(&h); HASH_STRING(&h, "tripe-switch-request");
- hashge(&h, kx->c); hashge(&h, kxc->c);
- HASH_DONE(&h, kxc->hswrq_out);
- HASH_INIT(&h); HASH_STRING(&h, "tripe-switch-confirm");
- hashge(&h, kx->c); hashge(&h, kxc->c);
- HASH_DONE(&h, kxc->hswok_out);
+ h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-request");
+ hashge(h, kx->c); hashge(h, kxc->c);
+ GH_DONE(h, kxc->hswrq_out); GH_DESTROY(h);
+ h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-confirm");
+ hashge(h, kx->c); hashge(h, kxc->c);
+ GH_DONE(h, kxc->hswok_out); GH_DESTROY(h);
- HASH_INIT(&h); HASH_STRING(&h, "tripe-switch-request");
- hashge(&h, kxc->c); hashge(&h, kx->c);
- HASH_DONE(&h, kxc->hswrq_in);
- HASH_INIT(&h); HASH_STRING(&h, "tripe-switch-confirm");
- hashge(&h, kxc->c); hashge(&h, kx->c);
- HASH_DONE(&h, kxc->hswok_in);
+ h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-request");
+ hashge(h, kxc->c); hashge(h, kx->c);
+ GH_DONE(h, kxc->hswrq_in); GH_DESTROY(h);
+ h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-confirm");
+ hashge(h, kxc->c); hashge(h, kx->c);
+ GH_DONE(h, kxc->hswok_in); GH_DESTROY(h);
IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
- trace_block(T_CRYPTO, "crypto: computed cookie", kxc->hc, HASHSZ);
- trace_block(T_CRYPTO, "crypto: expected-reply hash",
- buf, HASHSZ);
- trace(T_CRYPTO, "crypto: my reply check = %s", mpstr(kxc->ck));
- trace(T_CRYPTO, "crypto: shared secret = %s", gestr(gg, r));
trace_block(T_CRYPTO, "crypto: outbound switch request",
- kxc->hswrq_out, HASHSZ);
+ kxc->hswrq_out, algs.hashsz);
trace_block(T_CRYPTO, "crypto: outbound switch confirm",
- kxc->hswok_out, HASHSZ);
+ kxc->hswok_out, algs.hashsz);
trace_block(T_CRYPTO, "crypto: inbound switch request",
- kxc->hswrq_in, HASHSZ);
+ kxc->hswrq_in, algs.hashsz);
trace_block(T_CRYPTO, "crypto: inbound switch confirm",
- kxc->hswok_in, HASHSZ);
+ kxc->hswok_in, algs.hashsz);
}))
/* --- Create a new symmetric keyset --- */
p_name(kx->p)); )
kxc = kx->r[0];
b = p_txstart(kx->p, MSG_KEYEXCH | KX_SWITCH);
- buf_put(b, kx->hc, HASHSZ);
- buf_put(b, kxc->hc, HASHSZ);
+ buf_put(b, kx->hc, algs.hashsz);
+ buf_put(b, kxc->hc, algs.hashsz);
buf_init(&bb, buf_i, sizeof(buf_i));
G_TOBUF(gg, &bb, kxc->r);
- buf_put(&bb, kxc->hswrq_out, HASHSZ);
+ buf_put(&bb, kxc->hswrq_out, algs.hashsz);
buf_flip(&bb);
ks_encrypt(kxc->ks, MSG_KEYEXCH | KX_SWITCH, &bb, b);
break;
kxc = kx->r[0];
b = p_txstart(kx->p, MSG_KEYEXCH | KX_SWITCHOK);
buf_init(&bb, buf_i, sizeof(buf_i));
- buf_put(&bb, kxc->hswok_out, HASHSZ);
+ buf_put(&bb, kxc->hswok_out, algs.hashsz);
buf_flip(&bb);
ks_encrypt(kxc->ks, MSG_KEYEXCH | KX_SWITCHOK, &bb, b);
break;
/* --- Check the plaintext portions of the data --- */
IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
- trace_block(T_CRYPTO, "crypto: challenge", hc_in, HASHSZ);
- trace_block(T_CRYPTO, "crypto: cookie", hc_out, HASHSZ);
+ trace_block(T_CRYPTO, "crypto: challenge", hc_in, algs.hashsz);
+ trace_block(T_CRYPTO, "crypto: cookie", hc_out, algs.hashsz);
if (ck) trace(T_CRYPTO, "crypto: check value = %s", mpstr(ck));
}))
- if (memcmp(hc_out, kx->hc, HASHSZ) != 0) {
+ if (memcmp(hc_out, kx->hc, algs.hashsz) != 0) {
a_warn("incorrect cookie from `%s'", p_name(kx->p));
goto bad;
}
a_warn("unexpected reply from `%s'", p_name(kx->p));
goto bad;
}
- if ((hc_in = buf_get(b, HASHSZ)) == 0 ||
- (hc_out = buf_get(b, HASHSZ)) == 0 ||
+ if ((hc_in = buf_get(b, algs.hashsz)) == 0 ||
+ (hc_out = buf_get(b, algs.hashsz)) == 0 ||
(ck = buf_getmp(b)) == 0) {
a_warn("invalid reply packet from `%s'", p_name(kx->p));
goto bad;
const octet *hc_in, *hc_out, *hswrq;
kxchal *kxc;
- if ((hc_in = buf_get(b, HASHSZ)) == 0 ||
- (hc_out = buf_get(b, HASHSZ)) == 0) {
+ if ((hc_in = buf_get(b, algs.hashsz)) == 0 ||
+ (hc_out = buf_get(b, algs.hashsz)) == 0) {
a_warn("invalid switch request from `%s'", p_name(kx->p));
goto bad;
}
if ((kxc = matchreply(kx, MSG_KEYEXCH | KX_SWITCH,
hc_in, hc_out, 0, b)) == 0)
goto bad;
- if ((hswrq = buf_get(b, HASHSZ)) == 0 || BLEFT(b)) {
+ if ((hswrq = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) {
a_warn("invalid switch request from `%s'", p_name(kx->p));
goto bad;
}
IF_TRACING(T_KEYEXCH, {
- trace_block(T_CRYPTO, "crypto: switch request hash", hswrq, HASHSZ);
+ trace_block(T_CRYPTO, "crypto: switch request hash", hswrq, algs.hashsz);
})
- if (memcmp(hswrq, kxc->hswrq_in, HASHSZ) != 0) {
+ if (memcmp(hswrq, kxc->hswrq_in, algs.hashsz) != 0) {
a_warn("incorrect switch request hash from `%s'", p_name(kx->p));
goto bad;
}
goto bad;
}
buf_init(b, BBASE(&bb), BLEN(&bb));
- if ((hswok = buf_get(b, HASHSZ)) == 0 || BLEFT(b)) {
+ if ((hswok = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) {
a_warn("invalid switch confirmation from `%s'", p_name(kx->p));
goto bad;
}
IF_TRACING(T_KEYEXCH, {
- trace_block(T_CRYPTO, "crypto: switch confirmation hash", hswok, HASHSZ);
+ trace_block(T_CRYPTO, "crypto: switch confirmation hash",
+ hswok, algs.hashsz);
})
- if (memcmp(hswok, kxc->hswok_in, HASHSZ) != 0) {
+ if (memcmp(hswok, kxc->hswok_in, algs.hashsz) != 0) {
a_warn("incorrect switch confirmation hash from `%s'", p_name(kx->p));
goto bad;
}
static void start(keyexch *kx, time_t now)
{
- HASH_CTX h;
+ ghash *h;
assert(kx->f & KXF_DEAD);
kx->s = KXS_CHAL;
kx->t_valid = now + T_VALID;
- HASH_INIT(&h);
- HASH_STRING(&h, "tripe-cookie");
- hashge(&h, kx->c);
- HASH_DONE(&h, kx->hc);
+ h = GH_INIT(algs.h);
+ HASH_STRING(h, "tripe-cookie");
+ hashge(h, kx->c);
+ GH_DONE(h, kx->hc);
+ GH_DESTROY(h);
IF_TRACING(T_KEYEXCH, {
trace(T_KEYEXCH, "keyexch: creating new challenge");
trace(T_CRYPTO, "crypto: secret = %s", mpstr(kx->alpha));
trace(T_CRYPTO, "crypto: challenge = %s", gestr(gg, kx->c));
trace(T_CRYPTO, "crypto: expected response = %s", gestr(gg, kx->rx));
- trace_block(T_CRYPTO, "crypto: challenge cookie", kx->hc, HASHSZ);
+ trace_block(T_CRYPTO, "crypto: challenge cookie", kx->hc, algs.hashsz);
})
})
}