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 { \
typedef struct gencomp_chal {
bulkchal _b;
- gmac *m; size_t tagsz;
+ gmac *m;
} gencomp_chal;
static int gencomp_getalgs(gencomp_algs *a, const algswitch *asw,
return (&gc->_b);
}
-static int gencomp_chaltag(bulkchal *bc, const void *m, size_t msz, void *t)
+static int gencomp_chaltag(bulkchal *bc, const void *m, size_t msz,
+ uint32 seq, void *t)
{
gencomp_chal *gc = (gencomp_chal *)bc;
ghash *h = GM_INIT(gc->m);
- GH_HASH(h, m, msz);
+ GH_HASHU32(h, seq); if (msz) GH_HASH(h, m, msz);
memcpy(t, GH_DONE(h, 0), bc->tagsz);
GH_DESTROY(h);
return (0);
}
static int gencomp_chalvrf(bulkchal *bc, const void *m, size_t msz,
- const void *t)
+ uint32 seq, const void *t)
{
gencomp_chal *gc = (gencomp_chal *)bc;
ghash *h = GM_INIT(gc->m);
int ok;
- GH_HASH(h, m, msz);
+ GH_HASHU32(h, seq); if (msz) GH_HASH(h, m, msz);
ok = ct_memeq(GH_DONE(h, 0), t, gc->_b.tagsz);
GH_DESTROY(h);
return (ok ? 0 : -1);
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) {
const iiv_algs *a = (const iiv_algs *)aa;
gencomp_tracealgs(&a->ga);
- trace(T_CRYPTO, "crypto: blkc = %.*s", strlen(a->b->name) - 4, a->b->name);
+ trace(T_CRYPTO,
+ "crypto: blkc = %.*s", (int)strlen(a->b->name) - 4, a->b->name);
}
#endif
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);
trace(T_CHAL, "chal: generated new challenge key");
trace_block(T_CRYPTO, "chal: new key", buf_t, a->cksz);
})
- c->_b.tagsz = 16;
+ c->_b.tagsz = POLY1305_TAGSZ;
return (&c->_b);
}
-static int naclbox_chaltag(bulkchal *bc, const void *m, size_t msz, void *t)
+static int naclbox_chaltag(bulkchal *bc, const void *m, size_t msz,
+ uint32 seq, void *t)
{
naclbox_chal *c = (naclbox_chal *)bc;
- octet b0[SALSA20_NONCESZ];
- assert(msz <= sizeof(b0));
- memcpy(b0, m, msz); memset(b0 + msz, 0, sizeof(b0) - msz);
- GC_SETIV(c->c, b0);
- GC_ENCRYPT(c->c, 0, t, c->_b.tagsz);
+ poly1305_key pk;
+ poly1305_ctx pm;
+ octet b[POLY1305_KEYSZ + POLY1305_MASKSZ];
+
+ assert(SALSA20_NONCESZ <= sizeof(b));
+ memset(b, 0, SALSA20_NONCESZ - 4); STORE32(b + SALSA20_NONCESZ - 4, seq);
+ GC_SETIV(c->c, b); GC_ENCRYPT(c->c, 0, b, sizeof(b));
+ poly1305_keyinit(&pk, b, POLY1305_KEYSZ);
+ poly1305_macinit(&pm, &pk, b + POLY1305_KEYSZ);
+ if (msz) poly1305_hash(&pm, m, msz);
+ poly1305_done(&pm, t);
return (0);
}
static int naclbox_chalvrf(bulkchal *bc, const void *m, size_t msz,
- const void *t)
+ uint32 seq, const void *t)
{
naclbox_chal *c = (naclbox_chal *)bc;
- octet b0[SALSA20_NONCESZ], b1[16];
- assert(msz <= sizeof(b0)); assert(c->_b.tagsz <= sizeof(b1));
- memcpy(b0, m, msz); memset(b0 + msz, 0, sizeof(b0) - msz);
- GC_SETIV(c->c, b0);
- GC_ENCRYPT(c->c, 0, b1, c->_b.tagsz);
- return (ct_memeq(t, b1, c->_b.tagsz) ? 0 : -1);
+ poly1305_key pk;
+ poly1305_ctx pm;
+ octet b[POLY1305_KEYSZ + POLY1305_MASKSZ];
+
+ assert(SALSA20_NONCESZ <= sizeof(b));
+ memset(b, 0, SALSA20_NONCESZ - 4); STORE32(b + SALSA20_NONCESZ - 4, seq);
+ GC_SETIV(c->c, b); GC_ENCRYPT(c->c, 0, b, sizeof(b));
+ poly1305_keyinit(&pk, b, POLY1305_KEYSZ);
+ poly1305_macinit(&pm, &pk, b + POLY1305_KEYSZ);
+ if (msz) poly1305_hash(&pm, m, msz);
+ assert(POLY1305_TAGSZ <= sizeof(b)); poly1305_done(&pm, b);
+ return (ct_memeq(t, b, POLY1305_TAGSZ) ? 0 : -1);
}
static void naclbox_freechal(bulkchal *bc)
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) {