X-Git-Url: https://git.distorted.org.uk/~mdw/tripe/blobdiff_plain/d5cdcb8a4f5f6f30d2e6f2f5d16d438a430e3cb6..01f0d4f411f0435279bfc274437451c24f74b4d1:/server/bulkcrypto.c diff --git a/server/bulkcrypto.c b/server/bulkcrypto.c index 9af4bb8c..4c6be323 100644 --- a/server/bulkcrypto.c +++ b/server/bulkcrypto.c @@ -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); }