+/* --- Authenticated encryption --- */
+
+typedef struct aeadsetup_ctx {
+ const gcaead *aec;
+ octet *k; size_t ksz;
+ octet *n; size_t nsz;
+ size_t tsz;
+} aeadsetup_ctx;
+
+static void *aeadsetup_init(opts *o)
+{
+ aeadsetup_ctx *c = CREATE(aeadsetup_ctx);
+ if (!o->name)
+ die(1, "must specify encryption scheme name");
+ if ((c->aec = gaead_byname(o->name)) == 0)
+ die(1, "aead scheme `%s' not known", o->name);
+ c->ksz = keysz(o->fbits/8, c->aec->keysz);
+ c->nsz = keysz_pad(o->gbits/8, c->aec->noncesz);
+ c->tsz = keysz(0, c->aec->tagsz);
+ if (o->fbits%8 || (o->fbits && c->ksz != o->fbits/8))
+ die(1, "bad key size %u for %s", o->fbits, o->name);
+ if (o->gbits%8 || (o->gbits && c->nsz != o->gbits/8))
+ die(1, "bad nonce size %u for %s", o->gbits, o->name);
+ c->k = xmalloc(c->ksz); rand_get(RAND_GLOBAL, c->k, c->ksz);
+ c->n = xmalloc(c->nsz); rand_get(RAND_GLOBAL, c->n, c->nsz);
+ return (c);
+}
+
+static void aeadsetup_run(void *cc)
+{
+ aeadsetup_ctx *c = cc;
+ gaead_key *k = GAEAD_KEY(c->aec, c->k, c->ksz);
+ gaead_enc *e = GAEAD_ENC(k, c->n, c->nsz, 0, 0, c->tsz);
+ GAEAD_DESTROY(e); GAEAD_DESTROY(k);
+}
+
+typedef struct aeadenc_ctx {
+ gaead_enc *enc;
+ octet *n; size_t nsz;
+ octet *p, *q; size_t sz; size_t nn;
+ size_t tsz;
+} aeadenc_ctx;
+
+static void *aeadenc_init(opts *o)
+{
+ aeadenc_ctx *c = CREATE(aeadenc_ctx);
+ const gcaead *aec;
+ gaead_key *key;
+ octet *k; size_t ksz;
+
+ if (!o->name)
+ die(1, "must specify encryption scheme name");
+ if ((aec = gaead_byname(o->name)) == 0)
+ die(1, "aead scheme `%s' not known", o->name);
+ c->sz = o->gbits ? o->gbits : 65536;
+ c->nn = o->n ? o->n : 16;
+ ksz = keysz(o->fbits/8, aec->keysz);
+ c->nsz = keysz(0, aec->noncesz);
+ c->tsz = keysz(0, aec->tagsz);
+ if (o->fbits%8 || (o->fbits && ksz != o->fbits/8))
+ die(1, "bad key size %u for %s", o->fbits, o->name);
+
+ k = xmalloc(ksz); rand_get(RAND_GLOBAL, k, ksz);
+ c->n = xmalloc(c->nsz); rand_get(RAND_GLOBAL, c->n, c->nsz);
+ c->p = xmalloc(c->sz); c->q = xmalloc(c->sz + aec->bufsz);
+
+ key = GAEAD_KEY(aec, k, ksz);
+ c->enc = GAEAD_ENC(key, c->n, c->nsz, 0, 0, c->tsz);
+ GAEAD_DESTROY(key); xfree(k);
+
+ o->opwhat = "byte"; o->sc = c->nn*c->sz;
+ return (c);
+}
+
+static void aeadaad_run(void *cc)
+{
+ aeadenc_ctx *c = cc;
+ gaead_aad *a;
+ size_t i;
+
+ GAEAD_REINIT(c->enc, c->n, c->nsz, c->nn*c->sz, 0, c->tsz);
+ a = GAEAD_AAD(c->enc);
+ for (i = 0; i < c->nn; i++) GAEAD_HASH(a, c->p, c->sz);
+ GAEAD_DESTROY(a);
+}
+
+static void aeadenc_run(void *cc)
+{
+ aeadenc_ctx *c = cc;
+ buf b;
+ size_t i;
+
+ GAEAD_REINIT(c->enc, c->n, c->nsz, 0, c->nn*c->sz, c->tsz);
+ for (i = 0; i < c->nn; i++) {
+ buf_init(&b, c->q, c->sz + c->enc->ops->c->bufsz);
+ GAEAD_ENCRYPT(c->enc, c->p, c->sz, &b);
+ }
+}
+