buf b;
buf_init(&b, buf_i, PKBUFSZ);
- c_new(&b);
+ c_new(0, 0, &b);
a_info(a, "?B64", BBASE(&b), (size_t)BLEN(&b), A_END);
a_ok(a);
}
a_fail(a, "bad-base64", "%s", codec_strerror(err), A_END);
else {
buf_init(&b, d.buf, d.len);
- if (c_check(&b) || BBAD(&b) || BLEFT(&b))
+ if (c_check(0, 0, &b) || BBAD(&b) || BLEFT(&b))
a_fail(a, "invalid-challenge", A_END);
else
a_ok(a);
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);
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)
/* --- @c_new@ --- *
*
- * Arguments: @buf *b@ = where to put the challenge
+ * Arguments: @const void *m@ = pointer to associated message, or null
+ * @size_t msz@ = length of associated message
+ * @buf *b@ = where to put the challenge
*
* Returns: Zero if OK, nonzero on error.
*
* Use: Issues a new challenge.
*/
-int c_new(buf *b)
+int c_new(const void *m, size_t msz, buf *b)
{
- octet *p;
+ const octet *p;
+ octet *t;
+ int rc;
c_genkey();
p = BCUR(b);
- if (buf_putu32(b, oseq++) || !buf_get(b, bchal->tagsz)) return (-1);
- if (bchal->ops->chaltag(bchal, p, 4, p + 4)) return (-1);
+ if (buf_putu32(b, oseq) || (t = buf_get(b, bchal->tagsz)) == 0)
+ { rc = -1; goto done; }
+ if (bchal->ops->chaltag(bchal, m, msz, oseq, t)) { rc = -1; goto done; }
IF_TRACING(T_CHAL, {
- trace(T_CHAL, "chal: issuing challenge %lu", (unsigned long)(oseq - 1));
+ trace(T_CHAL, "chal: issuing challenge %lu", (unsigned long)oseq);
+ if (msz) trace_block(T_CRYPTO, "chal: message block", m, msz);
trace_block(T_CRYPTO, "chal: challenge block", p, BCUR(b) - p);
})
- return (0);
+ rc = 0;
+done:
+ oseq++;
+ return (rc);
}
/* --- @c_check@ --- *
*
- * Arguments: @buf *b@ = where to find the challenge
+ * Arguments: @const void *m@ = pointer to associated message, or null
+ * @size_t msz@ = length of associated message
+ * @buf *b@ = where to find the challenge
*
* Returns: Zero if OK, nonzero if it didn't work.
*
* Use: Checks a challenge. On failure, the buffer is broken.
*/
-int c_check(buf *b)
+int c_check(const void *m, size_t msz, buf *b)
{
- const octet *p;
- size_t sz;
+ const octet *p, *t;
uint32 seq;
if (!bchal) {
a_warn("CHAL", "impossible-challenge", A_END);
goto fail;
}
- sz = 4 + bchal->tagsz;
- if ((p = buf_get(b, sz)) == 0) {
+ p = BCUR(b);
+ if (buf_getu32(b, &seq) || (t = buf_get(b, bchal->tagsz)) == 0) {
a_warn("CHAL", "invalid-challenge", A_END);
goto fail;
}
- IF_TRACING(T_CHAL, trace_block(T_CRYPTO, "chal: check challenge", p, sz); )
- if (bchal->ops->chalvrf(bchal, p, 4, p + 4)) {
+ IF_TRACING(T_CHAL, {
+ trace(T_CHAL, "chal: checking challenge, seq = %lu", (unsigned long)seq);
+ if (msz) trace_block(T_CRYPTO, "chal: message block", m, msz);
+ trace_block(T_CRYPTO, "chal: check challenge", p, BCUR(b) - p);
+ })
+ if (bchal->ops->chalvrf(bchal, m, msz, seq, t)) {
a_warn("CHAL", "incorrect-tag", A_END);
goto fail;
}
- seq = LOAD32(p);
- if (seq_check(&iseq, seq, "CHAL"))
- goto fail;
- T( trace(T_CHAL, "chal: checked challenge %lu", (unsigned long)seq); )
+ if (seq_check(&iseq, seq, "CHAL")) goto fail;
+ T( trace(T_CHAL, "chal: challenge ok"); )
return (0);
fail:
})
buf_init(&b, buf_i, n);
buf_getbyte(&b);
- if (c_check(&b) || BLEFT(&b)) {
+ if (c_check(0, 0, &b) || BLEFT(&b)) {
a_warn("PEER", "-", "invalid-greeting", A_END);
return;
}
/* Release a bulk encryption context and the resources it holds. */
int (*chaltag)(bulkchal */*bc*/, const void */*m*/, size_t /*msz*/,
- void */*t*/);
- /* Calculate a tag for the challenge in @m@, @msz@, and write it to
- * @t@. Return @-1@ on error, zero on success.
+ uint32 /*seq*/, void */*t*/);
+ /* Calculate a tag for the challenge in @m@, @msz@, with the sequence
+ * number @seq@, and write it to @t@. Return @-1@ on error, zero on
+ * success.
*/
int (*chalvrf)(bulkchal */*bc*/, const void */*m*/, size_t /*msz*/,
- const void */*t*/);
- /* Check the tag @t@ on @m@, @msz@: return zero if the tag is OK,
- * nonzero if it's bad.
+ uint32 /*seq*/, const void */*t*/);
+ /* Check the tag @t@ on @m@, @msz@ and @seq@: return zero if the tag
+ * is OK, nonzero if it's bad.
*/
void (*freechal)(bulkchal */*bc*/);
/* --- @c_new@ --- *
*
- * Arguments: @buf *b@ = where to put the challenge
+ * Arguments: @const void *m@ = pointer to associated message, or null
+ * @size_t msz@ = length of associated message
+ * @buf *b@ = where to put the challenge
*
* Returns: Zero if OK, nonzero on error.
*
* Use: Issues a new challenge.
*/
-extern int c_new(buf */*b*/);
+extern int c_new(const void */*m*/, size_t /*msz*/, buf */*b*/);
/* --- @c_check@ --- *
*
- * Arguments: @buf *b@ = where to find the challenge
+ * Arguments: @const void *m@ = pointer to associated message, or null
+ * @size_t msz@ = length of associated message
+ * @buf *b@ = where to find the challenge
*
* Returns: Zero if OK, nonzero if it didn't work.
*
* Use: Checks a challenge. On failure, the buffer is broken.
*/
-extern int c_check(buf */*b*/);
+extern int c_check(const void */*m*/, size_t /*msz*/, buf */*b*/);
/*----- Administration interface ------------------------------------------*/