server/admin.c: Remove spurious `ping' in usage message.
[tripe] / server / bulkcrypto.c
index 9af4bb8..4c6be32 100644 (file)
@@ -285,10 +285,10 @@ static void gencomp_freechal(bulkchal *bc)
  * encrypt the input message with the cipher, and format the type, sequence
  * number, IV, and ciphertext as follows.
  *
- *             +------+ +------+---...---+------...------+
- *             | type | | seq  |   iv    |   ciphertext  |
- *             +------+ +------+---...---+------...------+
- *                32       32     blksz         sz
+ *             +--------+ +--------+---...---+------...------+
+ *             |  type  | |  seq   |   iv    |   ciphertext  |
+ *             +--------+ +--------+---...---+------...------+
+ *                 32         32      blksz         sz
  *
  * All of this is fed into the MAC to compute a tag.  The type is not
  * transmitted: the other end knows what type of message it expects, and the
@@ -296,10 +296,10 @@ static void gencomp_freechal(bulkchal *bc)
  * kind of ciphertext has been substituted.  The tag is prepended to the
  * remainder, to yield the finished cryptogram, as follows.
  *
- *             +---...---+------+---...---+------...------+
- *             |   tag   | seq  |   iv    |   ciphertext  |
- *             +---...---+------+---...---+------...------+
- *                tagsz     32     blksz         sz
+ *             +---...---+--------+---...---+------...------+
+ *             |   tag   |  seq   |   iv    |   ciphertext  |
+ *             +---...---+--------+---...---+------...------+
+ *                tagsz      32      blksz         sz
  *
  * Decryption: checks the overall size, verifies the tag, then decrypts the
  * ciphertext and extracts the sequence number.
@@ -527,10 +527,10 @@ static int v0_decrypt(bulkctx *bbc, unsigned ty,
  *
  * So, a MAC is computed over
  *
- *             +------+ +------+------...------+
- *             | type | | seq  |   ciphertext  |
- *             +------+ +------+------...------+
- *                32       32         sz
+ *             +--------+ +--------+------...------+
+ *             |  type  | |  seq   |   ciphertext  |
+ *             +--------+ +--------+------...------+
+ *                 32         32          sz
  *
  * and we actually transmit the following as the cryptogram.
  *
@@ -820,21 +820,40 @@ static int iiv_decrypt(bulkctx *bbc, unsigned ty,
  * additional data isn't necessary).  Good options include
  * `chacha20-poly1305' or `rijndael-ocb3'.
  *
- * To be acceptable, the scheme must accept at least a 64-bit nonce.  (All of
+ * To be acceptable, the scheme must accept at least a 40-bit nonce.  (All of
  * Catacomb's current AEAD schemes are suitable.)  The low 32 bits are the
- * sequence number, and the high 32 bits are the type, both big-endian.
+ * sequence number.  The type is written to the next 8--32 bytes: if the
+ * nonce size is 64 bits or more (preferred, for compatibility reasons) then
+ * the type is written as 32 bits, and the remaining space is padded with
+ * zero bytes; otherwise, the type is right-aligned in the remaining space.
+ * Both fields are big-endian.
+ *
+ *             +--------+--+
+ *             |  seq   |ty|
+ *             +--------+--+
+ *                 32    8
+ *
+ *             +--------+----+
+ *             |  seq   | ty |
+ *             +--------+----+
+ *                 32     16
  *
- *             +------+------+
- *             | seq  | type |
- *             +------+------+
- *                32     32
+ *             +--------+------+
+ *             |  seq   | type |
+ *             +--------+------+
+ *                 32      24
+ *
+ *             +--------+--------+---...---+
+ *             |  seq   |  type  |    0    |
+ *             +--------+--------+---...---+
+ *                 32       32     nsz - 64
  *
  * The ciphertext is formatted as
  *
- *             +---...---+------+------...------+
- *             |   tag   | seq  |   ciphertext  |
- *             +---...---+------+------...------+
- *                tagsz     32         sz
+ *             +---...---+--------+------...------+
+ *             |   tag   |  seq   |   ciphertext  |
+ *             +---...---+--------+------...------+
+ *                tagsz      32          sz
  *
  */
 
@@ -873,6 +892,7 @@ static bulkalgs *aead_getalgs(const algswitch *asw, dstr *e,
     goto fail;
   }
   a->nsz = keysz_pad(8, a->c->noncesz);
+  if (!a->nsz) a->nsz = keysz_pad(5, a->c->noncesz);
   if (!a->nsz) {
     a_format(e, "unsuitable-aead-cipher", "%s", p, "nonce-too-small", A_END);
     goto fail;
@@ -1072,6 +1092,20 @@ static void aead_freectx(bulkctx *bbc)
   DESTROY(bc);
 }
 
+static void aead_fmtnonce(aead_ctx *bc, octet *n, uint32 seq, unsigned ty)
+{
+  assert(bc->nsz <= AEAD_NONCEMAX); assert(ty <= 255);
+  STORE32(n, seq);
+  switch (bc->nsz) {
+    case 5: STORE8(n + SEQSZ, ty); break;
+    case 6: STORE16(n + SEQSZ, ty); break;
+    case 7: STORE24(n + SEQSZ, ty); break;
+    default: memset(n + 8, 0, bc->nsz - 8); /* and continue */
+    case 8: STORE32(n + SEQSZ, ty); break;
+  }
+  TRACE_IV(n, bc->nsz);
+}
+
 static int aead_encrypt(bulkctx *bbc, unsigned ty,
                        buf *b, buf *bb, uint32 seq)
 {
@@ -1090,11 +1124,7 @@ static int aead_encrypt(bulkctx *bbc, unsigned ty,
   qmac = BCUR(bb); qseq = qmac + bc->tsz; qpk = qseq + SEQSZ;
   STORE32(qseq, seq);
 
-  assert(bc->nsz <= sizeof(n));
-  memcpy(n, qseq, SEQSZ); STORE32(n + SEQSZ, ty);
-  if (bc->nsz > 8) memset(n + 8, 0, bc->nsz - 8);
-  TRACE_IV(n, bc->nsz);
-
+  aead_fmtnonce(bc, n, seq, ty);
   rc = gaead_encrypt(k, n, bc->nsz, 0, 0, p, sz, qpk, &csz, qmac, bc->tsz);
   assert(!rc);
   BSTEP(bb, bc->tsz + SEQSZ + csz);
@@ -1105,11 +1135,12 @@ static int aead_encrypt(bulkctx *bbc, unsigned ty,
 }
 
 static int aead_decrypt(bulkctx *bbc, unsigned ty,
-                      buf *b, buf *bb, uint32 *seq)
+                      buf *b, buf *bb, uint32 *seq_out)
 {
   aead_ctx *bc = (aead_ctx *)bbc;
   gaead_key *k = bc->d[DIR_IN].k;
   const octet *pmac, *pseq, *ppk;
+  uint32 seq;
   size_t psz = BLEFT(b);
   size_t sz;
   octet *q = BCUR(bb);
@@ -1124,17 +1155,14 @@ static int aead_decrypt(bulkctx *bbc, unsigned ty,
   }
   sz = psz - bc->tsz - SEQSZ;
   pmac = BCUR(b); pseq = pmac + bc->tsz; ppk = pseq + SEQSZ;
+  seq = LOAD32(pseq);
 
-  assert(bc->nsz <= sizeof(n));
-  memcpy(n, pseq, SEQSZ); STORE32(n + SEQSZ, ty);
-  if (bc->nsz > 8) memset(n + 8, 0, bc->nsz - 8);
-  TRACE_IV(n, bc->nsz);
-
+  aead_fmtnonce(bc, n, seq, ty);
   rc = gaead_decrypt(k, n, bc->nsz, 0, 0, ppk, sz, q, &sz, pmac, bc->tsz);
   assert(rc >= 0);
   if (!rc) { TRACE_MACERR(pmac, bc->tsz); return (KSERR_DECRYPT); }
 
-  *seq = LOAD32(pseq);
+  *seq_out = seq;
   BSTEP(bb, sz);
   return (0);
 }
@@ -1149,10 +1177,10 @@ static int aead_decrypt(bulkctx *bbc, unsigned ty,
  * Salsa20 and ChaCha accept a 64-bit nonce.  The low 32 bits are the
  * sequence number, and the high 32 bits are the type, both big-endian.
  *
- *             +------+------+
- *             | seq  | type |
- *             +------+------+
- *                32     32
+ *             +--------+--------+
+ *             |  seq   |  type  |
+ *             +--------+--------+
+ *                 32       32
  *
  * A stream is generated by concatenating the raw output blocks generated
  * with this nonce and successive counter values starting from zero.  The
@@ -1293,7 +1321,8 @@ static int naclbox_chaltag(bulkchal *bc, const void *m, size_t msz,
   poly1305_ctx pm;
   octet b[POLY1305_KEYSZ + POLY1305_MASKSZ];
 
-  assert(SALSA20_NONCESZ <= sizeof(b));
+  STATIC_ASSERT(SALSA20_NONCESZ <= sizeof(b), "Need more space for nonce");
+
   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);
@@ -1311,13 +1340,15 @@ static int naclbox_chalvrf(bulkchal *bc, const void *m, size_t msz,
   poly1305_ctx pm;
   octet b[POLY1305_KEYSZ + POLY1305_MASKSZ];
 
-  assert(SALSA20_NONCESZ <= sizeof(b));
+  STATIC_ASSERT(SALSA20_NONCESZ <= sizeof(b), "Need more space for nonce");
+  STATIC_ASSERT(POLY1305_TAGSZ <= sizeof(b), "Need more space for tag");
+
   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);
+  poly1305_done(&pm, b);
   return (ct_memeq(t, b, POLY1305_TAGSZ) ? 0 : -1);
 }