I'm not deploying the reservoir code here because the core update is
entangled with the buffering in an unusual way, to avoid having to spill
the working state. Switching to the reservoir logic would mean having
to factor out the core update, which would lead to spillage.
Instead, settle for renaming the buffering variables (and switching
which end we count from) and reformatting the code a bit.
{
uint32 buf[80] = { 0 };
const octet *kk = k;
{
uint32 buf[80] = { 0 };
const octet *kk = k;
- uint32 aa = LOAD32(kk);
- uint32 bb = LOAD32(kk + 4);
- uint32 cc = LOAD32(kk + 8);
- uint32 dd = LOAD32(kk + 12);
- uint32 ee = LOAD32(kk + 16);
+ uint32 a, aa = LOAD32(kk);
+ uint32 b, bb = LOAD32(kk + 4);
+ uint32 c, cc = LOAD32(kk + 8);
+ uint32 d, dd = LOAD32(kk + 12);
+ uint32 e, ee = LOAD32(kk + 16);
+
+ unsigned skip = i%5;
+ uint32 x;
+ int j;
i /= 5;
/* --- While there's hashing to do, do hashing --- */
while (sz) {
i /= 5;
/* --- While there's hashing to do, do hashing --- */
while (sz) {
- uint32 a = aa, b = bb, c = cc, d = dd, e = ee;
- int j;
+ a = aa, b = bb, c = cc, d = dd, e = ee;
/* --- Initialize and expand the buffer --- */
buf[0] = i++;
for (j = 16; j < 80; j++) {
/* --- Initialize and expand the buffer --- */
buf[0] = i++;
for (j = 16; j < 80; j++) {
- uint32 x = buf[j - 3] ^ buf[j - 8] ^ buf[j - 14] ^ buf[j - 16];
+ x = buf[j - 3] ^ buf[j - 8] ^ buf[j - 14] ^ buf[j - 16];
buf[j] = ROL32(x, 1);
}
/* --- Definitions for round functions --- */
buf[j] = ROL32(x, 1);
}
/* --- Definitions for round functions --- */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define F(x, y, z) (((x)&(y)) | (~(x)&(z)))
#define G(x, y, z) ((x) ^ (y) ^ (z))
#define G(x, y, z) ((x) ^ (y) ^ (z))
-#define H(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) (((x)&(y)) | ((x)&(z)) | ((y)&(z)))
#define T(v, w, x, y, z, i, f, k) do { \
uint32 _x; \
#define T(v, w, x, y, z, i, f, k) do { \
uint32 _x; \
* Since this isn't doing bulk hashing, do it the easy way.
*/
* Since this isn't doing bulk hashing, do it the easy way.
*/
- for (j = 0; j < 20; j++)
- FF(a, b, c, d, e, j);
- for (j = 20; j < 40; j++)
- GG(a, b, c, d, e, j);
- for (j = 40; j < 60; j++)
- HH(a, b, c, d, e, j);
- for (j = 60; j < 80; j++)
- II(a, b, c, d, e, j);
+ for (j = 0; j < 20; j++) FF(a, b, c, d, e, j);
+ for (j = 20; j < 40; j++) GG(a, b, c, d, e, j);
+ for (j = 40; j < 60; j++) HH(a, b, c, d, e, j);
+ for (j = 60; j < 80; j++) II(a, b, c, d, e, j);
/* --- Do the chaining at the end --- */
/* --- Do the chaining at the end --- */
/* --- Write to the output buffer --- */
switch (skip) {
/* --- Write to the output buffer --- */
switch (skip) {
- case 0:
- if (sz) { *p++ = a; sz--; }
- case 1:
- if (sz) { *p++ = b; sz--; }
- case 2:
- if (sz) { *p++ = c; sz--; }
- case 3:
- if (sz) { *p++ = d; sz--; }
- case 4:
- if (sz) { *p++ = e; sz--; }
- skip = 0;
+ case 0: if (sz) { *p++ = a; sz--; }
+ case 1: if (sz) { *p++ = b; sz--; }
+ case 2: if (sz) { *p++ = c; sz--; }
+ case 3: if (sz) { *p++ = d; sz--; }
+ case 4: if (sz) { *p++ = e; sz--; }
+ skip = 0;
void seal_initkey(seal_key *k, const void *buf, size_t sz)
{
void seal_initkey(seal_key *k, const void *buf, size_t sz)
{
/* --- Hash the key if it's the wrong size --- */
/* --- Hash the key if it's the wrong size --- */
- if (sz == SHA_HASHSZ)
- memcpy(k->k, buf, sizeof(k->k));
- else {
- sha_ctx c;
- sha_init(&c);
- sha_hash(&c, buf, sz);
- sha_done(&c, k->k);
- }
+ if (sz == SHA_HASHSZ) memcpy(k->k, buf, sizeof(k->k));
+ else { sha_init(&h); sha_hash(&h, buf, sz); sha_done(&h, k->k); }
/* --- Expand the key to fit the various tables --- */
/* --- Expand the key to fit the various tables --- */
/* --- Ensure that everything is sufficiently diffused --- */
/* --- Ensure that everything is sufficiently diffused --- */
- p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
- p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
- p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
- p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
- p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
- p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
- p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
- p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
+ p = A&0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
+ p = B&0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
+ p = C&0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
+ p = D&0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
+ p = A&0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
+ p = B&0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
+ p = C&0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
+ p = D&0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
/* --- Write out some context --- */
/* --- Write out some context --- */
/* --- Diffuse some more --- */
/* --- Diffuse some more --- */
- p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
- p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
- p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
- p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
+ p = A&0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
+ p = B&0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
+ p = C&0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
+ p = D&0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
/* --- Write out the magic numbers --- */
/* --- Write out the magic numbers --- */
c->l = 0;
c->r = k->r;
c->ri = 0x2000 + SEAL_R;
c->l = 0;
c->r = k->r;
c->ri = 0x2000 + SEAL_R;
void seal_encrypt(seal_ctx *c, const void *src, void *dest, size_t sz)
{
void seal_encrypt(seal_ctx *c, const void *src, void *dest, size_t sz)
{
+ octet *d = dest, *p;
+ uint32 A = c->a, B = c->b, C = c->c, D = c->d;
+ uint32 n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4;
+ uint32 aa, bb, cc, dd;
+ unsigned i, j;
+ unsigned P, Q;
/* --- Expect a big dollop of bytes --- */
/* --- Expect a big dollop of bytes --- */
- if (sz > c->qsz) {
- seal_key *k = c->k;
- uint32 A = c->a, B = c->b, C = c->c, D = c->d;
- uint32 n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4;
- uint32 aa, bb, cc, dd;
- unsigned j = c->i;
-
- /* --- Empty the queue first --- */
-
- if (c->qsz) {
- if (d) {
- unsigned i;
- octet *p = c->q + sizeof(c->q) - c->qsz;
- for (i = 0; i < c->qsz; i++)
- *d++ = (s ? *s++ ^ *p++ : *p++);
- }
- sz -= c->qsz;
+ if (sz > 16 - c->off) {
+ j = c->i;
+
+ /* --- Drain the buffer first --- */
+
+ if (c->off < 16) {
+ p = c->buf + c->off; sz -= 16 - c->off;
+ if (!d) /* nothing to do* */;
+ else if (!s) memcpy(d, p, 16 - c->off);
+ else for (i = c->off; i < 16; i++) *d++ = *s++ ^ *p++;
}
/* --- Main sequence --- */
for (;;) {
}
/* --- Main sequence --- */
for (;;) {
/* --- Reset if we've run out of steam on this iteration --- */
/* --- Reset if we've run out of steam on this iteration --- */
/* --- Make some new numbers --- */
/* --- Make some new numbers --- */
- P = A & 0x7fc; B += k->t[P >> 2]; A = ROR32(A, 9); B ^= A;
- Q = B & 0x7fc; C ^= k->t[Q >> 2]; B = ROR32(B, 9); C += B;
- P = (P + C) & 0x7fc; D += k->t[P >> 2]; C = ROR32(C, 9); D ^= C;
- Q = (Q + D) & 0x7fc; A ^= k->t[Q >> 2]; D = ROR32(D, 9); A += D;
- P = (P + A) & 0x7fc; B ^= k->t[P >> 2]; A = ROR32(A, 9);
- Q = (Q + B) & 0x7fc; C += k->t[Q >> 2]; B = ROR32(B, 9);
- P = (P + C) & 0x7fc; D ^= k->t[P >> 2]; C = ROR32(C, 9);
- Q = (Q + D) & 0x7fc; A += k->t[Q >> 2]; D = ROR32(D, 9);
+ P = A&0x7fc; B += k->t[P >> 2]; A = ROR32(A, 9); B ^= A;
+ Q = B&0x7fc; C ^= k->t[Q >> 2]; B = ROR32(B, 9); C += B;
+ P = (P + C)&0x7fc; D += k->t[P >> 2]; C = ROR32(C, 9); D ^= C;
+ Q = (Q + D)&0x7fc; A ^= k->t[Q >> 2]; D = ROR32(D, 9); A += D;
+ P = (P + A)&0x7fc; B ^= k->t[P >> 2]; A = ROR32(A, 9);
+ Q = (Q + B)&0x7fc; C += k->t[Q >> 2]; B = ROR32(B, 9);
+ P = (P + C)&0x7fc; D ^= k->t[P >> 2]; C = ROR32(C, 9);
+ Q = (Q + D)&0x7fc; A += k->t[Q >> 2]; D = ROR32(D, 9);
/* --- Remember the output and set up the next round --- */
/* --- Remember the output and set up the next round --- */
- aa = B + k->s[j + 0];
- bb = C ^ k->s[j + 1];
- cc = D + k->s[j + 2];
- dd = A ^ k->s[j + 3];
+ aa = B + k->s[j + 0]; bb = C ^ k->s[j + 1];
+ cc = D + k->s[j + 2]; dd = A ^ k->s[j + 3];
- if (j & 4)
- A += n1, B += n2, C ^= n1, D ^= n2;
- else
- A += n3, B += n4, C ^= n3, D ^= n4;
+ if (j&4) { A += n1; B += n2; C ^= n1; D ^= n2; }
+ else { A += n3; B += n4; C ^= n3; D ^= n4; }
/* --- Bail out here if we need to do buffering --- */
/* --- Bail out here if we need to do buffering --- */
/* --- Write the next 16 bytes --- */
/* --- Write the next 16 bytes --- */
+ if (!d) /* nothing to do */;
+ else {
- aa ^= LOAD32_L(s + 0);
- bb ^= LOAD32_L(s + 4);
- cc ^= LOAD32_L(s + 8);
- dd ^= LOAD32_L(s + 12);
+ aa ^= LOAD32_L(s + 0); bb ^= LOAD32_L(s + 4);
+ cc ^= LOAD32_L(s + 8); dd ^= LOAD32_L(s + 12);
- STORE32_L(d + 0, aa);
- STORE32_L(d + 4, bb);
- STORE32_L(d + 8, cc);
- STORE32_L(d + 12, dd);
+ STORE32_L(d + 0, aa); STORE32_L(d + 4, bb);
+ STORE32_L(d + 8, cc); STORE32_L(d + 12, dd);
- /* --- Write the new queue --- */
+ /* --- Write the new buffer --- */
- STORE32_L(c->q + 0, aa);
- STORE32_L(c->q + 4, bb);
- STORE32_L(c->q + 8, cc);
- STORE32_L(c->q + 12, dd);
- c->qsz = 16;
+ STORE32_L(c->buf + 0, aa);
+ STORE32_L(c->buf + 4, bb);
+ STORE32_L(c->buf + 8, cc);
+ STORE32_L(c->buf + 12, dd);
+ c->off = 0;
c->a = A; c->b = B; c->c = C; c->d = D;
c->i = j;
}
c->a = A; c->b = B; c->c = C; c->d = D;
c->i = j;
}
- /* --- Deal with the rest from the queue --- */
+ /* --- Deal with the rest from the buffer --- */
- unsigned i;
- octet *p = c->q + sizeof(c->q) - c->qsz;
- if (d) {
- for (i = 0; i < sz; i++)
- *d++ = (s ? *s++ ^ *p++ : *p++);
- }
- c->qsz -= sz;
+ p = c->buf + c->off; c->off += sz;
+ if (!d) /* nothing to do* */;
+ else if (!s) memcpy(d, p, sz);
+ else for (i = 0; i < sz; i++) *d++ = *s++ ^ *p++;
}
static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)
}
static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)
-{
- gctx *g = (gctx *)c;
- seal_encrypt(&g->cc, s, t, sz);
-}
+ { gctx *g = (gctx *)c; seal_encrypt(&g->cc, s, t, sz); }
static void gsetiv(gcipher *c, const void *iv)
{
static void gsetiv(gcipher *c, const void *iv)
{
}
static void gdestroy(gcipher *c)
}
static void gdestroy(gcipher *c)
-{
- gctx *g = (gctx *)c;
- BURN(*g);
- S_DESTROY(g);
-}
+ { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); }
static const gcipher_ops gops = {
&seal,
static const gcipher_ops gops = {
&seal,
} grctx;
static void grdestroy(grand *r)
} grctx;
static void grdestroy(grand *r)
-{
- grctx *g = (grctx *)r;
- BURN(*g);
- S_DESTROY(g);
-}
+ { grctx *g = (grctx *)r; BURN(*g); S_DESTROY(g); }
static int grmisc(grand *r, unsigned op, ...)
{
static int grmisc(grand *r, unsigned op, ...)
{
}
static void grfill(grand *r, void *p, size_t sz)
}
static void grfill(grand *r, void *p, size_t sz)
-{
- grctx *g = (grctx *)r;
- seal_encrypt(&g->cc, 0, p, sz);
-}
+ { grctx *g = (grctx *)r; seal_encrypt(&g->cc, 0, p, sz); }
static const grand_ops grops = {
"seal",
static const grand_ops grops = {
"seal",
uint32 a, b, c, d; /* Current chaining variables */
uint32 n1, n2, n3, n4; /* Increments for the variables */
unsigned i; /* Index into current iteration */
uint32 a, b, c, d; /* Current chaining variables */
uint32 n1, n2, n3, n4; /* Increments for the variables */
unsigned i; /* Index into current iteration */
- octet q[16]; /* Output buffer */
- unsigned qsz; /* Number of bytes in the buffer */
+ octet buf[16]; /* Output buffer */
+ unsigned off; /* Offset into the buffer */
uint32 rbuf[SEAL_R]; /* Buffer for later magic */
} seal_ctx;
uint32 rbuf[SEAL_R]; /* Buffer for later magic */
} seal_ctx;