{
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;
- unsigned skip = i % 5;
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++) {
- 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 --- */
-#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 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; \
* 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 --- */
/* --- 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)
{
+ sha_ctx h;
+
/* --- 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 --- */
/* --- 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 --- */
/* --- 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 --- */
c->l = 0;
c->r = k->r;
c->ri = 0x2000 + SEAL_R;
- c->qsz = 0;
+ c->off = 16;
seal_reset(c);
}
void seal_encrypt(seal_ctx *c, const void *src, void *dest, size_t sz)
{
+ seal_key *k = c->k;
const octet *s = src;
- octet *d = dest;
+ 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 --- */
- 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 (;;) {
- unsigned P, Q;
/* --- Reset if we've run out of steam on this iteration --- */
/* --- 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 --- */
- 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];
j += 4;
- 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 --- */
- if (sz < 16)
- break;
+ if (sz < 16) break;
/* --- Write the next 16 bytes --- */
- if (d) {
+ if (!d) /* nothing to do */;
+ else {
if (s) {
- 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);
s += 16;
}
- 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);
d += 16;
}
sz -= 16;
}
- /* --- 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;
}
- /* --- Deal with the rest from the queue --- */
+ /* --- Deal with the rest from the buffer --- */
if (sz) {
- 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)
-{
- 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 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,
} 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 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",
#include <string.h>
+#include <mLib/macros.h>
#include <mLib/testrig.h>
static int verify(dstr *v)
seal_initctx(&c, &k, n);
seal_encrypt(&c, 0, d.buf, i);
seal_encrypt(&c, z.buf, d.buf + i, d.len - i);
- if (memcmp(d.buf, v[2].buf, d.len) != 0) {
+ if (MEMCMP(d.buf, !=, v[2].buf, d.len)) {
ok = 0;
printf("*** seal failure\n");
printf("*** k = "); type_hex.dump(&v[0], stdout); putchar('\n');