+ kxc->c = G_CREATE(gg);
+ G_COPY(gg, kxc->c, c);
+
+ /* --- Work out the cookie for this challenge --- */
+
+ 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 --- */
+
+ 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 --- */
+
+ 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);
+
+ 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: outbound switch request",
+ kxc->hswrq_out, algs.hashsz);
+ trace_block(T_CRYPTO, "crypto: outbound switch confirm",
+ kxc->hswok_out, algs.hashsz);
+ trace_block(T_CRYPTO, "crypto: inbound switch request",
+ kxc->hswrq_in, algs.hashsz);
+ trace_block(T_CRYPTO, "crypto: inbound switch confirm",
+ kxc->hswok_in, algs.hashsz);
+ }))
+
+ /* --- Create a new symmetric keyset --- */
+
+ buf_init(b, buf_o, sizeof(buf_o));
+ G_TOBUF(gg, b, kx->c); x = BLEN(b);
+ G_TOBUF(gg, b, kxc->c); y = BLEN(b);
+ G_TOBUF(gg, b, r); z = BLEN(b);
+ assert(BOK(b));
+
+ kxc->ks = ks_gen(BBASE(b), x, y, z, kx->p);
+ G_DESTROY(gg, r);