X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/0f00dc4c8eb47e67bc0f148c2dd109f73a451e0a..HEAD:/symm/seal.c diff --git a/symm/seal.c b/symm/seal.c index df7cd1ba..070550dd 100644 --- a/symm/seal.c +++ b/symm/seal.c @@ -58,39 +58,41 @@ const octet seal_keysz[] = { KSZ_ANY, SHA_HASHSZ }; * Use: Initializes a SEAL key table. */ -static void gamma(uint32 *p, size_t sz, const void *k, unsigned i) +static void sealgamma(uint32 *p, size_t sz, const void *k, unsigned i) { 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; \ @@ -109,14 +111,10 @@ static void gamma(uint32 *p, size_t sz, const void *k, unsigned i) * 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 --- */ @@ -125,17 +123,12 @@ static void gamma(uint32 *p, size_t sz, const void *k, unsigned i) /* --- 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; } } } @@ -155,22 +148,18 @@ static void gamma(uint32 *p, size_t sz, const void *k, unsigned i) 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 --- */ - gamma(k->t, 512, k->k, 0); - gamma(k->s, 256, k->k, 0x1000); - gamma(k->r, SEAL_R, k->k, 0x2000); + sealgamma(k->t, 512, k->k, 0); + sealgamma(k->s, 256, k->k, 0x1000); + sealgamma(k->r, SEAL_R, k->k, 0x2000); } /* --- @seal_reset@ --- * @@ -193,7 +182,7 @@ static void seal_reset(seal_ctx *c) /* --- Initialize the new chaining variables --- */ if (c->l >= SEAL_R) { - gamma(c->rbuf, SEAL_R, k->k, c->ri); + sealgamma(c->rbuf, SEAL_R, k->k, c->ri); c->ri += SEAL_R; c->l = 0; c->r = c->rbuf; @@ -208,14 +197,14 @@ static void seal_reset(seal_ctx *c) /* --- 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 --- */ @@ -223,10 +212,10 @@ static void seal_reset(seal_ctx *c) /* --- 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 --- */ @@ -253,7 +242,7 @@ void seal_initctx(seal_ctx *c, seal_key *k, uint32 n) c->l = 0; c->r = k->r; c->ri = 0x2000 + SEAL_R; - c->qsz = 0; + c->off = 16; seal_reset(c); } @@ -274,34 +263,32 @@ void seal_initctx(seal_ctx *c, seal_key *k, uint32 n) 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 --- */ @@ -314,74 +301,63 @@ void seal_encrypt(seal_ctx *c, const void *src, void *dest, size_t sz) /* --- 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++; } } @@ -405,24 +381,17 @@ static gcipher *ginit(const void *k, 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) { gctx *g = (gctx *)c; - uint32 n = *(const uint32 *)iv; - seal_initctx(&g->cc, &g->k, n); + const octet *ivp = iv; + seal_initctx(&g->cc, &g->k, LOAD32(ivp)); } 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, @@ -430,7 +399,7 @@ static const gcipher_ops gops = { }; const gccipher seal = { - "seal", seal_keysz, 0, + "seal", seal_keysz, 4, ginit }; @@ -443,11 +412,7 @@ typedef struct grctx { } 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, ...) { @@ -520,16 +485,13 @@ static uint32 grword(grand *r) } 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", GRAND_CRYPTO, 0, grmisc, grdestroy, - grword, grbyte, grword, grand_range, grfill + grword, grbyte, grword, grand_defaultrange, grfill }; /* --- @seal_rand@ --- * @@ -559,6 +521,7 @@ grand *seal_rand(const void *k, size_t sz, uint32 n) #include +#include #include static int verify(dstr *v) @@ -581,7 +544,7 @@ 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');