+ dhgrp *g = kpub->grp;
+ dhsc *u = g->ops->randsc(g);
+ dhge *U = g->ops->mul(g, u, 0), *Z = g->ops->mul(g, u, kpub->K);
+ bulkalgs *algs = kpub->algs.bulk;
+ octet *len;
+ bulkctx *bulk;
+ deriveargs a;
+ size_t n;
+ buf bk;
+ int rc = 0;
+
+ IF_TRACING(T_CRYPTO, {
+ trace(T_CRYPTO,
+ "crypto: encrypting IES message (type 0x%02x) for recipient `%s'",
+ ty, kpub->tag);
+ trace_block(T_CRYPTO, "crypto: plaintext message", BCUR(b), BLEFT(b));
+ })
+
+ a.hc = kpub->algs.h; a.what = "tripe:ecies-"; a.f = DF_OUT;
+ buf_init(&bk, buf_u, sizeof(buf_u)); a.k = BBASE(&bk);
+ g->ops->stge(g, &bk, U, DHFMT_HASH); a.x = a.y = BLEN(&bk);
+ g->ops->stge(g, &bk, Z, DHFMT_HASH); a.z = BLEN(&bk);
+ assert(BOK(&bk));
+ T( trace_block(T_CRYPTO, "crypto: KEM clue", a.k, a.x);
+ trace_block(T_CRYPTO, "crypto: shared secret", a.k + a.y, a.z - a.y); )
+
+ len = BCUR(bb); buf_get(bb, 2);
+ bulk = algs->ops->genkeys(algs, &a);
+ bulk->ops = algs->ops;
+ g->ops->stge(g, bb, U, DHFMT_VAR); if (BBAD(bb)) goto end;
+ rc = bulk->ops->encrypt(bulk, ty, b, bb, 0);
+ if (rc || BBAD(bb)) goto end;
+ n = BCUR(bb) - len - 2; assert(n <= MASK16); STORE16(len, n);
+
+end:
+ bulk->ops->freectx(bulk);
+ g->ops->freesc(g, u);
+ g->ops->freege(g, U);
+ g->ops->freege(g, Z);
+ return (rc);