server/: Augment challenges to allow a payload.
authorMark Wooding <mdw@distorted.org.uk>
Mon, 4 Sep 2017 08:36:10 +0000 (09:36 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 16 Jun 2018 18:13:41 +0000 (19:13 +0100)
  * Augment the external interface to take a pointer/length pair
    designating the payload.

  * Change the bulk-crypto interface to pass the sequence number in
    separately from the (repurposed) payload buffer.

  * Modify the `naclbox' challenge handling to hash the payload using
    Poly1305, rather than just producing some Salsa20 output.

server/admin.c
server/bulkcrypto.c
server/chal.c
server/peer.c
server/tripe.h

index 46a7348..d80992c 100644 (file)
@@ -1776,7 +1776,7 @@ static void acmd_getchal(admin *a, unsigned ac, char *av[])
   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);
 }
@@ -1793,7 +1793,7 @@ static void acmd_checkchal(admin *a, unsigned ac, char *av[])
     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);
index fff2c82..d0e654c 100644 (file)
@@ -251,25 +251,26 @@ static bulkchal *gencomp_genchal(const gencomp_algs *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);
@@ -987,31 +988,44 @@ static bulkchal *naclbox_genchal(const bulkalgs *aa)
     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)
index e6a3005..68d7f04 100644 (file)
@@ -57,61 +57,73 @@ static void c_genkey(void)
 
 /* --- @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:
index 03ed2ae..0ad3291 100644 (file)
@@ -352,7 +352,7 @@ static void p_read(int fd, unsigned mode, void *v)
     })
     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;
     }
index 75ad2f1..6f61182 100644 (file)
@@ -376,15 +376,16 @@ typedef struct bulkops {
        /* 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*/);
@@ -1110,25 +1111,29 @@ extern int ksl_decrypt(keyset **/*ksroot*/, unsigned /*ty*/,
 
 /* --- @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 ------------------------------------------*/