+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
+}
+