trace_block(T_CRYPTO, "crypto: expected MAC", (pmac), (tagsz)); \
}) } while (0)
+/* --- @derivekey@ --- *
+ *
+ * Arguments: @octet *k@ = pointer to an output buffer of at least
+ * @MAXHASHSZ@ bytes
+ * @size_t ksz@ = actual size wanted (for tracing)
+ * @const deriveargs@ = derivation parameters, as passed into
+ * @genkeys@
+ * @int dir@ = direction for the key (@DIR_IN@ or @DIR_OUT@)
+ * @const char *what@ = label for the key (input to derivation)
+ *
+ * Returns: ---
+ *
+ * Use: Derives a session key, for use on incoming or outgoing data.
+ */
+
+static void derivekey(octet *k, size_t ksz, const deriveargs *a,
+ int dir, const char *what)
+{
+ const gchash *hc = a->hc;
+ ghash *h;
+
+ assert(ksz <= hc->hashsz);
+ assert(hc->hashsz <= MAXHASHSZ);
+ h = GH_INIT(hc);
+ GH_HASH(h, a->what, strlen(a->what)); GH_HASH(h, what, strlen(what) + 1);
+ switch (dir) {
+ case DIR_IN:
+ if (a->x) GH_HASH(h, a->k, a->x);
+ if (a->y != a->x) GH_HASH(h, a->k + a->x, a->y - a->x);
+ break;
+ case DIR_OUT:
+ if (a->y != a->x) GH_HASH(h, a->k + a->x, a->y - a->x);
+ if (a->x) GH_HASH(h, a->k, a->x);
+ break;
+ default:
+ abort();
+ }
+ GH_HASH(h, a->k + a->y, a->z - a->y);
+ GH_DONE(h, k);
+ GH_DESTROY(h);
+ IF_TRACING(T_KEYSET, { IF_TRACING(T_CRYPTO, {
+ char _buf[32];
+ sprintf(_buf, "crypto: %s key %s", dir ? "outgoing" : "incoming", what);
+ trace_block(T_CRYPTO, _buf, k, ksz);
+ }) })
+}
+
/*----- Common functionality for generic-composition transforms -----------*/
#define CHECK_MAC(h, pmac, tagsz) do { \
static size_t v0_expsz(const bulkalgs *aa)
{ const v0_algs *a = (const v0_algs *)aa; return (gencomp_expsz(&a->ga)); }
-static bulkctx *v0_genkeys(const bulkalgs *aa, const struct rawkey *rk)
+static bulkctx *v0_genkeys(const bulkalgs *aa, const deriveargs *da)
{
const v0_algs *a = (const v0_algs *)aa;
v0_ctx *bc = CREATE(v0_ctx);
bc->tagsz = a->ga.tagsz;
for (i = 0; i < NDIR; i++) {
- ks_derivekey(k, a->ga.cksz, rk, i, "encryption");
+ if (!(da->f&(1 << i))) { bc->d[i].c = 0; bc->d[i].m = 0; continue; }
+ derivekey(k, a->ga.cksz, da, i, "encryption");
bc->d[i].c = GC_INIT(a->ga.c, k, a->ga.cksz);
- ks_derivekey(k, a->ga.mksz, rk, i, "integrity");
+ derivekey(k, a->ga.mksz, da, i, "integrity");
bc->d[i].m = GM_KEY(a->ga.m, k, a->ga.mksz);
}
return (&bc->_b);
int i;
for (i = 0; i < NDIR; i++) {
- GC_DESTROY(bc->d[i].c);
- GM_DESTROY(bc->d[i].m);
+ if (bc->d[i].c) GC_DESTROY(bc->d[i].c);
+ if (bc->d[i].m) GM_DESTROY(bc->d[i].m);
}
DESTROY(bc);
}
const octet *p = BCUR(b);
size_t sz = BLEFT(b);
octet *qmac, *qseq, *qiv, *qpk;
- size_t ivsz = GC_CLASS(c)->blksz;
+ size_t ivsz;
size_t tagsz = bc->tagsz;
octet t[4];
+ assert(c);
+ ivsz = GC_CLASS(c)->blksz;
+
/* --- Determine the ciphertext layout --- */
if (buf_ensure(bb, tagsz + SEQSZ + ivsz + sz)) return (0);
octet *q = BCUR(bb);
ghash *h;
gcipher *c = bc->d[DIR_IN].c;
- size_t ivsz = GC_CLASS(c)->blksz;
+ size_t ivsz;
size_t tagsz = bc->tagsz;
octet t[4];
+ assert(c);
+ ivsz = GC_CLASS(c)->blksz;
+
/* --- Break up the packet into its components --- */
if (psz < ivsz + SEQSZ + tagsz) {
return (gencomp_expsz(&a->ga));
}
-static bulkctx *iiv_genkeys(const bulkalgs *aa, const struct rawkey *rk)
+static bulkctx *iiv_genkeys(const bulkalgs *aa, const deriveargs *da)
{
const iiv_algs *a = (const iiv_algs *)aa;
iiv_ctx *bc = CREATE(iiv_ctx);
bc->tagsz = a->ga.tagsz;
for (i = 0; i < NDIR; i++) {
- ks_derivekey(k, a->ga.cksz, rk, i, "encryption");
+ if (!(da->f&(1 << i)))
+ { bc->d[i].c = 0; bc->d[i].b = 0; bc->d[i].m = 0; continue; }
+ derivekey(k, a->ga.cksz, da, i, "encryption");
bc->d[i].c = GC_INIT(a->ga.c, k, a->ga.cksz);
- ks_derivekey(k, a->bksz, rk, i, "blkc");
+ derivekey(k, a->bksz, da, i, "blkc");
bc->d[i].b = GC_INIT(a->b, k, a->bksz);
- ks_derivekey(k, a->ga.mksz, rk, i, "integrity");
+ derivekey(k, a->ga.mksz, da, i, "integrity");
bc->d[i].m = GM_KEY(a->ga.m, k, a->ga.mksz);
}
return (&bc->_b);
int i;
for (i = 0; i < NDIR; i++) {
- GC_DESTROY(bc->d[i].c);
- GC_DESTROY(bc->d[i].b);
- GM_DESTROY(bc->d[i].m);
+ if (bc->d[i].c) GC_DESTROY(bc->d[i].c);
+ if (bc->d[i].b) GC_DESTROY(bc->d[i].b);
+ if (bc->d[i].m) GM_DESTROY(bc->d[i].m);
}
DESTROY(bc);
}
const octet *p = BCUR(b);
size_t sz = BLEFT(b);
octet *qmac, *qseq, *qpk;
- size_t ivsz = GC_CLASS(c)->blksz, blkcsz = GC_CLASS(blkc)->blksz;
+ size_t ivsz, blkcsz;
size_t tagsz = bc->tagsz;
octet t[4];
+ assert(c); assert(blkc);
+ ivsz = GC_CLASS(c)->blksz;
+ blkcsz = GC_CLASS(blkc)->blksz;
+
/* --- Determine the ciphertext layout --- */
if (buf_ensure(bb, tagsz + SEQSZ + sz)) return (0);
octet *q = BCUR(bb);
ghash *h;
gcipher *c = bc->d[DIR_IN].c, *blkc = bc->d[DIR_IN].b;
- size_t ivsz = GC_CLASS(c)->blksz, blkcsz = GC_CLASS(blkc)->blksz;
+ size_t ivsz, blkcsz;
size_t tagsz = bc->tagsz;
octet t[4];
+ assert(c); assert(blkc);
+ ivsz = GC_CLASS(c)->blksz;
+ blkcsz = GC_CLASS(blkc)->blksz;
+
/* --- Break up the packet into its components --- */
if (psz < SEQSZ + tagsz) {
static size_t naclbox_expsz(const bulkalgs *aa)
{ return (MEG(2048)); }
-static bulkctx *naclbox_genkeys(const bulkalgs *aa, const struct rawkey *rk)
+static bulkctx *naclbox_genkeys(const bulkalgs *aa, const deriveargs *da)
{
const naclbox_algs *a = (const naclbox_algs *)aa;
naclbox_ctx *bc = CREATE(naclbox_ctx);
int i;
for (i = 0; i < NDIR; i++) {
- ks_derivekey(k, a->cksz, rk, i, "encryption");
+ if (!(da->f&(1 << i))) { bc->d[i].c = 0; continue; }
+ derivekey(k, a->cksz, da, i, "encryption");
bc->d[i].c = GC_INIT(a->c, k, a->cksz);
}
return (&bc->_b);
naclbox_ctx *bc = (naclbox_ctx *)bbc;
int i;
- for (i = 0; i < NDIR; i++) GC_DESTROY(bc->d[i].c);
+ for (i = 0; i < NDIR; i++) { if (bc->d[i].c) GC_DESTROY(bc->d[i].c); }
DESTROY(bc);
}
size_t sz = BLEFT(b);
octet *qmac, *qseq, *qpk;
+ assert(c);
+
/* --- Determine the ciphertext layout --- */
if (buf_ensure(bb, POLY1305_TAGSZ + SEQSZ + sz)) return (0);
size_t sz;
octet *q = BCUR(bb);
+ assert(c);
+
/* --- Break up the packet into its components --- */
if (psz < SEQSZ + POLY1305_TAGSZ) {
dhge *C = 0;
dhge *R = 0;
dhge *CC = 0;
+ deriveargs a;
const octet *hc, *ck;
- size_t x, y, z;
dhsc *c = 0;
kxchal *kxc;
ghash *h = 0;
/* --- Create a new symmetric keyset --- */
- buf_init(&bb, buf_o, sizeof(buf_o));
- g->ops->stge(g, &bb, kx->C, DHFMT_HASH); x = BLEN(&bb);
- g->ops->stge(g, &bb, kxc->C, DHFMT_HASH); y = BLEN(&bb);
- g->ops->stge(g, &bb, R, DHFMT_HASH); z = BLEN(&bb);
+ buf_init(&bb, buf_o, sizeof(buf_o)); a.k = BBASE(&bb);
+ g->ops->stge(g, &bb, kx->C, DHFMT_HASH); a.x = BLEN(&bb);
+ g->ops->stge(g, &bb, kxc->C, DHFMT_HASH); a.y = BLEN(&bb);
+ g->ops->stge(g, &bb, R, DHFMT_HASH); a.z = BLEN(&bb);
assert(BOK(&bb));
- kxc->ks = ks_gen(BBASE(&bb), x, y, z, kx->p);
+ kxc->ks = ks_gen(&a, kx->p);
}
if (C) g->ops->freege(g, C);
DESTROY(ks);
}
-/* --- @ks_derivekey@ --- *
- *
- * Arguments: @octet *k@ = pointer to an output buffer of at least
- * @MAXHASHSZ@ bytes
- * @size_t ksz@ = actual size wanted (for tracing)
- * @const struct rawkey *rk@ = a raw key, as passed into
- * @genkeys@
- * @int dir@ = direction for the key (@DIR_IN@ or @DIR_OUT@)
- * @const char *what@ = label for the key (input to derivation)
- *
- * Returns: ---
- *
- * Use: Derives a session key, for use on incoming or outgoing data.
- * This function is part of a private protocol between @ks_gen@
- * and the bulk crypto transform @genkeys@ operation.
- */
-
-struct rawkey {
- const gchash *hc;
- const octet *k;
- size_t x, y, z;
-};
-
-void ks_derivekey(octet *k, size_t ksz, const struct rawkey *rk,
- int dir, const char *what)
-{
- const gchash *hc = rk->hc;
- ghash *h;
-
- assert(ksz <= hc->hashsz);
- assert(hc->hashsz <= MAXHASHSZ);
- h = GH_INIT(hc);
- GH_HASH(h, "tripe-", 6); GH_HASH(h, what, strlen(what) + 1);
- switch (dir) {
- case DIR_IN:
- GH_HASH(h, rk->k, rk->x);
- GH_HASH(h, rk->k + rk->x, rk->y - rk->x);
- break;
- case DIR_OUT:
- GH_HASH(h, rk->k + rk->x, rk->y - rk->x);
- GH_HASH(h, rk->k, rk->x);
- break;
- default:
- abort();
- }
- GH_HASH(h, rk->k + rk->y, rk->z - rk->y);
- GH_DONE(h, k);
- GH_DESTROY(h);
- IF_TRACING(T_KEYSET, { IF_TRACING(T_CRYPTO, {
- char _buf[32];
- sprintf(_buf, "crypto: %s key %s", dir ? "outgoing" : "incoming", what);
- trace_block(T_CRYPTO, _buf, k, ksz);
- }) })
-}
-
/* --- @ks_gen@ --- *
*
- * Arguments: @const void *k@ = pointer to key material
- * @size_t x, y, z@ = offsets into key material (see below)
+ * Arguments: @deriveargs *a@ = key derivation parameters (modified)
* @peer *p@ = pointer to peer information
*
* Returns: A pointer to the new keyset.
*
- * Use: Derives a new keyset from the given key material. The
- * offsets @x@, @y@ and @z@ separate the key material into three
- * parts. Between the @k@ and @k + x@ is `my' contribution to
- * the key material; between @k + x@ and @k + y@ is `your'
- * contribution; and between @k + y@ and @k + z@ is a shared
- * value we made together. These are used to construct two
- * collections of symmetric keys: one for outgoing messages, the
- * other for incoming messages.
+ * Use: Derives a new keyset from the given key material. This will
+ * set the @what@, @f@, and @hc@ members in @*a@; other members
+ * must be filled in by the caller.
*
* The new key is marked so that it won't be selected for output
* by @ksl_encrypt@. You can still encrypt data with it by
* calling @ks_encrypt@ directly.
*/
-keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p)
+keyset *ks_gen(deriveargs *a, peer *p)
{
keyset *ks = CREATE(keyset);
time_t now = time(0);
const algswitch *algs = &p->kx.kpriv->algs;
- struct rawkey rk;
T( static unsigned seq = 0; )
T( trace(T_KEYSET, "keyset: adding new keyset %u", seq); )
- rk.hc = algs->h; rk.k = k; rk.x = x; rk.y = y; rk.z = z;
- ks->bulk = algs->bulk->ops->genkeys(algs->bulk, &rk);
+ a->what = "tripe-"; a->f = DF_IN | DF_OUT; a->hc = algs->h;
+ ks->bulk = algs->bulk->ops->genkeys(algs->bulk, a);
ks->bulk->ops = algs->bulk->ops;
T( ks->seq = seq++; )
DHFMT_VAR /* Variable-width-format, mostly a bad idea */
};
+typedef struct deriveargs {
+ const char *what; /* Operation name (hashed) */
+ unsigned f; /* Flags */
+#define DF_IN 1u /* Make incoming key */
+#define DF_OUT 2u /* Make outgoing key */
+ const gchash *hc; /* Hash class */
+ const octet *k; /* Pointer to contributions */
+ size_t x, y, z; /* Markers in contributions */
+} deriveargs;
+
typedef struct bulkalgs {
const struct bulkops *ops;
} bulkalgs;
size_t tagsz;
} bulkchal;
-struct rawkey;
-
typedef struct dhops {
const char *name;
* after which the keys must no longer be used.
*/
- bulkctx *(*genkeys)(const bulkalgs */*a*/, const struct rawkey */*rk*/);
+ bulkctx *(*genkeys)(const bulkalgs */*a*/, const deriveargs */*a*/);
/* Generate session keys and construct and return an appropriate
- * context for using them, by calling @ks_derive@.
+ * context for using them. The offsets @a->x@, @a->y@ and @a->z@
+ * separate the key material into three parts. Between @a->k@ and
+ * @a->k + a->x@ is `my' contribution to the key material; between
+ * @a->k + a->x@ and @a->k + a->y@ is `your' contribution; and
+ * between @a->k + a->y@ and @a->k + a->z@ is a shared value we made
+ * together. These are used to construct (up to) two collections of
+ * symmetric keys: one for outgoing messages, the other for incoming
+ * messages. If @a->x == 0@ (or @a->y == a->x@) then my (or your)
+ * contribution is omitted.
*/
bulkchal *(*genchal)(const bulkalgs */*a*/);
extern void ks_drop(keyset */*ks*/);
-/* --- @ks_derivekey@ --- *
- *
- * Arguments: @octet *k@ = pointer to an output buffer of at least
- * @MAXHASHSZ@ bytes
- * @size_t ksz@ = actual size wanted (for tracing)
- * @const struct rawkey *rk@ = a raw key, as passed into
- * @genkeys@
- * @int dir@ = direction for the key (@DIR_IN@ or @DIR_OUT@)
- * @const char *what@ = label for the key (input to derivation)
- *
- * Returns: ---
- *
- * Use: Derives a session key, for use on incoming or outgoing data.
- * This function is part of a private protocol between @ks_gen@
- * and the bulk crypto transform @genkeys@ operation.
- */
-
-extern void ks_derivekey(octet */*k*/, size_t /*ksz*/,
- const struct rawkey */*rk*/,
- int /*dir*/, const char */*what*/);
-
/* --- @ks_gen@ --- *
*
- * Arguments: @const void *k@ = pointer to key material
- * @size_t x, y, z@ = offsets into key material (see below)
+ * Arguments: @deriveargs *a@ = key derivation parameters (modified)
* @peer *p@ = pointer to peer information
*
* Returns: A pointer to the new keyset.
*
- * Use: Derives a new keyset from the given key material. The
- * offsets @x@, @y@ and @z@ separate the key material into three
- * parts. Between the @k@ and @k + x@ is `my' contribution to
- * the key material; between @k + x@ and @k + y@ is `your'
- * contribution; and between @k + y@ and @k + z@ is a shared
- * value we made together. These are used to construct two
- * collections of symmetric keys: one for outgoing messages, the
- * other for incoming messages.
+ * Use: Derives a new keyset from the given key material. This will
+ * set the @what@, @f@, and @hc@ members in @*a@; other members
+ * must be filled in by the caller.
*
* The new key is marked so that it won't be selected for output
* by @ksl_encrypt@. You can still encrypt data with it by
* calling @ks_encrypt@ directly.
*/
-extern keyset *ks_gen(const void */*k*/,
- size_t /*x*/, size_t /*y*/, size_t /*z*/,
- peer */*p*/);
+extern keyset *ks_gen(deriveargs */*a*/, peer */*p*/);
/* --- @ks_activate@ --- *
*